22 namespace waypoint_generation
25 carma_planning_msgs::msg::VehicleState &ending_state_before_buffer,
const carma_planning_msgs::msg::VehicleState& state,
27 std::vector<PointSpeedPair> points_and_target_speeds;
30 std::unordered_set<lanelet::Id> visited_lanelets;
32 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"VehDowntrack:"<<max_starting_downtrack);
33 for(
const auto &maneuver : maneuvers)
38 starting_downtrack = std::min(starting_downtrack, max_starting_downtrack);
41 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Used downtrack: " << starting_downtrack);
43 if(maneuver.type == carma_planning_msgs::msg::Maneuver::LANE_FOLLOWING){
45 std::vector<PointSpeedPair> lane_follow_points =
create_lanefollow_geometry(maneuver, starting_downtrack, wm, general_config, detailed_config, visited_lanelets);
46 points_and_target_speeds.insert(points_and_target_speeds.end(), lane_follow_points.begin(), lane_follow_points.end());
48 else if(maneuver.type == carma_planning_msgs::msg::Maneuver::LANE_CHANGE){
50 std::vector<PointSpeedPair> lane_change_points =
get_lanechange_points_from_maneuver(maneuver, starting_downtrack, wm, ending_state_before_buffer, state, general_config, detailed_config);
51 points_and_target_speeds.insert(points_and_target_speeds.end(), lane_change_points.begin(), lane_change_points.end());
54 throw std::invalid_argument(
"This maneuver type is not supported");
60 if(maneuvers.back().type == carma_planning_msgs::msg::Maneuver::LANE_FOLLOWING){
61 points_and_target_speeds =
add_lanefollow_buffer(wm, points_and_target_speeds, maneuvers, ending_state_before_buffer, detailed_config);
64 return points_and_target_speeds;
70 const DetailedTrajConfig &detailed_config, std::unordered_set<lanelet::Id> &visited_lanelets)
72 if(maneuver.type != carma_planning_msgs::msg::Maneuver::LANE_FOLLOWING){
73 throw std::invalid_argument(
"Create_lanefollow called on a maneuver type which is not LANE_FOLLOW");
75 std::vector<PointSpeedPair> points_and_target_speeds;
77 carma_planning_msgs::msg::LaneFollowingManeuver lane_following_maneuver = maneuver.lane_following_maneuver;
79 if (maneuver.lane_following_maneuver.lane_ids.empty())
81 throw std::invalid_argument(
"No lanelets are defined for lanefollow maneuver");
84 std::vector<lanelet::ConstLanelet> lanelets = { wm->getMap()->laneletLayer.get(stoi(lane_following_maneuver.lane_ids[0]))};
85 for (
size_t i = 1;
i < lane_following_maneuver.lane_ids.size();
i++)
87 auto ll_id = lane_following_maneuver.lane_ids[
i];
88 int cur_id = stoi(ll_id);
89 auto cur_ll = wm->getMap()->laneletLayer.get(cur_id);
90 auto following_lanelets = wm->getMapRoutingGraph()->following(lanelets.back());
92 bool is_follower =
false;
93 for (
auto follower_ll : following_lanelets )
95 if (follower_ll.id() == cur_ll.id())
104 throw std::invalid_argument(
"Invalid list of lanelets they are not followers");
107 lanelets.push_back(cur_ll);
112 auto extra_following_lanelets = wm->getMapRoutingGraph()->following(lanelets.back());
114 for (
auto llt : wm->getRoute()->shortestPath())
116 for (
size_t i = 0;
i < extra_following_lanelets.size();
i++)
118 if (llt.id() == extra_following_lanelets[
i].id())
120 lanelets.push_back(extra_following_lanelets[
i]);
126 if (lanelets.empty())
128 RCLCPP_ERROR_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Detected no lanelets between starting downtrack: "<< starting_downtrack <<
", and lane_following_maneuver.end_dist: "<< lane_following_maneuver.end_dist);
129 throw std::invalid_argument(
"Detected no lanelets between starting_downtrack and end_dist");
134 lanelet::BasicLineString2d downsampled_centerline;
137 downsampled_centerline.reserve(400);
143 auto following_lanelets = wm->getMapRoutingGraph()->following(lanelets[curr_idx]);
144 lanelet::ConstLanelets straight_lanelets;
146 if(lanelets.size() <= 1)
148 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Detected one straight lanelet Id:" << lanelets[curr_idx].
id());
149 straight_lanelets = lanelets;
154 while (curr_idx + 1 < lanelets.size() &&
155 std::find(following_lanelets.begin(),following_lanelets.end(), lanelets[curr_idx + 1]) == following_lanelets.end())
157 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"As there were no directly following lanelets after this, skipping lanelet id: " << lanelets[curr_idx].
id());
159 following_lanelets = wm->getMapRoutingGraph()->following(lanelets[curr_idx]);
162 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Added lanelet Id for lane follow: " << lanelets[curr_idx].
id());
164 straight_lanelets.push_back(lanelets[curr_idx]);
166 while (curr_idx + 1 < lanelets.size() &&
167 std::find(following_lanelets.begin(),following_lanelets.end(), lanelets[curr_idx + 1]) != following_lanelets.end())
170 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Added lanelet Id forlane follow: " << lanelets[curr_idx].
id());
171 straight_lanelets.push_back(lanelets[curr_idx]);
172 following_lanelets = wm->getMapRoutingGraph()->following(lanelets[curr_idx]);
177 for (
auto l : straight_lanelets)
180 if (visited_lanelets.find(l.id()) == visited_lanelets.end())
183 bool is_turn =
false;
184 if(l.hasAttribute(
"turn_direction")) {
185 std::string turn_direction = l.attribute(
"turn_direction").value();
186 is_turn = turn_direction.compare(
"left") == 0 || turn_direction.compare(
"right") == 0;
189 lanelet::BasicLineString2d centerline = l.centerline2d().basicLineString();
190 lanelet::BasicLineString2d downsampled_points;
192 downsampled_points = carma_ros2_utils::containers::downsample_vector(centerline, general_config.
turn_downsample_ratio);
194 downsampled_points = carma_ros2_utils::containers::downsample_vector(centerline, general_config.
default_downsample_ratio);
197 if(downsampled_centerline.size() != 0 && downsampled_points.size() != 0
198 && lanelet::geometry::distance2d(downsampled_points.front(), downsampled_centerline.back()) <1.2){
199 downsampled_points = lanelet::BasicLineString2d(downsampled_points.begin() + 1, downsampled_points.end());
203 visited_lanelets.insert(l.id());
208 for (
auto p : downsampled_centerline)
210 if (first && !points_and_target_speeds.empty())
217 pair.
speed = lane_following_maneuver.end_speed;
218 points_and_target_speeds.push_back(pair);
221 return points_and_target_speeds;
226 carma_planning_msgs::msg::VehicleState &ending_state_before_buffer,
const DetailedTrajConfig &detailed_config){
229 double starting_route_downtrack = wm->routeTrackPos(points_and_target_speeds.front().point).downtrack;
234 double ending_downtrack = maneuvers.back().lane_following_maneuver.end_dist + detailed_config.
buffer_ending_downtrack;
236 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Add lanefollow buffer: ending_downtrack: " << ending_downtrack <<
", maneuvers.back().lane_following_maneuver.end_dist: " << maneuvers.back().lane_following_maneuver.end_dist <<
239 size_t max_i = points_and_target_speeds.size() - 1;
240 size_t unbuffered_idx = points_and_target_speeds.size() - 1;
241 bool found_unbuffered_idx =
false;
242 double dist_accumulator = starting_route_downtrack;
243 lanelet::BasicPoint2d prev_point;
245 boost::optional<lanelet::BasicPoint2d> delta_point;
246 for (
size_t i = 0;
i < points_and_target_speeds.size(); ++
i) {
247 auto current_point = points_and_target_speeds[
i].point;
250 prev_point = current_point;
254 double delta_d = lanelet::geometry::distance2d(prev_point, current_point);
256 dist_accumulator += delta_d;
257 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Index i: " <<
i <<
", delta_d: " << delta_d <<
", dist_accumulator:" << dist_accumulator <<
", current_point.x():" << current_point.x() <<
258 "current_point.y():" << current_point.y());
259 if (dist_accumulator > maneuvers.back().lane_following_maneuver.end_dist && !found_unbuffered_idx)
261 unbuffered_idx =
i - 1;
262 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Found index unbuffered_idx at: " << unbuffered_idx);
263 found_unbuffered_idx =
true;
266 if (dist_accumulator > ending_downtrack) {
268 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Max_i breaking at: i: " <<
i <<
", max_i: " << max_i);
275 if (
i == points_and_target_speeds.size() - 1)
278 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Extending trajectory using buffer beyond end of target lanelet");
280 while (delta_d < epsilon_ && j >= 0 && !delta_point)
282 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Looking at index j: " << j <<
", where i: " <<
i);
283 prev_point = points_and_target_speeds.at(j).point;
285 delta_d = lanelet::geometry::distance2d(prev_point, current_point);
292 delta_point = (current_point - prev_point) * 0.25;
296 auto new_point = current_point + delta_point.get();
299 new_pair.
point = new_point;
300 new_pair.
speed = points_and_target_speeds.back().speed;
303 points_and_target_speeds.push_back(new_pair);
306 prev_point = current_point;
309 ending_state_before_buffer.x_pos_global = points_and_target_speeds[unbuffered_idx].point.x();
310 ending_state_before_buffer.y_pos_global = points_and_target_speeds[unbuffered_idx].point.y();
311 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Here ending_state_before_buffer.x_pos_global: " << ending_state_before_buffer.x_pos_global <<
312 ", and y_pos_global" << ending_state_before_buffer.y_pos_global);
314 std::vector<PointSpeedPair> constrained_points(points_and_target_speeds.begin(), points_and_target_speeds.begin() + max_i);
316 return constrained_points;
319 std::vector<lanelet::BasicPoint2d>
create_lanechange_geometry(lanelet::Id starting_lane_id, lanelet::Id ending_lane_id,
double starting_downtrack,
double ending_downtrack,
322 std::vector<lanelet::BasicPoint2d> centerline_points;
325 lanelet::ConstLanelet starting_lanelet = wm->getMap()->laneletLayer.get(starting_lane_id);
326 lanelet::ConstLanelet ending_lanelet = wm->getMap()->laneletLayer.get(ending_lane_id);
328 lanelet::ConstLanelets starting_lane;
329 starting_lane.push_back(starting_lanelet);
331 std::vector<lanelet::BasicPoint2d> reference_centerline;
334 reference_centerline.reserve(400);
335 bool shared_boundary_found =
false;
336 bool is_lanechange_left =
false;
338 lanelet::BasicLineString2d current_lanelet_centerline = starting_lanelet.centerline2d().basicLineString();
339 lanelet::ConstLanelet current_lanelet = starting_lanelet;
340 reference_centerline.insert(reference_centerline.end(), current_lanelet_centerline.begin(), current_lanelet_centerline.end());
343 while(!shared_boundary_found){
345 if(current_lanelet.leftBound() == ending_lanelet.rightBound()){
347 is_lanechange_left =
true;
348 shared_boundary_found =
true;
351 else if(current_lanelet.rightBound() == ending_lanelet.leftBound()){
353 shared_boundary_found =
true;
358 if(wm->getMapRoutingGraph()->following(current_lanelet,
false).empty())
363 throw(std::invalid_argument(
"No following lanelets from current lanelet reachable without a lane change, incorrectly chosen end lanelet"));
366 current_lanelet = wm->getMapRoutingGraph()->following(current_lanelet,
false).front();
367 if(current_lanelet.id() == starting_lanelet.id()){
369 throw(std::invalid_argument(
"No lane change in path"));
372 auto current_lanelet_linestring = current_lanelet.centerline2d().basicLineString();
374 reference_centerline.insert(reference_centerline.end(), current_lanelet_linestring.begin() + 1, current_lanelet_linestring.end());
375 starting_lane.push_back(current_lanelet);
380 std::vector<lanelet::BasicPoint2d> target_lane_centerline;
381 for(
size_t i = 0;
i<starting_lane.size();++
i){
382 lanelet::ConstLanelet curr_end_lanelet;
384 if(is_lanechange_left){
387 if(wm->getMapRoutingGraph()->left(starting_lane[
i])){
388 curr_end_lanelet = wm->getMapRoutingGraph()->left(starting_lane[
i]).get();
391 curr_end_lanelet = wm->getMapRoutingGraph()->adjacentLeft(starting_lane[
i]).get();
397 if(wm->getMapRoutingGraph()->right(starting_lane[
i])){
398 curr_end_lanelet = wm->getMapRoutingGraph()->right(starting_lane[
i]).get();
401 curr_end_lanelet = wm->getMapRoutingGraph()->adjacentRight(starting_lane[
i]).get();
405 auto target_lane_linestring = curr_end_lanelet.centerline2d().basicLineString();
407 target_lane_centerline.insert(target_lane_centerline.end(), target_lane_linestring.begin() + 1, target_lane_linestring.end());
415 std::vector<lanelet::BasicPoint2d> downsampled_starting_centerline;
416 downsampled_starting_centerline.reserve(400);
417 downsampled_starting_centerline = carma_ros2_utils::containers::downsample_vector(reference_centerline, downsample_ratio);
419 std::vector<lanelet::BasicPoint2d> downsampled_target_centerline;
420 downsampled_target_centerline.reserve(400);
421 downsampled_target_centerline = carma_ros2_utils::containers::downsample_vector(target_lane_centerline, downsample_ratio);
425 carma_planning_msgs::msg::VehicleState start_state;
426 start_state.x_pos_global = downsampled_starting_centerline[start_index_starting_centerline].x();
427 start_state.y_pos_global = downsampled_starting_centerline[start_index_starting_centerline].y();
431 carma_planning_msgs::msg::VehicleState end_state;
432 end_state.x_pos_global = downsampled_target_centerline[end_index_target_centerline].x();
433 end_state.y_pos_global = downsampled_target_centerline[end_index_target_centerline].y();
436 std::vector<lanelet::BasicPoint2d> constrained_start_centerline(downsampled_starting_centerline.begin() + start_index_starting_centerline, downsampled_starting_centerline.begin() + end_index_starting_centerline);
437 std::vector<lanelet::BasicPoint2d> constrained_target_centerline(downsampled_target_centerline.begin() + start_index_target_centerline, downsampled_target_centerline.begin() + end_index_target_centerline);
440 if(constrained_start_centerline.size() != constrained_target_centerline.size())
443 constrained_start_centerline = centerlines[0];
444 constrained_target_centerline = centerlines[1];
449 double delta_step = 1.0 / constrained_start_centerline.size();
451 for (
size_t i = 0;
i < constrained_start_centerline.size(); ++
i)
453 lanelet::BasicPoint2d current_position;
454 lanelet::BasicPoint2d start_lane_pt = constrained_start_centerline[
i];
455 lanelet::BasicPoint2d target_lane_pt = constrained_target_centerline[
i];
456 double delta = delta_step *
i;
457 current_position.x() = target_lane_pt.x() * delta + (1 - delta) * start_lane_pt.x();
458 current_position.y() = target_lane_pt.y() * delta + (1 - delta) * start_lane_pt.y();
460 centerline_points.push_back(current_position);
464 double dist_to_target_lane_end = lanelet::geometry::distance2d(centerline_points.back(), downsampled_target_centerline.back());
465 centerline_points.insert(centerline_points.end(), downsampled_target_centerline.begin() + end_index_target_centerline, downsampled_target_centerline.end());
469 if (dist_to_target_lane_end < buffer_ending_downtrack) {
470 auto following_lanelets = wm->getMapRoutingGraph()->following(ending_lanelet,
false);
471 if(!following_lanelets.empty()){
473 auto following_lanelet_centerline = following_lanelets.front().centerline2d().basicLineString();
474 centerline_points.insert(centerline_points.end(), following_lanelet_centerline.begin(),
475 following_lanelet_centerline.end());
479 return centerline_points;
484 auto start_time = std::chrono::high_resolution_clock::now();
486 std::vector<std::vector<lanelet::BasicPoint2d>> output;
489 std::unique_ptr<smoothing::SplineI> fit_curve_1 =
compute_fit(line_1);
492 throw std::invalid_argument(
"Could not fit a spline curve along the starting_lane centerline points!");
495 std::unique_ptr<smoothing::SplineI> fit_curve_2 =
compute_fit(line_2);
498 throw std::invalid_argument(
"Could not fit a spline curve along the ending_lane centerline points!");
502 std::vector<lanelet::BasicPoint2d> all_sampling_points_line1;
503 std::vector<lanelet::BasicPoint2d> all_sampling_points_line2;
505 size_t total_point_size = std::min(line_1.size(), line_2.size());
507 all_sampling_points_line1.reserve(1 + total_point_size * 2);
514 all_sampling_points_line2.reserve(1 + total_point_size * 2);
519 double scaled_steps_along_curve = 0.0;
522 all_sampling_points_line2.reserve(1 + total_point_size * 2);
524 for(
size_t i = 0;
i<total_point_size; ++
i){
525 lanelet::BasicPoint2d p1 = (*fit_curve_1)(scaled_steps_along_curve);
526 lanelet::BasicPoint2d p2 = (*fit_curve_2)(scaled_steps_along_curve);
527 all_sampling_points_line1.push_back(p1);
528 all_sampling_points_line2.push_back(p2);
530 scaled_steps_along_curve += 1.0 / total_point_size;
533 output.push_back(all_sampling_points_line1);
534 output.push_back(all_sampling_points_line2);
536 auto end_time = std::chrono::high_resolution_clock::now();
538 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
539 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"ExecutionTime for resample lane change centerlines: " << duration.count() <<
" milliseconds");
548 if(maneuver.type != carma_planning_msgs::msg::Maneuver::LANE_CHANGE){
549 throw std::invalid_argument(
"Create_lanechange called on a maneuver type which is not LANE_CHANGE");
551 std::vector<PointSpeedPair> points_and_target_speeds;
552 std::unordered_set<lanelet::Id> visited_lanelets;
554 carma_planning_msgs::msg::LaneChangeManeuver lane_change_maneuver = maneuver.lane_change_maneuver;
555 double ending_downtrack = lane_change_maneuver.end_dist;
556 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Maneuver ending downtrack:"<<ending_downtrack);
557 if(starting_downtrack >= ending_downtrack)
559 throw(std::invalid_argument(
"Start distance is greater than or equal to ending distance"));
563 std::vector<lanelet::BasicPoint2d> route_geometry =
create_lanechange_geometry(std::stoi(lane_change_maneuver.starting_lane_id),std::stoi(lane_change_maneuver.ending_lane_id),
565 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Route geometry size:"<<route_geometry.size());
567 lanelet::BasicPoint2d state_pos(state.x_pos_global, state.y_pos_global);
568 double current_downtrack = wm->routeTrackPos(state_pos).downtrack;
571 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Nearest pt index in maneuvers to points: "<< nearest_pt_index);
572 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Ending pt index in maneuvers to points: "<< ending_pt_index);
574 ending_state_before_buffer.x_pos_global = route_geometry[ending_pt_index].x();
575 ending_state_before_buffer.y_pos_global = route_geometry[ending_pt_index].y();
577 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"ending_state_before_buffer_:"<<ending_state_before_buffer.x_pos_global <<
578 ", ending_state_before_buffer_.y_pos_global" << ending_state_before_buffer.y_pos_global);
581 double route_length = wm->getRouteEndTrackPos().downtrack;
589 ending_pt_index = route_geometry.size() - 1;
592 lanelet::BasicLineString2d future_route_geometry(route_geometry.begin() + nearest_pt_index, route_geometry.begin() + ending_pt_index);
594 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Future geom size:"<< future_route_geometry.size());
596 for (
auto p : future_route_geometry)
598 if (first && !points_and_target_speeds.empty())
606 pair.
speed = (state.longitudinal_vel > detailed_config.
minimum_speed) ? state.longitudinal_vel : lane_change_maneuver.end_speed;
607 points_and_target_speeds.push_back(pair);
610 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Const speed assigned:"<<points_and_target_speeds.back().speed);
611 return points_and_target_speeds;
617 const std::vector<double> speed_limits)
619 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Speeds list size: " << speeds.size());
620 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"SpeedLimits list size: " << speed_limits.size());
622 if (speeds.size() != speed_limits.size())
624 throw std::invalid_argument(
"Speeds and speed limit lists not same size");
626 std::vector<double> out;
627 for (
size_t i = 0;
i < speeds.size();
i++)
629 out.push_back(std::min(speeds[
i], speed_limits[
i]));
636 const lanelet::BasicPoint2d &p2)
638 Eigen::Rotation2Dd yaw(atan2(p2.y() - p1.y(), p2.x() - p1.x()));
646 std::vector<lanelet::BasicPoint2d> basic_points;
647 std::vector<double> speeds;
652 size_t time_boundary_exclusive_index =
653 trajectory_utils::time_boundary_index(downtracks, speeds, time_span);
655 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"time_boundary_exclusive_index = " << time_boundary_exclusive_index);
657 if (time_boundary_exclusive_index == 0)
659 throw std::invalid_argument(
"No points to fit in timespan");
662 std::vector<PointSpeedPair> time_bound_points;
663 time_bound_points.reserve(time_boundary_exclusive_index);
665 if (time_boundary_exclusive_index == points.size())
667 time_bound_points.insert(time_bound_points.end(), points.begin(),
672 time_bound_points.insert(time_bound_points.end(), points.begin(),
673 points.begin() + time_boundary_exclusive_index - 1);
676 return time_bound_points;
679 std::pair<double, size_t>
min_with_exclusions(
const std::vector<double> &values,
const std::unordered_set<size_t> &excluded)
681 double min = std::numeric_limits<double>::max();
682 size_t best_idx = -1;
683 for (
size_t i = 0;
i < values.size();
i++)
685 if (excluded.find(
i) != excluded.end())
696 return std::make_pair(min, best_idx);
699 std::vector<double>
optimize_speed(
const std::vector<double> &downtracks,
const std::vector<double> &curv_speeds,
double accel_limit)
701 if (downtracks.size() != curv_speeds.size())
703 throw std::invalid_argument(
"Downtracks and speeds do not have the same size");
706 if (accel_limit <= 0)
708 throw std::invalid_argument(
"Accel limits should be positive");
711 bool optimize =
true;
712 std::unordered_set<size_t> visited_idx;
713 visited_idx.reserve(curv_speeds.size());
715 std::vector<double> output = curv_speeds;
720 int min_idx = std::get<1>(min_pair);
726 visited_idx.insert(min_idx);
728 double v_i = std::get<0>(min_pair);
729 double x_i = downtracks[min_idx];
730 for (
int i = min_idx - 1;
i > 0;
i--)
733 double v_f = curv_speeds[
i];
734 double dv = v_f - v_i;
736 double x_f = downtracks[
i];
737 double dx = x_f - x_i;
741 v_f = std::min(v_f, sqrt(v_i * v_i - 2 * accel_limit * dx));
742 visited_idx.insert(
i);
756 output = trajectory_utils::apply_accel_limits_by_distance(downtracks, output, accel_limit, accel_limit);
763 const std::vector<lanelet::BasicPoint2d> &points,
const std::vector<double> ×,
const std::vector<double> &yaws,
764 rclcpp::Time startTime,
const std::string &desired_controller_plugin)
766 if (points.size() != times.size() || points.size() != yaws.size())
768 throw std::invalid_argument(
"All input vectors must have the same size");
771 std::vector<carma_planning_msgs::msg::TrajectoryPlanPoint> traj;
772 traj.reserve(points.size());
774 for (
size_t i = 0;
i < points.size();
i++)
776 carma_planning_msgs::msg::TrajectoryPlanPoint tpp;
777 rclcpp::Duration relative_time(times[
i] * 1e9);
778 tpp.target_time = startTime + relative_time;
779 tpp.x = points[
i].x();
780 tpp.y = points[
i].y();
783 tpp.controller_plugin_name = desired_controller_plugin;
793 std::vector<PointSpeedPair>
attach_past_points(
const std::vector<PointSpeedPair> &points_set, std::vector<PointSpeedPair> future_points,
794 const int nearest_pt_index,
double back_distance)
796 std::vector<PointSpeedPair> back_and_future;
797 back_and_future.reserve(points_set.size());
798 double total_dist = 0;
802 for (
int i = nearest_pt_index;
i >= 0; --
i)
805 total_dist += lanelet::geometry::distance2d(points_set[
i].
point, points_set[
i - 1].
point);
807 if (total_dist > back_distance)
813 back_and_future.insert(back_and_future.end(), points_set.begin() + min_i, points_set.begin() + nearest_pt_index + 1);
814 back_and_future.insert(back_and_future.end(), future_points.begin(), future_points.end());
815 return back_and_future;
818 std::unique_ptr<basic_autonomy::smoothing::SplineI>
compute_fit(
const std::vector<lanelet::BasicPoint2d> &basic_points)
820 if (basic_points.size() < 4)
826 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Original basic_points size: " << basic_points.size());
828 std::vector<lanelet::BasicPoint2d> resized_basic_points = basic_points;
832 if (resized_basic_points.size() > 400)
834 resized_basic_points.resize(400);
835 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Resized basic_points size: " << resized_basic_points.size());
837 size_t left_points_size = basic_points.size() - resized_basic_points.size();
838 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Number of left out basic_points size: " << left_points_size);
840 float percent_points_lost = 100.0 * (float)left_points_size/basic_points.size();
842 if (percent_points_lost > 50.0)
844 RCLCPP_WARN_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"More than half of basic points are ignored for spline fitting");
848 std::unique_ptr<basic_autonomy::smoothing::SplineI> spl = std::make_unique<basic_autonomy::smoothing::BSpline>();
850 spl->setPoints(resized_basic_points);
857 lanelet::BasicPoint2d f_prime_pt = fit_curve.
first_deriv(step_along_the_curve);
858 lanelet::BasicPoint2d f_prime_prime_pt = fit_curve.
second_deriv(step_along_the_curve);
860 Eigen::Vector3d f_prime = {f_prime_pt.x(), f_prime_pt.y(), 0};
861 Eigen::Vector3d f_prime_prime = {f_prime_prime_pt.x(), f_prime_prime_pt.y(), 0};
862 return (f_prime.cross(f_prime_prime)).norm() / (pow(f_prime.norm(), 3));
866 const std::vector<PointSpeedPair> &points,
const carma_planning_msgs::msg::VehicleState &state,
const rclcpp::Time &state_time,
const carma_wm::WorldModelConstPtr &wm,
867 const carma_planning_msgs::msg::VehicleState &ending_state_before_buffer, carma_debug_ros2_msgs::msg::TrajectoryCurvatureSpeeds& debug_msg,
const DetailedTrajConfig &detailed_config)
870 <<
" x: " << state.x_pos_global <<
" y: " << state.y_pos_global <<
" yaw: " << state.orientation
871 <<
" speed: " << state.longitudinal_vel);
877 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"NearestPtIndex: " << nearest_pt_index);
879 std::vector<PointSpeedPair> future_points(points.begin() + nearest_pt_index + 1, points.end());
881 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Ready to call constrain_to_time_boundary: future_points size = " << future_points.size() <<
", trajectory_time_length = " << detailed_config.
trajectory_time_length);
885 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Got time_bound_points with size:" << time_bound_points.size());
890 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Got back_and_future points with size" << back_and_future.size());
893 std::vector<double> speed_limits;
894 std::vector<lanelet::BasicPoint2d> curve_points;
897 std::unique_ptr<smoothing::SplineI> fit_curve =
compute_fit(curve_points);
900 throw std::invalid_argument(
"Could not fit a spline curve along the given trajectory!");
905 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"speed_limits.size() " << speed_limits.size());
907 std::vector<lanelet::BasicPoint2d> all_sampling_points;
908 all_sampling_points.reserve(1 + curve_points.size() * 2);
910 std::vector<double> distributed_speed_limits;
911 distributed_speed_limits.reserve(1 + curve_points.size() * 2);
919 int current_speed_index = 0;
920 size_t total_point_size = curve_points.size();
922 double step_threshold_for_next_speed = (double)total_step_along_curve / (
double)total_point_size;
923 double scaled_steps_along_curve = 0.0;
924 std::vector<double> better_curvature;
925 better_curvature.reserve(1 + curve_points.size() * 2);
927 for (
int steps_along_curve = 0; steps_along_curve < total_step_along_curve; steps_along_curve++)
929 lanelet::BasicPoint2d p = (*fit_curve)(scaled_steps_along_curve);
931 all_sampling_points.push_back(p);
933 better_curvature.push_back(
c);
934 if ((
double)steps_along_curve > step_threshold_for_next_speed)
936 step_threshold_for_next_speed += (double)total_step_along_curve / (
double)total_point_size;
937 current_speed_index++;
939 distributed_speed_limits.push_back(speed_limits[current_speed_index]);
940 scaled_steps_along_curve += 1.0 / total_step_along_curve;
943 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Got sampled points with size:" << all_sampling_points.size());
951 std::vector<double> ideal_speeds =
952 trajectory_utils::constrained_speeds_for_curvatures(curvatures, detailed_config.
lateral_accel_limit);
958 std::vector<double> constrained_speed_limits =
apply_speed_limits(ideal_speeds, distributed_speed_limits);
960 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Processed all points in computed fit");
962 if (all_sampling_points.empty())
964 RCLCPP_WARN_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"No trajectory points could be generated");
971 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Current state's nearest_pt_index: " << nearest_pt_index);
972 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Curvature right now: " << better_curvature[nearest_pt_index] <<
", at state x: " << state.x_pos_global <<
", state y: " << state.y_pos_global);
973 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Corresponding to point: x: " << all_sampling_points[nearest_pt_index].
x() <<
", y:" << all_sampling_points[nearest_pt_index].
y());
976 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Ending state's index before applying buffer (buffer_pt_index): " << buffer_pt_index);
977 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Corresponding to point: x: " << all_sampling_points[buffer_pt_index].
x() <<
", y:" << all_sampling_points[buffer_pt_index].
y());
979 if(nearest_pt_index + 1 >= buffer_pt_index){
981 lanelet::BasicPoint2d current_pos(state.x_pos_global, state.y_pos_global);
982 lanelet::BasicPoint2d ending_pos(ending_state_before_buffer.x_pos_global, ending_state_before_buffer.y_pos_global);
984 if(wm->routeTrackPos(ending_pos).downtrack < wm->routeTrackPos(current_pos).downtrack ){
986 RCLCPP_WARN_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Current state is at or past the planned end distance. Couldn't generate trajectory");
991 RCLCPP_WARN_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Returning the two remaining points in the maneuver");
993 std::vector<lanelet::BasicPoint2d> remaining_traj_points = {current_pos, ending_pos};
996 std::vector<double> speeds = {state.longitudinal_vel, state.longitudinal_vel};
997 std::vector<double> times;
998 trajectory_utils::conversions::speed_to_time(downtracks, speeds, ×);
999 std::vector<double> yaw = {state.orientation, state.orientation};
1001 std::vector<carma_planning_msgs::msg::TrajectoryPlanPoint> traj_points =
1011 std::vector<lanelet::BasicPoint2d> future_basic_points(all_sampling_points.begin() + nearest_pt_index + 1,
1012 all_sampling_points.begin()+ buffer_pt_index);
1014 std::vector<double> future_speeds(constrained_speed_limits.begin() + nearest_pt_index + 1,
1015 constrained_speed_limits.begin() + buffer_pt_index);
1016 std::vector<double> future_yaw(final_yaw_values.begin() + nearest_pt_index + 1,
1017 final_yaw_values.begin() + buffer_pt_index);
1018 std::vector<double> final_actual_speeds = future_speeds;
1019 all_sampling_points = future_basic_points;
1020 final_yaw_values = future_yaw;
1021 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Trimmed future points to size: "<< future_basic_points.size());
1023 lanelet::BasicPoint2d cur_veh_point(state.x_pos_global, state.y_pos_global);
1025 all_sampling_points.insert(all_sampling_points.begin(),
1028 final_actual_speeds.insert(final_actual_speeds.begin(), state.longitudinal_vel);
1030 final_yaw_values.insert(final_yaw_values.begin(), state.orientation);
1044 for (
auto &s : final_actual_speeds)
1052 std::vector<double> times;
1053 trajectory_utils::conversions::speed_to_time(downtracks, final_actual_speeds, ×);
1058 std::vector<carma_planning_msgs::msg::TrajectoryPlanPoint> traj_points =
1062 carma_debug_ros2_msgs::msg::TrajectoryCurvatureSpeeds msg;
1063 msg.velocity_profile = final_actual_speeds;
1064 msg.relative_downtrack = downtracks;
1065 msg.tangent_headings = final_yaw_values;
1066 std::vector<double> aligned_speed_limits(constrained_speed_limits.begin() + nearest_pt_index,
1067 constrained_speed_limits.end());
1069 msg.speed_limits = aligned_speed_limits;
1070 std::vector<double> aligned_curvatures(curvatures.begin() + nearest_pt_index,
1072 msg.curvatures = aligned_curvatures;
1074 msg.lon_accel_limit = detailed_config.
max_accel;
1075 msg.starting_state = state;
1083 double curve_resample_step_size,
1084 double minimum_speed,
1086 double lateral_accel_limit,
1087 int speed_moving_average_window_size,
1088 int curvature_moving_average_window_size,
1089 double back_distance,
1090 double buffer_ending_downtrack,
1091 std::string desired_controller_plugin)
1106 return detailed_config;
1110 int default_downsample_ratio,
1111 int turn_downsample_ratio)
1120 return general_config;
1125 const std::vector<PointSpeedPair> &points,
const carma_planning_msgs::msg::VehicleState &state,
const rclcpp::Time &state_time,
1128 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Input points size in compose traj from centerline: "<< points.size());
1130 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"nearest_pt_index: "<< nearest_pt_index);
1132 std::vector<PointSpeedPair> future_points(points.begin() + nearest_pt_index + 1, points.end());
1133 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"future_points size: "<< future_points.size());
1136 std::vector<lanelet::BasicPoint2d> future_geom_points;
1137 std::vector<double> final_actual_speeds;
1140 std::unique_ptr<smoothing::SplineI> fit_curve =
compute_fit(future_geom_points);
1142 throw std::invalid_argument(
"Could not fit a spline curve along the given trajectory!");
1145 std::vector<lanelet::BasicPoint2d> all_sampling_points;
1146 all_sampling_points.reserve(1 + future_geom_points.size() * 2);
1148 lanelet::BasicPoint2d current_vehicle_point(state.x_pos_global, state.y_pos_global);
1150 future_geom_points.insert(future_geom_points.begin(),
1151 current_vehicle_point);
1153 final_actual_speeds.insert(final_actual_speeds.begin(), state.longitudinal_vel);
1160 double scaled_steps_along_curve = 0.0;
1162 for(
int steps_along_curve = 0; steps_along_curve < total_step_along_curve; steps_along_curve++){
1163 lanelet::BasicPoint2d p = (*fit_curve)(scaled_steps_along_curve);
1165 all_sampling_points.push_back(p);
1167 scaled_steps_along_curve += 1.0 / total_step_along_curve;
1169 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Got sampled points with size:" << all_sampling_points.size());
1172 if(final_yaw_values.size() > 0) {
1173 final_yaw_values[0] = state.orientation;
1179 std::vector<double> times;
1180 trajectory_utils::conversions::speed_to_time(downtracks, final_actual_speeds, ×);
1183 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Before removing extra buffer points, future_geom_points.size()"<< future_geom_points.size());
1185 future_geom_points.resize(end_dist_pt_index + 1);
1186 times.resize(end_dist_pt_index + 1);
1187 final_yaw_values.resize(end_dist_pt_index + 1);
1188 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"After removing extra buffer points, future_geom_points.size():"<< future_geom_points.size());
1190 std::vector<carma_planning_msgs::msg::TrajectoryPlanPoint> traj_points =
1196 autoware_auto_msgs::msg::Trajectory
process_trajectory_plan(
const carma_planning_msgs::msg::TrajectoryPlan& tp,
double vehicle_response_lag )
1198 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Processing latest TrajectoryPlan message");
1200 std::vector<double> times;
1201 std::vector<double> downtracks;
1203 std::vector<carma_planning_msgs::msg::TrajectoryPlanPoint> trajectory_points = tp.trajectory_points;
1205 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Original Trajectory size:"<<trajectory_points.size());
1208 trajectory_utils::conversions::trajectory_to_downtrack_time(trajectory_points, &downtracks, ×);
1211 size_t stopping_index = 0;
1212 for (
size_t i = 1;
i < times.size();
i++)
1214 if (times[
i] == times[
i - 1])
1216 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Detected a stopping case where times is exactly equal: " << times[
i-1]);
1217 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"And index of that is: " <<
i <<
", where size is: " << times.size());
1223 std::vector<double> speeds;
1226 trajectory_utils::conversions::time_to_speed(downtracks, times, tp.initial_longitudinal_velocity, &speeds);
1228 catch(
const std::runtime_error& error)
1233 RCLCPP_WARN_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Detected a negative speed from <point,time> to <point,speed> trajectory conversion with error: "
1234 << error.what() <<
". Replacing the negative speed with 0.0 speed, but please revisit the trajectory logic. "
1235 "Responsible plugin is: " << trajectory_points[std::find(speeds.begin(), speeds.end(), 0.0) - speeds.begin()].planner_plugin_name);
1238 if (speeds.size() != trajectory_points.size())
1240 throw std::invalid_argument(
"Speeds and trajectory points sizes do not match");
1243 for (
size_t i = 0;
i < speeds.size();
i++) {
1244 if (stopping_index != 0 &&
i >= stopping_index - 1)
1252 speeds[
i] = std::max(0.0, speeds[
i]);
1256 std::vector<double> lag_speeds;
1259 autoware_auto_msgs::msg::Trajectory autoware_trajectory;
1260 autoware_trajectory.header = tp.header;
1261 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"size: " << trajectory_points.size());
1263 auto max_size = std::min(99, (
int)trajectory_points.size());
1265 for (
int i = 0;
i < max_size;
i++)
1267 autoware_auto_msgs::msg::TrajectoryPoint autoware_point;
1269 autoware_point.x = trajectory_points[
i].x;
1270 autoware_point.y = trajectory_points[
i].y;
1271 autoware_point.longitudinal_velocity_mps = lag_speeds[
i];
1275 yaw = std::atan2(trajectory_points[
i+1].
y - trajectory_points[
i].
y, trajectory_points[
i+1].
x - trajectory_points[
i].
x);
1280 yaw = std::atan2(trajectory_points[max_size-1].
y - trajectory_points[max_size-2].
y, trajectory_points[max_size-1].
x - trajectory_points[max_size-2].
x);
1283 autoware_point.heading.real = std::cos(yaw/2);
1284 autoware_point.heading.imag = std::sin(yaw/2);
1286 autoware_point.time_from_start = rclcpp::Duration(times[
i] * 1e9);
1287 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Setting waypoint idx: " <<
i <<
", with planner: << " << trajectory_points[
i].planner_plugin_name <<
", x: " << trajectory_points[
i].
x <<
1288 ", y: " << trajectory_points[
i].
y <<
1289 ", speed: " << lag_speeds[
i]* 2.23694 <<
"mph");
1290 autoware_trajectory.points.push_back(autoware_point);
1293 return autoware_trajectory;
1297 std::vector<double>
apply_response_lag(
const std::vector<double>& speeds,
const std::vector<double> downtracks,
double response_lag)
1299 if (speeds.size() != downtracks.size()) {
1300 throw std::invalid_argument(
"Speed list and downtrack list are not the same size.");
1303 std::vector<double> output;
1304 if (speeds.empty()) {
1308 double lookahead_distance = speeds[0] * response_lag;
1310 double downtrack_cutoff = downtracks[0] + lookahead_distance;
1311 size_t lookahead_count = std::lower_bound(downtracks.begin(),downtracks.end(), downtrack_cutoff) - downtracks.begin();
1312 output = trajectory_utils::shift_by_lookahead(speeds, (
unsigned int) lookahead_count);
1316 bool is_valid_yield_plan(
const std::shared_ptr<carma_ros2_utils::CarmaLifecycleNode>& node_handler,
const carma_planning_msgs::msg::TrajectoryPlan& yield_plan)
1318 if (yield_plan.trajectory_points.size() < 2)
1320 RCLCPP_WARN(node_handler->get_logger(),
"Invalid Yield Trajectory");
1324 RCLCPP_DEBUG_STREAM(node_handler->get_logger(),
"Yield Trajectory Time" << rclcpp::Time(yield_plan.trajectory_points[0].target_time).seconds());
1325 RCLCPP_DEBUG_STREAM(node_handler->get_logger(),
"Now:" << node_handler->now().seconds());
1327 if (rclcpp::Time(yield_plan.trajectory_points[0].target_time) + rclcpp::Duration(5.0, 0) > node_handler->now())
1333 RCLCPP_DEBUG(node_handler->get_logger(),
"Old Yield Trajectory");
1340 const std::shared_ptr<carma_ros2_utils::CarmaLifecycleNode>& node_handler,
1341 const carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr& req,
1342 const carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr& resp,
1343 const carma_ros2_utils::ClientPtr<carma_planning_msgs::srv::PlanTrajectory>& yield_client,
1344 int yield_plugin_service_call_timeout)
1346 RCLCPP_DEBUG(node_handler->get_logger(),
"Activate Object Avoidance");
1348 if (!yield_client || !yield_client->service_is_ready())
1350 throw std::runtime_error(
"Yield Client is not set or unavailable after configuration state of lifecycle");
1353 RCLCPP_DEBUG(node_handler->get_logger(),
"Yield Client is valid");
1355 auto yield_srv = std::make_shared<carma_planning_msgs::srv::PlanTrajectory::Request>();
1356 yield_srv->initial_trajectory_plan = resp->trajectory_plan;
1357 yield_srv->vehicle_state = req->vehicle_state;
1359 auto yield_resp = yield_client->async_send_request(yield_srv);
1361 auto future_status = yield_resp.wait_for(std::chrono::milliseconds(yield_plugin_service_call_timeout));
1363 if (future_status != std::future_status::ready)
1367 RCLCPP_WARN(node_handler->get_logger(),
"Service request to yield plugin timed out waiting on a reply from the service server");
1371 RCLCPP_DEBUG(node_handler->get_logger(),
"Received Traj from Yield");
1372 carma_planning_msgs::msg::TrajectoryPlan yield_plan = yield_resp.get()->trajectory_plan;
1375 RCLCPP_DEBUG(node_handler->get_logger(),
"Yield trajectory validated");
1376 resp->trajectory_plan = yield_plan;
1380 throw std::invalid_argument(
"Invalid Yield Trajectory");
#define GET_MANEUVER_PROPERTY(mvr, property)
Macro definition to enable easier access to fields shared across the maneuver types.
Interface to a spline interpolator that can be used to smoothly interpolate between points.
virtual lanelet::BasicPoint2d first_deriv(double x) const =0
Get the BasicPoint2d representing the first_deriv along the curve at t-th step.
virtual lanelet::BasicPoint2d second_deriv(double x) const =0
Get the BasicPoint2d representing the first_deriv along the curve at t-th step.
void printDoublesPerLineWithPrefix(const std::string &prefix, const std::vector< double > &values)
Print a RCLCPP_DEBUG_STREAM for each value in values where the printed value is << prefix << value.
std::string basicPointToStream(lanelet::BasicPoint2d point)
Helper function to convert a lanelet::BasicPoint2d to a string.
std::string pointSpeedPairToStream(waypoint_generation::PointSpeedPair point)
Helper function to convert a PointSpeedPair to a string.
void printDebugPerLine(const std::vector< T > &values, std::function< std::string(T)> func)
Print a RCLCPP_DEBUG_STREAM for each value in values where the printed value is a string returned by ...
std::vector< double > moving_average_filter(const std::vector< double > input, int window_size, bool ignore_first_point=true)
Extremely simplie moving average filter.
void split_point_speed_pairs(const std::vector< PointSpeedPair > &points, std::vector< lanelet::BasicPoint2d > *basic_points, std::vector< double > *speeds)
Helper method to split a list of PointSpeedPair into separate point and speed lists.
GeneralTrajConfig compose_general_trajectory_config(const std::string &trajectory_type, int default_downsample_ratio, int turn_downsample_ratio)
std::vector< std::vector< lanelet::BasicPoint2d > > resample_linestring_pair_to_same_size(std::vector< lanelet::BasicPoint2d > &line_1, std::vector< lanelet::BasicPoint2d > &line_2)
Resamples a pair of basicpoint2d lines to get lines of same number of points.
std::vector< lanelet::BasicPoint2d > create_lanechange_geometry(lanelet::Id starting_lane_id, lanelet::Id ending_lane_id, double starting_downtrack, double ending_downtrack, const carma_wm::WorldModelConstPtr &wm, int downsample_ratio, double buffer_ending_downtrack)
Creates a vector of lane change points using parameters defined.
carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr modify_trajectory_to_yield_to_obstacles(const std::shared_ptr< carma_ros2_utils::CarmaLifecycleNode > &node_handler, const carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr &req, const carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr &resp, const carma_ros2_utils::ClientPtr< carma_planning_msgs::srv::PlanTrajectory > &yield_client, int yield_plugin_service_call_timeout)
Applies a yield trajectory to the original trajectory set in response.
std::vector< double > apply_response_lag(const std::vector< double > &speeds, const std::vector< double > downtracks, double response_lag)
Applies a specified response lag in seconds to the trajectory shifting the whole thing by the specifi...
static const std::string BASIC_AUTONOMY_LOGGER
std::vector< carma_planning_msgs::msg::TrajectoryPlanPoint > compose_lanechange_trajectory_from_path(const std::vector< PointSpeedPair > &points, const carma_planning_msgs::msg::VehicleState &state, const rclcpp::Time &state_time, const carma_wm::WorldModelConstPtr &wm, const carma_planning_msgs::msg::VehicleState &ending_state_before_buffer, const DetailedTrajConfig &detailed_config)
Method converts a list of lanelet centerline points and current vehicle state into a usable list of t...
std::vector< double > optimize_speed(const std::vector< double > &downtracks, const std::vector< double > &curv_speeds, double accel_limit)
Applies the longitudinal acceleration limit to each point's speed.
DetailedTrajConfig compose_detailed_trajectory_config(double trajectory_time_length, double curve_resample_step_size, double minimum_speed, double max_accel, double lateral_accel_limit, int speed_moving_average_window_size, int curvature_moving_average_window_size, double back_distance, double buffer_ending_downtrack, std::string desired_controller_plugin="default")
int get_nearest_point_index(const std::vector< lanelet::BasicPoint2d > &points, const carma_planning_msgs::msg::VehicleState &state)
Returns the nearest point (in terms of cartesian 2d distance) to the provided vehicle pose in the pro...
bool is_valid_yield_plan(const std::shared_ptr< carma_ros2_utils::CarmaLifecycleNode > &node_handler, const carma_planning_msgs::msg::TrajectoryPlan &yield_plan)
Helper function to verify if the input yield trajectory plan is valid.
std::pair< double, size_t > min_with_exclusions(const std::vector< double > &values, const std::unordered_set< size_t > &excluded)
Returns the min, and its idx, from the vector of values, excluding given set of values.
std::unique_ptr< basic_autonomy::smoothing::SplineI > compute_fit(const std::vector< lanelet::BasicPoint2d > &basic_points)
Computes a spline based on the provided points.
std::vector< PointSpeedPair > create_lanefollow_geometry(const carma_planning_msgs::msg::Maneuver &maneuver, double max_starting_downtrack, const carma_wm::WorldModelConstPtr &wm, const GeneralTrajConfig &general_config, const DetailedTrajConfig &detailed_config, std::unordered_set< lanelet::Id > &visited_lanelets)
Converts a set of requested LANE_FOLLOWING maneuvers to point speed limit pairs.
int get_nearest_index_by_downtrack(const std::vector< lanelet::BasicPoint2d > &points, const carma_wm::WorldModelConstPtr &wm, double target_downtrack)
Returns the nearest "less than" point to the provided vehicle pose in the provided list by utilizing ...
std::vector< double > apply_speed_limits(const std::vector< double > speeds, const std::vector< double > speed_limits)
Applies the provided speed limits to the provided speeds such that each element is capped at its corr...
std::vector< carma_planning_msgs::msg::TrajectoryPlanPoint > trajectory_from_points_times_orientations(const std::vector< lanelet::BasicPoint2d > &points, const std::vector< double > ×, const std::vector< double > &yaws, rclcpp::Time startTime, const std::string &desired_controller_plugin)
Method combines input points, times, orientations, and an absolute start time to form a valid carma p...
std::vector< PointSpeedPair > create_geometry_profile(const std::vector< carma_planning_msgs::msg::Maneuver > &maneuvers, double max_starting_downtrack, const carma_wm::WorldModelConstPtr &wm, carma_planning_msgs::msg::VehicleState &ending_state_before_buffer, const carma_planning_msgs::msg::VehicleState &state, const GeneralTrajConfig &general_config, const DetailedTrajConfig &detailed_config)
Creates geometry profile to return a point speed pair struct for LANE FOLLOW and LANE CHANGE maneuver...
std::vector< PointSpeedPair > add_lanefollow_buffer(const carma_wm::WorldModelConstPtr &wm, std::vector< PointSpeedPair > &points_and_target_speeds, const std::vector< carma_planning_msgs::msg::Maneuver > &maneuvers, carma_planning_msgs::msg::VehicleState &ending_state_before_buffer, const DetailedTrajConfig &detailed_config)
Adds extra centerline points beyond required message length to lane follow maneuver points so that th...
std::vector< carma_planning_msgs::msg::TrajectoryPlanPoint > compose_lanefollow_trajectory_from_path(const std::vector< PointSpeedPair > &points, const carma_planning_msgs::msg::VehicleState &state, const rclcpp::Time &state_time, const carma_wm::WorldModelConstPtr &wm, const carma_planning_msgs::msg::VehicleState &ending_state_before_buffer, carma_debug_ros2_msgs::msg::TrajectoryCurvatureSpeeds &debug_msg, const DetailedTrajConfig &detailed_config)
Method converts a list of lanelet centerline points and current vehicle state into a usable list of t...
Eigen::Isometry2d compute_heading_frame(const lanelet::BasicPoint2d &p1, const lanelet::BasicPoint2d &p2)
Returns a 2D coordinate frame which is located at p1 and oriented so p2 lies on the +X axis.
double compute_curvature_at(const basic_autonomy::smoothing::SplineI &fit_curve, double step_along_the_curve)
Given the curvature fit, computes the curvature at the given step along the curve.
autoware_auto_msgs::msg::Trajectory process_trajectory_plan(const carma_planning_msgs::msg::TrajectoryPlan &tp, double vehicle_response_lag)
Given a carma type of trajectory_plan, generate autoware type of trajectory accounting for speed_lag ...
std::vector< PointSpeedPair > constrain_to_time_boundary(const std::vector< PointSpeedPair > &points, double time_span)
Reduces the input points to only those points that fit within the provided time boundary.
std::vector< PointSpeedPair > get_lanechange_points_from_maneuver(const carma_planning_msgs::msg::Maneuver &maneuver, double max_starting_downtrack, const carma_wm::WorldModelConstPtr &wm, carma_planning_msgs::msg::VehicleState &ending_state_before_buffer, const carma_planning_msgs::msg::VehicleState &state, const GeneralTrajConfig &general_config, const DetailedTrajConfig &detailed_config)
Converts a set of requested LANE_CHANGE maneuvers to point speed limit pairs.
std::vector< PointSpeedPair > attach_past_points(const std::vector< PointSpeedPair > &points_set, std::vector< PointSpeedPair > future_points, const int nearest_pt_index, double back_distance)
Attaches back_distance length of points behind the future points.
auto to_string(const UtmZone &zone) -> std::string
Eigen::Isometry2d build2dEigenTransform(const Eigen::Vector2d &position, const Eigen::Rotation2Dd &rotation)
Builds a 2D Eigen coordinate frame transform with not applied scaling (only translation and rotation)...
std::vector< double > compute_tangent_orientations(const lanelet::BasicLineString2d ¢erline)
Compute an approximate orientation for the vehicle at each point along the provided centerline.
std::vector< double > compute_arc_lengths(const std::vector< lanelet::BasicPoint2d > &data)
Compute the arc length at each point around the curve.
lanelet::BasicLineString2d concatenate_line_strings(const lanelet::BasicLineString2d &l1, const lanelet::BasicLineString2d &l2)
Helper function to concatenate 2 linestrings together and return the result. Neither LineString is mo...
std::shared_ptr< const WorldModel > WorldModelConstPtr
int speed_moving_average_window_size
int curvature_moving_average_window_size
double lateral_accel_limit
std::string desired_controller_plugin
double buffer_ending_downtrack
double trajectory_time_length
double curve_resample_step_size
int default_downsample_ratio
std::string trajectory_type
int turn_downsample_ratio
lanelet::BasicPoint2d point