CARLA
 
载入中...
搜索中...
未找到
CollisionStage.cpp
浏览该文件的文档.
1
2#include "carla/geom/Math.h"
3
6
8
9namespace carla {
10namespace traffic_manager {
11
12using Point2D = bg::model::point<double, 2, bg::cs::cartesian>;
14
15using namespace constants::Collision;
17
19 const std::vector<ActorId> &vehicle_id_list,
20 const SimulationState &simulation_state,
21 const BufferMap &buffer_map,
22 const TrackTraffic &track_traffic,
23 const Parameters &parameters,
24 CollisionFrame &output_array,
25 RandomGenerator &random_device)
26 : vehicle_id_list(vehicle_id_list),
27 simulation_state(simulation_state),
28 buffer_map(buffer_map),
29 track_traffic(track_traffic),
30 parameters(parameters),
31 output_array(output_array),
32 random_device(random_device) {}
33
34void CollisionStage::Update(const unsigned long index) {
35 ActorId obstacle_id = 0u;
36 bool collision_hazard = false;
37 float available_distance_margin = std::numeric_limits<float>::infinity();
38
39 const ActorId ego_actor_id = vehicle_id_list.at(index);
40 if (simulation_state.ContainsActor(ego_actor_id)) {
41 const cg::Location ego_location = simulation_state.GetLocation(ego_actor_id);
42 const Buffer &ego_buffer = buffer_map.at(ego_actor_id);
43 const unsigned long look_ahead_index = GetTargetWaypoint(ego_buffer, JUNCTION_LOOK_AHEAD).second;
44 const float velocity = simulation_state.GetVelocity(ego_actor_id).Length();
45
46 ActorIdSet overlapping_actors = track_traffic.GetOverlappingVehicles(ego_actor_id);
47 std::vector<ActorId> collision_candidate_ids;
48 // Run through vehicles with overlapping paths and filter them;
49 const float distance_to_leading = parameters.GetDistanceToLeadingVehicle(ego_actor_id);
50 float collision_radius_square = SQUARE(COLLISION_RADIUS_RATE * velocity + COLLISION_RADIUS_MIN);
51 if (velocity < 2.0f) {
52 const float length = simulation_state.GetDimensions(ego_actor_id).x;
53 const float collision_radius_stop = COLLISION_RADIUS_STOP + length;
54 collision_radius_square = SQUARE(collision_radius_stop);
55 }
56 if (distance_to_leading > collision_radius_square) {
57 collision_radius_square = SQUARE(distance_to_leading);
58 }
59
60 for (ActorId overlapping_actor_id : overlapping_actors) {
61 // If actor is within maximum collision avoidance and vertical overlap range.
62 const cg::Location &overlapping_actor_location = simulation_state.GetLocation(overlapping_actor_id);
63 if (overlapping_actor_id != ego_actor_id
64 && cg::Math::DistanceSquared(overlapping_actor_location, ego_location) < collision_radius_square
65 && std::abs(ego_location.z - overlapping_actor_location.z) < VERTICAL_OVERLAP_THRESHOLD) {
66 collision_candidate_ids.push_back(overlapping_actor_id);
67 }
68 }
69
70 // Sorting collision candidates in accending order of distance to current vehicle.
71 std::sort(collision_candidate_ids.begin(), collision_candidate_ids.end(),
72 [this, &ego_location](const ActorId &a_id_1, const ActorId &a_id_2) {
73 const cg::Location &e_loc = ego_location;
74 const cg::Location &loc_1 = simulation_state.GetLocation(a_id_1);
75 const cg::Location &loc_2 = simulation_state.GetLocation(a_id_2);
76 return (cg::Math::DistanceSquared(e_loc, loc_1) < cg::Math::DistanceSquared(e_loc, loc_2));
77 });
78
79 // Check every actor in the vicinity if it poses a collision hazard.
80 for (auto iter = collision_candidate_ids.begin();
81 iter != collision_candidate_ids.end() && !collision_hazard;
82 ++iter) {
83 const ActorId other_actor_id = *iter;
84 const ActorType other_actor_type = simulation_state.GetType(other_actor_id);
85
86 if (parameters.GetCollisionDetection(ego_actor_id, other_actor_id)
87 && buffer_map.find(ego_actor_id) != buffer_map.end()
88 && simulation_state.ContainsActor(other_actor_id)) {
89 std::pair<bool, float> negotiation_result = NegotiateCollision(ego_actor_id,
90 other_actor_id,
91 look_ahead_index);
92 if (negotiation_result.first) {
93 if ((other_actor_type == ActorType::Vehicle
95 || (other_actor_type == ActorType::Pedestrian
97 collision_hazard = true;
98 obstacle_id = other_actor_id;
99 available_distance_margin = negotiation_result.second;
100 }
101 }
102 }
103 }
104 }
105
106 CollisionHazardData &output_element = output_array.at(index);
107 output_element.hazard_actor_id = obstacle_id;
108 output_element.hazard = collision_hazard;
109 output_element.available_distance_margin = available_distance_margin;
110}
111
113 collision_locks.erase(actor_id);
114}
115
117 collision_locks.clear();
118}
119
121
122 const float velocity = cg::Math::Dot(simulation_state.GetVelocity(actor_id), simulation_state.GetHeading(actor_id));
123 float bbox_extension;
124 // Using a function to calculate boundary length.
125 float velocity_extension = VEL_EXT_FACTOR * velocity;
126 bbox_extension = BOUNDARY_EXTENSION_MINIMUM + velocity_extension * velocity_extension;
127 // If a valid collision lock present, change boundary length to maintain lock.
128 if (collision_locks.find(actor_id) != collision_locks.end()) {
129 const CollisionLock &lock = collision_locks.at(actor_id);
130 float lock_boundary_length = static_cast<float>(lock.distance_to_lead_vehicle + LOCKING_DISTANCE_PADDING);
131 // Only extend boundary track vehicle if the leading vehicle
132 // if it is not further than velocity dependent extension by MAX_LOCKING_EXTENSION.
133 if ((lock_boundary_length - lock.initial_lock_distance) < MAX_LOCKING_EXTENSION) {
134 bbox_extension = lock_boundary_length;
135 }
136 }
137
138 return bbox_extension;
139}
140
142 const ActorType actor_type = simulation_state.GetType(actor_id);
143 const cg::Vector3D heading_vector = simulation_state.GetHeading(actor_id);
144
145 float forward_extension = 0.0f;
146 if (actor_type == ActorType::Pedestrian) {
147 // Extend the pedestrians bbox to "predict" where they'll be and avoid collisions.
148 forward_extension = simulation_state.GetVelocity(actor_id).Length() * WALKER_TIME_EXTENSION;
149 }
150
151 cg::Vector3D dimensions = simulation_state.GetDimensions(actor_id);
152
153 float bbox_x = dimensions.x;
154 float bbox_y = dimensions.y;
155
156 const cg::Vector3D x_boundary_vector = heading_vector * (bbox_x + forward_extension);
157 const auto perpendicular_vector = cg::Vector3D(-heading_vector.y, heading_vector.x, 0.0f).MakeSafeUnitVector(EPSILON);
158 const cg::Vector3D y_boundary_vector = perpendicular_vector * (bbox_y + forward_extension);
159
160 // Four corners of the vehicle in top view clockwise order (left-handed system).
161 const cg::Location location = simulation_state.GetLocation(actor_id);
162 LocationVector bbox_boundary = {
163 location + cg::Location(x_boundary_vector - y_boundary_vector),
164 location + cg::Location(-1.0f * x_boundary_vector - y_boundary_vector),
165 location + cg::Location(-1.0f * x_boundary_vector + y_boundary_vector),
166 location + cg::Location(x_boundary_vector + y_boundary_vector),
167 };
168
169 return bbox_boundary;
170}
171
173 LocationVector geodesic_boundary;
174
175 if (geodesic_boundary_map.find(actor_id) != geodesic_boundary_map.end()) {
176 geodesic_boundary = geodesic_boundary_map.at(actor_id);
177 } else {
178 const LocationVector bbox = GetBoundary(actor_id);
179
180 if (buffer_map.find(actor_id) != buffer_map.end()) {
181 float bbox_extension = GetBoundingBoxExtention(actor_id);
182 const float specific_lead_distance = parameters.GetDistanceToLeadingVehicle(actor_id);
183 bbox_extension = std::max(specific_lead_distance, bbox_extension);
184 const float bbox_extension_square = SQUARE(bbox_extension);
185
186 LocationVector left_boundary;
187 LocationVector right_boundary;
188 cg::Vector3D dimensions = simulation_state.GetDimensions(actor_id);
189 const float width = dimensions.y;
190 const float length = dimensions.x;
191
192 const Buffer &waypoint_buffer = buffer_map.at(actor_id);
193 const TargetWPInfo target_wp_info = GetTargetWaypoint(waypoint_buffer, length);
194 const SimpleWaypointPtr boundary_start = target_wp_info.first;
195 const uint64_t boundary_start_index = target_wp_info.second;
196
197 // At non-signalized junctions, we extend the boundary across the junction
198 // and in all other situations, boundary length is velocity-dependent.
199 SimpleWaypointPtr boundary_end = nullptr;
200 SimpleWaypointPtr current_point = waypoint_buffer.at(boundary_start_index);
201 bool reached_distance = false;
202 for (uint64_t j = boundary_start_index; !reached_distance && (j < waypoint_buffer.size()); ++j) {
203 if (boundary_start->DistanceSquared(current_point) > bbox_extension_square || j == waypoint_buffer.size() - 1) {
204 reached_distance = true;
205 }
206 if (boundary_end == nullptr
207 || cg::Math::Dot(boundary_end->GetForwardVector(), current_point->GetForwardVector()) < COS_10_DEGREES
208 || reached_distance) {
209
210 const cg::Vector3D heading_vector = current_point->GetForwardVector();
211 const cg::Location location = current_point->GetLocation();
212 cg::Vector3D perpendicular_vector = cg::Vector3D(-heading_vector.y, heading_vector.x, 0.0f);
213 perpendicular_vector = perpendicular_vector.MakeSafeUnitVector(EPSILON);
214 // Direction determined for the left-handed system.
215 const cg::Vector3D scaled_perpendicular = perpendicular_vector * width;
216 left_boundary.push_back(location + cg::Location(scaled_perpendicular));
217 right_boundary.push_back(location + cg::Location(-1.0f * scaled_perpendicular));
218
219 boundary_end = current_point;
220 }
221
222 current_point = waypoint_buffer.at(j);
223 }
224
225 // Reversing right boundary to construct clockwise (left-hand system)
226 // boundary. This is so because both left and right boundary vectors have
227 // the closest point to the vehicle at their starting index for the right
228 // boundary,
229 // we want to begin at the farthest point to have a clockwise trace.
230 std::reverse(right_boundary.begin(), right_boundary.end());
231 geodesic_boundary.insert(geodesic_boundary.end(), right_boundary.begin(), right_boundary.end());
232 geodesic_boundary.insert(geodesic_boundary.end(), bbox.begin(), bbox.end());
233 geodesic_boundary.insert(geodesic_boundary.end(), left_boundary.begin(), left_boundary.end());
234 } else {
235
236 geodesic_boundary = bbox;
237 }
238
239 geodesic_boundary_map.insert({actor_id, geodesic_boundary});
240 }
241
242 return geodesic_boundary;
243}
244
246
247 traffic_manager::Polygon boundary_polygon;
248 for (const cg::Location &location : boundary) {
249 bg::append(boundary_polygon.outer(), Point2D(location.x, location.y));
250 }
251 bg::append(boundary_polygon.outer(), Point2D(boundary.front().x, boundary.front().y));
252
253 return boundary_polygon;
254}
255
257 const ActorId other_actor_id) {
258
259
260 std::pair<ActorId, ActorId> key_parts;
261 if (reference_vehicle_id < other_actor_id) {
262 key_parts = {reference_vehicle_id, other_actor_id};
263 } else {
264 key_parts = {other_actor_id, reference_vehicle_id};
265 }
266
267 uint64_t actor_id_key = 0u;
268 actor_id_key |= key_parts.first;
269 actor_id_key <<= 32;
270 actor_id_key |= key_parts.second;
271
272 GeometryComparison comparision_result{-1.0, -1.0, -1.0, -1.0};
273
274 if (geometry_cache.find(actor_id_key) != geometry_cache.end()) {
275
276 comparision_result = geometry_cache.at(actor_id_key);
277 double mref_veh_other = comparision_result.reference_vehicle_to_other_geodesic;
278 comparision_result.reference_vehicle_to_other_geodesic = comparision_result.other_vehicle_to_reference_geodesic;
279 comparision_result.other_vehicle_to_reference_geodesic = mref_veh_other;
280 } else {
281
282 const Polygon reference_polygon = GetPolygon(GetBoundary(reference_vehicle_id));
283 const Polygon other_polygon = GetPolygon(GetBoundary(other_actor_id));
284
285 const Polygon reference_geodesic_polygon = GetPolygon(GetGeodesicBoundary(reference_vehicle_id));
286
287 const Polygon other_geodesic_polygon = GetPolygon(GetGeodesicBoundary(other_actor_id));
288
289 const double reference_vehicle_to_other_geodesic = bg::distance(reference_polygon, other_geodesic_polygon);
290 const double other_vehicle_to_reference_geodesic = bg::distance(other_polygon, reference_geodesic_polygon);
291 const auto inter_geodesic_distance = bg::distance(reference_geodesic_polygon, other_geodesic_polygon);
292 const auto inter_bbox_distance = bg::distance(reference_polygon, other_polygon);
293
294 comparision_result = {reference_vehicle_to_other_geodesic,
295 other_vehicle_to_reference_geodesic,
296 inter_geodesic_distance,
297 inter_bbox_distance};
298
299 geometry_cache.insert({actor_id_key, comparision_result});
300 }
301
302 return comparision_result;
303}
304
305std::pair<bool, float> CollisionStage::NegotiateCollision(const ActorId reference_vehicle_id,
306 const ActorId other_actor_id,
307 const uint64_t reference_junction_look_ahead_index) {
308 // Output variables for the method.
309 bool hazard = false;
310 float available_distance_margin = std::numeric_limits<float>::infinity();
311
312 const cg::Location reference_location = simulation_state.GetLocation(reference_vehicle_id);
313 const cg::Location other_location = simulation_state.GetLocation(other_actor_id);
314
315 // Ego and other vehicle heading.
316 const cg::Vector3D reference_heading = simulation_state.GetHeading(reference_vehicle_id);
317 // Vector from ego position to position of the other vehicle.
318 cg::Vector3D reference_to_other = other_location - reference_location;
319 reference_to_other = reference_to_other.MakeSafeUnitVector(EPSILON);
320
321 // Other vehicle heading.
322 const cg::Vector3D other_heading = simulation_state.GetHeading(other_actor_id);
323 // Vector from other vehicle position to ego position.
324 cg::Vector3D other_to_reference = reference_location - other_location;
325 other_to_reference = other_to_reference.MakeSafeUnitVector(EPSILON);
326
327 float reference_vehicle_length = simulation_state.GetDimensions(reference_vehicle_id).x * SQUARE_ROOT_OF_TWO;
328 float other_vehicle_length = simulation_state.GetDimensions(other_actor_id).x * SQUARE_ROOT_OF_TWO;
329
330 float inter_vehicle_distance = cg::Math::DistanceSquared(reference_location, other_location);
331 float ego_bounding_box_extension = GetBoundingBoxExtention(reference_vehicle_id);
332 float other_bounding_box_extension = GetBoundingBoxExtention(other_actor_id);
333 // Calculate minimum distance between vehicle to consider collision negotiation.
334 float inter_vehicle_length = reference_vehicle_length + other_vehicle_length;
335 float ego_detection_range = SQUARE(ego_bounding_box_extension + inter_vehicle_length);
336 float cross_detection_range = SQUARE(ego_bounding_box_extension + inter_vehicle_length + other_bounding_box_extension);
337
338 // Conditions to consider collision negotiation.
339 bool other_vehicle_in_ego_range = inter_vehicle_distance < ego_detection_range;
340 bool other_vehicles_in_cross_detection_range = inter_vehicle_distance < cross_detection_range;
341 float reference_heading_to_other_dot = cg::Math::Dot(reference_heading, reference_to_other);
342 bool other_vehicle_in_front = reference_heading_to_other_dot > 0;
343 const Buffer &reference_vehicle_buffer = buffer_map.at(reference_vehicle_id);
344 SimpleWaypointPtr closest_point = reference_vehicle_buffer.front();
345 bool ego_inside_junction = closest_point->CheckJunction();
346 TrafficLightState reference_tl_state = simulation_state.GetTLS(reference_vehicle_id);
347 bool ego_at_traffic_light = reference_tl_state.at_traffic_light;
348 bool ego_stopped_by_light = reference_tl_state.tl_state != TLS::Green && reference_tl_state.tl_state != TLS::Off;
349 SimpleWaypointPtr look_ahead_point = reference_vehicle_buffer.at(reference_junction_look_ahead_index);
350 bool ego_at_junction_entrance = !closest_point->CheckJunction() && look_ahead_point->CheckJunction();
351
352 // Conditions to consider collision negotiation.
353 if (!(ego_at_junction_entrance && ego_at_traffic_light && ego_stopped_by_light)
354 && ((ego_inside_junction && other_vehicles_in_cross_detection_range)
355 || (!ego_inside_junction && other_vehicle_in_front && other_vehicle_in_ego_range))) {
356 GeometryComparison geometry_comparison = GetGeometryBetweenActors(reference_vehicle_id, other_actor_id);
357
358 // Conditions for collision negotiation.
359 bool geodesic_path_bbox_touching = geometry_comparison.inter_geodesic_distance < OVERLAP_THRESHOLD;
360 bool vehicle_bbox_touching = geometry_comparison.inter_bbox_distance < OVERLAP_THRESHOLD;
361 bool ego_path_clear = geometry_comparison.other_vehicle_to_reference_geodesic > OVERLAP_THRESHOLD;
362 bool other_path_clear = geometry_comparison.reference_vehicle_to_other_geodesic > OVERLAP_THRESHOLD;
363 bool ego_path_priority = geometry_comparison.reference_vehicle_to_other_geodesic < geometry_comparison.other_vehicle_to_reference_geodesic;
364 bool other_path_priority = geometry_comparison.reference_vehicle_to_other_geodesic > geometry_comparison.other_vehicle_to_reference_geodesic;
365 bool ego_angular_priority = reference_heading_to_other_dot< cg::Math::Dot(other_heading, other_to_reference);
366
367 // Whichever vehicle's path is farthest away from the other vehicle gets priority to move.
368 bool lower_priority = !ego_path_priority && (other_path_priority || !ego_angular_priority);
369 bool blocked_by_other_or_lower_priority = !ego_path_clear || (other_path_clear && lower_priority);
370 bool yield_pre_crash = !vehicle_bbox_touching && blocked_by_other_or_lower_priority;
371 bool yield_post_crash = vehicle_bbox_touching && !ego_angular_priority;
372
373 if (geodesic_path_bbox_touching && (yield_pre_crash || yield_post_crash)) {
374
375 hazard = true;
376
377 const float reference_lead_distance = parameters.GetDistanceToLeadingVehicle(reference_vehicle_id);
378 const float specific_distance_margin = std::max(reference_lead_distance, MIN_REFERENCE_DISTANCE);
379 available_distance_margin = static_cast<float>(std::max(geometry_comparison.reference_vehicle_to_other_geodesic
380 - static_cast<double>(specific_distance_margin), 0.0));
381
382 ///////////////////////////////////// Collision locking mechanism /////////////////////////////////
383 // The idea is, when encountering a possible collision,
384 // we should ensure that the bounding box extension doesn't decrease too fast and loose collision tracking.
385 // This enables us to smoothly approach the lead vehicle.
386
387 // When possible collision found, check if an entry for collision lock present.
388 if (collision_locks.find(reference_vehicle_id) != collision_locks.end()) {
389 CollisionLock &lock = collision_locks.at(reference_vehicle_id);
390 // Check if the same vehicle is under lock.
391 if (other_actor_id == lock.lead_vehicle_id) {
392 // If the body of the lead vehicle is touching the reference vehicle bounding box.
393 if (geometry_comparison.other_vehicle_to_reference_geodesic < OVERLAP_THRESHOLD) {
394 // Distance between the bodies of the vehicles.
395 lock.distance_to_lead_vehicle = geometry_comparison.inter_bbox_distance;
396 } else {
397 // Distance from reference vehicle body to other vehicle path polygon.
399 }
400 } else {
401 // If possible collision with a new vehicle, re-initialize with new lock entry.
402 lock = {geometry_comparison.inter_bbox_distance, geometry_comparison.inter_bbox_distance, other_actor_id};
403 }
404 } else {
405 // Insert and initialize lock entry if not present.
406 collision_locks.insert({reference_vehicle_id,
407 {geometry_comparison.inter_bbox_distance,
408 geometry_comparison.inter_bbox_distance,
409 other_actor_id}});
410 }
411 }
412 }
413
414 // If no collision hazard detected, then flush collision lock held by the vehicle.
415 if (!hazard && collision_locks.find(reference_vehicle_id) != collision_locks.end()) {
416 collision_locks.erase(reference_vehicle_id);
417 }
418
419 return {hazard, available_distance_margin};
420}
421
426
427} // namespace traffic_manager
428} // namespace carla
#define SQUARE(a)
This file contains various constants used in traffic manager arranged into sensible namespaces for re...
Definition Constants.h:13
Vector3D MakeSafeUnitVector(const float epsilon) const
CollisionStage(const std::vector< ActorId > &vehicle_id_list, const SimulationState &simulation_state, const BufferMap &buffer_map, const TrackTraffic &track_traffic, const Parameters &parameters, CollisionFrame &output_array, RandomGenerator &random_device)
const std::vector< ActorId > & vehicle_id_list
const SimulationState & simulation_state
GeometryComparison GetGeometryBetweenActors(const ActorId reference_vehicle_id, const ActorId other_actor_id)
LocationVector GetGeodesicBoundary(const ActorId actor_id)
Polygon GetPolygon(const LocationVector &boundary)
void RemoveActor(const ActorId actor_id) override
LocationVector GetBoundary(const ActorId actor_id)
float GetBoundingBoxExtention(const ActorId actor_id)
void Update(const unsigned long index) override
std::pair< bool, float > NegotiateCollision(const ActorId reference_vehicle_id, const ActorId other_actor_id, const uint64_t reference_junction_look_ahead_index)
float GetPercentageIgnoreWalkers(const ActorId &actor_id) const
Method to get % to ignore any walker.
float GetDistanceToLeadingVehicle(const ActorId &actor_id) const
Method to query distance to leading vehicle for a given vehicle.
bool GetCollisionDetection(const ActorId &reference_actor_id, const ActorId &other_actor_id) const
Method to query collision avoidance rule between a pair of vehicles.
float GetPercentageIgnoreVehicles(const ActorId &actor_id) const
Method to get % to ignore any vehicle.
This class holds the state of all the vehicles in the simlation.
bool ContainsActor(ActorId actor_id) const
cg::Location GetLocation(const ActorId actor_id) const
cg::Vector3D GetHeading(const ActorId actor_id) const
cg::Vector3D GetVelocity(const ActorId actor_id) const
ActorType GetType(const ActorId actor_id) const
cg::Vector3D GetDimensions(const ActorId actor_id) const
TrafficLightState GetTLS(const ActorId actor_id) const
ActorIdSet GetOverlappingVehicles(ActorId actor_id) const
bg::model::point< double, 2, bg::cs::cartesian > Point2D
std::deque< std::shared_ptr< SimpleWaypoint > > Buffer
std::vector< CollisionHazardData > CollisionFrame
std::shared_ptr< SimpleWaypoint > SimpleWaypointPtr
TargetWPInfo GetTargetWaypoint(const Buffer &waypoint_buffer, const float &target_point_distance)
std::unordered_set< ActorId > ActorIdSet
std::vector< cg::Location > LocationVector
std::unordered_map< carla::ActorId, Buffer > BufferMap
bg::model::polygon< bg::model::d2::point_xy< double > > Polygon
std::pair< SimpleWaypointPtr, uint64_t > TargetWPInfo
Method to return the wayPoints from the waypoint Buffer by using target point distance
This file contains definitions of common data structures used in traffic manager.
Definition Carla.cpp:133