CARLA
Loading...
Searching...
No Matches
LocalizationStage.cpp
Go to the documentation of this file.
1
4
6
7namespace carla {
8namespace traffic_manager {
9
10using namespace constants::PathBufferUpdate;
11using namespace constants::LaneChange;
12using namespace constants::WaypointSelection;
13using namespace constants::SpeedThreshold;
14using namespace constants::Collision;
15using namespace constants::MotionPlan;
16
18 const std::vector<ActorId> &vehicle_id_list,
19 BufferMap &buffer_map,
20 const SimulationState &simulation_state,
21 TrackTraffic &track_traffic,
22 const LocalMapPtr &local_map,
23 std::unordered_map<ActorId, std::pair<float, bool>> &large_vehicles,
24 Parameters &parameters,
25 std::vector<ActorId>& marked_for_removal,
26 LocalizationFrame &output_array,
27 RandomGenerator &random_device)
28 : vehicle_id_list(vehicle_id_list),
29 buffer_map(buffer_map),
30 simulation_state(simulation_state),
31 track_traffic(track_traffic),
32 local_map(local_map),
33 parameters(parameters),
34 marked_for_removal(marked_for_removal),
35 output_array(output_array),
36 random_device(random_device),
37 large_vehicles(large_vehicles) {}
38
39void LocalizationStage::Update(const unsigned long index) {
40
41 const ActorId actor_id = vehicle_id_list.at(index);
42 const cg::Location vehicle_location = simulation_state.GetLocation(actor_id);
43 const cg::Vector3D heading_vector = simulation_state.GetHeading(actor_id);
44 const cg::Vector3D vehicle_velocity_vector = simulation_state.GetVelocity(actor_id);
45 const float vehicle_speed = vehicle_velocity_vector.Length();
46
47 // Speed dependent waypoint horizon length.
48 float horizon_length = std::max(vehicle_speed * HORIZON_RATE, MINIMUM_HORIZON_LENGTH);
49 if (vehicle_speed > HIGHWAY_SPEED) {
50 horizon_length = std::max(vehicle_speed * HIGH_SPEED_HORIZON_RATE, MINIMUM_HORIZON_LENGTH);
51 }
52 const float horizon_square = SQUARE(horizon_length);
53
54 if (buffer_map.find(actor_id) == buffer_map.end()) {
55 buffer_map.insert({actor_id, Buffer()});
56 }
57 Buffer &waypoint_buffer = buffer_map.at(actor_id);
58
59 // Clear buffer if vehicle is too far from the first waypoint in the buffer.
60 if (!waypoint_buffer.empty() &&
61 cg::Math::DistanceSquared(waypoint_buffer.front()->GetLocation(),
62 vehicle_location) > SQUARE(MAX_START_DISTANCE)) {
63
64 auto number_of_pops = waypoint_buffer.size();
65 for (uint64_t j = 0u; j < number_of_pops; ++j) {
66 PopWaypoint(actor_id, track_traffic, waypoint_buffer);
67 }
68 }
69
70 bool is_at_junction_entrance = false;
71 if (!waypoint_buffer.empty()) {
72 // Purge passed waypoints.
73 float dot_product = DeviationDotProduct(vehicle_location, heading_vector, waypoint_buffer.front()->GetLocation());
74 while (dot_product <= 0.0f && !waypoint_buffer.empty()) {
75 PopWaypoint(actor_id, track_traffic, waypoint_buffer);
76 if (!waypoint_buffer.empty()) {
77 dot_product = DeviationDotProduct(vehicle_location, heading_vector, waypoint_buffer.front()->GetLocation());
78 }
79 }
80
81 if (!waypoint_buffer.empty()) {
82 // Determine if the vehicle is at the entrance of a junction.
83 SimpleWaypointPtr look_ahead_point = GetTargetWaypoint(waypoint_buffer, JUNCTION_LOOK_AHEAD).first;
84 SimpleWaypointPtr front_waypoint = waypoint_buffer.front();
85 bool front_waypoint_junction = front_waypoint->CheckJunction();
86 is_at_junction_entrance = !front_waypoint_junction && look_ahead_point->CheckJunction();
87 if (!is_at_junction_entrance) {
88 std::vector<SimpleWaypointPtr> last_passed_waypoints = front_waypoint->GetPreviousWaypoint();
89 if (last_passed_waypoints.size() == 1) {
90 is_at_junction_entrance = !last_passed_waypoints.front()->CheckJunction() && front_waypoint_junction;
91 }
92 }
93 if (is_at_junction_entrance
94 // Exception for roundabout in Town03.
95 && local_map->GetMapName() == "Carla/Maps/Town03"
96 && vehicle_location.SquaredLength() < SQUARE(30)) {
97 is_at_junction_entrance = false;
98 }
99 }
100
101 // Purge waypoints too far from the front of the buffer, but not if it has reached a junction.
102 while (!is_at_junction_entrance
103 && !waypoint_buffer.empty()
104 && waypoint_buffer.back()->DistanceSquared(waypoint_buffer.front()) > horizon_square + horizon_square
105 && !waypoint_buffer.back()->CheckJunction()) {
106 PopWaypoint(actor_id, track_traffic, waypoint_buffer, false);
107 }
108 }
109
110 // Initializing buffer if it is empty.
111 if (waypoint_buffer.empty()) {
112 SimpleWaypointPtr closest_waypoint = local_map->GetWaypoint(vehicle_location);
113 if (closest_waypoint == nullptr) {
114 // The map has no drivable waypoint at all (EmptyMap, or an OpenDRIVE
115 // file without roads): there is nothing to localize this vehicle
116 // against. Leave output.localized false so TrafficManagerLocal::Step
117 // skips the stages that assume a non-empty waypoint buffer.
118 output_array.at(index).localized = false;
119 return;
120 }
121 // Prefer a waypoint whose lane direction matches the vehicle heading.
122 // The nearest waypoint can belong to the opposing lane — or the vehicle
123 // may have been spun around (collision, player driving, bad resume
124 // pose) — and a buffer seeded against the heading makes the controller
125 // chase a target behind the vehicle at full lock and full throttle.
126 if (cg::Math::Dot(closest_waypoint->GetForwardVector(), heading_vector) < 0.0f) {
127 float best_dot = 0.0f;
128 for (const SimpleWaypointPtr &candidate :
129 local_map->GetWaypointsInDelta(vehicle_location, 8u, 4.0f)) {
130 const float dot = cg::Math::Dot(candidate->GetForwardVector(), heading_vector);
131 if (dot > best_dot) {
132 best_dot = dot;
133 closest_waypoint = candidate;
134 }
135 }
136 }
137 PushWaypoint(actor_id, track_traffic, waypoint_buffer, closest_waypoint);
138 }
139
140 // Assign a lane change.
141 const ChangeLaneInfo lane_change_info = parameters.GetForceLaneChange(actor_id);
142 bool force_lane_change = lane_change_info.change_lane;
143 bool lane_change_direction = lane_change_info.direction;
144
145 // Apply parameters for keep right rule and random lane changes.
146 if (!force_lane_change && vehicle_speed > MIN_LANE_CHANGE_SPEED){
147 const float perc_keep_slow = parameters.GetKeepSlowLanePercentage(actor_id);
148 const float perc_random_leftlanechange = parameters.GetRandomLeftLaneChangePercentage(actor_id);
149 const float perc_random_rightlanechange = parameters.GetRandomRightLaneChangePercentage(actor_id);
150 const bool is_rht = waypoint_buffer.front()->GetWaypoint()->IsRHT();
151
152 const bool is_keep_slow = perc_keep_slow > random_device.next();
153 const bool is_random_right_change = perc_random_rightlanechange >= random_device.next();
154 const bool is_random_left_change = perc_random_leftlanechange >= random_device.next();
155
156 const bool is_left_lane_change = is_rht ? is_random_left_change : is_keep_slow || is_random_left_change;
157 const bool is_right_lane_change = is_rht ? is_keep_slow || is_random_right_change : is_random_right_change;
158
159 // Determine which of the parameters we should apply.
160 if (is_left_lane_change && is_right_lane_change){
161 force_lane_change = true;
162 lane_change_direction = FIFTYPERC > random_device.next();
163 } else if (is_right_lane_change) {
164 force_lane_change = true;
165 lane_change_direction = true;
166 } else if (is_left_lane_change) {
167 force_lane_change = true;
168 lane_change_direction = false;
169 }
170 }
171
172 const SimpleWaypointPtr front_waypoint = waypoint_buffer.front();
173 const float lane_change_distance = SQUARE(std::max(10.0f * vehicle_speed, INTER_LANE_CHANGE_DISTANCE));
174
175 bool recently_not_executed_lane_change = last_lane_change_swpt.find(actor_id) == last_lane_change_swpt.end();
176 bool done_with_previous_lane_change = true;
177 if (!recently_not_executed_lane_change) {
178 float distance_frm_previous = cg::Math::DistanceSquared(last_lane_change_swpt.at(actor_id)->GetLocation(), vehicle_location);
179 done_with_previous_lane_change = distance_frm_previous > lane_change_distance;
180 if (done_with_previous_lane_change) last_lane_change_swpt.erase(actor_id);
181 }
182 bool auto_or_force_lane_change = parameters.GetAutoLaneChange(actor_id) || force_lane_change;
183 bool front_waypoint_not_junction = !front_waypoint->CheckJunction();
184
185 if (auto_or_force_lane_change
186 && front_waypoint_not_junction
187 && (recently_not_executed_lane_change || done_with_previous_lane_change)) {
188
189 SimpleWaypointPtr change_over_point = AssignLaneChange(actor_id, vehicle_location, vehicle_speed,
190 force_lane_change, lane_change_direction);
191
192 if (change_over_point != nullptr) {
193 if (last_lane_change_swpt.find(actor_id) != last_lane_change_swpt.end()) {
194 last_lane_change_swpt.at(actor_id) = change_over_point;
195 } else {
196 last_lane_change_swpt.insert({actor_id, change_over_point});
197 }
198 auto number_of_pops = waypoint_buffer.size();
199 for (uint64_t j = 0u; j < number_of_pops; ++j) {
200 PopWaypoint(actor_id, track_traffic, waypoint_buffer);
201 }
202 PushWaypoint(actor_id, track_traffic, waypoint_buffer, change_over_point);
203 }
204 }
205
206 Path imported_path = parameters.GetCustomPath(actor_id);
207 Route imported_actions = parameters.GetImportedRoute(actor_id);
208 // We are effectively importing a path.
209 if (!imported_path.empty()) {
210
211 ImportPath(imported_path, waypoint_buffer, actor_id, horizon_square);
212
213 } else if (!imported_actions.empty()) {
214
215 ImportRoute(imported_actions, waypoint_buffer, actor_id, horizon_square);
216
217 }
218
219 // Populating the buffer through randomly chosen waypoints.
220 else {
221 while (waypoint_buffer.back()->DistanceSquared(waypoint_buffer.front()) <= horizon_square) {
222 SimpleWaypointPtr furthest_waypoint = waypoint_buffer.back();
223 std::vector<SimpleWaypointPtr> next_waypoints = furthest_waypoint->GetNextWaypoint();
224 uint64_t selection_index = 0u;
225 // Pseudo-randomized path selection if found more than one choice.
226 if (next_waypoints.size() > 1) {
227 double r_sample = random_device.next();
228 selection_index = static_cast<uint64_t>(r_sample*next_waypoints.size()*0.01);
229 } else if (next_waypoints.size() == 0) {
230 if (!parameters.GetOSMMode()) {
231 std::cout << "This map has dead-end roads, please change the set_open_street_map parameter to true" << std::endl;
232 }
233 marked_for_removal.push_back(actor_id);
234 break;
235 }
236 SimpleWaypointPtr next_wp_selection = next_waypoints.at(selection_index);
237 PushWaypoint(actor_id, track_traffic, waypoint_buffer, next_wp_selection);
238 if (next_wp_selection->GetId() == waypoint_buffer.front()->GetId()){
239 // Found a loop, stop. Don't use zero distance as there can be two waypoints at the same location
240 break;
241 }
242 }
243 }
244 ExtendAndFindSafeSpace(actor_id, is_at_junction_entrance, waypoint_buffer);
245 HandleLargeVehicleJunction(actor_id, is_at_junction_entrance, waypoint_buffer);
246
247 // Editing output array
248 LocalizationData &output = output_array.at(index);
249 output.localized = true;
250 output.is_at_junction_entrance = is_at_junction_entrance;
251
252 if (is_at_junction_entrance) {
253 const SimpleWaypointPair &safe_space_end_points = vehicles_at_junction_entrance.at(actor_id);
254 output.junction_end_point = safe_space_end_points.first;
255 output.safe_point = safe_space_end_points.second;
256 } else {
257 output.junction_end_point = nullptr;
258 output.safe_point = nullptr;
259 }
260
261 // Updating geodesic grid position for actor.
262 track_traffic.UpdateGridPosition(actor_id, waypoint_buffer);
263}
264
266 const bool is_at_junction_entrance,
267 Buffer &waypoint_buffer) {
268
269 SimpleWaypointPtr junction_end_point = nullptr;
270 SimpleWaypointPtr safe_point_after_junction = nullptr;
271
272 if (is_at_junction_entrance
274
275 bool entered_junction = false;
276 bool past_junction = false;
277 bool safe_point_found = false;
278 SimpleWaypointPtr current_waypoint = nullptr;
279 SimpleWaypointPtr junction_begin_point = nullptr;
280 float safe_distance_squared = SQUARE(SAFE_DISTANCE_AFTER_JUNCTION);
281
282 // Scanning existing buffer points.
283 for (unsigned long i = 0u; i < waypoint_buffer.size() && !safe_point_found; ++i) {
284 current_waypoint = waypoint_buffer.at(i);
285 if (!entered_junction && current_waypoint->CheckJunction()) {
286 entered_junction = true;
287 junction_begin_point = current_waypoint;
288 }
289 if (entered_junction && !past_junction && !current_waypoint->CheckJunction()) {
290 past_junction = true;
291 junction_end_point = current_waypoint;
292 }
293 if (past_junction && junction_end_point->DistanceSquared(current_waypoint) > safe_distance_squared) {
294 safe_point_found = true;
295 safe_point_after_junction = current_waypoint;
296 }
297 }
298
299 // Extend buffer if safe point not found.
300 if (!safe_point_found) {
301 bool abort = false;
302
303 while (!past_junction && !abort) {
304 NodeList next_waypoints = current_waypoint->GetNextWaypoint();
305 if (!next_waypoints.empty()) {
306 current_waypoint = next_waypoints.front();
307 PushWaypoint(actor_id, track_traffic, waypoint_buffer, current_waypoint);
308 if (!current_waypoint->CheckJunction()) {
309 past_junction = true;
310 junction_end_point = current_waypoint;
311 }
312 } else {
313 abort = true;
314 }
315 }
316
317 while (!safe_point_found && !abort) {
318 std::vector<SimpleWaypointPtr> next_waypoints = current_waypoint->GetNextWaypoint();
319 if ((junction_end_point->DistanceSquared(current_waypoint) > safe_distance_squared)
320 || next_waypoints.size() > 1
321 || current_waypoint->CheckJunction()) {
322
323 safe_point_found = true;
324 safe_point_after_junction = current_waypoint;
325 } else {
326 if (!next_waypoints.empty()) {
327 current_waypoint = next_waypoints.front();
328 PushWaypoint(actor_id, track_traffic, waypoint_buffer, current_waypoint);
329 } else {
330 abort = true;
331 }
332 }
333 }
334 }
335
336 if (junction_end_point != nullptr &&
337 safe_point_after_junction != nullptr &&
338 junction_begin_point->DistanceSquared(junction_end_point) < SQUARE(MIN_JUNCTION_LENGTH)) {
339
340 junction_end_point = nullptr;
341 safe_point_after_junction = nullptr;
342 }
343
344 vehicles_at_junction_entrance.insert({actor_id, {junction_end_point, safe_point_after_junction}});
345 }
346 else if (!is_at_junction_entrance
348
349 vehicles_at_junction_entrance.erase(actor_id);
350 }
351}
352
354 const bool is_at_junction_entrance,
355 Buffer &waypoint_buffer) {
356
357 if (large_vehicles.find(actor_id) == large_vehicles.end()) {
358 return;
359 }
360
361 SimpleWaypointPtr current_waypoint{nullptr};
362 const bool is_at_junction{waypoint_buffer.front()->CheckJunction()};
363
364 if (is_at_junction_entrance
366 && large_vehicles_at_junction.find(actor_id) == large_vehicles_at_junction.end()) {
367
369
370 const SimpleWaypointPtr first_waypoint = waypoint_buffer.front();
371 const SimpleWaypointPtr last_waypoint = waypoint_buffer.back();
372 const SimpleWaypointPtr middle_waypoint = waypoint_buffer.at(waypoint_buffer.size() / 2);
373
374 const float radius = GetThreePointCircleRadius(
375 first_waypoint->GetLocation(),
376 middle_waypoint->GetLocation(),
377 last_waypoint->GetLocation());
378
380 return; // Straight path; no offset needed.
381 }
382
383 bool entered_junction{false};
384 float junction_length{0.0f};
385 bool is_straight_path{true};
386
387 for (unsigned long i = 0u; i < waypoint_buffer.size(); ++i) {
388 current_waypoint = waypoint_buffer.at(i);
389
390 if (!entered_junction && current_waypoint->CheckJunction()) {
391 entered_junction = true;
392 }
393
394 if (i > 0 && entered_junction) {
395 const SimpleWaypointPtr prev_waypoint = waypoint_buffer.at(i - 1);
396 const float new_distance = current_waypoint->Distance(prev_waypoint->GetLocation());
397 junction_length += new_distance;
398
399 if (is_straight_path) {
400 const RoadOption junction_type = current_waypoint->GetRoadOption();
401 if (junction_type == RoadOption::Right) {
402 large_vehicles[actor_id].second = true;
403 is_straight_path = false;
404 } else if (junction_type == RoadOption::Left) {
405 large_vehicles[actor_id].second = false;
406 is_straight_path = false;
407 }
408 }
409 }
410
411 if (entered_junction && !current_waypoint->CheckJunction()) {
412 break;
413 }
414 }
415 if (!is_straight_path) {
416 large_vehicles[actor_id].first = junction_length;
417 }
418
419 }
420 else if (
421 is_at_junction
423
425 large_vehicles_at_junction.insert(actor_id);
426 }
427 else if (
428 !is_at_junction
429 && large_vehicles_at_junction.find(actor_id) != large_vehicles_at_junction.end()) {
430
431 large_vehicles_at_junction.erase(actor_id);
432 if (large_vehicles.find(actor_id) != large_vehicles.end()) {
433 large_vehicles[actor_id].first = 0.0f;
434 }
435 }
436}
437
439 last_lane_change_swpt.erase(actor_id);
440 vehicles_at_junction_entrance.erase(actor_id);
441 vehicles_at_junction.erase(actor_id);
443 large_vehicles_at_junction.erase(actor_id);
444}
445
453
455 const cg::Location vehicle_location,
456 const float vehicle_speed,
457 bool force, bool direction) {
458
459 // Waypoint representing the new starting point for the waypoint buffer
460 // due to lane change. Remains nullptr if lane change not viable.
461 SimpleWaypointPtr change_over_point = nullptr;
462
463 // Retrieve waypoint buffer for current vehicle.
464 if (buffer_map.find(actor_id) == buffer_map.end()) {
465 return change_over_point;
466 }
467 const Buffer &waypoint_buffer = buffer_map.at(actor_id);
468
469 // Check buffer is not empty.
470 if (!waypoint_buffer.empty()) {
471 // Get the left and right waypoints for the current closest waypoint.
472 const SimpleWaypointPtr &current_waypoint = waypoint_buffer.front();
473 const SimpleWaypointPtr left_waypoint = current_waypoint->GetLeftWaypoint();
474 const SimpleWaypointPtr right_waypoint = current_waypoint->GetRightWaypoint();
475
476 // Retrieve vehicles with overlapping waypoint buffers with current vehicle.
477 const auto blocking_vehicles = track_traffic.GetOverlappingVehicles(actor_id);
478
479 // Find immediate in-lane obstacle and check if any are too close to initiate lane change.
480 bool obstacle_too_close = false;
481 float minimum_squared_distance = std::numeric_limits<float>::infinity();
482 ActorId obstacle_actor_id = 0u;
483 for (auto i = blocking_vehicles.begin();
484 i != blocking_vehicles.end() && !obstacle_too_close && !force;
485 ++i) {
486 const ActorId &other_actor_id = *i;
487 // Find vehicle in buffer map and check if it's buffer is not empty.
488 if (buffer_map.find(other_actor_id) != buffer_map.end() && !buffer_map.at(other_actor_id).empty()) {
489 const Buffer &other_buffer = buffer_map.at(other_actor_id);
490 const SimpleWaypointPtr &other_current_waypoint = other_buffer.front();
491 const cg::Location other_location = other_current_waypoint->GetLocation();
492
493 const cg::Vector3D reference_heading = current_waypoint->GetForwardVector();
494 cg::Vector3D reference_to_other = other_location - current_waypoint->GetLocation();
495 const cg::Vector3D other_heading = other_current_waypoint->GetForwardVector();
496
497 WaypointPtr current_raw_waypoint = current_waypoint->GetWaypoint();
498 WaypointPtr other_current_raw_waypoint = other_current_waypoint->GetWaypoint();
499 // Check both vehicles are not in junction,
500 // Check if the other vehicle is in front of the current vehicle,
501 // Check if the two vehicles have acceptable angular deviation between their headings.
502 if (!current_waypoint->CheckJunction()
503 && !other_current_waypoint->CheckJunction()
504 && other_current_raw_waypoint->GetRoadId() == current_raw_waypoint->GetRoadId()
505 && other_current_raw_waypoint->GetLaneId() == current_raw_waypoint->GetLaneId()
506 && cg::Math::Dot(reference_heading, reference_to_other) > 0.0f
507 && cg::Math::Dot(reference_heading, other_heading) > MAXIMUM_LANE_OBSTACLE_CURVATURE) {
508 float squared_distance = cg::Math::DistanceSquared(vehicle_location, other_location);
509 // Abort if the obstacle is too close.
510 if (squared_distance > SQUARE(MINIMUM_LANE_CHANGE_DISTANCE)) {
511 // Remember if the new vehicle is closer.
512 if (squared_distance < minimum_squared_distance && squared_distance < SQUARE(MAXIMUM_LANE_OBSTACLE_DISTANCE)) {
513 minimum_squared_distance = squared_distance;
514 obstacle_actor_id = other_actor_id;
515 }
516 } else {
517 obstacle_too_close = true;
518 }
519 }
520 }
521 }
522
523 // If a valid immediate obstacle found.
524 if (!obstacle_too_close && obstacle_actor_id != 0u && !force) {
525 const Buffer &other_buffer = buffer_map.at(obstacle_actor_id);
526 const SimpleWaypointPtr &other_current_waypoint = other_buffer.front();
527 const auto other_neighbouring_lanes = {other_current_waypoint->GetLeftWaypoint(),
528 other_current_waypoint->GetRightWaypoint()};
529
530 // Flags reflecting whether adjacent lanes are free near the obstacle.
531 bool distant_left_lane_free = false;
532 bool distant_right_lane_free = false;
533
534 // Check if the neighbouring lanes near the obstructing vehicle are free of other vehicles.
535 bool left_right = true;
536 for (auto &candidate_lane_wp : other_neighbouring_lanes) {
537 if (candidate_lane_wp != nullptr &&
538 track_traffic.GetPassingVehicles(candidate_lane_wp->GetId()).size() == 0) {
539
540 if (left_right)
541 distant_left_lane_free = true;
542 else
543 distant_right_lane_free = true;
544 }
545 left_right = !left_right;
546 }
547
548 // Based on what lanes are free near the obstacle,
549 // find the change over point with no vehicles passing through them.
550 if (distant_right_lane_free && right_waypoint != nullptr
551 && track_traffic.GetPassingVehicles(right_waypoint->GetId()).size() == 0) {
552 change_over_point = right_waypoint;
553 } else if (distant_left_lane_free && left_waypoint != nullptr
554 && track_traffic.GetPassingVehicles(left_waypoint->GetId()).size() == 0) {
555 change_over_point = left_waypoint;
556 }
557 } else if (force) {
558 if (direction && right_waypoint != nullptr) {
559 change_over_point = right_waypoint;
560 } else if (!direction && left_waypoint != nullptr) {
561 change_over_point = left_waypoint;
562 }
563 }
564
565 if (change_over_point != nullptr) {
566 const float change_over_distance = cg::Math::Clamp(1.5f * vehicle_speed, MIN_WPT_DISTANCE, MAX_WPT_DISTANCE);
567 const SimpleWaypointPtr starting_point = change_over_point;
568 while (change_over_point->DistanceSquared(starting_point) < SQUARE(change_over_distance) &&
569 !change_over_point->CheckJunction()) {
570 change_over_point = change_over_point->GetNextWaypoint().front();
571 }
572 }
573 }
574
575 return change_over_point;
576}
577
578void LocalizationStage::ImportPath(Path &imported_path, Buffer &waypoint_buffer, const ActorId actor_id, const float horizon_square) {
579 // Remove the waypoints already added to the path, except for the first.
580 if (parameters.GetUploadPath(actor_id)) {
581 auto number_of_pops = waypoint_buffer.size();
582 for (uint64_t j = 0u; j < number_of_pops - 1; ++j) {
583 PopWaypoint(actor_id, track_traffic, waypoint_buffer, false);
584 }
585 // We have successfully imported the path. Remove it from the list of paths to be imported.
586 parameters.RemoveUploadPath(actor_id, false);
587 }
588
589 // Get the latest imported waypoint. and find its closest waypoint in TM's InMemoryMap.
590 cg::Location latest_imported = imported_path.front();
591 SimpleWaypointPtr imported = local_map->GetWaypoint(latest_imported);
592
593 // We need to generate a path compatible with TM's waypoints.
594 while (!imported_path.empty() && waypoint_buffer.back()->DistanceSquared(waypoint_buffer.front()) <= horizon_square) {
595 // Get the latest point we added to the list. If starting, this will be the one referred to the vehicle's location.
596 SimpleWaypointPtr latest_waypoint = waypoint_buffer.back();
597
598 // Try to link the latest_waypoint to the imported waypoint.
599 std::vector<SimpleWaypointPtr> next_waypoints = latest_waypoint->GetNextWaypoint();
600 uint64_t selection_index = 0u;
601
602 // Choose correct path.
603 if (next_waypoints.size() > 1) {
604 const float imported_road_id = imported->GetWaypoint()->GetRoadId();
605 float min_distance = std::numeric_limits<float>::infinity();
606 for (uint64_t k = 0u; k < next_waypoints.size(); ++k) {
607 SimpleWaypointPtr junction_end_point = next_waypoints.at(k);
608 while (!junction_end_point->CheckJunction()) {
609 junction_end_point = junction_end_point->GetNextWaypoint().front();
610 }
611 while (junction_end_point->CheckJunction()) {
612 junction_end_point = junction_end_point->GetNextWaypoint().front();
613 }
614 while (next_waypoints.at(k)->DistanceSquared(junction_end_point) < 50.0f) {
615 junction_end_point = junction_end_point->GetNextWaypoint().front();
616 }
617 float jep_road_id = junction_end_point->GetWaypoint()->GetRoadId();
618 if (jep_road_id == imported_road_id) {
619 selection_index = k;
620 break;
621 }
622 float distance = junction_end_point->DistanceSquared(imported);
623 if (distance < min_distance) {
624 min_distance = distance;
625 selection_index = k;
626 }
627 }
628 } else if (next_waypoints.size() == 0) {
629 if (!parameters.GetOSMMode()) {
630 std::cout << "This map has dead-end roads, please change the set_open_street_map parameter to true" << std::endl;
631 }
632 marked_for_removal.push_back(actor_id);
633 break;
634 }
635 SimpleWaypointPtr next_wp_selection = next_waypoints.at(selection_index);
636
637 // Remove the imported waypoint from the path if it's close to the last one.
638 if (next_wp_selection->DistanceSquared(imported) < 30.0f) {
639 imported_path.erase(imported_path.begin());
640 std::vector<SimpleWaypointPtr> possible_waypoints = next_wp_selection->GetNextWaypoint();
641 if (std::find(possible_waypoints.begin(), possible_waypoints.end(), imported) != possible_waypoints.end()) {
642 // If the lane is changing, only push the new waypoint
643 PushWaypoint(actor_id, track_traffic, waypoint_buffer, next_wp_selection);
644 }
645 PushWaypoint(actor_id, track_traffic, waypoint_buffer, imported);
646 latest_imported = imported_path.front();
647 imported = local_map->GetWaypoint(latest_imported);
648 } else {
649 PushWaypoint(actor_id, track_traffic, waypoint_buffer, next_wp_selection);
650 }
651 }
652 if (imported_path.empty()) {
653 // Once we are done, check if we can clear the structure.
654 parameters.RemoveUploadPath(actor_id, true);
655 } else {
656 // Otherwise, update the structure with the waypoints that we still need to import.
657 parameters.UpdateUploadPath(actor_id, imported_path);
658 }
659}
660
661void LocalizationStage::ImportRoute(Route &imported_actions, Buffer &waypoint_buffer, const ActorId actor_id, const float horizon_square) {
662
663 if (parameters.GetUploadRoute(actor_id)) {
664 auto number_of_pops = waypoint_buffer.size();
665 for (uint64_t j = 0u; j < number_of_pops - 1; ++j) {
666 PopWaypoint(actor_id, track_traffic, waypoint_buffer, false);
667 }
668 // We have successfully imported the route. Remove it from the list of routes to be imported.
669 parameters.RemoveImportedRoute(actor_id, false);
670 }
671
672 RoadOption next_road_option = static_cast<RoadOption>(imported_actions.front());
673 while (!imported_actions.empty() && waypoint_buffer.back()->DistanceSquared(waypoint_buffer.front()) <= horizon_square) {
674 // Get the latest point we added to the list. If starting, this will be the one referred to the vehicle's location.
675 SimpleWaypointPtr latest_waypoint = waypoint_buffer.back();
676 RoadOption latest_road_option = latest_waypoint->GetRoadOption();
677 // Try to link the latest_waypoint to the correct next RouteOption.
678 std::vector<SimpleWaypointPtr> next_waypoints = latest_waypoint->GetNextWaypoint();
679 uint16_t selection_index = 0u;
680 if (next_waypoints.size() > 1) {
681 for (uint16_t i=0; i<next_waypoints.size(); ++i) {
682 if (next_waypoints.at(i)->GetRoadOption() == next_road_option) {
683 selection_index = i;
684 break;
685 } else {
686 if (i == next_waypoints.size() - 1) {
687 std::cout << "We couldn't find the RoadOption you were looking for. This route might diverge from the one expected." << std::endl;
688 }
689 }
690 }
691 } else if (next_waypoints.size() == 0) {
692 if (!parameters.GetOSMMode()) {
693 std::cout << "This map has dead-end roads, please change the set_open_street_map parameter to true" << std::endl;
694 }
695 marked_for_removal.push_back(actor_id);
696 break;
697 }
698
699 SimpleWaypointPtr next_wp_selection = next_waypoints.at(selection_index);
700 PushWaypoint(actor_id, track_traffic, waypoint_buffer, next_wp_selection);
701
702 // If we are switching to a new RoadOption, it means the current one is already fully imported.
703 if (latest_road_option != next_wp_selection->GetRoadOption() && next_road_option == next_wp_selection->GetRoadOption()) {
704 imported_actions.erase(imported_actions.begin());
705 next_road_option = static_cast<RoadOption>(imported_actions.front());
706 }
707 }
708 if (imported_actions.empty()) {
709 // Once we are done, check if we can clear the structure.
710 parameters.RemoveImportedRoute(actor_id, true);
711 } else {
712 // Otherwise, update the structure with the waypoints that we still need to import.
713 parameters.UpdateImportedRoute(actor_id, imported_actions);
714 }
715}
716
718 if (buffer_map.find(actor_id) == buffer_map.end()) {
719 return std::make_pair(RoadOption::Void, nullptr);
720 }
721 auto waypoint_buffer = buffer_map.at(actor_id);
722 auto next_action = std::make_pair(RoadOption::LaneFollow, waypoint_buffer.back()->GetWaypoint());
723 bool is_lane_change = false;
724 if (last_lane_change_swpt.find(actor_id) != last_lane_change_swpt.end()) {
725 // A lane change is happening.
726 is_lane_change = true;
727 const cg::Vector3D heading_vector = simulation_state.GetHeading(actor_id);
728 const cg::Vector3D relative_vector = simulation_state.GetLocation(actor_id) - last_lane_change_swpt.at(actor_id)->GetLocation();
729 bool left_heading = (heading_vector.x * relative_vector.y - heading_vector.y * relative_vector.x) > 0.0f;
730 if (left_heading) next_action = std::make_pair(RoadOption::ChangeLaneLeft, last_lane_change_swpt.at(actor_id)->GetWaypoint());
731 else next_action = std::make_pair(RoadOption::ChangeLaneRight, last_lane_change_swpt.at(actor_id)->GetWaypoint());
732 }
733 for (auto &swpt : waypoint_buffer) {
734 RoadOption road_opt = swpt->GetRoadOption();
735 if (road_opt != RoadOption::LaneFollow) {
736 if (!is_lane_change) {
737 // No lane change in sight, we can assume this will be the next action.
738 return std::make_pair(road_opt, swpt->GetWaypoint());
739 } else {
740 // A lane change will happen as well as another action, we need to figure out which one will happen first.
741 cg::Location lane_change = last_lane_change_swpt.at(actor_id)->GetLocation();
742 cg::Location actual_location = simulation_state.GetLocation(actor_id);
743 auto distance_lane_change = cg::Math::DistanceSquared(actual_location, lane_change);
744 auto distance_other_action = cg::Math::DistanceSquared(actual_location, swpt->GetLocation());
745 if (distance_lane_change < distance_other_action) return next_action;
746 else return std::make_pair(road_opt, swpt->GetWaypoint());
747 }
748 }
749 }
750 return next_action;
751}
752
754
755 ActionBuffer action_buffer;
756 if (buffer_map.find(actor_id) == buffer_map.end()) {
757 return action_buffer;
758 }
759 auto waypoint_buffer = buffer_map.at(actor_id);
760 Action lane_change;
761 bool is_lane_change = false;
762 SimpleWaypointPtr buffer_front = waypoint_buffer.front();
763 RoadOption last_road_opt = buffer_front->GetRoadOption();
764 action_buffer.push_back(std::make_pair(last_road_opt, buffer_front->GetWaypoint()));
765 if (last_lane_change_swpt.find(actor_id) != last_lane_change_swpt.end()) {
766 // A lane change is happening.
767 is_lane_change = true;
768 const cg::Vector3D heading_vector = simulation_state.GetHeading(actor_id);
769 const cg::Vector3D relative_vector = simulation_state.GetLocation(actor_id) - last_lane_change_swpt.at(actor_id)->GetLocation();
770 bool left_heading = (heading_vector.x * relative_vector.y - heading_vector.y * relative_vector.x) > 0.0f;
771 if (left_heading) lane_change = std::make_pair(RoadOption::ChangeLaneLeft, last_lane_change_swpt.at(actor_id)->GetWaypoint());
772 else lane_change = std::make_pair(RoadOption::ChangeLaneRight, last_lane_change_swpt.at(actor_id)->GetWaypoint());
773 }
774 for (auto &wpt : waypoint_buffer) {
775 RoadOption current_road_opt = wpt->GetRoadOption();
776 if (current_road_opt != last_road_opt) {
777 action_buffer.push_back(std::make_pair(current_road_opt, wpt->GetWaypoint()));
778 last_road_opt = current_road_opt;
779 }
780 }
781 if (is_lane_change) {
782 // Insert the lane change action in the appropriate part of the action buffer.
783 auto distance_lane_change = cg::Math::DistanceSquared(waypoint_buffer.front()->GetLocation(), lane_change.second->GetTransform().location);
784 for (uint16_t i = 0; i < action_buffer.size(); ++i) {
785 auto distance_action = cg::Math::DistanceSquared(waypoint_buffer.front()->GetLocation(), waypoint_buffer.at(i)->GetLocation());
786 // If the waypoint related to the next action is further away from the one of the lane change, insert lane change action here.
787 // If we reached the end of the buffer, place the action at the end.
788 if (i == action_buffer.size()-1) {
789 action_buffer.push_back(lane_change);
790 break;
791 } else if (distance_action > distance_lane_change) {
792 action_buffer.insert(action_buffer.begin()+i, lane_change);
793 break;
794 }
795 }
796 }
797 return action_buffer;
798}
799
800} // namespace traffic_manager
801} // namespace carla
float distance
#define SQUARE(a)
This file contains various constants used in traffic manager arranged into sensible namespaces for re...
Definition Constants.h:14
LocalizationStage(const std::vector< ActorId > &vehicle_id_list, BufferMap &buffer_map, const SimulationState &simulation_state, TrackTraffic &track_traffic, const LocalMapPtr &local_map, std::unordered_map< ActorId, std::pair< float, bool > > &large_vehicles, Parameters &parameters, std::vector< ActorId > &marked_for_removal, LocalizationFrame &output_array, RandomGenerator &random_device)
ActionBuffer ComputeActionBuffer(const ActorId &actor_id)
void ImportRoute(Route &imported_actions, Buffer &waypoint_buffer, const ActorId actor_id, const float horizon_square)
std::unordered_set< ActorId > large_vehicles_at_junction
void ImportPath(Path &imported_path, Buffer &waypoint_buffer, const ActorId actor_id, const float horizon_square)
void ExtendAndFindSafeSpace(const ActorId actor_id, const bool is_at_junction_entrance, Buffer &waypoint_buffer)
Action ComputeNextAction(const ActorId &actor_id)
std::unordered_map< ActorId, SimpleWaypointPair > vehicles_at_junction_entrance
const std::vector< ActorId > & vehicle_id_list
void HandleLargeVehicleJunction(const ActorId actor_id, const bool is_at_junction_entrance, Buffer &waypoint_buffer)
SimpleWaypointPtr AssignLaneChange(const ActorId actor_id, const cg::Location vehicle_location, const float vehicle_speed, bool force, bool direction)
void Update(const unsigned long index) override
void RemoveActor(const ActorId actor_id) override
std::unordered_map< ActorId, std::pair< float, bool > > & large_vehicles
std::pair< SimpleWaypointPtr, SimpleWaypointPtr > SimpleWaypointPair
std::unordered_set< ActorId > large_vehicles_at_junction_entrance
float GetRandomLeftLaneChangePercentage(const ActorId &actor_id)
Method to query percentage probability of a random right lane change for a vehicle.
ChangeLaneInfo GetForceLaneChange(const ActorId &actor_id)
Method to query lane change command for a vehicle.
Route GetImportedRoute(const ActorId &actor_id) const
Method to get a custom route.
float GetKeepSlowLanePercentage(const ActorId &actor_id)
Method to query percentage probability of keep slow lane rule for a vehicle.
bool GetUploadRoute(const ActorId &actor_id) const
Method to get if we are uploading a route.
void UpdateUploadPath(const ActorId &actor_id, const Path path)
Method to update an already set list of points.
bool GetOSMMode() const
Method to get Open Street Map mode.
void UpdateImportedRoute(const ActorId &actor_id, const Route route)
Method to update an already set route.
bool GetUploadPath(const ActorId &actor_id) const
Method to get if we are uploading a path.
float GetRandomRightLaneChangePercentage(const ActorId &actor_id)
Method to query percentage probability of a random left lane change for a vehicle.
void RemoveImportedRoute(const ActorId &actor_id, const bool remove_path)
Method to remove a route.
bool GetAutoLaneChange(const ActorId &actor_id) const
Method to query auto lane change rule for a vehicle.
Path GetCustomPath(const ActorId &actor_id) const
Method to get a custom path.
void RemoveUploadPath(const ActorId &actor_id, const bool remove_path)
Method to remove a list of points.
This class holds the state of all the vehicles in the simlation.
cg::Location GetLocation(const ActorId actor_id) const
cg::Vector3D GetHeading(const ActorId actor_id) const
cg::Vector3D GetVelocity(const ActorId actor_id) const
void UpdateGridPosition(const ActorId actor_id, const Buffer &buffer)
ActorIdSet GetPassingVehicles(uint64_t waypoint_id) const
ActorIdSet GetOverlappingVehicles(ActorId actor_id) const
carla::SharedPtr< cc::Waypoint > WaypointPtr
Definition InMemoryMap.h:45
std::deque< std::shared_ptr< SimpleWaypoint > > Buffer
std::shared_ptr< InMemoryMap > LocalMapPtr
Definition ALSM.h:38
void PopWaypoint(ActorId actor_id, TrackTraffic &track_traffic, Buffer &buffer, bool front_or_back)
std::vector< uint8_t > Route
std::unordered_map< carla::ActorId, Buffer > BufferMap
std::vector< SimpleWaypointPtr > NodeList
Definition InMemoryMap.h:47
std::vector< cg::Location > Path
void PushWaypoint(ActorId actor_id, TrackTraffic &track_traffic, Buffer &buffer, SimpleWaypointPtr &waypoint)
float GetThreePointCircleRadius(cg::Location first_location, cg::Location middle_location, cg::Location last_location)
Returns the radius of the circle defined by three points in the XY plane.
TargetWPInfo GetTargetWaypoint(const Buffer &waypoint_buffer, const float &target_point_distance)
std::pair< RoadOption, WaypointPtr > Action
std::vector< Action > ActionBuffer
std::vector< LocalizationData > LocalizationFrame
std::shared_ptr< SimpleWaypoint > SimpleWaypointPtr
float DeviationDotProduct(const cg::Location &reference_location, const cg::Vector3D &heading_vector, const cg::Location &target_location)
Returns the dot product between the vehicle's heading vector and the vector along the direction to th...
This file contains definitions of common data structures used in traffic manager.
constexpr float SquaredLength() const
bool localized
False when the localization stage could not place the vehicle on the map – a map without a single dri...