CARLA
Loading...
Searching...
No Matches
InMemoryMap.cpp
Go to the documentation of this file.
1// Copyright (c) 2026 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
7#include "carla/Logging.h"
8
11
12namespace carla {
13namespace traffic_manager {
14
15 namespace cg = carla::geom;
16 using namespace constants::Map;
17
18 using TopologyList = std::vector<std::pair<WaypointPtr, WaypointPtr>>;
19 using RawNodeList = std::vector<WaypointPtr>;
20
21 InMemoryMap::InMemoryMap(WorldMap world_map) : _world_map(world_map) {}
23 // The waypoints link to each other with shared pointers: without breaking
24 // the cycles, the whole dense topology would outlive the map, leaking it on
25 // every Traffic Manager shut down and every map change.
26 for (auto &simple_waypoint : dense_topology) {
27 if (simple_waypoint != nullptr) {
28 simple_waypoint->ClearLinks();
29 }
30 }
31 }
32
34 return std::make_tuple(wp->GetRoadId(), wp->GetLaneId(), wp->GetSectionId());
35 }
36
38 return GetSegmentId(swp->GetWaypoint());
39 }
40
42 const SegmentTopology &segment_topology,
43 const SegmentMap &segment_map) {
44 NodeList result;
45 if (segment_topology.find(segment_id) == segment_topology.end()) {
46 return result;
47 }
48
49 for (const auto &successor_segment_id : segment_topology.at(segment_id).second) {
50 if (segment_map.find(successor_segment_id) == segment_map.end()) {
51 auto successors = GetSuccessors(successor_segment_id, segment_topology, segment_map);
52 result.insert(result.end(), successors.begin(), successors.end());
53 } else {
54 result.emplace_back(segment_map.at(successor_segment_id).front());
55 }
56 }
57 return result;
58 }
59
61 const SegmentTopology &segment_topology,
62 const SegmentMap &segment_map) {
63 NodeList result;
64 if (segment_topology.find(segment_id) == segment_topology.end()) {
65 return result;
66 }
67
68 for (const auto &predecessor_segment_id : segment_topology.at(segment_id).first) {
69 if (segment_map.find(predecessor_segment_id) == segment_map.end()) {
70 auto predecessors = GetPredecessors(predecessor_segment_id, segment_topology, segment_map);
71 result.insert(result.end(), predecessors.begin(), predecessors.end());
72 } else {
73 result.emplace_back(segment_map.at(predecessor_segment_id).back());
74 }
75 }
76 return result;
77 }
78
79 void InMemoryMap::Cook(WorldMap world_map, const std::string& path) {
80 InMemoryMap local_map(world_map);
81 local_map.SetUp();
82 local_map.Save(path);
83 }
84
85 void InMemoryMap::Save(const std::string& path) {
86 std::string filename;
87 if (path.empty()) {
88 filename = this->GetMapName() + ".bin";
89 } else {
90 filename = path;
91 }
92
93 std::ofstream out_file;
94 out_file.open(filename, std::ios::binary);
95 if (!out_file.is_open()) {
96 log_error("Could not open binary file");
97 return;
98 }
99
100 // write total records
101 uint32_t total = static_cast<uint32_t>(dense_topology.size());
102 out_file.write(reinterpret_cast<const char *>(&total), sizeof(uint32_t));
103
104 // write simple waypoints
105 std::unordered_set<uint64_t> used_ids;
106 for (auto& wp: dense_topology) {
107 if (used_ids.find(wp->GetId()) != used_ids.end()) {
108 log_error("Could not generate the binary file. There are repeated waypoints");
109 }
110 CachedSimpleWaypoint cached_wp(wp);
111 cached_wp.Write(out_file);
112
113 used_ids.insert(wp->GetId());
114 }
115
116 out_file.close();
117 return;
118 }
119
120 bool InMemoryMap::Load(const std::vector<uint8_t>& content) {
121 unsigned long pos = 0;
122 std::vector<CachedSimpleWaypoint> cached_waypoints;
123 std::unordered_map<uint64_t, uint32_t> id2index;
124
125 // A cache that does not belong to the current map (another town's file, or
126 // one written for an older OpenDRIVE) must not be trusted: every lookup
127 // below is checked and a mismatch leaves the map empty for SetUp() to
128 // rebuild it, instead of dereferencing a null waypoint.
129 const auto fail = [this](const char *what) {
130 log_warning("InMemoryMap cache rejected:", what, "- rebuilding the local map from the OpenDRIVE");
131 dense_topology.clear();
132 return false;
133 };
134
135 // read total records
136 uint32_t total;
137 if (content.size() < sizeof(total)) {
138 return fail("truncated header");
139 }
140 memcpy(&total, &content[pos], sizeof(total));
141 pos += sizeof(total);
142
143 // read simple waypoints
144 for (uint32_t i=0; i < total; i++) {
145 if (pos + CachedSimpleWaypoint::MinimumSize() > content.size()) {
146 return fail("truncated waypoint records");
147 }
148 CachedSimpleWaypoint cached_wp;
149 cached_wp.Read(content, pos);
150 if (pos > content.size()) {
151 return fail("truncated waypoint records");
152 }
153 cached_waypoints.push_back(cached_wp);
154 id2index.insert({cached_wp.waypoint_id, i});
155
156 WaypointPtr waypoint_ptr = _world_map->GetWaypointXODR(cached_wp.road_id, cached_wp.lane_id, cached_wp.s);
157 if (waypoint_ptr == nullptr) {
158 return fail("it references a road/lane the current map does not have");
159 }
160 SimpleWaypointPtr wp = std::make_shared<SimpleWaypoint>(waypoint_ptr);
161 wp->SetGeodesicGridId(cached_wp.geodesic_grid_id);
162 wp->SetIsJunction(cached_wp.is_junction);
163 wp->SetRoadOption(static_cast<RoadOption>(cached_wp.road_option));
164 dense_topology.push_back(wp);
165 }
166
167 // connect waypoints
168 const auto lookup = [&](uint64_t id) -> SimpleWaypointPtr {
169 const auto it = id2index.find(id);
170 return it == id2index.end() ? nullptr : dense_topology.at(it->second);
171 };
172 for (uint32_t i=0; i < dense_topology.size(); i++) {
173 auto wp = dense_topology.at(i);
174 auto cached_wp = cached_waypoints.at(i);
175
176 std::vector<SimpleWaypointPtr> next_waypoints;
177 for (auto id : cached_wp.next_waypoints) {
178 const auto next = lookup(id);
179 if (next == nullptr) {
180 return fail("it links waypoints that are not in the cache");
181 }
182 next_waypoints.push_back(next);
183 }
184 std::vector<SimpleWaypointPtr> previous_waypoints;
185 for (auto id : cached_wp.previous_waypoints) {
186 const auto previous = lookup(id);
187 if (previous == nullptr) {
188 return fail("it links waypoints that are not in the cache");
189 }
190 previous_waypoints.push_back(previous);
191 }
192 wp->SetNextWaypoint(next_waypoints);
193 wp->SetPreviousWaypoint(previous_waypoints);
194 if (cached_wp.next_left_waypoint > 0) {
195 auto left = lookup(cached_wp.next_left_waypoint);
196 if (left == nullptr) {
197 return fail("it links waypoints that are not in the cache");
198 }
199 wp->SetLeftWaypoint(left);
200 }
201 if (cached_wp.next_right_waypoint > 0) {
202 auto right = lookup(cached_wp.next_right_waypoint);
203 if (right == nullptr) {
204 return fail("it links waypoints that are not in the cache");
205 }
206 wp->SetRightWaypoint(right);
207 }
208 }
209
210 // create spatial tree
212
213 return true;
214 }
215
217
218 // 1. Building segment topology (i.e., defining set of segment predecessors and successors)
219 assert(_world_map != nullptr && "No map reference found.");
220 auto waypoint_topology = _world_map->GetTopology();
221
222 SegmentTopology segment_topology;
223 std::unordered_map<int64_t, std::pair<std::set<crd::RoadId>, std::set<crd::RoadId>>> std_road_connectivity;
224 std::unordered_map<crd::RoadId, bool> is_real_junction;
225
226 for (auto &connection : waypoint_topology) {
227 auto &waypoint = connection.first;
228 auto &successor = connection.second;
229
230 // Setting segment predecessors and successors.
231 SegmentId waypoint_segment_id = GetSegmentId(connection.first);
232 SegmentId successor_segment_id = GetSegmentId(connection.second);
233 if (waypoint_segment_id == successor_segment_id){
234 // If both topology waypoints are at the same segment, ignore them.
235 // This happens at lanes that have either no successor or predecessor connections.
236 continue;
237 }
238 using SegIdVectorPair = std::pair<std::vector<SegmentId>, std::vector<SegmentId>>;
239 SegIdVectorPair &connection_first = segment_topology[waypoint_segment_id];
240 SegIdVectorPair &connection_second = segment_topology[successor_segment_id];
241 connection_first.second.push_back(successor_segment_id);
242 connection_second.first.push_back(waypoint_segment_id);
243
244 // From path to standard road.
245 bool waypoint_is_junction = waypoint->IsJunction();
246 bool successor_is_junction = successor->IsJunction();
247 if (waypoint_is_junction && !successor_is_junction) {
248 crd::RoadId path_id = waypoint->GetRoadId();
249 int64_t std_road_id = static_cast<int64_t>(successor->GetRoadId());
250 std_road_id = (successor->GetLaneId() < 0) ? -1 * std_road_id : std_road_id;
251
252 std::set<crd::RoadId> &in_paths = std_road_connectivity[std_road_id].first;
253 in_paths.insert(path_id);
254
255 if (in_paths.size() >= 2) {
256 for (auto &in_path_id: in_paths) {
257 is_real_junction[in_path_id] = true;
258 }
259 }
260 }
261
262 // From standard road to path.
263 if (!waypoint_is_junction && successor_is_junction) {
264 crd::RoadId path_id = successor->GetRoadId();
265 int64_t std_road_id = static_cast<int64_t>(waypoint->GetRoadId());
266 std_road_id = (waypoint->GetLaneId() < 0) ? -1 * std_road_id : std_road_id;
267
268 std::set<crd::RoadId> &out_paths = std_road_connectivity[std_road_id].second;
269 out_paths.insert(path_id);
270
271 if (out_paths.size() >= 2) {
272 for (auto &out_path_id: out_paths) {
273 is_real_junction[out_path_id] = true;
274 }
275 }
276 }
277 }
278
279 // 2. Consuming the raw dense topology from cc::Map into SimpleWaypoints.
280 SegmentMap segment_map;
281 assert(_world_map != nullptr && "No map reference found.");
282 auto raw_dense_topology = _world_map->GenerateWaypoints(MAP_RESOLUTION);
283 for (auto &waypoint_ptr: raw_dense_topology) {
284 if (waypoint_ptr->GetLaneWidth() > MIN_LANE_WIDTH){
285 // Avoid making the vehicles move through very narrow lanes
286 segment_map[GetSegmentId(waypoint_ptr)].emplace_back(std::make_shared<SimpleWaypoint>(waypoint_ptr));
287 }
288 }
289
290 // 3. Processing waypoints.
291 auto distance_squared = [](cg::Location l1, cg::Location l2) {
292 return cg::Math::DistanceSquared(l1, l2);
293 };
294 auto square = [](float input) {return std::pow(input, 2);};
295 auto compare_s = [](const SimpleWaypointPtr &swp1, const SimpleWaypointPtr &swp2) {
296 return (swp1->GetWaypoint()->GetDistance() < swp2->GetWaypoint()->GetDistance());
297 };
298 auto wpt_angle = [](cg::Vector3D l1, cg::Vector3D l2) {
299 return cg::Math::GetVectorAngle(l1, l2);
300 };
301 auto max = [](int16_t x, int16_t y) {
302 return x ^ ((x ^ y) & -(x < y));
303 };
304
305 GeoGridId geodesic_grid_id_counter = -1;
306 for (auto &segment: segment_map) {
307 auto &segment_waypoints = segment.second;
308
309 // Generating geodesic grid ids.
310 ++geodesic_grid_id_counter;
311
312 // Ordering waypoints according to road direction.
313 std::sort(segment_waypoints.begin(), segment_waypoints.end(), compare_s);
314 auto is_positive_direction = segment_waypoints.front()->GetWaypoint()->IsPositiveDirection();
315 if (!is_positive_direction) {
316 std::reverse(segment_waypoints.begin(), segment_waypoints.end());
317 }
318
319 // Adding more waypoints if the angle is too tight or if they are too distant.
320 for (std::size_t i = 0; i < segment_waypoints.size() - 1; ++i) {
321 double distance = std::abs(segment_waypoints.at(i)->GetWaypoint()->GetDistance() - segment_waypoints.at(i+1)->GetWaypoint()->GetDistance());
322 double angle = wpt_angle(segment_waypoints.at(i)->GetTransform().GetForwardVector(), segment_waypoints.at(i+1)->GetTransform().GetForwardVector());
323 int16_t angle_splits = static_cast<int16_t>(angle/MAX_WPT_RADIANS);
324 int16_t distance_splits = static_cast<int16_t>((distance*distance)/MAX_WPT_DISTANCE);
325 auto max_splits = max(angle_splits, distance_splits);
326 if (max_splits >= 1) {
327 // Compute how many waypoints do we need to generate.
328 for (uint16_t j = 0; j < max_splits; ++j) {
329 auto next_waypoints = segment_waypoints.at(i)->GetWaypoint()->GetNext(distance/(max_splits+1));
330 if (next_waypoints.size() != 0) {
331 auto new_waypoint = next_waypoints.front();
332 i++;
333 segment_waypoints.insert(segment_waypoints.begin()+static_cast<int64_t>(i), std::make_shared<SimpleWaypoint>(new_waypoint));
334 } else {
335 // Reached end of the road.
336 break;
337 }
338 }
339 }
340 }
341
342 // Placing intra-segment connections.
343 cg::Location grid_edge_location = segment_waypoints.front()->GetLocation();
344 for (std::size_t i = 0; i < segment_waypoints.size() - 1; ++i) {
345 SimpleWaypointPtr current_waypoint = segment_waypoints.at(i);
346 SimpleWaypointPtr next_waypoint = segment_waypoints.at(i+1);
347 // Assigning grid id.
348 if (distance_squared(grid_edge_location, current_waypoint->GetLocation()) >
349 square(MAX_GEODESIC_GRID_LENGTH)) {
350 ++geodesic_grid_id_counter;
351 grid_edge_location = current_waypoint->GetLocation();
352 }
353 current_waypoint->SetGeodesicGridId(geodesic_grid_id_counter);
354
355 current_waypoint->SetNextWaypoint({next_waypoint});
356 next_waypoint->SetPreviousWaypoint({current_waypoint});
357
358 }
359 segment_waypoints.back()->SetGeodesicGridId(geodesic_grid_id_counter);
360
361 // Adding simple waypoints to processed dense topology.
362 for (auto swp: segment_waypoints) {
363 // Checking whether the waypoint is in a real junction.
364 auto wpt = swp->GetWaypoint();
365 auto road_id = wpt->GetRoadId();
366 if (wpt->IsJunction() && !is_real_junction.count(road_id)) {
367 swp->SetIsJunction(false);
368 } else {
369 swp->SetIsJunction(swp->GetWaypoint()->IsJunction());
370 }
371
372 dense_topology.push_back(swp);
373 }
374 }
375
377
378 // Placing inter-segment connections.
379 for (auto &segment : segment_map) {
380 SegmentId segment_id = segment.first;
381 auto &segment_waypoints = segment.second;
382
383 auto successors = GetSuccessors(segment_id, segment_topology, segment_map);
384 auto predecessors = GetPredecessors(segment_id, segment_topology, segment_map);
385
386 segment_waypoints.front()->SetPreviousWaypoint(predecessors);
387 segment_waypoints.back()->SetNextWaypoint(successors);
388 }
389
390 // Linking lane change connections.
391 for (auto &swp : dense_topology) {
392 if (!swp->CheckJunction()) {
394 }
395 }
396
397 // Linking any unconnected segments.
398 for (auto &swp : dense_topology) {
399 if (swp->GetNextWaypoint().empty()) {
400 auto neighbour = swp->GetRightWaypoint();
401 if (!neighbour) {
402 neighbour = swp->GetLeftWaypoint();
403 }
404
405 if (neighbour) {
406 swp->SetNextWaypoint(neighbour->GetNextWaypoint());
407 for (auto next_waypoint : neighbour->GetNextWaypoint()) {
408 next_waypoint->SetPreviousWaypoint({swp});
409 }
410 }
411 }
412 }
413
414 // Specifying a RoadOption for each SimpleWaypoint
416 }
417
419 for (auto &simple_waypoint: dense_topology) {
420 if (simple_waypoint != nullptr) {
421 const cg::Location loc = simple_waypoint->GetLocation();
422 Point3D point(loc.x, loc.y, loc.z);
423 rtree.insert(std::make_pair(point, simple_waypoint));
424 }
425 }
426 }
427
429 for (auto &swp : dense_topology) {
430 std::vector<SimpleWaypointPtr> next_waypoints = swp->GetNextWaypoint();
431 std::size_t next_swp_size = next_waypoints.size();
432
433 if (next_swp_size == 0) {
434 // No next waypoint means that this is an end of the road.
435 swp->SetRoadOption(RoadOption::RoadEnd);
436 }
437
438 else if (next_swp_size > 1 || (!swp->CheckJunction() && next_waypoints.front()->CheckJunction())) {
439 // To check if we are in an actual junction, and not on an highway, we try to see
440 // if there's a landmark nearby of type Traffic Light, Stop Sign or Yield Sign.
441
442 bool found_landmark= false;
443 if (next_swp_size <= 1) {
444
445 auto all_landmarks = swp->GetWaypoint()->GetAllLandmarksInDistance(15.0);
446
447 if (all_landmarks.empty()) {
448 // Landmark hasn't been found, this isn't a junction.
449 swp->SetRoadOption(RoadOption::LaneFollow);
450 } else {
451 for (auto &landmark : all_landmarks) {
452 auto landmark_type = landmark->GetType();
453 if (landmark_type == "1000001" || landmark_type == "206" || landmark_type == "205") {
454 // We found a landmark.
455 found_landmark= true;
456 break;
457 }
458 }
459 if (!found_landmark) {
460 swp->SetRoadOption(RoadOption::LaneFollow);
461 }
462 }
463 }
464
465 // If we did find a landmark, or we are in the other case, find all waypoints
466 // in the junction and assign the correct RoadOption.
467 if (found_landmark || next_swp_size > 1) {
468 swp->SetRoadOption(RoadOption::LaneFollow);
469 for (auto &next_swp : next_waypoints) {
470 std::vector<SimpleWaypointPtr> traversed_waypoints;
471 SimpleWaypointPtr junction_end_waypoint;
472
473 if (next_swp_size > 1) {
474 junction_end_waypoint = next_swp;
475 } else {
476 junction_end_waypoint = next_waypoints.front();
477 }
478
479 while (junction_end_waypoint->CheckJunction()){
480 traversed_waypoints.push_back(junction_end_waypoint);
481 std::vector<SimpleWaypointPtr> temp = junction_end_waypoint->GetNextWaypoint();
482 if (temp.empty()) {
483 break;
484 }
485 junction_end_waypoint = temp.front();
486 }
487
488 if (traversed_waypoints.empty()) {
489 // This branch's waypoint is not itself flagged as a junction, even though
490 // its predecessor has multiple successors (or a landmark marked it as an
491 // entry point). This happens with malformed/placeholder OpenDRIVE junction
492 // connections (e.g. incomingRoad="-1" placeholders seen on some imported
493 // maps), which starve is_real_junction of enough distinct paths to flag the
494 // road as a real junction. Skip angle computation for this branch instead of
495 // dereferencing the empty traversed_waypoints container.
496 continue;
497 }
498
499 // Calculate the angle between the first and the last point of the junction.
500 int16_t current_angle = static_cast<int16_t>(traversed_waypoints.front()->GetTransform().rotation.yaw);
501 int16_t junction_end_angle = static_cast<int16_t>(traversed_waypoints.back()->GetTransform().rotation.yaw);
502 int16_t diff_angle = (junction_end_angle - current_angle) % 360;
503 bool straight = (diff_angle < STRAIGHT_DEG && diff_angle > -STRAIGHT_DEG) ||
504 (diff_angle > 360-STRAIGHT_DEG && diff_angle <= 360) ||
505 (diff_angle < -360+STRAIGHT_DEG && diff_angle >= -360);
506 bool right = (diff_angle >= STRAIGHT_DEG && diff_angle <= 180) ||
507 (diff_angle <= -180 && diff_angle >= -360+STRAIGHT_DEG);
508
509 auto assign_option = [](RoadOption ro, std::vector<SimpleWaypointPtr> traversed_waypoints) {
510 for (auto &twp : traversed_waypoints) {
511 twp->SetRoadOption(ro);
512 }
513 };
514
515 // Assign RoadOption according to the angle.
516 if (straight) assign_option(RoadOption::Straight, traversed_waypoints);
517 else if (right) assign_option(RoadOption::Right, traversed_waypoints);
518 else assign_option(RoadOption::Left, traversed_waypoints);
519 }
520 }
521 }
522 else if (next_swp_size == 1 && swp->GetRoadOption() == RoadOption::Void) {
523 swp->SetRoadOption(RoadOption::LaneFollow);
524 }
525 }
526 }
527
529
530 Point3D query_point(loc.x, loc.y, loc.z);
531 std::vector<SpatialTreeEntry> result_1;
532
533 rtree.query(bgi::nearest(query_point, 1), std::back_inserter(result_1));
534
535 // A map without a single drivable waypoint (EmptyMap, or an OpenDRIVE file
536 // with no road) leaves the tree empty and the query without a result.
537 // Callers must handle "there is nowhere to drive here".
538 if (result_1.empty()) {
539 return nullptr;
540 }
541
542 SpatialTreeEntry &closest_entry = result_1.front();
543 SimpleWaypointPtr &closest_point = closest_entry.second;
544
545 return closest_point;
546 }
547
548 NodeList InMemoryMap::GetWaypointsInDelta(const cg::Location loc, const uint16_t n_points, const float random_sample) const {
549 Point3D query_point(loc.x, loc.y, loc.z);
550
551 Point3D lower_p1(loc.x + random_sample, loc.y + random_sample, loc.z + Z_DELTA);
552 Point3D lower_p2(loc.x - random_sample, loc.y - random_sample, loc.z - Z_DELTA);
553 Point3D upper_p1(loc.x + random_sample + DELTA, loc.y + random_sample + DELTA, loc.z + Z_DELTA);
554 Point3D upper_p2(loc.x - random_sample - DELTA, loc.y - random_sample - DELTA, loc.z - Z_DELTA);
555
556 Box lower_query_box(lower_p2, lower_p1);
557 Box upper_query_box(upper_p2, upper_p1);
558
559 NodeList result;
560 uint8_t x = 0;
561 for (Rtree::const_query_iterator
562 it = rtree.qbegin(bgi::within(upper_query_box)
563 && !bgi::within(lower_query_box)
564 && bgi::satisfies([&](SpatialTreeEntry const& v) { return !v.second->CheckJunction();}));
565 it != rtree.qend();
566 ++it) {
567 x++;
568 result.push_back(it->second);
569 if (x >= n_points)
570 break;
571 }
572
573 return result;
574 }
575
579
581
582 const WaypointPtr raw_waypoint = reference_waypoint->GetWaypoint();
583 const crd::element::LaneMarking::LaneChange lane_change = raw_waypoint->GetLaneChange();
584
585 /// Cheack for transits
586 switch(lane_change)
587 {
588 /// Left transit way point present only
589 case crd::element::LaneMarking::LaneChange::Left:
590 {
591 const WaypointPtr left_waypoint = raw_waypoint->GetLeft();
592 if (left_waypoint != nullptr &&
593 left_waypoint->GetType() == crd::Lane::LaneType::Driving &&
594 (left_waypoint->GetLaneId() * raw_waypoint->GetLaneId() > 0)) {
595
596 SimpleWaypointPtr closest_simple_waypoint = GetWaypoint(left_waypoint->GetTransform().location);
597 reference_waypoint->SetLeftWaypoint(closest_simple_waypoint);
598 }
599 }
600 break;
601
602 /// Right transit way point present only
603 case crd::element::LaneMarking::LaneChange::Right:
604 {
605 const WaypointPtr right_waypoint = raw_waypoint->GetRight();
606 if(right_waypoint != nullptr &&
607 right_waypoint->GetType() == crd::Lane::LaneType::Driving &&
608 (right_waypoint->GetLaneId() * raw_waypoint->GetLaneId() > 0)) {
609
610 SimpleWaypointPtr closest_simple_waypoint = GetWaypoint(right_waypoint->GetTransform().location);
611 reference_waypoint->SetRightWaypoint(closest_simple_waypoint);
612 }
613 }
614 break;
615
616 /// Both left and right transit present
617 case crd::element::LaneMarking::LaneChange::Both:
618 {
619 /// Right transit way point
620 const WaypointPtr right_waypoint = raw_waypoint->GetRight();
621 if (right_waypoint != nullptr &&
622 right_waypoint->GetType() == crd::Lane::LaneType::Driving &&
623 (right_waypoint->GetLaneId() * raw_waypoint->GetLaneId() > 0)) {
624
625 SimpleWaypointPtr closest_simple_waypointR = GetWaypoint(right_waypoint->GetTransform().location);
626 reference_waypoint->SetRightWaypoint(closest_simple_waypointR);
627 }
628
629 /// Left transit way point
630 const WaypointPtr left_waypoint = raw_waypoint->GetLeft();
631 if (left_waypoint != nullptr &&
632 left_waypoint->GetType() == crd::Lane::LaneType::Driving &&
633 (left_waypoint->GetLaneId() * raw_waypoint->GetLaneId() > 0)) {
634
635 SimpleWaypointPtr closest_simple_waypointL = GetWaypoint(left_waypoint->GetTransform().location);
636 reference_waypoint->SetLeftWaypoint(closest_simple_waypointL);
637 }
638 }
639 break;
640
641 /// For no transit waypoint (left or right)
642 default: break;
643 }
644 }
645
647 assert(_world_map != nullptr && "No map reference found.");
648 return _world_map->GetName();
649 }
650
652 return *_world_map;
653 }
654
655
656} // namespace traffic_manager
657} // namespace carla
float distance
float y
float x
geom::Point point
Definition LaneGraph.cpp:41
std::string road_id
Definition LaneGraph.cpp:39
static constexpr unsigned long MinimumSize()
Bytes of a record with empty next/previous lists: id (8), road/section/lane/s (16),...
void Read(const std::vector< uint8_t > &content, unsigned long &start)
This class builds a discretized local map-cache.
Definition InMemoryMap.h:63
bool Load(const std::vector< uint8_t > &content)
WorldMap _world_map
Object to hold the world map received by the constructor.
Definition InMemoryMap.h:68
void FindAndLinkLaneChange(SimpleWaypointPtr reference_waypoint)
This method is used to find and place lane change links.
NodeList GetPredecessors(const SegmentId segment_id, const SegmentTopology &segment_topology, const SegmentMap &segment_map)
static void Cook(WorldMap world_map, const std::string &path)
SegmentId GetSegmentId(const WaypointPtr &wp) const
Computes the segment id of a given waypoint.
NodeList GetDenseTopology() const
This method returns the full list of discrete samples of the map in the local cache.
void SetUp()
This method constructs the local map with a resolution of sampling_resolution.
NodeList GetWaypointsInDelta(const cg::Location loc, const uint16_t n_points, const float random_sample) const
This method returns n waypoints in an delta area with a certain distance from the ego vehicle.
NodeList GetSuccessors(const SegmentId segment_id, const SegmentTopology &segment_topology, const SegmentMap &segment_map)
SimpleWaypointPtr GetWaypoint(const cg::Location loc) const
This method returns the closest waypoint to a given location on the map.
Rtree rtree
Spatial quadratic R-tree for indexing and querying waypoints.
Definition InMemoryMap.h:73
NodeList dense_topology
Structure to hold all custom waypoint objects after interpolation of sparse topology.
Definition InMemoryMap.h:71
void Save(const std::string &path)
uint32_t RoadId
Definition RoadTypes.h:15
static const float MAX_GEODESIC_GRID_LENGTH
Definition Constants.h:171
bg::model::box< Point3D > Box
Definition InMemoryMap.h:52
carla::SharedPtr< cc::Waypoint > WaypointPtr
Definition InMemoryMap.h:45
std::map< SegmentId, std::pair< std::vector< SegmentId >, std::vector< SegmentId > > > SegmentTopology
Definition InMemoryMap.h:56
std::vector< std::pair< WaypointPtr, WaypointPtr > > TopologyList
std::map< SegmentId, std::vector< SimpleWaypointPtr > > SegmentMap
Definition InMemoryMap.h:57
std::vector< SimpleWaypointPtr > NodeList
Definition InMemoryMap.h:47
bg::model::point< float, 3, bg::cs::cartesian > Point3D
Definition InMemoryMap.h:51
carla::SharedPtr< const cc::Map > WorldMap
Definition InMemoryMap.h:49
std::tuple< crd::RoadId, crd::LaneId, crd::SectionId > SegmentId
Definition InMemoryMap.h:55
std::pair< Point3D, SimpleWaypointPtr > SpatialTreeEntry
Definition InMemoryMap.h:53
std::vector< WaypointPtr > RawNodeList
std::shared_ptr< SimpleWaypoint > SimpleWaypointPtr
This file contains definitions of common data structures used in traffic manager.
static void log_error(Args &&... args)
Definition Logging.h:110
static void log_warning(Args &&... args)
Definition Logging.h:96