Carma-platform v4.2.0
CARMA Platform is built on robot operating system (ROS) and utilizes open source software (OSS) that enables Cooperative Driving Automation (CDA) features to allow Automated Driving Systems to interact and cooperate with infrastructure and other vehicles through communication.
traffic_incident_parser_worker.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2020-2022 LEIDOS.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
18#include <boost/uuid/uuid.hpp>
19#include <boost/uuid/uuid_generators.hpp>
20#include <carma_ros2_utils/containers/containers.hpp>
21#include <lanelet2_core/Attribute.h>
22#include <lanelet2_core/geometry/LineString.h>
23#include <lanelet2_core/primitives/Traits.h>
24#include <proj.h>
25
27{
29 rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr logger, rclcpp::Clock::SharedPtr clock)
30 : traffic_control_pub_(traffic_control_pub), wm_(wm), logger_(logger), clock_(clock) {}
31
32 void TrafficIncidentParserWorker::mobilityOperationCallback(carma_v2x_msgs::msg::MobilityOperation::UniquePtr mobility_msg)
33 {
34
35 if(mobility_msg->strategy=="carma3/Incident_Use_Case")
36 {
37
38 bool valid_msg = mobilityMessageParser(mobility_msg->strategy_params);
39
40 if(valid_msg && event_type=="CLOSED")
41 {
42 previous_strategy_params=mobility_msg->strategy_params;
43 carma_v2x_msgs::msg::TrafficControlMessage traffic_control_msg;
44 traffic_control_msg.choice = carma_v2x_msgs::msg::TrafficControlMessage::TCMV01;
45 for(const auto &traffic_msg : composeTrafficControlMesssages())
46 {
47 traffic_control_msg.tcm_v01=traffic_msg;
48 traffic_control_pub_(traffic_control_msg); // Publish the message to existing subscribers
49 }
50 }
51 else
52 {
53 return;
54 }
55 }
56 }
57
58 void TrafficIncidentParserWorker::georeferenceCallback(std_msgs::msg::String::UniquePtr projection_msg)
59 {
60 projection_msg_=projection_msg->data;
61 }
62
63
64 bool TrafficIncidentParserWorker::mobilityMessageParser(std::string mobility_strategy_params)
65 {
66
67 std::vector<std::string> vec={};
68 std::string delimiter = ",";
69 size_t pos = 0;
70 std::string token;
71 while ((pos = mobility_strategy_params.find(delimiter)) != std::string::npos)
72 {
73 token = mobility_strategy_params.substr(0, pos);
74 vec.push_back(token);
75 mobility_strategy_params.erase(0, pos + delimiter.length());
76 }
77 vec.push_back(mobility_strategy_params);
78
79 if (vec.size() != 8)
80 {
81 RCLCPP_ERROR_STREAM(logger_->get_logger(),"Given mobility strategy params are not correctly formatted.");
82 return false;
83 }
84
85 std::string lat_str=vec[0];
86 std::string lon_str=vec[1];
87 std::string downtrack_str=vec[2];
88 std::string uptrack_str=vec[3];
89 std::string min_gap_str=vec[4];
90 std::string speed_advisory_str=vec[5];
91 std::string event_reason_str=vec[6];
92 std::string event_type_str=vec[7];
93
94 // Evaluate if this message should be forwarded based on the gps point
95 double temp_lat = stod(stringParserHelper(lat_str,lat_str.find_last_of("lat:")));
96 double temp_lon = stod(stringParserHelper(lon_str,lon_str.find_last_of("lon:")));
97
98 double constexpr APPROXIMATE_DEG_PER_5M = 0.00005;
99 double delta_lat = temp_lat - latitude;
100 double delta_lon = temp_lon - longitude;
101 double approximate_degree_delta = sqrt(delta_lat*delta_lat + delta_lon*delta_lon);
102
103 double temp_down_track=stod(stringParserHelper(downtrack_str,downtrack_str.find_last_of("down_track:")));
104 double temp_up_track=stod(stringParserHelper(uptrack_str,uptrack_str.find_last_of("up_track:")));
105 double temp_min_gap=stod(stringParserHelper(min_gap_str,min_gap_str.find_last_of("min_gap:")));
106 double temp_speed_advisory=stod(stringParserHelper(speed_advisory_str,speed_advisory_str.find_last_of("advisory_speed:")));
107 std::string temp_event_reason=stringParserHelper(event_reason_str,event_reason_str.find_last_of("event_reason:"));
108 std::string temp_event_type=stringParserHelper(event_type_str,event_type_str.find_last_of("event_type:"));
109
110 if ( approximate_degree_delta < APPROXIMATE_DEG_PER_5M // If the vehicle has not moved more than 5m and the parameters remain unchanged
111 && temp_down_track == down_track
112 && temp_up_track == up_track
113 && temp_min_gap == min_gap
114 && temp_speed_advisory == speed_advisory
115 && temp_event_reason == event_reason
116 && temp_event_type == event_type) {
117
118 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Strategy params are unchanged so ignoring new message: " << mobility_strategy_params
119 << " degree_delta: " << approximate_degree_delta
120 << " prev_lat: " << latitude << " prev_lon: " << longitude);
121
122 return false;
123
124 }
125
126 // Valid message contents so populate member variables
127 latitude = temp_lat;
128 longitude = temp_lon;
129 down_track = temp_down_track;
130 up_track = temp_up_track;
131 min_gap = temp_min_gap;
132 speed_advisory = temp_speed_advisory;
133 event_reason = temp_event_reason;
134 event_type = temp_event_type;
135
136 return true;
137 }
138
139 std::string TrafficIncidentParserWorker::stringParserHelper(std::string str, unsigned long str_index) const
140 {
141 std::string str_temp="";
142 for(size_t i=str_index+1;i<str.length();i++)
143 {
144 str_temp+=str[i];
145 }
146 return str_temp;
147 }
148
150 {
151 lanelet::projection::LocalFrameProjector projector(projection_msg_.c_str());
152 lanelet::GPSPoint gps_point;
153 gps_point.lat = latitude;
154 gps_point.lon = longitude;
155 gps_point.ele = 0;
156 auto local_point3d = projector.forward(gps_point);
157 return {local_point3d.x(), local_point3d.y()};
158 }
159
163 size_t getNearestPointIndex(const lanelet::ConstLineString3d& points,
164 const lanelet::BasicPoint2d& point)
165 {
166 double min_distance = std::numeric_limits<double>::max();
167 size_t i = 0;
168 size_t best_index = 0;
169 for (const auto& p : points)
170 {
171 double distance = lanelet::geometry::distance2d(p, point);
172 if (distance < min_distance)
173 {
174 best_index = i;
175 min_distance = distance;
176 }
177 i++;
178 }
179
180 return best_index;
181 }
182
183 void TrafficIncidentParserWorker::getAdjacentForwardCenterlines(const lanelet::ConstLanelets& adjacentSet,
184 const lanelet::BasicPoint2d& start_point, double downtrack, std::vector<std::vector<lanelet::BasicPoint2d>>* forward_lanes) const
185 {
186 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "getAdjacentForwardCenterlines");
187 for (const auto& ll : adjacentSet) {
188 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Processing adjacent lanelet: " << ll.id());
189 std::vector<lanelet::BasicPoint2d> following_lane;
190 auto cur_ll = ll;
191 double dist = 0;
192
193
194 // Identify the point to start the accumulation from
195 size_t p_idx = getNearestPointIndex(cur_ll.centerline(), start_point); // Get the index of the nearest point
196
197 lanelet::BasicPoint2d prev_point = cur_ll.centerline()[p_idx].basicPoint2d();
198
199 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "nearest point" << cur_ll.centerline()[p_idx].id() << " : " << prev_point.x() << ", " << prev_point.y());
200
201 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "p_idx: " << p_idx);
202
203 // Accumulate distance
204 while (dist < downtrack) {
205 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Accumulating lanelet: " << cur_ll.id());
206 if (p_idx == cur_ll.centerline().size()) {
207 auto next_lls = wm_->getMapRoutingGraph()->following(cur_ll, false);
208 if (next_lls.empty()) {
209 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "No followers");
210 break;
211 }
212 const auto& next = next_lls[0];
213 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Getting next lanelet: " << next.id());
214 cur_ll = next;
215 p_idx = 0;
216 }
217 if (p_idx != 0 || dist == 0) {
218 following_lane.push_back(lanelet::traits::to2D(cur_ll.centerline()[p_idx]));
219 dist += lanelet::geometry::distance2d(prev_point, following_lane.back());
220 }
221 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "distance " << dist);
222 prev_point = lanelet::traits::to2D(cur_ll.centerline()[p_idx]);
223 p_idx++;
224 }
225 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Adding lane with size: " << following_lane.size());
226 forward_lanes->emplace_back(following_lane);
227 }
228 }
229
230 void TrafficIncidentParserWorker::getAdjacentReverseCenterlines(const lanelet::ConstLanelets& adjacentSet,
231 const lanelet::BasicPoint2d& start_point, double uptrack, std::vector<std::vector<lanelet::BasicPoint2d>>* reverse_lanes) const
232 {
233 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "getAdjacentReverseCenterlines");
234 for (const auto& ll : adjacentSet) {
235 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Processing adjacent lanelet: " << ll.id());
236 std::vector<lanelet::BasicPoint2d> previous_lane;
237 auto cur_ll = ll;
238 double dist = 0;
239
240 // Identify the point to start the accumulation from
241 size_t p_idx = getNearestPointIndex(cur_ll.centerline(), start_point); // Get the index of the nearest point
242
243 lanelet::BasicPoint2d prev_point = cur_ll.centerline()[p_idx].basicPoint2d();
244
245 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "nearest point" << cur_ll.centerline()[p_idx].id() << " : " << prev_point.x() << ", " << prev_point.y());
246
247 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "p_idx: " << p_idx);
248
249 // Accumulate distance
250 while (dist < uptrack) {
251 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Accumulating lanelet: " << cur_ll.id());
252 if (p_idx == 0) {
253 auto next_lls = wm_->getMapRoutingGraph()->previous(cur_ll, false);
254 if (next_lls.empty()) {
255 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "No previous lanelets");
256 break;
257 }
258 const auto& next = next_lls[0];
259 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Getting next lanelet: " << next.id());
260 cur_ll = next;
261 p_idx = cur_ll.centerline().size() - 1;
262 }
263 if (p_idx != cur_ll.centerline().size() - 1 || dist == 0) {
264
265 previous_lane.push_back(lanelet::traits::to2D(cur_ll.centerline()[p_idx]));
266 dist += lanelet::geometry::distance2d(prev_point, previous_lane.back());
267 }
268 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "distance " << dist);
269 prev_point = lanelet::traits::to2D(cur_ll.centerline()[p_idx]);
270 p_idx--;
271 }
272 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Adding lane with size: " << previous_lane.size());
273 reverse_lanes->emplace_back(previous_lane);
274 }
275 }
276
277 std::vector<carma_v2x_msgs::msg::TrafficControlMessageV01> TrafficIncidentParserWorker::composeTrafficControlMesssages()
278 {
279 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "In composeTrafficControlMesssages");
280 if(!wm_->getMap())
281 {
282 RCLCPP_WARN_STREAM(logger_->get_logger(), "Traffic Incident Parser is composing a Traffic Control Message, but it has not loaded the map yet. Returning empty list");
283 return {};
284 }
285 if (projection_msg_ == "")
286 {
287 RCLCPP_WARN_STREAM(logger_->get_logger(), "Traffic Incident Parser is composing a Traffic Control Message, but georeference has not loaded yet. Returning empty list");
288 return {};
289 }
291 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Responder point in map frame: " << local_point_.x() << ", " << local_point_.y());
292 auto current_lanelets = lanelet::geometry::findNearest(wm_->getMap()->laneletLayer, local_point_, 1);
293 if (current_lanelets.empty()) {
294 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "No nearest lanelet to responder vehicle in map point: " << local_point_.x() << ", " << local_point_.y());
295 return {};
296 }
297
298 lanelet::ConstLanelet current_lanelet = current_lanelets[0].second;
299
300 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Nearest Lanelet: " << current_lanelet.id());
301
302 lanelet::ConstLanelets lefts = { current_lanelet };
303 for (const auto& l : wm_->getMapRoutingGraph()->lefts(current_lanelet)) {
304 lefts.emplace_back(l);
305 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Left lanelet: " << l.id());
306 }
307
308 lanelet::ConstLanelets rights = wm_->getMapRoutingGraph()->rights(current_lanelet);
309 for (const auto& l : rights) {
310 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Right lanelet: " << l.id());
311 }
312
313 // Assume that if there are more lanelets to the left than the right then the tahoe is on the left
314 std::vector<std::vector<lanelet::BasicPoint2d>> forward_lanes;
315 std::vector<std::vector<lanelet::BasicPoint2d>> reverse_lanes;
316
317 if (lefts.size() >= rights.size()) {
318 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Emergency vehicle on the right ");
320 getAdjacentReverseCenterlines(lefts, local_point_, up_track, &reverse_lanes);
321 } else {
322 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Emergency vehicle on the left ");
323 getAdjacentForwardCenterlines(rights, local_point_, down_track, &forward_lanes);
324 getAdjacentReverseCenterlines(rights, local_point_, up_track, &reverse_lanes);
325 }
326
327 for (auto& lane : reverse_lanes) {
328 std::reverse(lane.begin(), lane.end()); // Reverse the backward points
329 }
330
331 // Compine results
332 for (size_t i = 0; i < reverse_lanes.size(); i++) {
333 if (forward_lanes[i].size() > 1) {
334 reverse_lanes[i].insert(reverse_lanes[i].end(), forward_lanes[i].begin() + 1, forward_lanes[i].end()); // Concat linestirngs but drop the shared point
335 }
336 }
337
338 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Constructing message for lanes: " << reverse_lanes.size());
339 std::vector<carma_v2x_msgs::msg::TrafficControlMessageV01> output_msg;
340
341 carma_v2x_msgs::msg::TrafficControlMessageV01 traffic_mobility_msg;
342
343 traffic_mobility_msg.geometry_exists=true;
344 traffic_mobility_msg.params_exists=true;
345 traffic_mobility_msg.package_exists=true;
346 j2735_v2x_msgs::msg::TrafficControlVehClass veh_type;
347 veh_type.vehicle_class = j2735_v2x_msgs::msg::TrafficControlVehClass::ANY; // TODO decide what vehicle is affected
348 traffic_mobility_msg.params.vclasses.push_back(veh_type);
349 traffic_mobility_msg.params.schedule.start=clock_->now();
350 traffic_mobility_msg.params.schedule.end_exists=false;
351 traffic_mobility_msg.params.schedule.dow_exists=false;
352 traffic_mobility_msg.params.schedule.between_exists=false;
353 traffic_mobility_msg.params.schedule.repeat_exists = false;
354
356 // Begin handling of projection definition
357 // This logic works by enforcing the ROS2 message specifications for TrafficControlMessage on the output data
358 // First the latlon point in the provided data is identified, then a projection with a north east oriented tmerc frame is created to compute node locations
360 std::string common_frame = "WGS84"; // Common frame to use for lat/lon definition. This will populate the datum field of the message. A more complex CRS should not be used here
361
362 PJ* common_to_map_proj = proj_create_crs_to_crs(PJ_DEFAULT_CTX, common_frame.c_str(), projection_msg_.c_str() , nullptr); // Create transformation between map frame and common frame. Reverse here takes map->latlon. Froward is latlon->map
363
364 if (common_to_map_proj == nullptr) { // proj_create_crs_to_crs returns 0 when there is an error in the projection
365
366 RCLCPP_ERROR_STREAM(logger_->get_logger(), "Failed to generate projection between map georeference and common frame with error number: " << proj_context_errno(PJ_DEFAULT_CTX)
367 << " projection_msg_: " << projection_msg_ << " common_frame: " << common_frame);
368
369 return {}; // Ignore geofence if it could not be projected into the map frame
370 }
371
372 PJ_COORD map_origin_map_frame{{0.0, 0.0, 0.0, 0.0}}; // Map origin to use as ref lat/lon
373 PJ_COORD map_origin_in_common_frame;
374
375 map_origin_in_common_frame = proj_trans(common_to_map_proj, PJ_INV, map_origin_map_frame);
376
377 traffic_mobility_msg.geometry.datum = "WGS84";
378 traffic_mobility_msg.geometry.reflat = map_origin_in_common_frame.lpz.lam;
379 traffic_mobility_msg.geometry.reflon = map_origin_in_common_frame.lpz.phi;
380
381 std::ostringstream lat_string;
382 std::ostringstream lon_string;
383
384 lat_string.precision(14);
385 lat_string << std::fixed << traffic_mobility_msg.geometry.reflat;
386
387 lon_string.precision(14);
388 lon_string << std::fixed << traffic_mobility_msg.geometry.reflon;
389
390 // Create a local transverse mercator frame at the reference point to allow us to get east,north oriented data reguardless of map projection orientation
391 // This is needed to match the TrafficControlMessage specification
392 std::string local_tmerc_enu_proj = "+proj=tmerc +datum=WGS84 +h_0=0 +lat_0=" + lat_string.str() + " +lon_0=" + lon_string.str() + " +k=1 +x_0=0 +y_0=0 +units=m +vunits=m +no_defs";
393
394 PJ* map_to_tmerc_proj = proj_create_crs_to_crs(PJ_DEFAULT_CTX, projection_msg_.c_str(), local_tmerc_enu_proj.c_str() , nullptr); // Create transformation between the common frame and the local ENU oriented frame
395
396 if (map_to_tmerc_proj == nullptr) { // proj_create_crs_to_crs returns 0 when there is an error in the projection
397
398 RCLCPP_ERROR_STREAM(logger_->get_logger(), "Failed to generate projection between map georeference and tmerc frame with error number: " << proj_context_errno(PJ_DEFAULT_CTX)
399 << " projection_msg_: " << projection_msg_ << " local_tmerc_enu_proj: " << local_tmerc_enu_proj);
400
401 return {}; // Ignore geofence if it could not be projected into the map frame
402 }
403
404 traffic_mobility_msg.geometry.proj = local_tmerc_enu_proj;
405
406 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Projection in message: " << traffic_mobility_msg.geometry.proj);
407
409 // Projections setup. Next projections will be used for node computation
411
412 for (size_t i = 0; i < reverse_lanes.size(); i++) {
413
414 traffic_mobility_msg.geometry.nodes.clear();
415 if (reverse_lanes[i].size() == 0) {
416 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "Skipping empty lane");
417 continue;
418 }
419
420
421 PJ_COORD map_pt{{reverse_lanes[i].front().x(), reverse_lanes[i].front().y(), 0.0, 0.0}}; // Map point to convert to tmerc frame
422
423 PJ_COORD tmerc_pt = proj_trans(map_to_tmerc_proj, PJ_FWD, map_pt);
424
425 carma_v2x_msgs::msg::PathNode prev_point;
426 prev_point.x = tmerc_pt.xyz.x;
427 prev_point.y = tmerc_pt.xyz.y;
428 bool first = true;
429 for(const auto& p : carma_ros2_utils::containers::downsample_vector(reverse_lanes[i], 8))
430 {
431 carma_v2x_msgs::msg::PathNode delta;
432
433 map_pt = PJ_COORD({p.x(), p.y(), 0.0, 0.0}); // Map point to convert to tmerc frame
434 tmerc_pt = proj_trans(map_to_tmerc_proj, PJ_FWD, map_pt); // Convert point to tmerc frame
435
436 delta.x=tmerc_pt.xyz.x - prev_point.x;
437 delta.y=tmerc_pt.xyz.y - prev_point.y;
438
439 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "prev_point x" << prev_point.x << ", prev_point y " << prev_point.y);
440 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "tmerc_pt.xyz.x" << tmerc_pt.xyz.x << ", tmerc_pt.xyz.y " << tmerc_pt.xyz.y);
441 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "map_pt x" << p.x() << ", map_pt y " << p.y());
442
443 RCLCPP_DEBUG_STREAM(logger_->get_logger(), "calculated diff x" << delta.x << ", diff y" << delta.y);
444 if (first)
445 {
446 traffic_mobility_msg.geometry.nodes.push_back(prev_point);
447 first = false;
448 }
449 else
450 {
451 traffic_mobility_msg.geometry.nodes.push_back(delta);
452 }
453
454 prev_point.x = p.x();
455 prev_point.y = p.y();
456 }
457
458 if (i == 0) {
459 boost::uuids::uuid closure_id = boost::uuids::random_generator()();
460 std::copy(closure_id.begin(), closure_id.end(), traffic_mobility_msg.id.id.begin());
461 traffic_mobility_msg.params.detail.choice=carma_v2x_msgs::msg::TrafficControlDetail::CLOSED_CHOICE;
462 traffic_mobility_msg.params.detail.closed=carma_v2x_msgs::msg::TrafficControlDetail::CLOSED;
463 traffic_mobility_msg.package.label=event_reason;
464 output_msg.push_back(traffic_mobility_msg);
465 }
466
467 boost::uuids::uuid headway_id = boost::uuids::random_generator()();
468 std::copy(headway_id.begin(), headway_id.end(), traffic_mobility_msg.id.id.begin());
469 traffic_mobility_msg.params.detail.choice=carma_v2x_msgs::msg::TrafficControlDetail::MINHDWY_CHOICE;
470 traffic_mobility_msg.params.detail.minhdwy=min_gap;
471 output_msg.push_back(traffic_mobility_msg);
472
473 boost::uuids::uuid speed_id = boost::uuids::random_generator()();
474 std::copy(speed_id.begin(), speed_id.end(), traffic_mobility_msg.id.id.begin());
475 traffic_mobility_msg.params.detail.choice=carma_v2x_msgs::msg::TrafficControlDetail::MAXSPEED_CHOICE;
476 traffic_mobility_msg.params.detail.maxspeed=speed_advisory;
477 output_msg.push_back(traffic_mobility_msg);
478
479 }
480
481
482 return output_msg;
483
484 }
485
486} // traffic_incident_parser
std::function< void(const carma_v2x_msgs::msg::TrafficControlMessage &)> PublishTrafficControlCallback
std::string stringParserHelper(std::string str, unsigned long str_index) const
Function to help convert string to double data type.
TrafficIncidentParserWorker(carma_wm::WorldModelConstPtr wm, const PublishTrafficControlCallback &traffic_control_pub, rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr logger, rclcpp::Clock::SharedPtr clock)
TrafficIncidentParserWorker constructor.
lanelet::BasicPoint2d getIncidentOriginPoint() const
Function to convert internally saved incident origin point from lat/lon to local map frame.
rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr logger_
std::vector< carma_v2x_msgs::msg::TrafficControlMessageV01 > composeTrafficControlMesssages()
Algorithm for extracting the closed lanelet from internally saved mobility message (or geofence) para...
bool mobilityMessageParser(std::string mobility_strategy_params)
Function to help parse incoming mobility operation messages to required format.
void georeferenceCallback(std_msgs::msg::String::UniquePtr projection_msg)
Callback for the georeference subscriber used to set the map projection.
void getAdjacentForwardCenterlines(const lanelet::ConstLanelets &adjacentSet, const lanelet::BasicPoint2d &start_point, double downtrack, std::vector< std::vector< lanelet::BasicPoint2d > > *forward_lanes) const
Helper method to compute the concatenated centerlines of the lanes in front of the emergency vehicle ...
void mobilityOperationCallback(carma_v2x_msgs::msg::MobilityOperation::UniquePtr mobility_msg)
Function to receive the incoming mobility operation message from the message node and publish the geo...
void getAdjacentReverseCenterlines(const lanelet::ConstLanelets &adjacentSet, const lanelet::BasicPoint2d &start_point, double uptrack, std::vector< std::vector< lanelet::BasicPoint2d > > *reverse_lanes) const
Helper method that is identical to getAdjacentForwardCenterlines except it works in reverse using upt...
std::shared_ptr< const WorldModel > WorldModelConstPtr
Definition: WorldModel.hpp:452
size_t getNearestPointIndex(const lanelet::ConstLineString3d &points, const lanelet::BasicPoint2d &point)
Helper method to get the nearest point index of a point and a linestring.