CARLA
Loading...
Searching...
No Matches
ALSM.cpp
Go to the documentation of this file.
1
2#include <algorithm>
3#include <cctype>
4#include <string>
5
6#include "boost/pointer_cast.hpp"
7
8#include "carla/Logging.h"
11#include "carla/client/Walker.h"
12
16
18
19namespace carla {
20namespace traffic_manager {
21
23 AtomicActorSet &registered_vehicles,
24 BufferMap &buffer_map,
25 TrackTraffic &track_traffic,
26 std::vector<ActorId>& marked_for_removal,
27 const Parameters &parameters,
28 const cc::World &world,
29 const LocalMapPtr &local_map,
30 SimulationState &simulation_state,
31 std::unordered_map<ActorId, std::pair<float, bool>> &large_vehicles,
32 LocalizationStage &localization_stage,
33 CollisionStage &collision_stage,
34 TrafficLightStage &traffic_light_stage,
35 MotionPlanStage &motion_plan_stage,
36 VehicleLightStage &vehicle_light_stage)
37 : registered_vehicles(registered_vehicles),
38 buffer_map(buffer_map),
39 track_traffic(track_traffic),
40 marked_for_removal(marked_for_removal),
41 parameters(parameters),
42 world(world),
43 local_map(local_map),
44 simulation_state(simulation_state),
45 localization_stage(localization_stage),
46 collision_stage(collision_stage),
47 traffic_light_stage(traffic_light_stage),
48 motion_plan_stage(motion_plan_stage),
49 vehicle_light_stage(vehicle_light_stage),
50 large_vehicles(large_vehicles) {}
51
53
54 bool hybrid_physics_mode = parameters.GetHybridPhysicsMode();
55
56 std::set<ActorId> world_vehicle_ids;
57 std::set<ActorId> world_pedestrian_ids;
58 std::vector<ActorId> unregistered_list_to_be_deleted;
59
61 ActorList world_actors = world.GetActors();
62
63 // Find destroyed actors and perform clean up.
64 const ALSM::DestroyeddActors destroyed_actors = IdentifyDestroyedActors(world_actors);
65
66 const ActorIdSet &destroyed_registered = destroyed_actors.first;
67 for (const auto &deletion_id: destroyed_registered) {
68 RemoveActor(deletion_id, true);
69 }
70
71 const ActorIdSet &destroyed_unregistered = destroyed_actors.second;
72 for (auto deletion_id : destroyed_unregistered) {
73 RemoveActor(deletion_id, false);
74 }
75
76 // Invalidate hero actor if it is not alive anymore.
77 if (hero_actors.size() != 0u) {
78 ActorIdSet hero_actors_to_delete;
79 for (auto &hero_actor_info: hero_actors) {
80 if (destroyed_unregistered.find(hero_actor_info.first) != destroyed_unregistered.end()) {
81 hero_actors_to_delete.insert(hero_actor_info.first);
82 }
83 if (destroyed_registered.find(hero_actor_info.first) != destroyed_registered.end()) {
84 hero_actors_to_delete.insert(hero_actor_info.first);
85 }
86 }
87
88 for (auto &deletion_id: hero_actors_to_delete) {
89 hero_actors.erase(deletion_id);
90 }
91 }
92
93 // Scan for new unregistered actors.
94 IdentifyNewActors(world_actors);
95
96 // Update dynamic state and static attributes for all registered vehicles.
97 ALSM::IdleInfo max_idle_time = std::make_pair(0u, current_timestamp.elapsed_seconds);
98 UpdateRegisteredActorsData(hybrid_physics_mode, max_idle_time);
99
100 // Destroy registered vehicle if stuck at a location for too long.
101 if (IsVehicleStuck(max_idle_time.first)
103 && hero_actors.find(max_idle_time.first) == hero_actors.end()) {
104 registered_vehicles.Destroy(max_idle_time.first);
105 RemoveActor(max_idle_time.first, true);
107 }
108
109 // Destorying vehicles for marked for removal by stages.
110 if (parameters.GetOSMMode()) {
111 for (const ActorId& actor_id: marked_for_removal) {
113 RemoveActor(actor_id, true);
114 }
115 marked_for_removal.clear();
116 }
117
118 // Update dynamic state and static attributes for unregistered actors.
120}
121
122void ALSM::IdentifyNewActors(const ActorList &actor_list) {
123 for (auto iter = actor_list->begin(); iter != actor_list->end(); ++iter) {
124 ActorPtr actor = *iter;
125 ActorId actor_id = actor->GetId();
126 // Identify any new hero vehicle
127 if (actor->GetTypeId().front() == 'v') {
128 if (hero_actors.size() == 0u || hero_actors.find(actor_id) == hero_actors.end()) {
129 for (auto&& attribute: actor->GetAttributes()) {
130 if (attribute.GetId() == "role_name" && attribute.GetValue() == "hero") {
131 hero_actors.insert({actor_id, actor});
132 }
133 }
134 }
135 }
136 if (!registered_vehicles.Contains(actor_id)
137 && unregistered_actors.find(actor_id) == unregistered_actors.end()) {
138
139 unregistered_actors.insert({actor_id, actor});
140 }
141 }
142}
143
145
146 ALSM::DestroyeddActors destroyed_actors;
147 ActorIdSet &deleted_registered = destroyed_actors.first;
148 ActorIdSet &deleted_unregistered = destroyed_actors.second;
149
150 // Building hash set of actors present in current frame.
151 ActorIdSet current_actors;
152 for (auto iter = actor_list->begin(); iter != actor_list->end(); ++iter) {
153 current_actors.insert((*iter)->GetId());
154 }
155
156 // Searching for destroyed registered actors.
157 std::vector<ActorId> registered_ids = registered_vehicles.GetIDList();
158 for (const ActorId &actor_id : registered_ids) {
159 if (current_actors.find(actor_id) == current_actors.end()) {
160 deleted_registered.insert(actor_id);
161 }
162 }
163
164 // Searching for destroyed unregistered actors.
165 for (const auto &actor_info: unregistered_actors) {
166 const ActorId &actor_id = actor_info.first;
167 if (current_actors.find(actor_id) == current_actors.end()
168 || registered_vehicles.Contains(actor_id)) {
169 deleted_unregistered.insert(actor_id);
170 }
171 }
172
173 return destroyed_actors;
174}
175
176void ALSM::UpdateRegisteredActorsData(const bool hybrid_physics_mode, ALSM::IdleInfo &max_idle_time) {
177
178 std::vector<ActorPtr> vehicle_list = registered_vehicles.GetList();
179 bool hero_actor_present = hero_actors.size() != 0u;
180 float physics_radius = parameters.GetHybridPhysicsRadius();
181 float physics_radius_square = SQUARE(physics_radius);
182 bool is_respawn_vehicles = parameters.GetRespawnDormantVehicles();
183 if (is_respawn_vehicles && !hero_actor_present) {
185 }
186 // A vehicle can die after the snapshot (destroyed through its handle, or by a map load): drop it, don't throw.
187 std::vector<ActorId> vanished_heroes;
188 std::vector<ActorId> vanished_vehicles;
189 // Update first the information regarding any hero vehicle.
190 for (auto &hero_actor_info: hero_actors){
191 try {
192 if (is_respawn_vehicles) {
193 track_traffic.SetHeroLocation(hero_actor_info.second->GetTransform().location);
194 }
195 UpdateData(hybrid_physics_mode, hero_actor_info.second, hero_actor_present, physics_radius_square);
196 } catch (const std::exception &e) {
197 log_debug("Traffic Manager: dropping hero vehicle", hero_actor_info.first, ":", e.what());
198 vanished_heroes.push_back(hero_actor_info.first);
199 }
200 }
201 // Update information for all other registered vehicles.
202 for (const Actor &vehicle : vehicle_list) {
203 ActorId actor_id = vehicle->GetId();
204 if (hero_actors.find(actor_id) == hero_actors.end()) {
205 try {
206 UpdateData(hybrid_physics_mode, vehicle, hero_actor_present, physics_radius_square);
207 } catch (const std::exception &e) {
208 log_debug("Traffic Manager: dropping vehicle", actor_id, ":", e.what());
209 vanished_vehicles.push_back(actor_id);
210 continue;
211 }
212 UpdateIdleTime(max_idle_time, actor_id);
213 }
214 }
215 for (const ActorId actor_id : vanished_heroes) {
216 RemoveActor(actor_id, false);
217 }
218 for (const ActorId actor_id : vanished_vehicles) {
219 RemoveActor(actor_id, true);
220 }
221}
222
223void ALSM::UpdateData(const bool hybrid_physics_mode, const Actor &vehicle,
224 const bool hero_actor_present, const float physics_radius_square) {
225
226 ActorId actor_id = vehicle->GetId();
227 cg::Transform vehicle_transform = vehicle->GetTransform();
228 cg::Location vehicle_location = vehicle_transform.location;
229 cg::Rotation vehicle_rotation = vehicle_transform.rotation;
230 cg::Vector3D vehicle_velocity = vehicle->GetVelocity();
231 bool state_entry_present = simulation_state.ContainsActor(actor_id);
232
233 // Initializing idle times.
234 if (idle_time.find(actor_id) == idle_time.end() && current_timestamp.elapsed_seconds != 0.0) {
235 idle_time.insert({actor_id, current_timestamp.elapsed_seconds});
236 }
237
238 // Check if current actor is in range of hero actor and enable physics in hybrid mode.
239 bool in_range_of_hero_actor = false;
240 if (hero_actor_present && hybrid_physics_mode) {
241 for (auto &hero_actor_info: hero_actors) {
242 const ActorId &hero_actor_id = hero_actor_info.first;
243 if (simulation_state.ContainsActor(hero_actor_id)) {
244 const cg::Location &hero_location = simulation_state.GetLocation(hero_actor_id);
245 if (cg::Math::DistanceSquared(vehicle_location, hero_location) < physics_radius_square) {
246 in_range_of_hero_actor = true;
247 break;
248 }
249 }
250 }
251 }
252
253 bool enable_physics = hybrid_physics_mode ? in_range_of_hero_actor : true;
254 if (!has_physics_enabled.count(actor_id) || has_physics_enabled[actor_id] != enable_physics) {
255 if (hero_actors.find(actor_id) == hero_actors.end()) {
256 vehicle->SetSimulatePhysics(enable_physics);
257 has_physics_enabled[actor_id] = enable_physics;
258 if (enable_physics == true && state_entry_present) {
259 vehicle->SetTargetVelocity(simulation_state.GetVelocity(actor_id));
260 }
261 }
262 }
263
264 // If physics are disabled, calculate velocity based on change in position.
265 // Do not use 'enable_physics' as turning off the physics in this tick doesn't remove the velocity.
266 // To avoid issues with other clients teleporting the actors, use the previous outpout location.
267 if (state_entry_present && !simulation_state.IsPhysicsEnabled(actor_id)){
268 cg::Location previous_location = simulation_state.GetLocation(actor_id);
269 cg::Location previous_end_location = simulation_state.GetHybridEndLocation(actor_id);
270 cg::Vector3D displacement = (previous_end_location - previous_location);
271 vehicle_velocity = displacement * INV_HYBRID_DT;
272 }
273
274 // Updated kinematic state object.
275 auto vehicle_ptr = std::static_pointer_cast<cc::Vehicle>(vehicle);
276 KinematicState kinematic_state{vehicle_location, vehicle_rotation,
277 vehicle_velocity, vehicle_ptr->GetSpeedLimit(),
278 enable_physics, vehicle->IsDormant(), cg::Location()};
279
280 // Updated traffic light state object.
281 TrafficLightState tl_state = {vehicle_ptr->GetTrafficLightState(), vehicle_ptr->IsAtTrafficLight()};
282
283 // Update simulation state.
284 if (state_entry_present) {
285 simulation_state.UpdateKinematicState(actor_id, kinematic_state);
286 simulation_state.UpdateTrafficLightState(actor_id, tl_state);
287 }
288 else {
289 cg::Vector3D dimensions = vehicle_ptr->GetBoundingBox().extent;
290 StaticAttributes attributes{ActorType::Vehicle, dimensions.x, dimensions.y, dimensions.z};
291
292 // One-time query of the physical steering lock: the motion-plan stage
293 // normalizes steering authority (gains and envelope) by it. Guarded so a
294 // failed RPC (e.g. the actor died this frame) falls back to the default.
295 try {
296 const auto physics_control = vehicle_ptr->GetPhysicsControl();
297 float max_steer_angle = 0.0f;
298 for (const auto &wheel : physics_control.wheels) {
299 max_steer_angle = std::max(max_steer_angle, wheel.max_steer_angle);
300 }
301 if (max_steer_angle > 1.0f) {
302 attributes.max_steer_angle = max_steer_angle;
303 }
304 } catch (const std::exception &) {}
305
306 simulation_state.AddActor(actor_id, kinematic_state, attributes, tl_state);
307 }
308}
309
310
312 for (auto &actor_info: unregistered_actors) {
313
314 const ActorId actor_id = actor_info.first;
315 const ActorPtr actor_ptr = actor_info.second;
316 const std::string type_id = actor_ptr->GetTypeId();
317
318 const cg::Transform actor_transform = actor_ptr->GetTransform();
319 const cg::Location actor_location = actor_transform.location;
320 const cg::Rotation actor_rotation = actor_transform.rotation;
321 const cg::Vector3D actor_velocity = actor_ptr->GetVelocity();
322 const bool actor_is_dormant = actor_ptr->IsDormant();
323 KinematicState kinematic_state {actor_location, actor_rotation, actor_velocity, -1.0f, true, actor_is_dormant, cg::Location()};
324
325 TrafficLightState tl_state;
326 ActorType actor_type = ActorType::Any;
327 cg::Vector3D dimensions;
328 std::vector<SimpleWaypointPtr> nearest_waypoints;
329
330 bool state_entry_not_present = !simulation_state.ContainsActor(actor_id);
331 if (type_id.front() == 'v') {
332 auto vehicle_ptr = std::static_pointer_cast<cc::Vehicle>(actor_ptr);
333 kinematic_state.speed_limit = vehicle_ptr->GetSpeedLimit();
334
335 tl_state = {vehicle_ptr->GetTrafficLightState(), vehicle_ptr->IsAtTrafficLight()};
336
337 if (state_entry_not_present) {
338 dimensions = vehicle_ptr->GetBoundingBox().extent;
339 actor_type = ActorType::Vehicle;
340 StaticAttributes attributes {actor_type, dimensions.x, dimensions.y, dimensions.z};
341
342 simulation_state.AddActor(actor_id, kinematic_state, attributes, tl_state);
343 } else {
344 simulation_state.UpdateKinematicState(actor_id, kinematic_state);
345 simulation_state.UpdateTrafficLightState(actor_id, tl_state);
346 }
347
348 // Identify occupied waypoints.
349 cg::Vector3D extent = vehicle_ptr->GetBoundingBox().extent;
350 cg::Vector3D heading_vector = vehicle_ptr->GetTransform().GetForwardVector();
351 std::vector<cg::Location> corners = {actor_location + cg::Location(extent.x * heading_vector),
352 actor_location,
353 actor_location + cg::Location(-extent.x * heading_vector)};
354 for (cg::Location &vertex: corners) {
355 SimpleWaypointPtr nearest_waypoint = local_map->GetWaypoint(vertex);
356 if (nearest_waypoint != nullptr) {
357 nearest_waypoints.push_back(nearest_waypoint);
358 }
359 }
360 }
361 else if (type_id.front() == 'w') {
362 auto walker_ptr = std::static_pointer_cast<cc::Walker>(actor_ptr);
363
364 if (state_entry_not_present) {
365 dimensions = walker_ptr->GetBoundingBox().extent;
366 actor_type = ActorType::Pedestrian;
367 StaticAttributes attributes {actor_type, dimensions.x, dimensions.y, dimensions.z};
368
369 simulation_state.AddActor(actor_id, kinematic_state, attributes, tl_state);
370 } else {
371 simulation_state.UpdateKinematicState(actor_id, kinematic_state);
372 }
373
374 // Identify occupied waypoints.
375 SimpleWaypointPtr nearest_waypoint = local_map->GetWaypoint(actor_location);
376 if (nearest_waypoint != nullptr) {
377 nearest_waypoints.push_back(nearest_waypoint);
378 }
379 }
380
381 track_traffic.UpdateUnregisteredGridPosition(actor_id, nearest_waypoints);
382 }
383}
384
385void ALSM::UpdateIdleTime(std::pair<ActorId, double>& max_idle_time, const ActorId& actor_id) {
386 if (idle_time.find(actor_id) != idle_time.end()) {
387 double &idle_duration = idle_time.at(actor_id);
389 idle_duration = current_timestamp.elapsed_seconds;
390 }
391
392 // Checking maximum idle time.
393 if (max_idle_time.first == 0u || max_idle_time.second > idle_duration) {
394 max_idle_time = std::make_pair(actor_id, idle_duration);
395 }
396 }
397}
398
399bool ALSM::IsVehicleStuck(const ActorId& actor_id) {
400 if (idle_time.find(actor_id) != idle_time.end()) {
401 double delta_idle_time = current_timestamp.elapsed_seconds - idle_time.at(actor_id);
402 TrafficLightState tl_state = simulation_state.GetTLS(actor_id);
403 if ((delta_idle_time >= RED_TL_BLOCKED_TIME_THRESHOLD)
404 || (delta_idle_time >= BLOCKED_TIME_THRESHOLD && tl_state.tl_state != TLS::Red))
405 {
406 return true;
407 }
408 }
409 return false;
410}
411
412void ALSM::AddActor(const Actor actor) {
413 const ActorId actor_id = actor->GetId();
414 for (auto &&attribute : actor->GetAttributes()) {
415 if (attribute.GetId() != "base_type") {
416 continue;
417 }
418 std::string value = attribute.GetValue();
419 std::transform(
420 value.begin(),
421 value.end(),
422 value.begin(),
423 [](unsigned char c) { return std::tolower(c); });
424 const std::string_view value_view{value};
425 const auto match = std::find(
426 large_vehicle_types.begin(),
428 value_view);
429 if (match != large_vehicle_types.end()) {
430 large_vehicles[actor_id] = std::make_pair(0.0f, false);
431 }
432 // There is at most one "base_type" attribute, so stop scanning once it
433 // has been handled.
434 break;
435 }
436}
437
438void ALSM::RemoveActor(const ActorId actor_id, const bool registered_actor) {
439 if (registered_actor) {
440 registered_vehicles.Remove({actor_id});
441 buffer_map.erase(actor_id);
442 idle_time.erase(actor_id);
448
449 large_vehicles.erase(actor_id);
450 }
451 else {
452 unregistered_actors.erase(actor_id);
453 hero_actors.erase(actor_id);
454 }
455
456 track_traffic.DeleteActor(actor_id);
458}
459
467
468} // namespace traffic_manager
469} // namespace carla
#define SQUARE(a)
This file contains various constants used in traffic manager arranged into sensible namespaces for re...
Definition Constants.h:14
double elapsed_seconds
Simulated seconds elapsed since the beginning of the current episode.
Definition Timestamp.h:33
const Timestamp & GetTimestamp() const
Get timestamp of this snapshot.
SharedPtr< ActorList > GetActors() const
Return a list with all the actors currently present in the world.
Definition World.cpp:126
WorldSnapshot GetSnapshot() const
Return a snapshot of the world at this moment.
Definition World.cpp:114
Euler angles of a rotation in CARLA's / Unreal's left-handed frame: x forward, y right,...
Definition Rotation.h:45
A rigid transform in CARLA's / Unreal's left-handed frame: x forward, y right, z up,...
void AddActor(const Actor actor)
Definition ALSM.cpp:412
const cc::World & world
Definition ALSM.h:58
void IdentifyNewActors(const ActorList &actor_list)
Definition ALSM.cpp:122
void RemoveActor(const ActorId actor_id, const bool registered_actor)
Definition ALSM.cpp:438
AtomicActorSet & registered_vehicles
Definition ALSM.h:46
static constexpr std::array< std::string_view, 2 > large_vehicle_types
Definition ALSM.h:72
std::unordered_map< ActorId, std::pair< float, bool > > & large_vehicles
Definition ALSM.h:70
LocalizationStage & localization_stage
Definition ALSM.h:61
const LocalMapPtr & local_map
Definition ALSM.h:59
std::unordered_map< ActorId, bool > has_physics_enabled
Definition ALSM.h:69
VehicleLightStage & vehicle_light_stage
Definition ALSM.h:65
std::pair< ActorId, double > IdleInfo
Definition ALSM.h:88
bool IsVehicleStuck(const ActorId &actor_id)
Definition ALSM.cpp:399
MotionPlanStage & motion_plan_stage
Definition ALSM.h:64
IdleTimeMap idle_time
Definition ALSM.h:51
std::pair< ActorIdSet, ActorIdSet > DestroyeddActors
Definition ALSM.h:83
CollisionStage & collision_stage
Definition ALSM.h:62
void UpdateData(const bool hybrid_physics_mode, const Actor &vehicle, const bool hero_actor_present, const float physics_radius_square)
Definition ALSM.cpp:223
ActorMap unregistered_actors
Definition ALSM.h:48
cc::Timestamp current_timestamp
Definition ALSM.h:68
const Parameters & parameters
Definition ALSM.h:57
std::vector< ActorId > & marked_for_removal
Definition ALSM.h:56
SimulationState & simulation_state
Definition ALSM.h:60
void UpdateRegisteredActorsData(const bool hybrid_physics_mode, IdleInfo &max_idle_time)
Definition ALSM.cpp:176
BufferMap & buffer_map
Definition ALSM.h:49
ALSM(AtomicActorSet &registered_vehicles, BufferMap &buffer_map, TrackTraffic &track_traffic, std::vector< ActorId > &marked_for_removal, const Parameters &parameters, const cc::World &world, const LocalMapPtr &local_map, SimulationState &simulation_state, std::unordered_map< ActorId, std::pair< float, bool > > &large_vehicles, LocalizationStage &localization_stage, CollisionStage &collision_stage, TrafficLightStage &traffic_light_stage, MotionPlanStage &motion_plan_stage, VehicleLightStage &vehicle_light_stage)
Definition ALSM.cpp:22
TrafficLightStage & traffic_light_stage
Definition ALSM.h:63
void UpdateIdleTime(std::pair< ActorId, double > &max_idle_time, const ActorId &actor_id)
Definition ALSM.cpp:385
TrackTraffic & track_traffic
Definition ALSM.h:54
DestroyeddActors IdentifyDestroyedActors(const ActorList &actor_list)
Definition ALSM.cpp:144
double elapsed_last_actor_destruction
Definition ALSM.h:67
void Remove(std::vector< ActorId > actor_id_list)
std::vector< ActorPtr > GetList()
This class has functionality to detect potential collision with a nearby actor.
void RemoveActor(const ActorId actor_id) override
This class has functionality to maintain a horizon of waypoints ahead of the vehicle for it to follow...
void RemoveActor(const ActorId actor_id) override
void RemoveActor(const ActorId actor_id)
bool GetOSMMode() const
Method to get Open Street Map mode.
float GetHybridPhysicsRadius() const
Method to retrieve hybrid physics radius.
bool GetRespawnDormantVehicles() const
Method to retrieve if we are automatically respawning vehicles.
bool GetHybridPhysicsMode() const
Method to retrieve hybrid physics mode.
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::Location GetHybridEndLocation(const ActorId actor_id) const
void UpdateKinematicState(ActorId actor_id, KinematicState state)
void AddActor(ActorId actor_id, KinematicState kinematic_state, StaticAttributes attributes, TrafficLightState tl_state)
void UpdateTrafficLightState(ActorId actor_id, TrafficLightState state)
cg::Vector3D GetVelocity(const ActorId actor_id) const
bool IsPhysicsEnabled(const ActorId actor_id) const
TrafficLightState GetTLS(const ActorId actor_id) const
void UpdateUnregisteredGridPosition(const ActorId actor_id, const std::vector< SimpleWaypointPtr > waypoints)
void DeleteActor(ActorId actor_id)
Method to delete actor data from tracking.
void SetHeroLocation(const cg::Location location)
This class has functionality for responding to traffic lights and managing entry into non-signalized ...
void RemoveActor(const ActorId actor_id) override
This class has functionality for turning on/off the vehicle lights according to the current vehicle s...
void RemoveActor(const ActorId actor_id) override
std::shared_ptr< InMemoryMap > LocalMapPtr
Definition ALSM.h:38
carla::SharedPtr< cc::Actor > Actor
std::unordered_set< ActorId > ActorIdSet
std::unordered_map< carla::ActorId, Buffer > BufferMap
carla::SharedPtr< cc::ActorList > ActorList
Definition ALSM.h:35
carla::SharedPtr< cc::Actor > ActorPtr
std::shared_ptr< SimpleWaypoint > SimpleWaypointPtr
This file contains definitions of common data structures used in traffic manager.
static void log_debug(Args &&... args)
Definition Logging.h:68
constexpr float SquaredLength() const