22namespace traffic_manager {
24using namespace constants::MotionPlan;
25using namespace constants::WaypointSelection;
26using namespace constants::SpeedThreshold;
34 const std::vector<ActorId> &vehicle_id_list,
39 const std::vector<float> &urban_longitudinal_parameters,
40 const std::vector<float> &highway_longitudinal_parameters,
41 const std::vector<float> &urban_lateral_parameters,
42 const std::vector<float> &highway_lateral_parameters,
49 std::unordered_map<
ActorId, std::pair<float, bool>> &large_vehicles)
50 : vehicle_id_list(vehicle_id_list),
51 simulation_state(simulation_state),
52 parameters(parameters),
53 buffer_map(buffer_map),
54 track_traffic(track_traffic),
55 urban_longitudinal_parameters(urban_longitudinal_parameters),
56 highway_longitudinal_parameters(highway_longitudinal_parameters),
57 urban_lateral_parameters(urban_lateral_parameters),
58 highway_lateral_parameters(highway_lateral_parameters),
59 localization_frame(localization_frame),
60 collision_frame(collision_frame),
62 output_array(output_array),
63 random_device(random_device),
65 large_vehicles(large_vehicles) {}
76 const float vehicle_speed = vehicle_velocity.
Length();
83 const bool &tl_hazard =
tl_frame.at(index);
91 bool is_hero_alive = hero_location !=
cg::Location(0, 0, 0);
107 float dilate_factor = (upper_bound-lower_bound)/100.0f;
113 float random_sample = (
static_cast<float>(
random_device.
next())*dilate_factor) + lower_bound;
115 if (!teleport_waypoint_list.empty()) {
116 for (
auto &teleport_waypoint : teleport_waypoint_list) {
117 GeoGridId geogrid_id = teleport_waypoint->GetGeodesicGridId();
119 teleportation_transform = teleport_waypoint->GetTransform();
120 teleportation_transform.
location.
z += 0.5f;
132 vehicle_velocity, vehicle_speed_limit,
144 float max_landmark_target_velocity =
GetLandmarkTargetVelocity(*(waypoint_buffer.at(0)), vehicle_location, actor_id, max_target_velocity);
147 float max_turn_target_velocity =
GetTurnTargetVelocity(waypoint_buffer, vehicle_location, max_target_velocity);
148 max_target_velocity = std::min(std::min(max_target_velocity, max_landmark_target_velocity), max_turn_target_velocity);
151 std::pair<bool, float> collision_response =
CollisionHandling(collision_hazard, tl_hazard, vehicle_velocity,
152 vehicle_heading, max_target_velocity);
153 bool collision_emergency_stop = collision_response.first;
154 float dynamic_target_velocity = collision_response.second;
157 bool safe_after_junction =
SafeAfterJunction(localization, tl_hazard, collision_emergency_stop);
160 bool emergency_stop = tl_hazard || collision_emergency_stop || !safe_after_junction;
179 const cg::Location &pursuit_reference{vehicle_location};
183 float target_point_distance{std::clamp(
189 target_point_distance,
200 0.5f * target_point_distance,
203 waypoint_buffer.front()->GetLocation(),
206 const float sagitta_distance_cap =
208 if (sagitta_distance_cap < target_point_distance) {
209 target_point_distance = std::max(sagitta_distance_cap,
213 target_point_distance,
216 const uint64_t target_index = target_data.second;
227 const float lateral_gain_scale =
236 const float steer_authority_correction{std::clamp(
244 target_waypoint->CheckJunction(),
246 const auto right_vector = target_waypoint->GetTransform().GetRightVector();
250 if (std::abs(base_offset) > EPSILON) {
252 (base_offset > 0.0f) ? right_vector : (-1.0f * right_vector)};
260 offset * right_vector.x,
261 offset * right_vector.y,
263 target_location = target_location + offset_location;
269 const cg::Vector3D target_vector{target_location - pursuit_reference};
270 const float target_yaw{std::atan2(target_vector.y, target_vector.x) * 180.0f / PI};
271 float angular_deviation{target_yaw - vehicle_rotation.
yaw};
272 if (angular_deviation > 180.0f) {
273 angular_deviation -= 360.0f;
274 }
else if (angular_deviation < -180.0f) {
275 angular_deviation += 360.0f;
277 angular_deviation /= 180.0f;
283 if (std::abs(angular_deviation) > 0.25f) {
284 dynamic_target_velocity = std::min(dynamic_target_velocity, 3.0f);
296 using namespace constants::StuckRecovery;
298 const float abs_deviation = std::abs(angular_deviation);
299 bool recovering =
false;
302 if (abs_deviation < ALIGN_EXIT_DEVIATION) {
313 if (now >= rec_it->second.phase_until) {
314 rec_it->second.reversing = !rec_it->second.reversing;
315 rec_it->second.phase_until = now + PHASE_DURATION;
319 if (abs_deviation < 0.5f) {
320 rec_it->second.steer_direction =
321 (angular_deviation > 0.0f) ? 1.0f : -1.0f;
325 if (!recovering && !emergency_stop) {
326 bool stuck_trigger =
false;
327 if (dynamic_target_velocity > STUCK_SPEED && vehicle_speed < STUCK_SPEED) {
329 stuck_trigger = (now - stuck_it->second > STUCK_TIME);
333 const bool misaligned = abs_deviation > ALIGN_ENTER_DEVIATION &&
334 vehicle_speed < MISALIGN_MAX_SPEED;
335 if (stuck_trigger || misaligned) {
337 now + PHASE_DURATION,
true,
338 (angular_deviation > 0.0f) ? 1.0f : -1.0f};
347 recovery_control.
brake = 0.0f;
348 recovery_control.
steer =
366 std::vector<float> longitudinal_parameters;
367 std::vector<float> lateral_parameters;
382 float control_dt =
static_cast<float>(
384 if (control_dt <= 0.0f) {
391 dynamic_target_velocity,
395 reference_velocity, vehicle_speed, dynamic_target_velocity)};
399 current_state = {
current_timestamp, angular_deviation, velocity_deviation, 0.0f};
412 const float wheel_lock_rad{wheel_lock * PI / 180.0f};
413 const float alpha_rad{angular_deviation * PI};
415 2.0f * std::sin(alpha_rad) /
416 std::max(target_point_distance, 1.0f)};
417 const float pursuit_steer{std::atan(wheelbase * pursuit_curvature) /
422 const float lateral_damping_scale{std::min(
423 lateral_gain_scale * steer_authority_correction,
427 actuation_signal =
PID::RunStep(current_state, previous_state,
428 longitudinal_parameters, lateral_parameters,
429 vehicle_speed, control_dt,
431 lateral_damping_scale,
432 steer_authority_correction);
434 if (emergency_stop) {
435 actuation_signal.throttle = 0.0f;
436 actuation_signal.brake = 1.0f;
443 vehicle_control.
throttle = actuation_signal.throttle;
444 vehicle_control.
brake = actuation_signal.brake;
445 vehicle_control.
steer = actuation_signal.steer;
450 current_state.
steer = actuation_signal.steer;
451 current_state.
throttle = actuation_signal.throttle;
452 current_state.
brake = actuation_signal.brake;
454 state = current_state;
475 const float target_displacement = dynamic_target_velocity * HYBRID_MODE_DT_FL;
477 cg::Transform target_base_transform = teleport_target->GetTransform();
480 cg::Vector3D correct_heading = (target_base_location - vehicle_location).MakeUnitVector(EPSILON);
482 if (vehicle_location.
Distance(target_base_location) < target_displacement) {
503 const bool tl_hazard,
504 const bool collision_emergency_stop) {
509 bool safe_after_junction =
true;
510 if (!tl_hazard && !collision_emergency_stop
512 && junction_end_point !=
nullptr && safe_point !=
nullptr
517 cg::Location mid_point = (junction_end_point->GetLocation() + safe_point->GetLocation())/2.0f;
522 std::set_difference(passing_safe_point.begin(), passing_safe_point.end(),
523 passing_junction_end_point.begin(), passing_junction_end_point.end(),
524 std::inserter(difference, difference.begin()));
525 if (difference.size() > 0) {
526 for (
const ActorId &blocking_id: difference) {
530 safe_after_junction =
false;
537 return safe_after_junction;
542 const Buffer &waypoint_buffer,
543 const bool is_target_junction,
544 const uint64_t target_index) {
559 if (large_vehicle.first == 0.0f) {
563 float junction_missing_length{0.0f};
564 for (
unsigned long i = target_index; i < waypoint_buffer.size(); ++i) {
567 if (i > target_index) {
569 const float new_distance = current_waypoint->
Distance(prev_waypoint->GetLocation());
570 junction_missing_length += new_distance;
573 if (!current_waypoint->CheckJunction()) {
578 const float junction_length{large_vehicle.first};
579 const bool turn_flag{large_vehicle.second};
594 const float t{junction_missing_length / junction_length};
602 offset = turn_flag ? offset : -offset;
609 const float offset_magnitude) {
612 if (overlapping_vehicles.empty()) {
616 std::vector<std::pair<cg::Location, float>> neighbours;
617 neighbours.reserve(overlapping_vehicles.size());
618 for (
const ActorId other_id : overlapping_vehicles) {
619 if (other_id == actor_id) {
623 const float radius{std::max(other_dimensions.x, other_dimensions.y)};
629 const float longitudinal_window{
643 const bool tl_hazard,
646 const float max_target_velocity) {
647 bool collision_emergency_stop =
false;
648 float dynamic_target_velocity = max_target_velocity;
649 const float vehicle_speed = vehicle_velocity.
Length();
651 if (collision_hazard.
hazard && !tl_hazard) {
654 const float vehicle_relative_speed = (vehicle_velocity - other_velocity).Length();
657 const float other_speed_along_heading = cg::Math::Dot(other_velocity, vehicle_heading);
661 if (vehicle_relative_speed > EPSILON_RELATIVE_SPEED) {
665 if (available_distance_margin > follow_lead_distance) {
668 dynamic_target_velocity = other_speed_along_heading;
677 collision_emergency_stop =
true;
681 collision_emergency_stop =
true;
686 if (dynamic_target_velocity < vehicle_speed - max_gradual_velocity) {
688 dynamic_target_velocity = vehicle_speed - max_gradual_velocity;
690 dynamic_target_velocity = std::min(max_target_velocity, dynamic_target_velocity);
692 return {collision_emergency_stop, dynamic_target_velocity};
698 float max_target_velocity) {
702 float landmark_target_velocity = std::numeric_limits<float>::max();
704 auto all_landmarks = waypoint.
GetWaypoint()->GetAllLandmarksInDistance(max_distance,
false);
706 for (
auto &landmark: all_landmarks) {
708 auto landmark_location = landmark->GetWaypoint()->GetTransform().location;
709 auto landmark_type = landmark->GetType();
710 auto distance = landmark_location.Distance(vehicle_location);
716 float minimum_velocity = max_target_velocity;
717 if (landmark_type ==
"1000001") {
719 }
else if (landmark_type ==
"206") {
721 }
else if (landmark_type ==
"205") {
723 }
else if (landmark_type ==
"274") {
724 float value =
static_cast<float>(landmark->GetValue()) / 3.6f;
726 minimum_velocity = (value < max_target_velocity) ? value : max_target_velocity;
731 float v = std::max(((max_target_velocity - minimum_velocity) / max_distance) *
distance + minimum_velocity, minimum_velocity);
732 landmark_target_velocity = std::min(landmark_target_velocity, v);
735 return landmark_target_velocity;
740 float max_target_velocity) {
742 if (waypoint_buffer.size() < 3) {
743 return max_target_velocity;
749 std::vector<cg::Location> path;
750 path.reserve(waypoint_buffer.size() + 1u);
751 float path_start_offset = vehicle_location.
Distance(waypoint_buffer.front()->GetLocation());
753 const std::vector<SimpleWaypointPtr> passed_waypoints =
754 waypoint_buffer.front()->GetPreviousWaypoint();
755 if (passed_waypoints.size() == 1u) {
756 path.push_back(passed_waypoints.front()->GetLocation());
757 path_start_offset = -vehicle_location.
Distance(path.front());
759 for (
const auto &waypoint : waypoint_buffer) {
760 path.push_back(waypoint->GetLocation());
765 max_target_velocity);
#define SQUARE(a)
This file contains various constants used in traffic manager arranged into sensible namespaces for re...
double elapsed_seconds
Simulated seconds elapsed since the beginning of the current episode.
Euler angles of a rotation in CARLA's / Unreal's left-handed frame: x forward, y right,...
const LocalMapPtr & local_map
const std::vector< float > urban_longitudinal_parameters
std::unordered_map< ActorId, RecoveryState > recovery_state
cc::Timestamp current_timestamp
const LocalizationFrame & localization_frame
const BufferMap & buffer_map
std::unordered_map< ActorId, double > stuck_since
const CollisionFrame & collision_frame
const std::vector< float > highway_lateral_parameters
std::unordered_map< ActorId, cc::Timestamp > teleportation_instance
TrackTraffic & track_traffic
bool SafeAfterJunction(const LocalizationData &localization, const bool tl_hazard, const bool collision_emergency_stop)
ControlFrame & output_array
RandomGenerator & random_device
void Update(const unsigned long index)
const Parameters & parameters
const std::vector< float > highway_longitudinal_parameters
SimulationState & simulation_state
float CalculateBaseOffset(const ActorId actor_id, const Buffer &waypoint_buffer, const bool is_target_junction, const uint64_t target_index)
const std::vector< ActorId > & vehicle_id_list
float GetLandmarkTargetVelocity(const SimpleWaypoint &waypoint, const cg::Location vehicle_location, const ActorId actor_id, float max_target_velocity)
float GetTurnTargetVelocity(const Buffer &waypoint_buffer, const cg::Location vehicle_location, float max_target_velocity)
std::unordered_map< ActorId, std::pair< float, bool > > & large_vehicles
bool IsWideTurnSideOccupied(const ActorId actor_id, const cg::Vector3D offset_direction, const float offset_magnitude)
Returns true when the lateral band that the wide-turn offset would swing actor_id into is occupied by...
void RemoveActor(const ActorId actor_id)
void SetCycleTimestamp(const cc::Timestamp ×tamp)
Pins one frame for the whole cycle; reading it per vehicle lets a frame land mid-cycle and skews the ...
const std::vector< float > urban_lateral_parameters
std::unordered_map< ActorId, StateEntry > pid_state_map
MotionPlanStage(const std::vector< ActorId > &vehicle_id_list, SimulationState &simulation_state, const Parameters ¶meters, const BufferMap &buffer_map, TrackTraffic &track_traffic, const std::vector< float > &urban_longitudinal_parameters, const std::vector< float > &highway_longitudinal_parameters, const std::vector< float > &urban_lateral_parameters, const std::vector< float > &highway_lateral_parameters, const LocalizationFrame &localization_frame, const CollisionFrame &collision_frame, const TLFrame &tl_frame, ControlFrame &output_array, RandomGenerator &random_device, const LocalMapPtr &local_map, std::unordered_map< ActorId, std::pair< float, bool > > &large_vehicles)
std::pair< bool, float > CollisionHandling(const CollisionHazardData &collision_hazard, const bool tl_hazard, const cg::Vector3D ego_velocity, const cg::Vector3D ego_heading, const float max_target_velocity)
bool GetLargeVehicleWideTurn(const ActorId &actor_id) const
Method to query whether the wide-turn manoeuvre is enabled for a large vehicle (per-vehicle override,...
float GetLaneOffset(const ActorId &actor_id) const
Method to query lane offset for a vehicle.
float GetVehicleTargetVelocity(const ActorId &actor_id, const float speed_limit) const
Method to query target velocity for a vehicle.
float GetUpperBoundaryRespawnDormantVehicles() const
Method to retrieve maximum distance from hero vehicle when respawning vehicles.
float GetLowerBoundaryRespawnDormantVehicles() const
Method to retrieve minimum distance from hero vehicle when respawning vehicles.
bool GetRespawnDormantVehicles() const
Method to retrieve if we are automatically respawning vehicles.
bool GetSynchronousMode() const
Method to get synchronous mode.
This is a simple wrapper class on Carla's waypoint object.
WaypointPtr GetWaypoint() const
Returns a carla::shared_ptr to carla::waypoint.
This class holds the state of all the vehicles in the simlation.
cg::Location GetLocation(const ActorId actor_id) const
void UpdateKinematicHybridEndLocation(ActorId actor_id, cg::Location location)
cg::Vector3D GetHeading(const ActorId actor_id) const
void UpdateKinematicState(ActorId actor_id, KinematicState state)
float GetSpeedLimit(const ActorId actor_id) const
cg::Rotation GetRotation(const ActorId actor_id) const
cg::Vector3D GetVelocity(const ActorId actor_id) const
bool IsPhysicsEnabled(const ActorId actor_id) const
cg::Vector3D GetDimensions(const ActorId actor_id) const
float GetMaxSteerAngle(const ActorId actor_id) const
bool IsDormant(const ActorId actor_id) const
cg::Location GetHeroLocation() const
ActorIdSet GetPassingVehicles(uint64_t waypoint_id) const
ActorIdSet GetOverlappingVehicles(ActorId actor_id) const
bool IsGeoGridFree(const GeoGridId geogrid_id) const
void AddTakenGrid(const GeoGridId geogrid_id, const ActorId actor_id)
ActuationSignal RunStep(StateEntry present_state, StateEntry previous_state, const std::vector< float > &longitudinal_parameters, const std::vector< float > &lateral_parameters, const float vehicle_speed, const float control_dt=DT, const float lateral_pursuit_steer=0.0f, const float lateral_damping_scale=1.0f, const float steer_authority_correction=1.0f)
This function calculates the actuation signals based on the resent state change of the vehicle to min...
float RelativeVelocityDeviation(const float reference_velocity, const float vehicle_speed, const float target_velocity)
The target is exactly zero behind a stopped vehicle; the floor avoids a 0/0 NaN that the derivative t...
float ShapeReferenceVelocity(const float previous_reference, const float vehicle_speed, const float target_velocity, const float control_dt, const bool emergency_stop)
Reference speed that closes on target_velocity at COMFORT_ACCELERATION instead of stepping to it.
void SmoothActuation(const StateEntry &previous_state, const float control_dt, const float vehicle_speed, ActuationSignal &actuation_signal)
A zero pedal demand bypasses the deadband, so pedals rest exactly at zero and nothing here delays a d...
static const float EPSILON
static const double HYBRID_MODE_DT
static const float HYBRID_MODE_DT_FL
static const float LATERAL_COMFORT_ACCELERATION
static const float PERC_MAX_SLOWDOWN
static const float CURVATURE_SAMPLE_SPACING
static const float LANDMARK_DETECTION_TIME
static const float CRITICAL_BRAKING_MARGIN
static const float FOLLOW_LEAD_FACTOR
static const float MAX_JUNCTION_BLOCK_DISTANCE
static const float RELATIVE_APPROACH_SPEED
static const float TL_TARGET_VELOCITY
static const uint16_t ATTEMPTS_TO_TELEPORT
static const float MIN_FOLLOW_LEAD_DISTANCE
static const float STOP_TARGET_VELOCITY
static const float YIELD_TARGET_VELOCITY
static const float TURN_BRAKING_DECELERATION
static const float MAX_STEER_AUTHORITY_CORRECTION
static const float WHEELBASE_FRACTION
static const float REF_MAX_STEER_ANGLE
static const float PURSUIT_CURVATURE_MARGIN
static const float MAX_LATERAL_GAIN_SCALE
static const float REF_VEHICLE_LENGTH
static const float AFTER_JUNCTION_MIN_SPEED
static const float HIGHWAY_SPEED
static const float LARGE_VEHICLES_JUNCTION_OFFSET
static const float LARGE_VEHICLES_JUNCTION_INBOARD_SCALE
static const float LARGE_VEHICLES_JUNCTION_POINT
static const float TARGET_WAYPOINT_TIME_HORIZON
static const float MIN_SAFE_INTERVAL_LENGTH
static const float LARGE_VEHICLES_JUNCTION_OFFSET_GAIN
static const float LARGE_VEHICLES_JUNCTION_REF_LENGTH
static const float MAX_TARGET_WAYPOINT_DISTANCE
static const float MAX_PURSUIT_CHORD_SAGITTA
static const float MIN_TARGET_WAYPOINT_DISTANCE
static const float LARGE_VEHICLES_JUNCTION_SIDE_MARGIN
static const float LARGE_VEHICLES_JUNCTION_CLEARANCE
float LargeVehicleJunctionOffsetProfile(float t, float max_offset, float max_offset_point, float inboard_scale)
Lateral offset profile for the large-vehicle wide turn, as a function of t, the fraction of the junct...
float GetPathSpeedLimit(const std::vector< cg::Location > &path, const float path_start_offset, const float sample_spacing, const float lateral_acceleration, const float braking_deceleration, const float max_speed)
Lowest sqrt(R * lateral_acceleration + 2 * braking_deceleration * distance) over every three consecut...
std::deque< std::shared_ptr< SimpleWaypoint > > Buffer
std::shared_ptr< InMemoryMap > LocalMapPtr
std::unordered_set< ActorId > ActorIdSet
std::unordered_map< carla::ActorId, Buffer > BufferMap
std::vector< SimpleWaypointPtr > NodeList
std::vector< CollisionHazardData > CollisionFrame
std::vector< bool > TLFrame
std::pair< cg::Location, uint64_t > GetTargetData(const Buffer &waypoint_buffer, float target_distance, cg::Location vehicle_location)
Returns the location reached by walking target_distance along the waypoint buffer from vehicle_locati...
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.
bool IsOffsetSideOccupied(cg::Location ego_location, cg::Vector3D ego_forward, cg::Vector3D offset_direction, float offset_magnitude, float lateral_clearance, float longitudinal_window, const std::vector< std::pair< cg::Location, float > > &neighbours)
Returns true when a neighbouring vehicle sits in the lateral band that the wide-turn offset would swi...
float LargeVehicleOffsetMagnitude(float vehicle_length, float reference_length, float gain, float offset_cap)
Wide-turn offset magnitude scaled by vehicle length: clamp(gain * (vehicle_length - reference_length)...
std::vector< carla::rpc::Command > ControlFrame
std::vector< LocalizationData > LocalizationFrame
std::shared_ptr< SimpleWaypoint > SimpleWaypointPtr
This file contains definitions of common data structures used in traffic manager.
auto Distance(Location loc) const
constexpr float SquaredLength() const
Vector3D MakeUnitVector(const float epsilon=2.0f *std::numeric_limits< float >::epsilon()) const
Return a unit-length copy of this vector.
Structure to hold the actuation signals.
float available_distance_margin
SimpleWaypointPtr safe_point
bool is_at_junction_entrance
SimpleWaypointPtr junction_end_point
Structure to hold the controller state.
cc::Timestamp time_instance
float reference_velocity
Zero is a safe initial value: the shaping raises it to the current speed.