Skip to content

Commit 18742ee

Browse files
authored
refactor(autoware_lanelet2_utils): reuse geometry helpers, fix int-narrowing, dedup offset-bound builders (#1128)
* refactor(autoware_lanelet2_utils): reuse geometry helpers, fix int-narrowing, dedup offset-bound builders Internal-only cleanup of src/geometry.cpp plus a coverage test for nn_search: - get_pose_from_2d_arc_length: replace the hand-rolled half-yaw quaternion and field-by-field point assignment with autoware_utils_geometry::create_quaternion_from_yaw / create_point. - get_closest_center_pose: use create_quaternion(0,0,0,1) for the identity orientation fallback instead of a hand-written literal. - compute_num_segments: compute the segment count directly in size_t (std::ceil + std::max<size_t>) to avoid the prior int narrowing. - Factor the four near-identical offset-bound builders (get_fine_centerline, get_centerline_with_offset, get_right_bound_with_offset, get_left_bound_with_offset) into a single anonymous-namespace helper build_offset_linestring that takes the per-point formula, the point-id policy, and a diagnostic context string. The left-bound builder keeps its unique-id behavior; the other three keep InvalId. - Add TestNNSearchZRange covering find_nearest's previously untested z-range filtering branch (above-range, below-range, in-range, filter-disabled) and the early-return guards (count==0, r_range<0, z_range<0, no candidate). All public signatures are unchanged. The only observable difference is the text of one RCLCPP_ERROR diagnostic in get_centerline_with_offset, which now matches the shared helper's message; the returned value (empty linestring) is unchanged. Refs: #1096 Signed-off-by: Yutaka Kondo <yutaka.kondo@youtalk.jp> * style(autoware_lanelet2_utils): add <vector> include to satisfy cpplint Signed-off-by: Yutaka Kondo <yutaka.kondo@youtalk.jp> --------- Signed-off-by: Yutaka Kondo <yutaka.kondo@youtalk.jp>
1 parent a451577 commit 18742ee

2 files changed

Lines changed: 208 additions & 129 deletions

File tree

common/autoware_lanelet2_utils/src/geometry.cpp

Lines changed: 84 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@
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

3638
namespace 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

106158
lanelet::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(
626670
lanelet::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

657679
lanelet::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

694692
lanelet::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

727704
lanelet::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

761716
bool is_in_lanelet(

0 commit comments

Comments
 (0)