17namespace traffic_manager {
33 const float ax{first_location.
x - middle_location.
x};
34 const float ay{first_location.
y - middle_location.
y};
35 const float bx{last_location.
x - middle_location.
x};
36 const float by{last_location.
y - middle_location.
y};
40 const float cross{ax * by - ay * bx};
41 if (std::abs(cross) <= EPSILON) {
42 return std::numeric_limits<float>::max();
44 const float side_a{std::sqrt(ax * ax + ay * ay)};
45 const float side_b{std::sqrt(bx * bx + by * by)};
46 const float side_c{std::sqrt((ax - bx) * (ax - bx) + (ay - by) * (ay - by))};
47 return (side_a * side_b * side_c) / (2.0f * std::abs(cross));
51 const std::vector<cg::Location> &waypoint_locations,
52 float target_distance,
55 if (waypoint_locations.empty()) {
56 return std::make_pair(vehicle_location, 0u);
59 if (waypoint_locations.size() == 1u) {
60 return std::make_pair(waypoint_locations.front(), 0u);
63 const float target_square_distance{target_distance * target_distance};
68 size_t closest_index{0u};
69 size_t farthest_index{0u};
70 bool found_bracket{
false};
71 for (
size_t i = 0u; i < waypoint_locations.size(); ++i) {
72 const float close_dist_square{vehicle_location.
DistanceSquared(waypoint_locations.at(i))};
74 if (close_dist_square < target_square_distance) {
86 const size_t last_index{waypoint_locations.size() - 1u};
87 return std::make_pair(waypoint_locations.at(last_index), last_index);
93 if (closest_index == 0u && farthest_index == 0u) {
97 const cg::Location target_close_location{waypoint_locations.at(closest_index)};
98 const cg::Location target_far_location{waypoint_locations.at(farthest_index)};
99 const float target_close_distance{vehicle_location.
Distance(target_close_location)};
100 const float target_far_distance{vehicle_location.
Distance(target_far_location)};
103 const float span{target_far_distance - target_close_distance};
104 if (std::abs(span) <= EPSILON) {
105 return std::make_pair(target_close_location, closest_index);
108 const float t{(target_distance - target_close_distance) / span};
110 target_close_location.
x + (target_far_location.x - target_close_location.x) * t,
111 target_close_location.y + (target_far_location.y - target_close_location.y) * t,
112 target_close_location.z + (target_far_location.z - target_close_location.z) * t};
114 return std::make_pair(target_location, closest_index);
118 const Buffer &waypoint_buffer,
119 float target_distance,
122 std::vector<cg::Location> locations;
123 locations.reserve(waypoint_buffer.size());
125 locations.emplace_back(waypoint->GetLocation());
131 const std::vector<cg::Location> &path,
132 const float path_start_offset,
133 const float sample_spacing,
134 const float lateral_acceleration,
135 const float braking_deceleration,
136 const float max_speed) {
138 if (path.size() < 3u || sample_spacing <= 0.0f) {
142 float speed_limit = max_speed;
143 std::array<cg::Location, 3> samples{path.front(), path.front(), path.front()};
144 uint32_t sample_count = 1u;
146 float travelled = 0.0f;
147 float next_sample_at = sample_spacing;
150 const float segment = location.
Distance(previous_location);
151 const float segment_start = travelled;
152 travelled += segment;
154 while (segment > EPSILON && travelled >= next_sample_at) {
155 const float fraction = (next_sample_at - segment_start) / segment;
156 samples = {samples[1], samples[2],
157 cg::Location{previous_location.
x + (location.x - previous_location.
x) * fraction,
158 previous_location.
y + (location.y - previous_location.
y) * fraction,
159 previous_location.
z + (location.z - previous_location.
z) * fraction}};
161 const float distance_to_arc =
162 path_start_offset + next_sample_at - 2.0f * sample_spacing;
163 next_sample_at += sample_spacing;
165 if (++sample_count < 3u) {
169 speed_limit = std::min(
171 std::sqrt(radius * lateral_acceleration +
172 2.0f * braking_deceleration * std::max(distance_to_arc, 0.0f)));
174 previous_location = location;
183 float max_offset_point,
184 float inboard_scale) {
186 t = std::clamp(t, 0.0f, 1.0f);
193 if (t < max_offset_point) {
194 const float a{t / max_offset_point};
195 offset = max_offset * 0.5f * (1.0f - std::cos(PI * a));
196 }
else if (t < 1.0f - max_offset_point) {
197 const float a{(t - max_offset_point) / (1.0f - 2.0f * max_offset_point)};
198 offset = max_offset * std::cos(PI * a);
200 const float a{(t - (1.0f - max_offset_point)) / max_offset_point};
201 offset = -max_offset * 0.5f * (1.0f + std::cos(PI * a));
208 offset *= inboard_scale;
214 float vehicle_length,
215 float reference_length,
219 const float scaled{gain * (vehicle_length - reference_length)};
220 return std::clamp(scaled, 0.0f, offset_cap);
227 float offset_magnitude,
228 float lateral_clearance,
229 float longitudinal_window,
230 const std::vector<std::pair<cg::Location, float>> &neighbours) {
232 for (
const auto &[location, radius] : neighbours) {
234 location.
x - ego_location.
x,
235 location.y - ego_location.
y,
237 const float lateral{relative.x * offset_direction.
x + relative.y * offset_direction.
y};
238 const float longitudinal{relative.x * ego_forward.
x + relative.y * ego_forward.
y};
240 const bool on_offset_side{
242 && lateral <= offset_magnitude + lateral_clearance + radius};
243 const bool alongside{std::abs(longitudinal) <= longitudinal_window + radius};
245 if (on_offset_side && alongside) {
static const float EPSILON
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::pair< cg::Location, uint64_t > InterpolateBufferAt(const std::vector< cg::Location > &waypoint_locations, float target_distance, cg::Location vehicle_location)
Locations-only variant of GetTargetData.
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::shared_ptr< SimpleWaypoint > SimpleWaypointPtr
This file contains definitions of common data structures used in traffic manager.
constexpr auto DistanceSquared(Location loc) const
auto Distance(Location loc) const