23namespace waypoint_generation
26 const carma_planning_msgs::msg::VehicleState& state)
28 lanelet::BasicPoint2d veh_point(state.x_pos_global, state.y_pos_global);
29 double min_distance = std::numeric_limits<double>::max();
32 for (
const auto& p : points)
34 double distance = lanelet::geometry::distance2d(p, veh_point);
35 if (distance < min_distance)
38 min_distance = distance;
46 const carma_planning_msgs::msg::VehicleState& state)
48 lanelet::BasicPoint2d veh_point(state.x_pos_global, state.y_pos_global);
49 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"veh_point: " << veh_point.x() <<
", " << veh_point.y());
50 double min_distance = std::numeric_limits<double>::max();
53 for (
const auto& p : points)
55 double distance = lanelet::geometry::distance2d(p.point, veh_point);
56 if (distance < min_distance)
59 min_distance = distance;
67 const std::vector<carma_planning_msgs::msg::TrajectoryPlanPoint>& trajectory,
68 const lanelet::BasicPoint2d& position)
70 size_t closest_idx = 0;
71 double min_dist = std::numeric_limits<double>::max();
73 for (
size_t i = 0;
i < trajectory.size();
i++)
75 auto dist = sqrt(pow(position.x() - trajectory.at(
i).x, 2) +
76 pow(position.y() - trajectory.at(
i).y, 2));
90 if(std::empty(points)){
91 RCLCPP_WARN_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"Empty points vector received, returning -1");
96 const auto itr = std::find_if(std::cbegin(points), std::cend(points),
97 [&wm = std::as_const(wm), target_downtrack](
const auto &
point) {
return wm->routeTrackPos(
point).downtrack > target_downtrack; });
99 int best_index = std::size(points) - 1;
102 if(itr != std::cbegin(points)){
103 best_index = std::distance(std::cbegin(points), std::prev(itr));
109 RCLCPP_DEBUG_STREAM(rclcpp::get_logger(
BASIC_AUTONOMY_LOGGER),
"get_nearest_index_by_downtrack>> Found best_index: " << best_index<<
", points[i].x(): " << points.at(best_index).x() <<
", points[i].y(): " << points.at(best_index).y());
115 std::vector<lanelet::BasicPoint2d>* basic_points,
116 std::vector<double>* speeds)
118 basic_points->reserve(points.size());
119 speeds->reserve(points.size());
121 for (
const auto& p : points)
123 basic_points->push_back(p.point);
124 speeds->push_back(p.speed);
129 const carma_planning_msgs::msg::VehicleState& state)
131 lanelet::BasicPoint2d state_pos(state.x_pos_global, state.y_pos_global);
132 double ending_downtrack = wm->routeTrackPos(state_pos).downtrack;
133 std::vector<lanelet::BasicPoint2d> basic_points;
134 std::vector<double> speeds;
140 const carma_planning_msgs::msg::VehicleState& state)
142 lanelet::BasicPoint2d state_pos(state.x_pos_global, state.y_pos_global);
143 double ending_downtrack = wm->routeTrackPos(state_pos).downtrack;
148 lanelet::ConstLanelet pivot,
149 double backward_length,
150 double forward_length)
152 std::vector<lanelet::ConstLanelet> chain{pivot};
153 std::unordered_set<lanelet::Id> visited{pivot.id()};
156 while (covered_back < backward_length)
158 auto previous = wm->getMapRoutingGraph()->previous(chain.front(),
false);
159 bool no_predecessor = previous.empty();
160 bool loop_detected = !no_predecessor && visited.count(previous.front().id()) > 0;
165 "create_lanechange_geometry: No routable predecessor lanelet found before lanelet "
166 << chain.front().id() <<
" (possibly closed or missing from the map). Using the "
167 << covered_back <<
"m of centerline that was reachable going backward.");
173 "create_lanechange_geometry: Detected a loop in lanelet connectivity before lanelet "
174 << chain.front().id() <<
"; stopping centerline extension.");
177 if (no_predecessor || loop_detected)
182 lanelet::ConstLanelet prev = previous.front();
183 visited.insert(prev.id());
185 chain.insert(chain.begin(), prev);
188 double covered_fwd = 0.0;
189 while (covered_fwd < forward_length)
191 auto following = wm->getMapRoutingGraph()->following(chain.back(),
false);
192 bool no_successor = following.empty();
193 bool loop_detected = !no_successor && visited.count(following.front().id()) > 0;
198 "create_lanechange_geometry: No routable successor lanelet found after lanelet "
199 << chain.back().id() <<
" (possibly closed or missing from the map). Using the "
200 << covered_fwd <<
"m of centerline that was reachable going forward.");
206 "create_lanechange_geometry: Detected a loop in lanelet connectivity after lanelet "
207 << chain.back().id() <<
"; stopping centerline extension.");
210 if (no_successor || loop_detected)
215 lanelet::ConstLanelet next = following.front();
216 visited.insert(next.id());
218 chain.push_back(next);
221 std::vector<lanelet::BasicPoint2d> centerline;
222 centerline.reserve(400);
223 for (
size_t i = 0;
i < chain.size(); ++
i)
225 auto ls = chain[
i].centerline2d().basicLineString();
228 centerline.insert(centerline.end(), ls.begin(), ls.end());
233 centerline.insert(centerline.end(), ls.begin() + 1, ls.end());
239 void extrapolate_to_length(std::vector<lanelet::BasicPoint2d>& centerline,
double target_length,
const std::string& description)
241 if (centerline.size() < 2)
243 throw std::invalid_argument(
"create_lanechange_geometry: " + description +
244 " has fewer than 2 centerline points; cannot build or extrapolate a lane change trajectory from this map data");
248 if (current_length >= target_length)
254 "create_lanechange_geometry: Only " << current_length <<
"m of connected lanelet centerline was "
255 <<
"available for " << description <<
" (needed " << target_length <<
"m). Extrapolating a "
256 <<
"straight line from the last known heading so a lane change trajectory can still be produced.");
258 lanelet::BasicPoint2d last = centerline.back();
259 lanelet::BasicPoint2d prev = centerline[centerline.size() - 2];
260 lanelet::BasicPoint2d direction = last - prev;
261 if (direction.norm() < 1e-6)
264 direction = last - centerline.front();
266 direction.normalize();
268 constexpr double step = 1.0;
269 double remaining = target_length - current_length;
270 for (
int step_count = 1; step_count * step < remaining; ++step_count)
272 centerline.push_back(last + direction * (step_count * step));
274 centerline.push_back(last + direction * remaining);
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.
void extrapolate_to_length(std::vector< lanelet::BasicPoint2d > ¢erline, double target_length, const std::string &description)
Pads a centerline out to target_length by extrapolating a straight line from its last known heading,...
static const std::string BASIC_AUTONOMY_LOGGER
std::vector< lanelet::BasicPoint2d > build_chain_centerline(const carma_wm::WorldModelConstPtr &wm, lanelet::ConstLanelet pivot, double backward_length, double forward_length)
Builds a centerline covering [pivot_end_point - backward_length, pivot_end_point + forward_length] by...
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...
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 ...
double get_lanelet_centerline_length(const lanelet::ConstLanelet &ll)
Returns the total 2d arc length of a lanelet's centerline.
std::vector< double > compute_arc_lengths(const std::vector< lanelet::BasicPoint2d > &data)
Compute the arc length at each point around the curve.
std::shared_ptr< const WorldModel > WorldModelConstPtr