2929#include < lanelet2_core/primitives/Point.h>
3030
3131#include < algorithm>
32+ #include < cmath>
3233#include < iostream>
3334#include < limits>
35+ #include < string>
3436#include < vector>
3537
3638namespace autoware ::experimental::lanelet2_utils
@@ -45,7 +47,8 @@ size_t compute_num_segments(const lanelet::ConstLanelet & lanelet, const double
4547 const double left_length = static_cast <double >(lanelet::geometry::length (lanelet.leftBound ()));
4648 const double right_length = static_cast <double >(lanelet::geometry::length (lanelet.rightBound ()));
4749 const double longer_distance = (left_length > right_length) ? left_length : right_length;
48- const size_t num_segments = std::max (static_cast <int >(ceil (longer_distance / resolution)), 1 );
50+ const size_t num_segments =
51+ static_cast <size_t >(std::max (std::ceil (longer_distance / resolution), 1.0 ));
4952 return num_segments;
5053}
5154
@@ -101,6 +104,55 @@ lanelet::BasicPoints3d resample_points(
101104 }
102105 return resampled_points;
103106}
107+
108+ /* *
109+ * @brief Build an offset linestring by resampling a lanelet's left/right bounds and applying a
110+ * per-point formula.
111+ *
112+ * This factors out the shared scaffolding of get_fine_centerline / get_centerline_with_offset /
113+ * get_right_bound_with_offset / get_left_bound_with_offset, which only differ in the per-point
114+ * formula, the id assigned to each generated point, and the diagnostic message on failure.
115+ *
116+ * @param lanelet_obj Source lanelet whose bounds are resampled.
117+ * @param resolution Resampling resolution forwarded to compute_num_segments.
118+ * @param use_unique_id If true, each generated point gets a fresh id via lanelet::utils::getId();
119+ * otherwise lanelet::InvalId is used.
120+ * @param error_context Substring inserted into the diagnostic message when fewer than two points
121+ * are produced.
122+ * @param point_fn Formula mapping the resampled left/right points at an index to a 3d point.
123+ * @return The assembled linestring, or an empty linestring if fewer than two points are produced.
124+ */
125+ template <typename PointFn>
126+ lanelet::ConstLineString3d build_offset_linestring (
127+ const lanelet::ConstLanelet & lanelet_obj, const double resolution, const bool use_unique_id,
128+ const std::string & error_context, PointFn && point_fn)
129+ {
130+ // get number of segments from resolution and longer bound
131+ const auto num_segments = compute_num_segments (lanelet_obj, resolution);
132+
133+ // Resample points
134+ const auto left_points = resample_points (lanelet_obj.leftBound ().basicLineString (), num_segments);
135+ const auto right_points =
136+ resample_points (lanelet_obj.rightBound ().basicLineString (), num_segments);
137+
138+ lanelet::ConstPoints3d points;
139+ points.reserve (num_segments + 1 );
140+ for (size_t i = 0 ; i < num_segments + 1 ; i++) {
141+ const lanelet::BasicPoint3d basic_point = point_fn (left_points.at (i), right_points.at (i));
142+ const lanelet::Id id = use_unique_id ? lanelet::utils::getId () : lanelet::InvalId;
143+ points.emplace_back (id, basic_point.x (), basic_point.y (), basic_point.z ());
144+ }
145+
146+ const auto linestring_opt = create_safe_linestring (points);
147+ if (!linestring_opt.has_value ()) {
148+ RCLCPP_ERROR (
149+ rclcpp::get_logger (" autoware_lanelet2_utility" ),
150+ " %s has less than two points. Returning empty linestring." , error_context.c_str ());
151+ return lanelet::ConstLineString3d ();
152+ }
153+
154+ return *linestring_opt;
155+ }
104156} // namespace
105157
106158lanelet::ConstPoint3d extrapolate_point (
@@ -268,18 +320,13 @@ std::optional<geometry_msgs::msg::Pose> get_pose_from_2d_arc_length(
268320 if (!const_pt.has_value ()) {
269321 return std::nullopt ;
270322 }
271- auto P = const_pt.value ().basicPoint ();
323+ const auto P = const_pt.value ().basicPoint ();
272324
273- double half_yaw = std::atan2 (next_pt.y () - pt.y (), next_pt.x () - pt.x ()) * 0.5 ;
325+ const double yaw = std::atan2 (next_pt.y () - pt.y (), next_pt.x () - pt.x ());
274326
275327 geometry_msgs::msg::Pose pose;
276- pose.position .x = P.x ();
277- pose.position .y = P.y ();
278- pose.position .z = P.z ();
279- pose.orientation .x = 0.0 ;
280- pose.orientation .y = 0.0 ;
281- pose.orientation .z = std::sin (half_yaw);
282- pose.orientation .w = std::cos (half_yaw);
328+ pose.position = autoware_utils_geometry::create_point (P.x (), P.y (), P.z ());
329+ pose.orientation = autoware_utils_geometry::create_quaternion_from_yaw (yaw);
283330
284331 return pose;
285332 }
@@ -370,10 +417,7 @@ geometry_msgs::msg::Pose get_closest_center_pose(
370417 if (segment.empty ()) {
371418 geometry_msgs::msg::Pose closest_pose;
372419 closest_pose.position = to_ros (lanelet.centerline ().front (), search_pt.z ());
373- closest_pose.orientation .x = 0.0 ;
374- closest_pose.orientation .y = 0.0 ;
375- closest_pose.orientation .z = 0.0 ;
376- closest_pose.orientation .w = 1.0 ;
420+ closest_pose.orientation = autoware_utils_geometry::create_quaternion (0.0 , 0.0 , 0.0 , 1.0 );
377421 return closest_pose;
378422 }
379423
@@ -626,136 +670,47 @@ std::optional<lanelet::ConstLanelets> get_dirty_expanded_lanelets(
626670lanelet::ConstLineString3d get_fine_centerline (
627671 const lanelet::ConstLanelet & lanelet_obj, const double resolution)
628672{
629- // get number of segments from resolution and longer bound
630- const auto num_segments = compute_num_segments (lanelet_obj, resolution);
631-
632- // Resample points
633- const auto left_points = resample_points (lanelet_obj.leftBound ().basicLineString (), num_segments);
634- const auto right_points =
635- resample_points (lanelet_obj.rightBound ().basicLineString (), num_segments);
636-
637- lanelet::ConstPoints3d center_points;
638- for (size_t i = 0 ; i < num_segments + 1 ; i++) {
639- const auto center_basic_point = (right_points.at (i) + left_points.at (i)) / 2 ;
640-
641- const lanelet::ConstPoint3d center_point (
642- lanelet::InvalId, center_basic_point.x (), center_basic_point.y (), center_basic_point.z ());
643- center_points.push_back (center_point);
644- }
645-
646- const auto centerline_opt = create_safe_linestring (center_points);
647- if (!centerline_opt.has_value ()) {
648- RCLCPP_ERROR (
649- rclcpp::get_logger (" autoware_lanelet2_utility" ),
650- " center_points has less than two points. Returning empty linestring." );
651- return lanelet::ConstLineString3d ();
652- }
653-
654- return *centerline_opt;
673+ return build_offset_linestring (
674+ lanelet_obj, resolution, /* use_unique_id=*/ false , " center_points" ,
675+ [](const lanelet::BasicPoint3d & left, const lanelet::BasicPoint3d & right)
676+ -> lanelet::BasicPoint3d { return (right + left) / 2 ; });
655677}
656678
657679lanelet::ConstLineString3d get_centerline_with_offset (
658680 const lanelet::ConstLanelet & lanelet_obj, const double offset, const double resolution)
659681{
660- // get number of segments from resolution and longer bound
661- const auto num_segments = compute_num_segments (lanelet_obj, resolution);
662-
663- // Resample points
664- const auto left_points = resample_points (lanelet_obj.leftBound ().basicLineString (), num_segments);
665- const auto right_points =
666- resample_points (lanelet_obj.rightBound ().basicLineString (), num_segments);
667-
668- lanelet::ConstPoints3d center_points;
669- for (size_t i = 0 ; i < num_segments + 1 ; i++) {
670- const auto center_basic_point = (right_points.at (i) + left_points.at (i)) / 2 ;
671-
672- const auto vec_right_2_left = (left_points.at (i) - right_points.at (i)).normalized ();
673-
674- const auto offset_center_basic_point = center_basic_point + vec_right_2_left * offset;
675-
676- const lanelet::ConstPoint3d center_point (
677- lanelet::InvalId, offset_center_basic_point.x (), offset_center_basic_point.y (),
678- offset_center_basic_point.z ());
679- center_points.push_back (center_point);
680- }
681-
682- const auto centerline_opt = create_safe_linestring (center_points);
683- if (!centerline_opt.has_value ()) {
684- RCLCPP_ERROR (
685- rclcpp::get_logger (" autoware_lanelet2_utility" ),
686- " center_points has less than two points in get_centerline_with_offset. "
687- " Returning empty linestring." );
688- return lanelet::ConstLineString3d ();
689- }
690-
691- return *centerline_opt;
682+ return build_offset_linestring (
683+ lanelet_obj, resolution, /* use_unique_id=*/ false , " center_points" ,
684+ [offset](const lanelet::BasicPoint3d & left, const lanelet::BasicPoint3d & right)
685+ -> lanelet::BasicPoint3d {
686+ const auto center_basic_point = (right + left) / 2 ;
687+ const auto vec_right_2_left = (left - right).normalized ();
688+ return center_basic_point + vec_right_2_left * offset;
689+ });
692690}
693691
694692lanelet::ConstLineString3d get_right_bound_with_offset (
695693 const lanelet::ConstLanelet & lanelet_obj, const double offset, const double resolution)
696694{
697- // get number of segments from resolution and longer bound
698- const auto num_segments = compute_num_segments (lanelet_obj, resolution);
699-
700- // Resample points
701- const auto left_points = resample_points (lanelet_obj.leftBound ().basicLineString (), num_segments);
702- const auto right_points =
703- resample_points (lanelet_obj.rightBound ().basicLineString (), num_segments);
704-
705- lanelet::ConstPoints3d right_bound_points;
706- for (size_t i = 0 ; i < num_segments + 1 ; i++) {
707- const auto vec_left_2_right = (right_points.at (i) - left_points.at (i)).normalized ();
708-
709- const auto offset_right_basic_point = right_points.at (i) + vec_left_2_right * offset;
710-
711- const lanelet::ConstPoint3d right_bound_point (
712- lanelet::InvalId, offset_right_basic_point.x (), offset_right_basic_point.y (),
713- offset_right_basic_point.z ());
714- right_bound_points.push_back (right_bound_point);
715- }
716- const auto right_bound_opt = create_safe_linestring (right_bound_points);
717- if (!right_bound_opt.has_value ()) {
718- RCLCPP_ERROR (
719- rclcpp::get_logger (" autoware_lanelet2_utility" ),
720- " right_bound_points has less than two points. Returning empty linestring." );
721- return lanelet::ConstLineString3d ();
722- }
723-
724- return *right_bound_opt;
695+ return build_offset_linestring (
696+ lanelet_obj, resolution, /* use_unique_id=*/ false , " right_bound_points" ,
697+ [offset](const lanelet::BasicPoint3d & left, const lanelet::BasicPoint3d & right)
698+ -> lanelet::BasicPoint3d {
699+ const auto vec_left_2_right = (right - left).normalized ();
700+ return right + vec_left_2_right * offset;
701+ });
725702}
726703
727704lanelet::ConstLineString3d get_left_bound_with_offset (
728705 const lanelet::ConstLanelet & lanelet_obj, const double offset, const double resolution)
729706{
730- // get number of segments from resolution and longer bound
731- const auto num_segments = compute_num_segments (lanelet_obj, resolution);
732-
733- // Resample points
734- const auto left_points = resample_points (lanelet_obj.leftBound ().basicLineString (), num_segments);
735- const auto right_points =
736- resample_points (lanelet_obj.rightBound ().basicLineString (), num_segments);
737-
738- lanelet::ConstPoints3d left_bound_points;
739- for (size_t i = 0 ; i < num_segments + 1 ; i++) {
740- const auto vec_right_2_left = (left_points.at (i) - right_points.at (i)).normalized ();
741-
742- const auto offset_left_basic_point = left_points.at (i) + vec_right_2_left * offset;
743-
744- const lanelet::ConstPoint3d left_bound_point (
745- lanelet::utils::getId (), offset_left_basic_point.x (), offset_left_basic_point.y (),
746- offset_left_basic_point.z ());
747- left_bound_points.push_back (left_bound_point);
748- }
749-
750- const auto left_bound_opt = create_safe_linestring (left_bound_points);
751- if (!left_bound_opt.has_value ()) {
752- RCLCPP_ERROR (
753- rclcpp::get_logger (" autoware_lanelet2_utility" ),
754- " left_bound_points has less than two points. Returning empty linestring." );
755- return lanelet::ConstLineString3d ();
756- }
757-
758- return *left_bound_opt;
707+ return build_offset_linestring (
708+ lanelet_obj, resolution, /* use_unique_id=*/ true , " left_bound_points" ,
709+ [offset](const lanelet::BasicPoint3d & left, const lanelet::BasicPoint3d & right)
710+ -> lanelet::BasicPoint3d {
711+ const auto vec_right_2_left = (left - right).normalized ();
712+ return left + vec_right_2_left * offset;
713+ });
759714}
760715
761716bool is_in_lanelet (
0 commit comments