Carma-platform v4.2.0
CARMA Platform is built on robot operating system (ROS) and utilizes open source software (OSS) that enables Cooperative Driving Automation (CDA) features to allow Automated Driving Systems to interact and cooperate with infrastructure and other vehicles through communication.
lci_strategic_plugin_algo.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2023 LEIDOS.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
18
20{
21
22#define EPSILON 0.01
23
24double LCIStrategicPlugin::estimate_distance_to_stop(double v, double a) const
25{
26 return (v * v) / (2.0 * a);
27}
28
29double LCIStrategicPlugin::estimate_time_to_stop(double d, double v) const
30{
31 return 2.0 * d / v;
32};
33
34double LCIStrategicPlugin::get_distance_to_accel_or_decel_twice(double free_flow_speed, double current_speed, double departure_speed, double max_accel, double max_decel) const
35{
36 // (v_e^2 - v^2)/ 2a_a + (v_d^2 - v_e^2)/ 2a_d
37 return (std::pow(free_flow_speed, 2) - std::pow(current_speed, 2))/(2 * max_accel) + (std::pow(departure_speed, 2) - std::pow(free_flow_speed, 2))/(2* max_decel);
38}
39
40double LCIStrategicPlugin::get_distance_to_accel_or_decel_once (double current_speed, double departure_speed, double max_accel, double max_decel) const
41{
42 if (current_speed <= departure_speed + epsilon_)
43 {
44 return (std::pow(departure_speed, 2) - std::pow(current_speed, 2))/(2 * max_accel);
45 }
46 else
47 {
48 return (std::pow(departure_speed, 2) - std::pow(current_speed, 2))/(2 * max_decel);
49 }
50}
51
52rclcpp::Time LCIStrategicPlugin::get_eet_or_tbd(const rclcpp::Time& earliest_entry_time, const lanelet::CarmaTrafficSignalPtr& signal) const
53{
54 // If no green signal found after earliest entry time
55 auto start_of_tbd_time = rclcpp::Time((lanelet::time::toSec(signal->recorded_time_stamps.back().first) + EPSILON) * 1e9);
56 if (earliest_entry_time > start_of_tbd_time)
57 {
58 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "Not enough signals are available to check for EET, so returning EET at: " << std::to_string(earliest_entry_time.seconds()));
59 return earliest_entry_time; //return TBD or EET red if no green is found...
60 }
61
62 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "No valid green entry time found, so returning start of TBD at: " << std::to_string(start_of_tbd_time.seconds()));
63 return start_of_tbd_time;
64}
65
66std::optional<rclcpp::Time> LCIStrategicPlugin::get_nearest_green_entry_time(const rclcpp::Time& current_time, const rclcpp::Time& earliest_entry_time, const lanelet::CarmaTrafficSignalPtr& signal, double minimum_required_green_time) const
67{
68 boost::posix_time::time_duration g = lanelet::time::durationFromSec(minimum_required_green_time); // provided by considering min headways of vehicles in front
69 boost::posix_time::ptime t = lanelet::time::timeFromSec(current_time.seconds()); // time variable
70 boost::posix_time::ptime eet = lanelet::time::timeFromSec(earliest_entry_time.seconds()); // earliest entry time
71
72 // check if the signal even has a green signal
73 bool has_green_signal = false;
74 for (auto pair : signal->recorded_time_stamps)
75 {
76 if (pair.second == lanelet::CarmaTrafficSignalState::PROTECTED_MOVEMENT_ALLOWED &&
77 t <= pair.first )
78 {
79 has_green_signal = true;
80 break;
81 }
82 }
83
84 if (!has_green_signal)
85 {
86 return std::nullopt;
87 }
88
89 auto curr_pair = signal->predictState(t);
90 if (!curr_pair)
91 throw std::invalid_argument("Traffic signal with id:" + std::to_string(signal->id()) + ", does not have any recorded time stamps!");
92
93 boost::posix_time::time_duration theta = curr_pair.get().first - t; // remaining time left in this state
94 auto p = curr_pair.get().second;
95 while ( 0.0 < g.total_milliseconds() || p != lanelet::CarmaTrafficSignalState::PROTECTED_MOVEMENT_ALLOWED) //green
96 {
97 if ( p == lanelet::CarmaTrafficSignalState::PROTECTED_MOVEMENT_ALLOWED)
98 {
99 if (g < theta)
100 {
101 t = t + g;
102 theta = theta - g;
103 g = boost::posix_time::seconds(0);
104 }
105 else
106 {
107 t = t + theta;
108 g = g - theta;
109 curr_pair = signal->predictState(t + boost::posix_time::milliseconds(20)); // select next phase
110 p = curr_pair.get().second;
111 theta = curr_pair.get().first - t;
112 }
113 }
114 else
115 {
116 t = t + theta;
117 curr_pair = signal->predictState(t + boost::posix_time::milliseconds(20)); // select next phase
118 p = curr_pair.get().second;
119 theta = curr_pair.get().first - t;
120 }
121 }
122
123 if (t <= eet)
124 {
125 double cycle_duration = signal->fixed_cycle_duration.total_milliseconds()/1000.0;
126 if (cycle_duration < 0.001) //if it is a dynamic traffic signal not fixed
127 cycle_duration = lanelet::time::toSec(signal->recorded_time_stamps.back().first) - lanelet::time::toSec(signal->recorded_start_time_stamps.front());
128
129 t = t + lanelet::time::durationFromSec(std::floor((eet - t).total_milliseconds()/1000.0/cycle_duration) * cycle_duration); //fancy logic was needed to compile
130 curr_pair = signal->predictState(t + boost::posix_time::milliseconds(20)); // select next phase
131 p = curr_pair.get().second;
132 theta = curr_pair.get().first - t;
133 while ( t < eet || p != lanelet::CarmaTrafficSignalState::PROTECTED_MOVEMENT_ALLOWED)
134 {
135 if ( p == lanelet::CarmaTrafficSignalState::PROTECTED_MOVEMENT_ALLOWED && eet - t < theta)
136 {
137 t = eet;
138 theta = theta - (eet - t);
139 }
140 else
141 {
142 t = t + theta;
143 curr_pair = signal->predictState(t + boost::posix_time::milliseconds(20)); // select next phase
144 p = curr_pair.get().second;
145 theta = curr_pair.get().first - t;
146 }
147
148 if (t != lanelet::time::timeFromSec(lanelet::time::INFINITY_END_TIME_FOR_NOT_ENOUGH_STATES))
149 continue;
150
151 // if no green signal left in the signal states, return
152 return std::nullopt;
153 }
154 }
155 return rclcpp::Time(lanelet::time::toSec(t) * 1e9);
156}
157
158double LCIStrategicPlugin::get_trajectory_smoothing_activation_distance(double time_remaining_at_free_flow, double full_cycle_duration, double current_speed, double speed_limit, double departure_speed, double max_accel, double max_decel) const
159{
160 // TSMO USE CASE 2: Figure 7. Trajectory smoothing solution Case 2. Subsituted a+ as max_accel and solved for inflection_speed
161 double accel_ratio = max_accel / max_decel;
162 double remaining_time = time_remaining_at_free_flow - full_cycle_duration / 2;
163 double inflection_speed = (max_accel * remaining_time - accel_ratio * departure_speed + current_speed)/ (1 - accel_ratio);
164 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "ENTER TRAJ CALC: time_remaining_at_free_flow: " << time_remaining_at_free_flow << ", full_cycle_duration: " << full_cycle_duration << ", inflection_speed: " << inflection_speed);
165
166 if (remaining_time < 0)
167 return -1;
168
169 if (inflection_speed > 0 && inflection_speed <= speed_limit + epsilon_ && inflection_speed >= departure_speed - epsilon_)
170 {
171 // kinematic equation to find distance of acceleration + deceleration
172 // (vf^2 - vi^2)/2a = d
173 double d = (std::pow(inflection_speed, 2) - std::pow (current_speed, 2)) / (2 * max_accel) + (std::pow(departure_speed, 2) - std::pow(inflection_speed, 2)) / (2 * max_decel);
174 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "calculated distance WITHOUT cruising: " << d);
175 return d;
176 }
177 else //there must be cruising
178 {
179 // acceleration and deceleration parts must reach maximum speed
180 // kinematic equation: t = (vf - vi)/ a where vf = 0
181 double decel_time = (current_speed - speed_limit) / max_decel;
182 double accel_time = (speed_limit - current_speed) / max_accel;
183 double cruising_time = remaining_time - decel_time - accel_time;
184 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "decel_time: " << decel_time << ", accel_time: " << accel_time << ", cruising_time: " << cruising_time);
185 double d = (std::pow(speed_limit, 2) - std::pow (current_speed, 2)) / (2 * max_accel) + (std::pow(departure_speed, 2) - std::pow(speed_limit, 2)) / (2 * max_decel) + cruising_time * speed_limit;
186 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "calculated distance with cruising: " << d << ", accel_seg: " << (std::pow(speed_limit, 2) - std::pow (current_speed, 2)) / (2 * max_accel) <<
187 ", cruising: " << + cruising_time * speed_limit << ", decel_seg:" << (std::pow(departure_speed, 2) - std::pow(speed_limit, 2)) / (2 * max_decel));
188 return d;
189 }
190}
191
192rclcpp::Duration LCIStrategicPlugin::get_earliest_entry_time(double remaining_distance, double free_flow_speed, double current_speed, double departure_speed, double max_accel, double max_decel) const
193{
194 double x = remaining_distance;
195 double x2 = get_distance_to_accel_or_decel_once(current_speed, departure_speed, max_accel, max_decel);
196 double x1 = get_distance_to_accel_or_decel_twice(free_flow_speed, current_speed, departure_speed, max_accel, max_decel);
197 double v_hat = get_inflection_speed_value(x, x1, x2, free_flow_speed, current_speed, departure_speed, max_accel, max_decel);
198
199 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "x: " << x << ", x2: " << x2 << ", x1: " << x1 << ", v_hat: " << v_hat);
200
201 if (v_hat <= config_.algo_minimum_speed - epsilon_ || isnan(v_hat))
202 {
203 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "Detected that v_hat is smaller than allowed!!!: " << v_hat);
205 }
206
207 if (v_hat >= free_flow_speed + epsilon_)
208 {
209 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "Detected that v_hat is Bigger than allowed!!!: " << v_hat);
210 v_hat = free_flow_speed;
211 }
212
213 rclcpp::Duration t_accel(0,0);
214 if ( x < x2 && current_speed > departure_speed)
215 {
216 t_accel = rclcpp::Duration(0.0);
217 }
218 else
219 {
220 t_accel = rclcpp::Duration(std::max((v_hat - current_speed) / max_accel, 0.0) * 1e9);
221 }
222 rclcpp::Duration t_decel(0,0);
223 if ( x < x2 && current_speed < departure_speed)
224 {
225 t_decel = rclcpp::Duration(0.0);
226 }
227 else
228 {
229 if (x < x2)
230 {
231 t_decel = rclcpp::Duration(std::max((v_hat - current_speed) / max_decel, 0.0) * 1e9);
232
233 }
234 else
235 {
236 t_decel = rclcpp::Duration(std::max((departure_speed - v_hat) / max_decel, 0.0) * 1e9);
237 }
238 }
239
240 rclcpp::Duration t_cruise(0,0);
241 if (x1 <= x)
242 {
243 t_cruise = rclcpp::Duration(std::max((x - x1)/v_hat, 0.0) * 1e9);
244 }
245 else
246 {
247 t_cruise = rclcpp::Duration(0.0);
248 }
249 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "t_accel: " << t_accel.seconds() << ", t_cruise: " << t_cruise.seconds() << ", t_decel: " << t_decel.seconds());
250 return t_accel + t_cruise + t_decel;
251
252}
253
254std::tuple<rclcpp::Time, bool, bool> LCIStrategicPlugin::get_final_entry_time_and_conditions(const VehicleState& current_state, const rclcpp::Time& earliest_entry_time, lanelet::CarmaTrafficSignalPtr traffic_light)
255{
256 rclcpp::Time nearest_green_entry_time = rclcpp::Time(0);
257 bool is_entry_time_within_green_or_tbd = false;
258 bool in_tbd = true;
259
261 {
262 auto nearest_green_entry_time_optional = get_nearest_green_entry_time(current_state.stamp, earliest_entry_time, traffic_light);
263 is_entry_time_within_green_or_tbd = true;
264
265 if (!nearest_green_entry_time_optional)
266 {
267 nearest_green_entry_time = get_eet_or_tbd(earliest_entry_time, traffic_light);
268 }
269 else
270 {
271 in_tbd = false;
272 nearest_green_entry_time = nearest_green_entry_time_optional.value() + rclcpp::Duration(EPSILON * 1e9); //0.01sec more buffer since green_light algorithm's timestamp picks the previous signal - Vehicle Estimation
273 }
274 }
276 {
277 nearest_green_entry_time = rclcpp::Time(std::max(earliest_entry_time.seconds(), (scheduled_enter_time_)/1000.0) * 1e9) + rclcpp::Duration(EPSILON * 1e9); //Carma Street
278
279 // check if scheduled_enter_time_ is inside the available states interval
280 size_t i = 0;
281
282
283 for (auto pair : traffic_light->recorded_time_stamps)
284 {
285 if (lanelet::time::timeFromSec(nearest_green_entry_time.seconds()) < pair.first)
286 {
287 if (pair.second == lanelet::CarmaTrafficSignalState::PROTECTED_MOVEMENT_ALLOWED)
288 {
289 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "ET is inside the GREEN phase! where starting time: " << std::to_string(lanelet::time::toSec(traffic_light->recorded_start_time_stamps[i]))
290 << ", ending time of that green signal is: " << std::to_string(lanelet::time::toSec(pair.first)));
291 is_entry_time_within_green_or_tbd = true;
292 }
293 else
294 {
295 RCLCPP_ERROR_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "Vehicle should plan cruise and stop as ET is inside the RED or YELLOW phase! where starting time: " << std::to_string(lanelet::time::toSec(traffic_light->recorded_start_time_stamps[i]))
296 << ", ending time of that green signal is: " << std::to_string(lanelet::time::toSec(pair.first)));
297 is_entry_time_within_green_or_tbd = false;
298 }
299
300 in_tbd = false;
301 break;
302 }
303 i++;
304 }
305
306 if (in_tbd)
307 {
308 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "ET is inside TBD phase! where starting time: " << std::to_string(lanelet::time::toSec(traffic_light->recorded_time_stamps.back().first)));
309 is_entry_time_within_green_or_tbd = true;
310 }
311
312 }
313 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "nearest_green_entry_time: " << nearest_green_entry_time.get_clock_type());
314 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "current_state.stamp: " << current_state.stamp.get_clock_type());
315
316 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "nearest_green_entry_time: " << std::to_string(nearest_green_entry_time.seconds()) << ", with : " << std::to_string((nearest_green_entry_time - current_state.stamp).seconds()) << " seconds left at: " << std::to_string(current_state.stamp.seconds()));
317
319 { // always pick later of buffered green entry time, or earliest entry time
320 nearest_green_entry_time = rclcpp::Time(std::max(nearest_green_entry_time.seconds(), nearest_green_entry_time_cached_.get().seconds()) * 1e9);
321 }
322
323 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "After accounting for cached - nearest_green_entry_time: " << std::to_string(nearest_green_entry_time.seconds()) << ", with : " << std::to_string((nearest_green_entry_time - current_state.stamp).seconds()) << " seconds left at: " << std::to_string(current_state.stamp.seconds()));
324
325 if (!nearest_green_entry_time_cached_ && is_entry_time_within_green_or_tbd)
326 {
327 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "Applying green_light_buffer for the first time and caching! nearest_green_entry_time (without buffer):" << std::to_string(nearest_green_entry_time.seconds()) << ", and earliest_entry_time: " << std::to_string(earliest_entry_time.seconds()));
328 // save first calculated nearest_green_entry_time + buffer to compare against in the future as nearest_green_entry_time changes with earliest_entry_time
329
330 // check if it needs buffer below:
331 rclcpp::Time early_arrival_time_green_et =
332 nearest_green_entry_time - rclcpp::Duration(config_.green_light_time_buffer * 1e9);
333
334 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "early_arrival_time_green_et: " << std::to_string(early_arrival_time_green_et.seconds()));
335
336 auto early_arrival_state_green_et_optional = traffic_light->predictState(lanelet::time::timeFromSec(early_arrival_time_green_et.seconds()));
337
338 if (!validLightState(early_arrival_state_green_et_optional, early_arrival_time_green_et))
339 {
340 RCLCPP_ERROR_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "Unable to resolve give signal...");
341 return std::make_tuple(rclcpp::Time(0), is_entry_time_within_green_or_tbd, in_tbd);
342 }
343
344 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "early_arrival_state_green_et: " << early_arrival_state_green_et_optional.get().second);
345
346 bool can_make_early_arrival = (early_arrival_state_green_et_optional.get().second == lanelet::CarmaTrafficSignalState::PROTECTED_MOVEMENT_ALLOWED);
347
348 // nearest_green_entry_time is by definition on green, so only check early_arrival
349 if (can_make_early_arrival) // Green light with Certainty
350 {
351 nearest_green_entry_time_cached_ = nearest_green_entry_time; //don't apply buffer if ET is in green
352 }
353 else //buffer is needed
354 {
355 // below logic stores correct buffered timestamp into nearest_green_entry_time_cached_ to be used later
356
357 rclcpp::Time nearest_green_signal_start_time = rclcpp::Time(0);
358 if (traffic_light->fixed_cycle_duration.total_milliseconds()/1000.0 > 1.0) // UC2
359 {
360 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "UC2 Handling");
361 auto normal_arrival_state_green_et_optional = traffic_light->predictState(lanelet::time::timeFromSec(nearest_green_entry_time.seconds()));
362
363 if (!validLightState(normal_arrival_state_green_et_optional, nearest_green_entry_time))
364 {
365 RCLCPP_ERROR_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "Unable to resolve give signal...");
366 return std::make_tuple(rclcpp::Time(0), is_entry_time_within_green_or_tbd, in_tbd);
367 }
368
369 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "normal_arrival_signal_end_time: " << std::to_string(lanelet::time::toSec(normal_arrival_state_green_et_optional.get().first)));
370
371 // nearest_green_signal_start_time = normal_arrival_signal_end_time (green guaranteed) - green_signal_duration
372 nearest_green_signal_start_time = rclcpp::Time(lanelet::time::toSec(normal_arrival_state_green_et_optional.get().first - traffic_light->signal_durations[lanelet::CarmaTrafficSignalState::PROTECTED_MOVEMENT_ALLOWED]) * 1e9);
373 }
374 else // UC3
375 {
376 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "UC3 Handling");
377
378 for (size_t i = 0; i < traffic_light->recorded_start_time_stamps.size(); i++)
379 {
380 if (traffic_light->recorded_time_stamps[i].second == lanelet::CarmaTrafficSignalState::PROTECTED_MOVEMENT_ALLOWED &&
381 lanelet::time::timeFromSec(nearest_green_entry_time.seconds()) < traffic_light->recorded_time_stamps[i].first ) // Make sure it is in correct GREEN phase there are multiple
382 {
383 nearest_green_signal_start_time = rclcpp::Time(lanelet::time::toSec(traffic_light->recorded_start_time_stamps[i]) * 1e9);
384 break;
385 }
386 }
387
388 if (nearest_green_signal_start_time == rclcpp::Time(0)) //in tdb
389 {
390 nearest_green_signal_start_time = rclcpp::Time(lanelet::time::toSec(traffic_light->recorded_time_stamps.back().first) * 1e9);
391 }
392 }
393
394 // If ET is within green or TBD, it should always aim for at least minimum of "start_time of green or tdb + green_buffer" for safety
395
396 nearest_green_entry_time_cached_ = nearest_green_signal_start_time + rclcpp::Duration((config_.green_light_time_buffer + EPSILON) * 1e9);
397
398 // EPSILON=0.01 is there because if predictState's input exactly falls on ending_time it picks the previous state.
399 //For example, if 0 - 10s is GREEN, and 10 - 12s is YELLOW, checking exactly 10.0s will return GREEN,
400 //but 10.01s will return YELLOW. This 0.01 convention is used throughout the file, so thought it is better
401 //to keep it consistent and probably too detailed for the user to think about, which is why it is not included in the buffer.
402 //Actually including in the buffer doesn't work because it uses that same buffer to check early and late. If buffer is 2s and
403 //green starts at 10s, it will check +/-2s from 12s. If the buffer was 2.01s and green starts at 10s again, it checks +/-2.01
404 //from 12.01, so both checks 10s.
405
406 }
407
408 nearest_green_entry_time = rclcpp::Time(std::max(nearest_green_entry_time.seconds(), nearest_green_entry_time_cached_.get().seconds()) * 1e9);
409 }
410
411 if (nearest_green_entry_time_cached_ && nearest_green_entry_time > nearest_green_entry_time_cached_.get())
412 {
413 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "Earliest entry time... has gone past the cashed entering time. nearest_green_entry_time_cached_ (which can also be TBD):" << std::to_string(nearest_green_entry_time_cached_.get().seconds()) << ", and earliest_entry_time: " << std::to_string(earliest_entry_time.seconds()));
414 }
415 return std::make_tuple(nearest_green_entry_time, is_entry_time_within_green_or_tbd, in_tbd);
416}
417
418double LCIStrategicPlugin::get_inflection_speed_value(double x, double x1, double x2, double free_flow_speed, double current_speed, double departure_speed, double max_accel, double max_decel) const
419{
420 if (x >= x1)
421 {
422 return free_flow_speed;
423 }
424 else if (x1 > x && x >= x2)
425 {
426 return std::sqrt((2 * x * max_accel * max_decel + max_decel * std::pow(current_speed, 2) - max_accel * (std::pow(departure_speed, 2)))/(max_decel - max_accel));
427 }
428 else if (x2 > x)
429 {
430 if (current_speed <= departure_speed)
431 {
432 return std::sqrt(2 * x * max_accel + std::pow(current_speed, 2));
433 }
434 else
435 {
436 return std::sqrt(2 * x * max_decel + std::pow(current_speed, 2));
437 }
438 }
439
440}
441
442double LCIStrategicPlugin::calc_estimated_entry_time_left(double entry_dist, double current_speed, double departure_speed) const
443{
444 double t_entry = 0;
445 // t = 2 * d / (v_i + v_f)
446 // from TSMO USE CASE 2 Algorithm Doc - Figure 4. Equation: Estimation of t*_nt
447 t_entry = 2*entry_dist/(current_speed + departure_speed);
448 return t_entry;
449}
450
452BoundaryDistances LCIStrategicPlugin::get_delta_x(double v0, double v1, double v_max, double v_min, double a_max, double a_min)
453{
454 BoundaryDistances distances;
455
456 distances.dx1 = ((pow(v_max, 2) - pow(v0, 2)) / (2 * a_max)) + ((pow(v1, 2) - pow(v_max, 2)) / (2 * a_min));
457 if (v1 > v0)
458 distances.dx2 = ((pow(v1, 2) - pow(v0, 2)) / (2 * a_max));
459 else
460 distances.dx2 = ((pow(v1, 2) - pow(v0, 2)) / (2 * a_min));
461
462 distances.dx3 = ((pow(v_min, 2) - pow(v0, 2)) / (2 * a_min)) + ((pow(v1, 2) - pow(v_min, 2)) / (2 * a_max));
463 distances.dx4 = ((pow(v_min, 2) - pow(v0, 2)) / (2 * a_min));
464 distances.dx5 = - pow(v0, 2) / (2 * a_min);
465
466 return distances;
467}
468
470{
471 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "\n");
472 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "t0: " << std::to_string(params.t0_));
473 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "v0: " << params.v0_);
474 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "x0: " << params.x0_);
475
476 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "t1: " << std::to_string(params.t1_));
477 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "v1: " << params.v1_);
478 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "x1: " << params.x1_);
479 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "a1: " << params.a1_);
480
481 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "t2: " << std::to_string(params.t2_));
482 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "v2: " << params.v2_);
483 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "x2: " << params.x2_);
484 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "a2: " << params.a2_);
485
486 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "t3: " << std::to_string(params.t3_));
487 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "v3: " << params.v3_);
488 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "x3: " << params.x3_);
489 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "a3: " << params.a3_);
490
491 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "\n");
492}
493
495{
496 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "\n");
497 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "dx1: " << delta_xs.dx1);
498 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "dx2: " << delta_xs.dx2);
499 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "dx3: " << delta_xs.dx3);
500 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "dx4: " << delta_xs.dx4);
501 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "dx5: " << delta_xs.dx5 << "\n");
502}
503
504std::vector<TrajectoryParams> LCIStrategicPlugin::get_boundary_traj_params(double t, double v0, double v1, double v_max, double v_min, double a_max, double a_min, double x0, double x_end, double dx, BoundaryDistances boundary_distances)
505{
506 double dx1 = boundary_distances.dx1;
507 double dx2 = boundary_distances.dx2;
508 double dx3 = boundary_distances.dx3;
509 double dx4 = boundary_distances.dx4;
510 double dx5 = boundary_distances.dx5;
511 TrajectoryParams traj1, traj2, traj3, traj4, traj5, traj6, traj7, traj8;
512
513 // t1, t2, t3
514 if (dx < dx2)
515 {
516 traj1 = boundary_accel_or_decel_incomplete_upper(t, v0, v1, a_max, a_min, x0, x_end, dx);
517 traj2 = traj1;
518 traj3 = traj1;
519 }
520 else if (dx < dx1)
521 {
522 traj1 = boundary_accel_nocruise_notmaxspeed_decel(t, v0, v1, a_max, a_min, x0, x_end, dx);
523 traj2 = traj1;
524 traj3 = boundary_accel_or_decel_complete_upper(t, v0, v1, x0, x_end, dx);
525 }
526 else
527 {
528 traj1 = boundary_accel_cruise_maxspeed_decel(t, v0, v1, v_max, a_max, a_min, x0, x_end, dx);
529 traj2 = boundary_accel_nocruise_maxspeed_decel(t, v0, v1, v_max, a_max, a_min, x0, x_end, dx);
530 traj3 = boundary_accel_or_decel_complete_upper(t, v0, v1, x0, x_end, dx);
531 }
532 // t4, t5, t6, t7
533 if (dx < dx4)
534 {
535 traj4 = traj1;
536 traj5 = traj1;
537 traj6 = boundary_decel_incomplete_lower(t, v0, a_min, x0, x_end, dx);
538 traj7 = traj6;
539 }
540 else if (dx < dx3)
541 {
542 if (dx < dx2)
543 {
544 traj4 = traj1;
545 }
546 else
547 {
548 traj4 = boundary_decel_nocruise_notminspeed_accel(t, v0, v1, v_min, a_max, a_min, x0, x_end, dx);
549 }
550 traj5 = traj4;
551 traj6 = boundary_decel_nocruise_minspeed_accel_incomplete(t, v0, v_min, a_max, a_min, x0, x_end, dx);
552 traj7 = boundary_decel_cruise_minspeed(t, v0, v_min, a_min, x0, x_end, dx);
553
554 }
555 else
556 {
557 traj4 = boundary_decel_nocruise_minspeed_accel_complete(t, v0, v1, v_max, v_min, a_max, a_min, x0, x_end, dx);
558 traj5 = boundary_decel_cruise_minspeed_accel(t, v0, v1, v_min, a_max, a_min, x0, x_end, dx);
559 traj6 = traj5;
560 traj7 = boundary_decel_cruise_minspeed(t, v0, v_min, a_min, x0, x_end, dx);
561 }
562 // t8
563 if (dx < dx4)
564 {
565 traj8 = traj6;
566 }
567 else if (dx < dx5)
568 {
569 traj8 = boundary_decel_incomplete_lower(t, v0, a_min, x0, x_end, dx);
570 }
571 else
572 {
573 traj8 = boundary_decel_cruise_minspeed_decel(t, v0, v_min, a_min, x0, x_end, dx);
574 }
575
576 return {traj1, traj2, traj3, traj4, traj5, traj6, traj7, traj8};
577}
578
579TrajectoryParams LCIStrategicPlugin::get_ts_case(double t, double et, double v0, double v1, double v_max, double v_min, double a_max, double a_min, double x0, double x_end, double dx, BoundaryDistances boundary_distances, std::vector<TrajectoryParams> params)
580{
581 double dx1 = boundary_distances.dx1;
582 double dx2 = boundary_distances.dx2;
583 double dx3 = boundary_distances.dx3;
584 double dx4 = boundary_distances.dx4;
585 double dx5 = boundary_distances.dx5;
586
587 if (params.size() != 8)
588 {
589 throw std::invalid_argument("Not enough trajectory paras given! Given size: " + std::to_string(params.size()));
590 }
591
592 TrajectoryParams traj1 = params[0];
593 TrajectoryParams traj2 = params[1];
594 TrajectoryParams traj3 = params[2];
595 TrajectoryParams traj4 = params[3];
596 TrajectoryParams traj5 = params[4];
597 TrajectoryParams traj6 = params[5];
598 TrajectoryParams traj7 = params[6];
599 TrajectoryParams traj8 = params[7];
600 TrajectoryParams veh_traj;
601 veh_traj.is_algorithm_successful = true;
602
603 if (traj1.t3_ <= et && et < traj2.t3_)
604 {
605 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "CALCULATED: case 1");
606 veh_traj = ts_case1(t, et, v0, v1, v_max, a_max, a_min, x0, x_end, dx);
607 veh_traj.case_num = CASE_1;
608 }
609 else if (traj2.t3_ <= et && et < traj3.t3_)
610 {
611 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "CALCULATED: case 2");
612 veh_traj = ts_case2(t, et, v0, v1, a_max, a_min, x0, x_end, dx);
613 veh_traj.case_num = CASE_2;
614 }
615 else if (traj3.t3_ <= et && et < traj4.t3_)
616 {
617 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "CALCULATED: case 3");
618 veh_traj = ts_case3(t, et, v0, v1, a_max, a_min, x0, x_end, dx);
619 veh_traj.case_num = CASE_3;
620 }
621 else if (traj4.t3_ <= et && et < traj5.t3_)
622 {
623 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "CALCULATED: case 4");
624 veh_traj = ts_case4(t, et, v0, v1, v_min, a_max, a_min, x0, x_end, dx);
625 veh_traj.case_num = CASE_4;
626 }
627 else if (traj5.t3_ <= et && et < traj6.t3_)
628 {
629 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "CALCULATED: case 5");
630 veh_traj = ts_case5(t, et, v0, a_max, a_min, x0, x_end, dx);
631 veh_traj.case_num = CASE_5;
632 }
633 else if (traj6.t3_ <= et && et < traj7.t3_)
634 {
635 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "CALCULATED: case 6");
636 veh_traj = ts_case6(t, et, v0, v_min, a_min, x0, x_end, dx, dx3, traj6);
637 veh_traj.case_num = CASE_6;
638 }
639 else if (traj7.t3_ <= et && et <= traj8.t3_)
640 {
641 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "CALCULATED: case 7");
642 veh_traj = ts_case7(t, et, v0, v_min, a_min, x0, x_end, dx);
643 veh_traj.case_num = CASE_7;
644 }
645 else
646 {
647 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "CALCULATED: case 8");
648 veh_traj = ts_case8(dx, dx5, traj8);
649 veh_traj.case_num = CASE_8;
650 }
651
652 return veh_traj;
653}
654
655
656TrajectoryParams LCIStrategicPlugin::ts_case1(double t, double et, double v0, double v1, double v_max, double a_max, double a_min, double x0, double x_end, double dx)
657{
658 TrajectoryParams traj;
659
660 traj.t0_ = t;
661 traj.v0_ = v0;
662 traj.x0_ = x0;
663
664 double dt = et - t;
665 double nom1 = 2 * dx * (((1 - (a_max / a_min)) * v_max) + ((a_max / a_min) * v1) - v0);
666 double nom2 = dt * (((1 - (a_max / a_min)) * pow(v_max, 2)) + ((a_max / a_min) * pow(v1, 2)) - pow(v0, 2));
667 double den = pow(v_max - v0, 2) - ((a_max / a_min) * pow(v_max - v1, 2));
668
669 if (den <= epsilon_ && den >= -epsilon_)
670 throw std::invalid_argument("CASE1: Received den near zero..." + std::to_string(den));
671
672 double tc = (nom1 - nom2) / den;
673
674 traj.v1_ = v_max;
675
676 if (dt - tc <= epsilon_ && dt - tc >= -epsilon_)
677 throw std::invalid_argument("CASE1: Received dt - tc near zero..." + std::to_string(dt - tc));
678
679 traj.a1_ = (((1 - (a_max / a_min)) * v_max) + ((a_max / a_min) * v1) - v0) / (dt - tc);
680
681 if (traj.a1_ <= accel_epsilon_ && traj.a1_ >= -accel_epsilon_)
682 {
683 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "CASE1: Received traj.a1_ near zero...");
684 traj.t1_ = traj.t0_ + ((dt - tc) * (a_max / (a_min + a_max)));
685 traj.x1_ = traj.x0_ + (v_max * (traj.t1_ - traj.t0_));
686 }
687 else
688 {
689 traj.t1_ = traj.t0_ + ((traj.v1_ - traj.v0_) / traj.a1_);
690 traj.x1_ = traj.x0_ + ((pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * traj.a1_));
691 }
692 traj.a2_ = 0;
693 traj.v2_ = v_max;
694 traj.t2_ = traj.t1_ + tc;
695 traj.x2_ = traj.x1_ + (v_max * tc);
696
697 traj.t3_ = et;
698 traj.a3_ = traj.a1_ * (a_min / a_max);
699 traj.v3_ = v1;
700 traj.x3_ = x_end;
701
702 return traj;
703
704}
705TrajectoryParams LCIStrategicPlugin::ts_case2(double t, double et, double v0, double v1, double a_max, double a_min, double x0, double x_end, double dx)
706{
707 TrajectoryParams traj;
708
709 traj.t0_ = t;
710 traj.v0_ = v0;
711 traj.x0_ = x0;
712
713 double dt = et - t;
714
715 if (dt <= epsilon_ && dt >= -epsilon_)
716 throw std::invalid_argument("CASE2: Received dt near zero..." + std::to_string(dt));
717
718 double sqr1 = pow(1 - (a_max / a_min), 2) * pow(dx / dt, 2);
719 double sqr2 = (1 - (a_max / a_min)) * (((a_max / a_min) * v1 * (v1 - (2 * dx / dt))) + (v0 * ((2 * dx / dt) - v0)));
720 double v_hat = (dx / dt) + (sqrt(sqr1 - sqr2) / (1 - (a_max / a_min)));
721
722 traj.v1_ = v_hat;
723 traj.a1_ = (((1 - (a_max / a_min)) * v_hat) + ((a_max / a_min) * v1) - v0) / dt;
724
725 if (traj.a1_ <= accel_epsilon_ && traj.a1_ >= -accel_epsilon_)
726 {
727 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "CASE2: Received traj.a1_ near zero...");
728 traj.t1_ = traj.t0_ + (dt * (a_max / (a_min + a_max)));
729 traj.x1_ = traj.x0_ + (v_hat * (traj.t1_ - traj.t0_));
730 }
731 else
732 {
733 traj.t1_ = traj.t0_ + ((traj.v1_ - traj.v0_) / traj.a1_);
734 traj.x1_ = traj.x0_ + ((pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * traj.a1_));
735 }
736
737 traj.v2_ = v1;
738 traj.a2_ = traj.a1_ * a_min / a_max;
739
740 if (traj.a2_ <= accel_epsilon_ && traj.a2_ >= -accel_epsilon_)
741 {
742 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "CASE2: Received traj.a2_ near zero...");
743 traj.t2_ = traj.t1_ + (dt * (a_min / (a_min + a_max)));
744 traj.x2_ = traj.x1_ + (v_hat * (traj.t2_ - traj.t1_));
745 }
746 else
747 {
748 traj.t2_ = traj.t1_ + ((traj.v2_ - traj.v1_) / traj.a2_);
749 traj.x2_ = x_end;
750 }
751
752 traj.t3_ = traj.t2_;
753 traj.a3_ = 0;
754 traj.v3_ = traj.v2_;
755 traj.x3_ = traj.x2_;
756
757 return traj;
758}
759TrajectoryParams LCIStrategicPlugin::ts_case3(double t, double et, double v0, double v1, double a_max, double a_min, double x0, double x_end, double dx)
760{
761 TrajectoryParams traj;
762
763 traj.t0_ = t;
764 traj.v0_ = v0;
765 traj.x0_ = x0;
766
767 double dt = et - t;
768
769 if (dt <= epsilon_ && dt >= -epsilon_)
770 throw std::invalid_argument("CASE3: Received dt near zero..." + std::to_string(dt));
771
772 double sqr1 = pow((a_max / a_min) - 1, 2) * pow(dx / dt, 2);
773 double sqr2 = ((a_max / a_min) - 1) * ((v1 * (v1 - (2 * dx / dt))) + ((a_max / a_min) * v0 * ((2 * dx / dt) - v0)));
774 double v_hat = (dx / dt) + (sqrt(sqr1 - sqr2) / ((a_max / a_min) - 1));
775
776 traj.v1_ = v_hat;
777 traj.a1_ = (((1 - (a_min / a_max)) * v_hat) + ((a_min / a_max) * v1) - v0) / dt;
778
779 if (traj.a1_ <= accel_epsilon_ && traj.a1_ >= -accel_epsilon_)
780 {
781 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "CASE3: Received traj.a1_ near zero...");
782 traj.t1_ = traj.t0_ + (dt * (a_max / (a_min + a_max)));
783 traj.x1_ = traj.x0_ + (v_hat * (traj.t1_ - traj.t0_));
784 }
785 else
786 {
787 traj.t1_ = traj.t0_ + ((traj.v1_ - traj.v0_) / traj.a1_);
788 traj.x1_ = traj.x0_ + ((pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * traj.a1_));
789 }
790
791 traj.v2_ = v1;
792 traj.a2_ = traj.a1_ * a_max / a_min;
793 traj.t2_ = traj.t1_ + ((traj.v2_ - traj.v1_) / traj.a2_);
794 traj.x2_ = x_end;
795
796 traj.t3_ = traj.t2_;
797 traj.a3_ = 0;
798 traj.v3_ = traj.v2_;
799 traj.x3_ = traj.x2_;
800
801 return traj;
802}
803TrajectoryParams LCIStrategicPlugin::ts_case4(double t, double et, double v0, double v1, double v_min, double a_max, double a_min, double x0, double x_end, double dx)
804{
805 TrajectoryParams traj;
806
807 traj.t0_ = t;
808 traj.v0_ = v0;
809 traj.x0_ = x0;
810
811 double dt = et - t;
812 double nom1 = 2 * dx * ((((a_max / a_min) - 1) * v_min) + v1 - ((a_max / a_min) * v0));
813 double nom2 = dt * ((((a_max / a_min) - 1) * pow(v_min, 2)) + pow(v1, 2) - ((a_max / a_min) * pow(v0, 2)));
814 double den = ((a_max / a_min) * pow(v_min - v0, 2)) - pow(v_min - v1, 2);
815
816 if (den <= epsilon_ && den >= -epsilon_)
817 throw std::invalid_argument("CASE4: Received den near zero..." + std::to_string(den));
818
819 double tc = (nom1 - nom2) / den;
820
821 traj.v1_ = v_min;
822
823 if (dt - tc <= epsilon_ && dt - tc >= -epsilon_)
824 throw std::invalid_argument("CASE4: Received dt - tc near zero..." + std::to_string(dt - tc));
825
826 traj.a1_ = (((1 - (a_min / a_max)) * v_min) + ((a_min / a_max) * v1) - v0) / (dt - tc);
827
828 if (traj.a1_ <= accel_epsilon_ && traj.a1_ >= -accel_epsilon_)
829 {
830 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "CASE4: Received traj.a1_ near zero...");
831 traj.t1_ = traj.t0_ + ((dt - tc) * (a_min / (a_min + a_max)));
832 traj.x1_ = traj.x0_ + (v_min * (traj.t1_ - traj.t0_));
833 }
834 else
835 {
836 traj.t1_ = traj.t0_ + ((traj.v1_ - traj.v0_) / traj.a1_);
837 traj.x1_ = traj.x0_ + ((pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * traj.a1_));
838 }
839
840 traj.v2_ = v_min;
841 traj.a2_ = 0;
842 traj.t2_ = traj.t1_ + tc;
843 traj.x2_ = traj.x1_ + (v_min * tc);
844
845 traj.t3_ = et;
846 traj.a3_ = traj.a1_ * a_max / a_min;
847 traj.v3_ = v1;
848 traj.x3_ = x_end;
849
850 return traj;
851}
852
853TrajectoryParams LCIStrategicPlugin::ts_case5(double t, double et, double v0, double a_max, double a_min, double x0, double x_end, double dx)
854{
855 TrajectoryParams traj;
856
857 traj.t0_ = t;
858 traj.v0_ = v0;
859 traj.x0_ = x0;
860
861 double dt = et - t;
862 double sqr = ((a_max / a_min) - 1) * ((2 * a_min * (dx - (v0 * dt))) - pow(a_min * dt, 2));
863 double v_hat = (v0 + (a_min * dt)) - (sqrt(sqr) / ((a_max / a_min) - 1));
864 double v_p = ((1 - (a_max / a_min)) * v_hat) + ((a_max / a_min) * v0) + (a_max * dt);
865
866 traj.v1_ = v_hat;
867 traj.a1_ = a_min;
868
869 traj.t1_ = traj.t0_ + ((traj.v1_ - traj.v0_) / traj.a1_);
870 traj.x1_ = traj.x0_ + ((pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * traj.a1_));
871
872 traj.v2_ = v_p;
873 traj.a2_ = a_max;
874 traj.t2_ = traj.t1_ + ((traj.v2_ - traj.v1_) / traj.a2_);
875 traj.x2_ = x_end;
876
877 traj.t3_ = traj.t2_;
878 traj.a3_ = 0;
879 traj.v3_ = traj.v2_;
880 traj.x3_ = traj.x2_;
881
882 return traj;
883}
884
885TrajectoryParams LCIStrategicPlugin::ts_case6(double t, double et, double v0, double v_min, double a_min, double x0, double x_end, double dx, double dx3, TrajectoryParams traj6)
886{
887 TrajectoryParams traj;
888
889 traj.t0_ = t;
890 traj.v0_ = v0;
891 traj.x0_ = x0;
892
893 double dt = et - t;
894
895 traj.v1_ = v_min;
896 traj.a1_ = a_min;
897 traj.t1_ = traj.t0_ + ((traj.v1_ - traj.v0_) / traj.a1_);
898 traj.x1_ = traj.x0_ + ((pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * traj.a1_));
899
900 double tc;
901
902 if (dx <= dx3)
903 tc = 0;
904 else
905 tc = traj6.t2_ - traj6.t1_;
906
907 traj.v2_ = v_min;
908 traj.a2_ = 0;
909 traj.t2_ = traj.t1_ + tc;
910 traj.x2_ = traj.x1_ + (v_min * tc);
911
912 double dt_p = dt - (traj.t1_ - traj.t0_) - tc;
913
914 if (dt_p <= epsilon_ && dt_p >= -epsilon_)
915 throw std::invalid_argument("CASE6: Received dt_p near zero..." + std::to_string(dt_p));
916
917 double v_p = ((2 * a_min * (dx - (v_min * tc))) - (pow(v_min, 2) - pow(v0, 2)) - (v_min * dt_p * a_min)) / (dt_p * a_min);
918
919 traj.v3_ = v_p;
920 traj.a3_ = (v_p - v_min) / dt_p;
921 traj.t3_ = et;
922 traj.x3_ = x_end;
923
924 return traj;
925}
926
927TrajectoryParams LCIStrategicPlugin::ts_case7(double t, double et, double v0, double v_min, double a_min, double x0, double x_end, double dx)
928{
929 TrajectoryParams traj;
930
931 traj.t0_ = t;
932 traj.v0_ = v0;
933 traj.x0_ = x0;
934
935 traj.v1_ = v_min;
936 traj.a1_ = a_min;
937 traj.t1_ = traj.t0_ + ((traj.v1_ - traj.v0_) / traj.a1_);
938 traj.x1_ = traj.x0_ + ((pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * traj.a1_));
939
940 double dt = et - t;
941 double v_p = v_min - sqrt(pow(v_min - v0, 2) - (2 * a_min * ((v_min * dt) - dx)));
942 double dt_p = (v_p - v_min) / a_min;
943
944 if (dt_p <= epsilon_ && dt_p >= -epsilon_)
945 throw std::invalid_argument("CASE7: Received dt_p near zero..." + std::to_string(dt_p));
946
947 double tc = dt - ((v_p - v0) / a_min);
948
949 traj.v2_ = v_min;
950 traj.a2_ = 0;
951 traj.t2_ = traj.t1_ + tc;
952 traj.x2_ = traj.x1_ + (v_min * tc);
953
954 traj.v3_ = v_p;
955 traj.a3_ = (v_p - v_min) / dt_p;
956 traj.t3_ = et;
957 traj.x3_ = x_end;
958
959 return traj;
960}
961
963{
964 TrajectoryParams traj = traj8;
965 if (dx < dx5)
966 {
967 traj.is_algorithm_successful = false;
968 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "CASE8: Not within safe stopping distance originally planned!");
969 }
970 return traj;
971}
972
973
974TrajectoryParams LCIStrategicPlugin::boundary_accel_or_decel_incomplete_upper(double t, double v0, double v1, double a_max, double a_min, double x0, double x_end, double dx)
975{
976 double t_end;
977
978 if (v0 <= v1 + epsilon_)
979 t_end = t + (sqrt(pow(v0, 2) + (2 * a_max * dx)) - v0)/a_max;
980 else
981 t_end = t + (sqrt(pow(v0, 2) + (2 * a_min * dx)) - v0) / a_min;
982
983 TrajectoryParams traj;
984
985 traj.t0_ = t;
986 traj.v0_ = v0;
987 traj.x0_ = x0;
988
989 traj.t1_ = t_end;
990
991 if (v0 <= v1 + epsilon_)
992 {
993 traj.a1_ = a_max;
994 traj.v1_ = sqrt(pow(v0, 2) + (2 * a_max * dx));
995 }
996 else
997 {
998 traj.a1_ = a_min;
999 traj.v1_ = sqrt(pow(v0, 2) + (2 * a_min * dx));
1000 }
1001
1002 traj.x1_ = x_end;
1003
1004 traj.t2_ = traj.t1_;
1005 traj.a2_ = 0;
1006 traj.v2_ = traj.v1_;
1007 traj.x2_ = traj.x1_;
1008
1009 traj.t3_ = traj.t1_;
1010 traj.a3_ = 0;
1011 traj.v3_ = traj.v1_;
1012 traj.x3_ = traj.x1_;
1013
1014 return traj;
1015}
1016
1017TrajectoryParams LCIStrategicPlugin::boundary_accel_nocruise_notmaxspeed_decel(double t, double v0, double v1, double a_max, double a_min, double x0, double x_end, double dx)
1018{
1019
1020 double v_hat = sqrt(((2 * dx * a_max * a_min) + (a_min * pow(v0, 2)) - (a_max * pow(v1, 2))) / (a_min - a_max));
1021 double t_end = t + ((v_hat * (a_min - a_max)) - (v0 * a_min) + (v1 * a_max)) / (a_max * a_min);
1022
1023 TrajectoryParams traj;
1024
1025 traj.t0_ = t;
1026 traj.v0_ = v0;
1027 traj.x0_ = x0;
1028
1029 traj.v1_ = v_hat;
1030 traj.a1_ = a_max;
1031 traj.t1_ = traj.t0_ + ((traj.v1_ - traj.v0_) / traj.a1_);
1032
1033 traj.x1_ = traj.x0_ + ((pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * traj.a1_));
1034
1035 traj.t2_ = t_end;
1036 traj.a2_ = a_min;
1037 traj.v2_ = v1;
1038 traj.x2_ = x_end;
1039
1040 traj.t3_ = traj.t2_;
1041 traj.a3_ = 0;
1042 traj.v3_ = traj.v2_;
1043 traj.x3_ = traj.x2_;
1044
1045 return traj;
1046
1047}
1048
1049TrajectoryParams LCIStrategicPlugin::boundary_accel_cruise_maxspeed_decel(double t, double v0, double v1, double v_max, double a_max, double a_min, double x0, double x_end, double dx)
1050{
1051 double t_end = t + (dx / v_max) + (pow(v_max - v0, 2) / (2 * a_max * v_max)) - (pow(v1 - v_max, 2) / (2 * a_min * v_max));
1052
1053 TrajectoryParams traj;
1054
1055 traj.t0_ = t;
1056 traj.v0_ = v0;
1057 traj.x0_ = x0;
1058
1059 traj.v1_ = v_max;
1060 traj.a1_ = a_max;
1061 traj.t1_ = traj.t0_ + ((traj.v1_ - traj.v0_) / traj.a1_);
1062 traj.x1_ = traj.x0_ + ((pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * traj.a1_));
1063
1064 traj.v2_ = v_max;
1065 traj.a2_ = 0;
1066 traj.t2_ = t_end - ((v1 - v_max) / a_min);
1067 traj.x2_ = x_end - ((pow(v1, 2) - pow(v_max, 2)) / (2 * a_min));
1068
1069 traj.t3_ = t_end;
1070 traj.a3_ = a_min;
1071 traj.v3_ = v1;
1072 traj.x3_ = x_end;
1073
1074 return traj;
1075}
1076
1077TrajectoryParams LCIStrategicPlugin::boundary_accel_nocruise_maxspeed_decel(double t, double v0, double v1, double v_max, double a_max, double a_min, double x0, double x_end, double dx)
1078{
1079 double nom = (v_max - v0) + ((a_max / a_min) * (v1 - v_max));
1080 double den = (pow(v_max, 2) - pow(v0, 2)) + ((a_max / a_min) * (pow(v1, 2) - pow(v_max, 2)));
1081
1082 if (den <= epsilon_ && den >= -epsilon_)
1083 throw std::invalid_argument("boundary_accel_nocruise_maxspeed_decel: Received den near zero..." + std::to_string(den));
1084
1085 double t_end = t + (2 * dx * nom / den);
1086
1087 TrajectoryParams traj;
1088
1089 traj.t0_ = t;
1090 traj.v0_ = v0;
1091 traj.x0_ = x0;
1092
1093 double dt = t_end - t;
1094 double tc = 0;
1095
1096 traj.v1_ = v_max;
1097
1098 if (dt - tc <= epsilon_ && dt - tc >= -epsilon_)
1099 throw std::invalid_argument("boundary_accel_nocruise_maxspeed_decel: Received dt - tc near zero..." + std::to_string(dt - tc));
1100
1101 traj.a1_ = (((1 - (a_max / a_min)) * v_max) + ((a_max / a_min) * v1) - v0) / (dt - tc);
1102
1103 if (traj.a1_ <= accel_epsilon_ && traj.a1_ >= -accel_epsilon_)
1104 {
1105 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("lci_strategic_plugin"), "boundary_accel_nocruise_maxspeed_decel: Received traj.a1_ near zero...");
1106 traj.t1_ = traj.t0_ + (dt * (a_max / (a_min + a_max)));
1107 traj.x1_ = traj.x0_ + (v_max * (traj.t1_ - traj.t0_));
1108 }
1109 else
1110 {
1111 traj.t1_ = traj.t0_ + ((traj.v1_ - traj.v0_) / traj.a1_);
1112 traj.x1_ = traj.x0_ + ((pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * traj.a1_));
1113 }
1114
1115 traj.t2_ = t_end;
1116 traj.a2_ = ((((a_min / a_max) - 1) * v_max) + v1 - ((a_min / a_max) * v0)) / (dt - tc);
1117 traj.v2_ = v1;
1118 traj.x2_ = x_end;
1119
1120 traj.t3_ = traj.t2_;
1121 traj.a3_ = 0;
1122 traj.v3_ = traj.v2_;
1123 traj.x3_ = traj.x2_;
1124
1125 return traj;
1126}
1127
1128TrajectoryParams LCIStrategicPlugin::boundary_accel_or_decel_complete_upper(double t, double v0, double v1, double x0, double x_end, double dx)
1129{
1130 if (v0 + v1 <= epsilon_ && v0 + v1 >= -epsilon_)
1131 throw std::invalid_argument("boundary_accel_or_decel_complete_upper: Received v0 + v1 near zero..." + std::to_string(v0 + v1));
1132
1133 double t_end = t + ((2 * dx) / (v0 + v1));
1134
1135 TrajectoryParams traj;
1136
1137 traj.t0_ = t;
1138 traj.v0_ = v0;
1139 traj.x0_ = x0;
1140
1141 traj.t1_ = t_end;
1142
1143 if (dx <= epsilon_ && dx >= -epsilon_)
1144 throw std::invalid_argument("boundary_accel_or_decel_complete_upper: Received dx near zero..." + std::to_string(dx));
1145
1146 traj.a1_ = (pow(v1, 2) - pow(v0, 2)) / (2 * dx);
1147 traj.v1_ = v1;
1148 traj.x1_ = x_end;
1149
1150 traj.t2_ = traj.t1_;
1151 traj.a2_ = 0;
1152 traj.v2_ = traj.v1_;
1153 traj.x2_ = traj.x1_;
1154
1155 traj.t3_ = traj.t1_;
1156 traj.a3_ = 0;
1157 traj.v3_ = traj.v1_;
1158 traj.x3_ = traj.x1_;
1159
1160 return traj;
1161}
1162
1163TrajectoryParams LCIStrategicPlugin::boundary_decel_nocruise_notminspeed_accel(double t, double v0, double v1, double v_min, double a_max, double a_min, double x0, double x_end, double dx)
1164{
1165 double v_hat = sqrt(((2 * dx * a_max * a_min) + (a_max * pow(v0, 2)) - (a_min * pow(v1, 2))) / (a_max - a_min));
1166 double t_end = t + ((v_hat * (a_max - a_min)) - (v0 * a_max) + (v1 * a_min)) / (a_max * a_min);
1167
1168 TrajectoryParams traj;
1169
1170 traj.t0_ = t;
1171 traj.v0_ = v0;
1172 traj.x0_ = x0;
1173
1174 traj.v1_ = v_hat;
1175 traj.a1_ = a_min;
1176 traj.t1_ = traj.t0_ + ((traj.v1_ - traj.v0_) / traj.a1_);
1177 traj.x1_ = traj.x0_ + ((pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * traj.a1_));
1178
1179 traj.t2_ = t_end;
1180 traj.a2_ = a_max;
1181 traj.v2_ = v1;
1182 traj.x2_ = x_end;
1183
1184 traj.t3_ = traj.t2_;
1185 traj.a3_ = 0;
1186 traj.v3_ = traj.v2_;
1187 traj.x3_ = traj.x2_;
1188
1189 return traj;
1190}
1191
1192TrajectoryParams LCIStrategicPlugin::boundary_decel_nocruise_minspeed_accel_incomplete(double t, double v0, double v_min, double a_max, double a_min, double x0, double x_end, double dx)
1193{
1194 double sqr = sqrt((2 * a_max * dx) - ((pow(v_min, 2) - pow(v0, 2)) * (a_max / a_min)) + pow(v_min, 2));
1195
1196 double t_end = t + ((sqr - v_min) / a_max) + ((v_min - v0) / a_min);
1197
1198 TrajectoryParams traj;
1199
1200 traj.t0_ = t;
1201 traj.v0_ = v0;
1202 traj.x0_ = x0;
1203
1204 traj.v1_ = v_min;
1205 traj.a1_ = a_min;
1206 traj.t1_ = traj.t0_ + (traj.v1_ - traj.v0_) / a_min;
1207 traj.x1_ = traj.x0_ + (pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * a_min);
1208
1209 traj.t2_ = t_end;
1210 traj.a2_ = a_max;
1211 traj.v2_ = (traj.a2_ * (traj.t2_ - traj.t1_)) + traj.v1_;
1212 traj.x2_ = x_end;
1213
1214 traj.t3_ = traj.t2_;
1215 traj.a3_ = 0;
1216 traj.v3_ = traj.v2_;
1217 traj.x3_ = traj.x2_;
1218
1219 return traj;
1220}
1221
1222TrajectoryParams LCIStrategicPlugin::boundary_decel_nocruise_minspeed_accel_complete(double t, double v0, double v1, double v_max, double v_min, double a_max, double a_min, double x0, double x_end, double dx)
1223{
1224 double nom = (v1 - v_min) + ((a_max / a_min) * (v_min - v0));
1225 double den = (pow(v1, 2) - pow(v_min, 2)) + ((a_max / a_min) * (pow(v_min, 2) - pow(v0, 2)));
1226
1227 if (den <= epsilon_ && den >= -epsilon_)
1228 throw std::invalid_argument("boundary_decel_nocruise_minspeed_accel_complete: Received den near zero..." + std::to_string(den));
1229
1230 double t_end = t + (2 * dx * nom / den);
1231 TrajectoryParams traj;
1232
1233 traj.t0_ = t;
1234 traj.v0_ = v0;
1235 traj.x0_ = x0;
1236
1237 double dt = t_end - t;
1238 double tc = 0;
1239
1240 traj.v1_ = v_min;
1241
1242 if (dt - tc <= epsilon_ && dt - tc >= -epsilon_)
1243 throw std::invalid_argument("boundary_decel_nocruise_minspeed_accel_complete: Received dt - tc near zero..." + std::to_string(dt - tc));
1244
1245 traj.a1_ = (((1 - (a_min / a_max)) * v_min) + ((a_min / a_max) * v1) - v0) / (dt - tc);
1246 traj.t1_ = traj.t0_ + ((traj.v1_ - traj.v0_) / traj.a1_);
1247 traj.x1_ = traj.x0_ + ((pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * traj.a1_));
1248
1249 traj.t2_ = t_end;
1250 traj.a2_ = ((((a_max / a_min) - 1) * v_min) + v1 - ((a_max / a_min) * v0)) / (dt - tc);
1251 traj.v2_ = v1;
1252 traj.x2_ = x_end;
1253
1254 traj.t3_ = traj.t2_;
1255 traj.a3_ = 0;
1256 traj.v3_ = traj.v2_;
1257 traj.x3_ = traj.x2_;
1258
1259 return traj;
1260}
1261TrajectoryParams LCIStrategicPlugin::boundary_decel_cruise_minspeed_accel(double t, double v0, double v1, double v_min, double a_max, double a_min, double x0, double x_end, double dx)
1262{
1263 double t_end = t + (dx / v_min) + ((pow(v_min - v0, 2)) / (2 * a_min * v_min)) - ((pow(v1 - v_min, 2)) / (2 * a_max * v_min));
1264
1265 TrajectoryParams traj;
1266
1267 traj.t0_ = t;
1268 traj.v0_ = v0;
1269 traj.x0_ = x0;
1270
1271 traj.v1_ = v_min;
1272 traj.a1_ = a_min;
1273 traj.t1_ = traj.t0_ + ((traj.v1_ - traj.v0_) / traj.a1_);
1274 traj.x1_ = traj.x0_ + ((pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * traj.a1_));
1275
1276 traj.v2_ = v_min;
1277 traj.a2_ = 0;
1278 traj.t2_ = t_end - ((v1 - v_min) / a_max);
1279 traj.x2_ = x_end - ((pow(v1, 2) - pow(v_min, 2)) / (2 * a_max));
1280
1281 traj.t3_ = t_end;
1282 traj.a3_ = a_max;
1283 traj.v3_ = v1;
1284 traj.x3_ = x_end;
1285
1286 return traj;
1287}
1288
1289TrajectoryParams LCIStrategicPlugin::boundary_decel_cruise_minspeed(double t, double v0, double v_min, double a_min, double x0, double x_end, double dx)
1290{
1291 double t_end = t + (dx / v_min) + (pow(v_min - v0, 2) / (2 * a_min * v_min));
1292
1293 TrajectoryParams traj;
1294
1295 traj.t0_ = t;
1296 traj.v0_ = v0;
1297 traj.x0_ = x0;
1298
1299 traj.v1_ = v_min;
1300 traj.a1_ = a_min;
1301 traj.t1_ = traj.t0_ + ((traj.v1_ - traj.v0_) / traj.a1_);
1302 traj.x1_ = traj.x0_ + ((pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * traj.a1_));
1303
1304 traj.v2_ = v_min;
1305 traj.a2_ = 0;
1306 traj.t2_ = t_end;
1307 traj.x2_ = x_end;
1308
1309 traj.t3_ = traj.t2_;
1310 traj.a3_ = traj.a2_;
1311 traj.v3_ = traj.v2_;
1312 traj.x3_ = traj.x2_;
1313
1314 return traj;
1315}
1316TrajectoryParams LCIStrategicPlugin::boundary_decel_incomplete_lower(double t, double v0, double a_min, double x0, double x_end, double dx)
1317{
1318 double t_end = t + (sqrt(pow(v0, 2) + (2 * a_min * dx)) - v0) / a_min;
1319
1320 TrajectoryParams traj;
1321
1322 traj.t0_ = t;
1323 traj.v0_ = v0;
1324 traj.x0_ = x0;
1325
1326 traj.t1_ = t_end;
1327 traj.v1_ = sqrt(pow(v0, 2) + (2 * a_min * dx));
1328 traj.a1_ = a_min;
1329 traj.x1_ = x_end;
1330
1331 traj.t2_ = traj.t1_;
1332 traj.a2_ = 0;
1333 traj.v2_ = traj.v1_;
1334 traj.x2_ = traj.x1_;
1335
1336 traj.t3_ = traj.t1_;
1337 traj.a3_ = 0;
1338 traj.v3_ = traj.v1_;
1339 traj.x3_ = traj.x1_;
1340
1341 return traj;
1342}
1343TrajectoryParams LCIStrategicPlugin::boundary_decel_cruise_minspeed_decel(double t, double v0, double v_min, double a_min, double x0, double x_end, double dx)
1344{
1345 double t_end = t + (dx / v_min) + (v0 * (v0 - (2 * v_min)) / (2 * a_min * v_min));
1346
1347 TrajectoryParams traj;
1348
1349 traj.t0_ = t;
1350 traj.v0_ = v0;
1351 traj.x0_ = x0;
1352
1353 traj.v1_ = v_min;
1354 traj.a1_ = a_min;
1355 traj.t1_ = traj.t0_ + ((traj.v1_ - traj.v0_) / traj.a1_);
1356 traj.x1_ = traj.x0_ + ((pow(traj.v1_, 2) - pow(traj.v0_, 2)) / (2 * traj.a1_));
1357
1358 traj.a2_ = 0;
1359 traj.v2_ = v_min;
1360 traj.t2_ = t_end - ((0 - traj.v2_) / a_min);
1361 traj.x2_ = x_end - ((0 - pow(traj.v2_, 2)) / (2 * a_min));
1362
1363 traj.t3_ = t_end;
1364 traj.a3_ = a_min;
1365 traj.v3_ = 0;
1366 traj.x3_ = x_end;
1367
1368 return traj;
1369}
1370
1371
1373} // namespace lci_strategic_plugin
TrajectoryParams boundary_decel_nocruise_notminspeed_accel(double t, double v0, double v1, double v_min, double a_max, double a_min, double x0, double x_end, double dx)
TrajectoryParams boundary_decel_cruise_minspeed_decel(double t, double v0, double v_min, double a_min, double x0, double x_end, double dx)
LCIStrategicPluginConfig config_
Config containing configurable algorithm parameters.
BoundaryDistances get_delta_x(double v0, double v1, double v_max, double v_min, double a_max, double a_min)
Get boundary distances used to compare against current state in order to create trajectory smoothing ...
double get_distance_to_accel_or_decel_twice(double free_flow_speed, double current_speed, double departure_speed, double max_accel, double max_decel) const
Get required distance to accel then decel, or vise versa - each at least once - to reach departure_sp...
rclcpp::Time get_eet_or_tbd(const rclcpp::Time &earliest_entry_time, const lanelet::CarmaTrafficSignalPtr &signal) const
Returns the later of earliest_entry_time or the end of the available signal states in the traffic_sig...
double estimate_time_to_stop(double d, double v) const
Helper method to use basic kinematics to compute an estimated stopping time from from the inputs.
bool validLightState(const boost::optional< std::pair< boost::posix_time::ptime, lanelet::CarmaTrafficSignalState > > &optional_state, const rclcpp::Time &source_time) const
Helper method that checks both if the input optional light state is set and if the state it contains ...
TrajectoryParams ts_case7(double t, double et, double v0, double v_min, double a_min, double x0, double x_end, double dx)
boost::optional< rclcpp::Time > nearest_green_entry_time_cached_
TrajectoryParams boundary_accel_nocruise_maxspeed_decel(double t, double v0, double v1, double v_max, double a_max, double a_min, double x0, double x_end, double dx)
TrajectoryParams ts_case1(double t, double et, double v0, double v1, double v_max, double a_max, double a_min, double x0, double x_end, double dx)
Trajectory Smoothing Algorithm 8 cases. TSMO UC2, UC3 algorithm equations.
TrajectoryParams boundary_accel_or_decel_complete_upper(double t, double v0, double v1, double x0, double x_end, double dx)
std::optional< rclcpp::Time > get_nearest_green_entry_time(const rclcpp::Time &current_time, const rclcpp::Time &earliest_entry_time, const lanelet::CarmaTrafficSignalPtr &signal, double minimum_required_green_time=0.0) const
Provides the scheduled entry time for the vehicle in the future. This scheduled time is the earliest ...
TrajectoryParams boundary_accel_or_decel_incomplete_upper(double t, double v0, double v1, double a_max, double a_min, double x0, double x_end, double dx)
double calc_estimated_entry_time_left(double entry_dist, double current_speed, double departure_speed) const
calculate the time vehicle will enter to intersection with optimal deceleration
rclcpp::Duration get_earliest_entry_time(double remaining_distance, double free_flow_speed, double current_speed, double departure_speed, double max_accel, double max_decel) const
Gets the earliest entry time into the intersection that is kinematically possible for the vehicle....
TrajectoryParams boundary_accel_nocruise_notmaxspeed_decel(double t, double v0, double v1, double a_max, double a_min, double x0, double x_end, double dx)
TrajectoryParams boundary_decel_nocruise_minspeed_accel_incomplete(double t, double v0, double v_min, double a_max, double a_min, double x0, double x_end, double dx)
std::tuple< rclcpp::Time, bool, bool > get_final_entry_time_and_conditions(const VehicleState &current_state, const rclcpp::Time &earliest_entry_time, lanelet::CarmaTrafficSignalPtr traffic_light)
Get the final entry time from either vehicle's own internal ET calculation (TSMO UC2) or from carma-s...
TrajectoryParams boundary_accel_cruise_maxspeed_decel(double t, double v0, double v1, double v_max, double a_max, double a_min, double x0, double x_end, double dx)
TrajectoryParams boundary_decel_incomplete_lower(double t, double v0, double a_min, double x0, double x_end, double dx)
TrajectoryParams ts_case6(double t, double et, double v0, double v_min, double a_min, double x0, double x_end, double dx, double dx3, TrajectoryParams traj6)
TrajectoryParams ts_case4(double t, double et, double v0, double v1, double v_min, double a_max, double a_min, double x0, double x_end, double dx)
TrajectoryParams boundary_decel_cruise_minspeed_accel(double t, double v0, double v1, double v_min, double a_max, double a_min, double x0, double x_end, double dx)
void print_params(TrajectoryParams params)
Helper method to print TrajectoryParams.
TrajectoryParams ts_case2(double t, double et, double v0, double v1, double a_max, double a_min, double x0, double x_end, double dx)
TrajectoryParams get_ts_case(double t, double et, double v0, double v1, double v_max, double v_min, double a_max, double a_min, double x0, double x_end, double dx, BoundaryDistances boundary_distances, std::vector< TrajectoryParams > params)
TrajectoryParams boundary_decel_nocruise_minspeed_accel_complete(double t, double v0, double v1, double v_max, double v_min, double a_max, double a_min, double x0, double x_end, double dx)
double get_distance_to_accel_or_decel_once(double current_speed, double departure_speed, double max_accel, double max_decel) const
Get required distance to accel or decel to reach departure_speed with given speed and acceleration pa...
TrajectoryParams boundary_decel_cruise_minspeed(double t, double v0, double v_min, double a_min, double x0, double x_end, double dx)
double get_inflection_speed_value(double x, double x1, double x2, double free_flow_speed, double current_speed, double departure_speed, double max_accel, double max_decel) const
Get the speed between the acceleration and deceleration pieces.
double get_trajectory_smoothing_activation_distance(double time_remaining_at_free_flow, double full_cycle_duration, double current_speed, double speed_limit, double departure_speed, double max_accel, double max_decel) const
Gets maximum distance (nearest downtrack) the trajectory smoothing algorithm makes difference than si...
TrajectoryParams ts_case8(double dx, double dx5, TrajectoryParams traj8)
TrajectoryParams ts_case3(double t, double et, double v0, double v1, double a_max, double a_min, double x0, double x_end, double dx)
double estimate_distance_to_stop(double v, double a) const
Helper method to use basic kinematics to compute an estimated stopping distance from from the inputs.
TrajectoryParams ts_case5(double t, double et, double v0, double a_max, double a_min, double x0, double x_end, double dx)
std::vector< TrajectoryParams > get_boundary_traj_params(double t, double v0, double v1, double v_max, double v_min, double a_max, double a_min, double x0, double x_end, double dx, BoundaryDistances boundary_distances)
Get all possible trajectory smoothing parameters for each segments. Later this will be used to genera...
void print_boundary_distances(BoundaryDistances delta_xs)
Helper method to print TrajectoryParams.
#define EPSILON
auto to_string(const UtmZone &zone) -> std::string
Definition: utm_zone.cpp:21
bool enable_carma_streets_connection
Bool: Enable carma streets connection.
double algo_minimum_speed
Minimum allowable speed TS algorithm in m/s.
double green_light_time_buffer
A buffer in seconds around the green phase which will reduce the phase length such that vehicle still...
Struct representing a vehicle state for the purposes of planning.