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