18#include <lanelet2_core/geometry/Point.h>
19#include <tf2/LinearMath/Transform.h>
20#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
21#include <tf2/transform_datatypes.h>
36 if (
x < -1.0)
x = -1.0 ;
37 else if (
x > 1.0)
x = 1.0 ;
47 if (
x < -1.0)
x = -1.0 ;
48 else if (
x > 1.0)
x = 1.0 ;
54 tf2::Matrix3x3 mat(q);
55 mat.getRPY(roll, pitch, yaw);
58void rpyFromQuaternion(
const geometry_msgs::msg::Quaternion& q_msg,
double& roll,
double& pitch,
double& yaw)
67 double vec1Mag = vec1.norm();
68 double vec2Mag = vec2.norm();
69 if (vec1Mag == 0.0 || vec2Mag == 0.0)
73 return safeAcos(vec1.dot(vec2) / (vec1Mag * vec2Mag));
76TrackPos trackPos(
const lanelet::BasicPoint2d& p,
const lanelet::BasicPoint2d& seg_start,
77 const lanelet::BasicPoint2d& seg_end)
79 Eigen::Vector2d vec_to_p(p);
80 Eigen::Vector2d vec_to_start(seg_start);
81 Eigen::Vector2d vec_to_end(seg_end);
84 Eigen::Vector2d start_to_p = vec_to_p - vec_to_start;
87 Eigen::Vector2d start_to_end = vec_to_end - vec_to_start;
93 double start_to_p_mag = start_to_p.norm();
94 double downtrack_dist = start_to_p_mag * std::cos(interior_angle);
111 double d = (start_to_p[0] * start_to_end[1]) - (start_to_p[1] * start_to_end[0]);
112 double sign = d >= 0 ? 1.0 : -1.0;
115 double crosstrack = start_to_p_mag * std::sin(interior_angle) * sign;
117 return TrackPos(downtrack_dist, crosstrack);
122 auto center_line = lanelet::utils::to2D(
lanelet.centerline());
124 if (center_line.numSegments() < 1)
126 throw std::invalid_argument(
"Provided lanelet has invalid centerline containing no points");
130 return std::get<0>(tuple);
157 double first_seg_length,
double second_seg_length)
159 const bool first_seg_in_downtrack =
160 (0 <= first_seg_trackPos.
downtrack && first_seg_trackPos.
downtrack < first_seg_length);
161 const bool second_seg_in_downtrack =
162 (0 <= second_seg_trackPos.
downtrack && second_seg_trackPos.
downtrack < second_seg_length);
164 if (first_seg_in_downtrack && !second_seg_in_downtrack)
169 else if (second_seg_in_downtrack && !first_seg_in_downtrack)
173 else if (first_seg_in_downtrack && second_seg_in_downtrack)
187std::tuple<TrackPos, lanelet::BasicSegment2d>
matchSegment(
const lanelet::BasicPoint2d& p,
188 const lanelet::BasicLineString2d& line_string)
190 if (line_string.size() < 2)
192 throw std::invalid_argument(
"Provided with linestring containing fewer than 2 points");
195 lanelet::BasicSegment2d best_segment =
196 std::make_pair(line_string[0], line_string[1]);
197 auto point_2d = lanelet::utils::to2D(p);
199 double min_distance = lanelet::geometry::distance2d(point_2d, line_string[0]);
200 size_t best_point_index = 0;
201 double best_accumulated_length = 0;
202 double best_last_accumulated_length = 0;
203 double best_seg_length = 0;
204 double best_last_seg_length = 0;
205 double last_seg_length = 0;
207 double accumulated_length = 0;
208 double last_accumulated_length = 0;
209 for (
size_t i = 0;
i < line_string.size();
i++)
211 double seg_length = 0;
212 if (
i < line_string.size() - 1)
214 seg_length = lanelet::geometry::distance2d(line_string[
i], line_string[
i + 1]);
217 double distance = lanelet::geometry::distance2d(p, line_string[
i]);
218 if (distance < min_distance)
220 min_distance = distance;
221 best_point_index =
i;
222 best_accumulated_length = accumulated_length;
223 best_last_accumulated_length = last_accumulated_length;
224 best_seg_length = seg_length;
225 best_last_seg_length = last_seg_length;
228 last_accumulated_length = accumulated_length;
229 accumulated_length += seg_length;
230 last_seg_length = seg_length;
241 if (best_point_index == 0)
243 best_pos =
trackPos(p, line_string[0], line_string[1]);
244 best_segment = std::make_pair(line_string[0], line_string[1]);
246 else if (best_point_index == line_string.size() - 1)
248 best_pos =
trackPos(p, line_string[line_string.size() - 2], line_string[line_string.size() - 1]);
249 best_pos.
downtrack += best_last_accumulated_length;
250 best_segment = std::make_pair(line_string[line_string.size() - 2], line_string[line_string.size() - 1]);
254 TrackPos first_seg_trackPos =
trackPos(p, line_string[best_point_index - 1], line_string[best_point_index]);
255 TrackPos second_seg_trackPos =
trackPos(p, line_string[best_point_index], line_string[best_point_index + 1]);
256 if (
selectFirstSegment(first_seg_trackPos, second_seg_trackPos, best_last_seg_length, best_seg_length))
258 best_pos = first_seg_trackPos;
259 best_pos.
downtrack += best_last_accumulated_length;
260 best_segment = std::make_pair(line_string[best_point_index - 1], line_string[best_point_index]);
264 best_pos = second_seg_trackPos;
265 best_pos.
downtrack += best_accumulated_length;
266 best_segment = std::make_pair(line_string[best_point_index], line_string[best_point_index + 1]);
272 return std::make_tuple(best_pos, best_segment);
277 const lanelet::BasicPoint2d& p3)
279 auto dp = 0.5 * (p3 - p1);
280 auto ddp = p3 - 2.0 * p2 + p1;
281 auto denom = std::pow(dp.x() * dp.x() + dp.y() * dp.y(), 3.0 / 2.0);
282 if (std::fabs(denom) < 1e-20)
286 return static_cast<double>((ddp.y() * dp.x() - dp.y() * ddp.x()) / denom);
289lanelet::BasicPolygon2d
objectToMapPolygon(
const geometry_msgs::msg::Pose& pose,
const geometry_msgs::msg::Vector3& size)
291 tf2::Transform object_tf;
292 tf2::fromMsg(pose, object_tf);
294 double half_x_bound = size.x / 2;
295 double half_y_bound = size.y / 2;
298 tf2::Vector3 obj_p1(half_x_bound, half_y_bound, 0);
299 tf2::Vector3 obj_p2(half_x_bound, -half_y_bound, 0);
300 tf2::Vector3 obj_p3(-half_x_bound, -half_y_bound, 0);
301 tf2::Vector3 obj_p4(-half_x_bound, half_y_bound, 0);
303 tf2::Vector3 obj_p1_map = object_tf * obj_p1;
304 tf2::Vector3 obj_p2_map = object_tf * obj_p2;
305 tf2::Vector3 obj_p3_map = object_tf * obj_p3;
306 tf2::Vector3 obj_p4_map = object_tf * obj_p4;
308 lanelet::BasicPoint2d p1(obj_p1_map.getX(), obj_p1_map.getY());
309 lanelet::BasicPoint2d p2(obj_p2_map.getX(), obj_p2_map.getY());
310 lanelet::BasicPoint2d p3(obj_p3_map.getX(), obj_p3_map.getY());
311 lanelet::BasicPoint2d p4(obj_p4_map.getX(), obj_p4_map.getY());
313 return { p1, p2, p3, p4 };
318 if (lanelets.empty()) {
319 return lanelet::BasicLineString2d();
321 lanelet::BasicLineString2d centerline_points = lanelets[0].centerline2d().basicLineString();
322 lanelet::BasicLineString2d new_points;
323 for (
size_t i = 1;
i < lanelets.size();
i++) {
324 new_points = lanelets[
i].centerline2d().basicLineString();
328 return centerline_points;
331template <
class P,
class A>
336 if (centerline_points.empty()) {
337 throw std::invalid_argument(
"No points in centerline for curvature calculation");
341 std::vector<Eigen::Vector2d> normalized_tangent_vectors =
normalize_vectors(spatial_derivative);
345 std::vector<Eigen::Vector2d> tangent_derivative =
347 normalized_tangent_vectors,
372lanelet::BasicLineString2d
374 const lanelet::BasicLineString2d& b)
376 lanelet::BasicLineString2d out;
378 int start_offset = 0;
383 out.insert(out.end(), a.begin(), a.end());
384 out.insert(out.end(), b.begin() + start_offset, b.end());
389template <
class P,
class A>
390std::vector<Eigen::Vector2d>
393 std::vector<Eigen::Vector2d> out;
394 Eigen::Vector2d diff;
395 Eigen::Vector2d vec_i_plus_1;
396 Eigen::Vector2d vec_i_minus_1;
398 for (
size_t i = 0;
i <
data.size();
i++) {
402 }
else if (
i ==
data.size() - 1) {
407 vec_i_plus_1 =
data[
i + 1];
408 vec_i_minus_1 =
data[
i - 1];
409 diff = (vec_i_plus_1 - vec_i_minus_1)/2.0;
418std::vector<Eigen::Vector2d>
431 std::vector<double> out;
433 for (
size_t i = 0;
i <
data.size();
i++) {
437 }
else if (
i ==
data.size() - 1) {
449std::vector<Eigen::Vector2d>
452 if (
x.size() !=
y.size()) {
453 throw std::invalid_argument(
"Attempting to differentiate two unequal sized lists!");
456 std::vector<Eigen::Vector2d> out;
457 Eigen::Vector2d diff;
458 for (
size_t i = 0;
i <
x.size();
i++) {
460 diff = (
x[
i + 1] -
x[
i])/(
y[
i + 1] -
y[
i]);
461 }
else if (
i ==
x.size() - 1) {
462 diff = (
x[
i] -
x[
i - 1])/(
y[
i] -
y[
i - 1]);
464 diff = (
x[
i + 1] -
x[
i - 1])/(
y[
i + 1] -
y[
i - 1]);
473template <
class P,
class A>
476 std::vector<double> out;
479 for (
size_t i = 0;
i <
data.size();
i++) {
485 out.push_back(total);
506 return std::sqrt(std::pow(b[0] - a[0], 2) + std::pow(b[1] - a[1], 2));
509std::vector<Eigen::Vector2d>
512 std::vector<Eigen::Vector2d> out;
513 for (
auto vec : vectors) {
514 out.push_back(vec.normalized());
522 std::vector<double> out;
523 for (
auto vec : vectors) {
524 out.push_back(vec.norm());
530template<
class P,
class A>
534 std::vector<double> out;
535 if (centerline.empty())
540 for (
auto tangent : tangents)
542 geometry_msgs::msg::Quaternion q;
546 double norm = tangent.norm();
548 auto normalized_tanged = tangent / norm;
549 yaw = atan2(normalized_tanged[1], normalized_tanged[0]);
571 Eigen::Vector2d scale(1.0, 1.0);
572 Eigen::Isometry2d tf;
573 return tf.fromPositionOrientationScale(position, rotation, scale);
577 Eigen::Vector3d scale(1.0, 1.0, 1.0);
578 Eigen::Isometry3d tf;
579 return tf.fromPositionOrientationScale(position, rotation, scale);
583 Eigen::Vector3d scale(1.0, 1.0, 1.0);
584 Eigen::Isometry3d tf;
585 return tf.fromPositionOrientationScale(position, rotation, scale);
588double point_to_point_yaw(
const lanelet::BasicPoint2d& cur_point,
const lanelet::BasicPoint2d& next_point)
590 double dx = next_point[0] - cur_point[0];
591 double dy = next_point[1] - cur_point[1];
592 double yaw = atan2(dy, dx);
598 double dist = sqrt(pow(cur_point[0] - next_point[0], 2) + pow(cur_point[1] - next_point[1], 2));
602 double r = 0.5 * (dist / std::sin(angle));
604 double max_curvature = 100000;
605 double curvature = std::min(1 / r, max_curvature);
611 std::vector<double> curvatures;
612 curvatures.reserve(points.size());
614 if (lookahead <= 0) {
615 throw std::invalid_argument(
"local_circular_arc_curvatures lookahead must be greater than 0");
618 if (points.empty()) {
621 else if (points.size() == 1) {
622 curvatures.push_back(0.0);
626 for (
size_t i = 0;
i < points.size() - 1;
i++)
628 size_t next_point_index =
i + lookahead;
629 if (next_point_index >= points.size()) {
630 next_point_index = points.size() - 1;
633 curvatures.push_back(fabs(cur));
635 curvatures.push_back(curvatures.back());
Position in a track based coordinate system where the axis are downtrack and crosstrack....
Eigen::Isometry3d build3dEigenTransform(const Eigen::Vector3d &position, const Eigen::Quaterniond &rotation)
Builds a 3D Eigen coordinate frame transform with not applied scaling (only translation and rotation)...
std::vector< double > compute_templated_tangent_orientations(const std::vector< P, A > ¢erline)
lanelet::BasicPolygon2d objectToMapPolygon(const geometry_msgs::msg::Pose &pose, const geometry_msgs::msg::Vector3 &size)
Uses the provided pose and size vector of an ExternalObject to compute what the polygon would be of t...
std::vector< double > local_curvatures(const lanelet::BasicLineString2d ¢erline_points)
Returns a list of local (computed by discrete derivative) curvatures for the input centerlines....
constexpr double SPATIAL_EPSILON_M
void rpyFromQuaternion(const tf2::Quaternion &q, double &roll, double &pitch, double &yaw)
Extract extrinsic roll-pitch-yaw from quaternion.
std::vector< double > compute_templated_arc_lengths(const std::vector< P, A > &data)
double safeAcos(double x)
acos method that caps the input x value for 1 or -1 to avoid undefined output. This is meant to preve...
std::vector< Eigen::Vector2d > normalize_vectors(const std::vector< Eigen::Vector2d > &vectors)
Normalize the vectors in the input list such that their magnitudes = 1.
double point_to_point_yaw(const lanelet::BasicPoint2d &cur_point, const lanelet::BasicPoint2d &next_point)
Computes the 2d orientation of the vector from the provided start point to end point.
double circular_arc_curvature(const lanelet::BasicPoint2d &cur_point, const lanelet::BasicPoint2d &next_point)
Computes the curvature of a circular arc that passes through the two provided points....
double compute_euclidean_distance(const Eigen::Vector2d &a, const Eigen::Vector2d &b)
Compute the Euclidean distance between the two points.
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::tuple< TrackPos, lanelet::BasicSegment2d > matchSegment(const lanelet::BasicPoint2d &p, const lanelet::BasicLineString2d &line_string)
Get the TrackPos of the provided point along the linestring and the segment of the line string which ...
double safeAsin(double x)
asin method that caps the input x value for 1 or -1 to avoid undefined output. This is meant to preve...
double getAngleBetweenVectors(const Eigen::Vector2d &vec1, const Eigen::Vector2d &vec2)
Calculates the angle between two vectors.
std::vector< double > compute_tangent_orientations(const lanelet::BasicLineString2d ¢erline)
Compute an approximate orientation for the vehicle at each point along the provided centerline.
lanelet::BasicLineString2d concatenate_lanelets(const std::vector< lanelet::ConstLanelet > &lanelets)
Helper function to a list of lanelets together and return the result. Neither LineString is modified ...
std::vector< double > templated_local_curvatures(const std::vector< P, A > ¢erline_points)
std::vector< double > compute_arc_lengths(const std::vector< lanelet::BasicPoint2d > &data)
Compute the arc length at each point around the curve.
bool selectFirstSegment(const TrackPos &first_seg_trackPos, const TrackPos &second_seg_trackPos, double first_seg_length, double second_seg_length)
Helper function to identify whether to select the preceeding or succeeding segment of a linstring poi...
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::vector< Eigen::Vector2d > compute_templated_finite_differences(const std::vector< P, A > &data)
double computeCurvature(const lanelet::BasicPoint2d &p1, const lanelet::BasicPoint2d &p2, const lanelet::BasicPoint2d &p3)
Function for computing curvature from 3 points.
TrackPos trackPos(const lanelet::ConstLanelet &lanelet, const lanelet::BasicPoint2d &point)
Returns the TrackPos, computed in 2d, of the provided point relative to the centerline of the provide...
std::vector< double > local_circular_arc_curvatures(const std::vector< lanelet::BasicPoint2d > &points, int lookahead)
Computes the curvature of each point in the provided list by calling circular_arc_curvature using tha...
std::vector< Eigen::Vector2d > compute_finite_differences(const lanelet::BasicLineString2d &data)
Use finite differences methods to compute the derivative of the input data set with respect to index ...
std::vector< double > compute_magnitude_of_vectors(const std::vector< Eigen::Vector2d > &vectors)
Compute the magnitude of each vector in the input list.
void convert(const carma_v2x_msgs::msg::PSM &in_msg, carma_perception_msgs::msg::ExternalObject &out_msg, const std::string &map_frame_id, double pred_period, double pred_step_size, const lanelet::projection::LocalFrameProjector &map_projector, const tf2::Quaternion &ned_in_map_rotation, rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock)