Skip to content

Commit 41d6312

Browse files
feat(autoware_test_utils): add path with lane id parser (#9098)
* add path with lane id parser Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> * refactor parse to use template Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp> --------- Signed-off-by: Zulfaqar Azmi <zulfaqar.azmi@tier4.jp>
1 parent 99b8664 commit 41d6312

File tree

7 files changed

+267
-77
lines changed

7 files changed

+267
-77
lines changed

common/autoware_test_utils/include/autoware_test_utils/mock_data_parser.hpp

+53-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <autoware_planning_msgs/msg/lanelet_route.hpp>
2020
#include <autoware_planning_msgs/msg/lanelet_segment.hpp>
2121
#include <geometry_msgs/msg/pose.hpp>
22+
#include <tier4_planning_msgs/msg/path_with_lane_id.hpp>
2223

2324
#include <yaml-cpp/yaml.h>
2425

@@ -30,17 +31,64 @@ namespace autoware::test_utils
3031
using autoware_planning_msgs::msg::LaneletPrimitive;
3132
using autoware_planning_msgs::msg::LaneletRoute;
3233
using autoware_planning_msgs::msg::LaneletSegment;
34+
using geometry_msgs::msg::Point;
3335
using geometry_msgs::msg::Pose;
36+
using std_msgs::msg::Header;
37+
using tier4_planning_msgs::msg::PathPointWithLaneId;
38+
using tier4_planning_msgs::msg::PathWithLaneId;
3439

35-
Pose parse_pose(const YAML::Node & node);
40+
/**
41+
* @brief Parses a YAML node and converts it into an object of type T.
42+
*
43+
* This function extracts data from the given YAML node and converts it into an object of type T.
44+
* If no specialization exists for T, it will result in a compile-time error.
45+
*
46+
* @tparam T The type of object to parse the node contents into.
47+
* @param node The YAML node to be parsed.
48+
* @return T An object of type T containing the parsed data.
49+
*/
50+
template <typename T>
51+
T parse(const YAML::Node & node);
3652

37-
LaneletPrimitive parse_lanelet_primitive(const YAML::Node & node);
53+
template <>
54+
Pose parse(const YAML::Node & node);
3855

39-
std::vector<LaneletPrimitive> parse_lanelet_primitives(const YAML::Node & node);
56+
template <>
57+
LaneletPrimitive parse(const YAML::Node & node);
4058

41-
std::vector<LaneletSegment> parse_segments(const YAML::Node & node);
59+
template <>
60+
std::vector<LaneletPrimitive> parse(const YAML::Node & node);
4261

43-
LaneletRoute parse_lanelet_route_file(const std::string & filename);
62+
template <>
63+
std::vector<LaneletSegment> parse(const YAML::Node & node);
64+
65+
template <>
66+
std::vector<Point> parse(const YAML::Node & node);
67+
68+
template <>
69+
Header parse(const YAML::Node & node);
70+
71+
template <>
72+
std::vector<PathPointWithLaneId> parse(const YAML::Node & node);
73+
74+
/**
75+
* @brief Parses a YAML file and converts it into an object of type T.
76+
*
77+
* This function reads the specified YAML file and converts its contents into an object of the given
78+
* type T. If no specialization exists for T, it will result in a compile-time error.
79+
*
80+
* @tparam T The type of object to parse the file contents into.
81+
* @param filename The path to the YAML file to be parsed.
82+
* @return T An object of type T containing the parsed data.
83+
*/
84+
template <typename T>
85+
T parse(const std::string & filename);
86+
87+
template <>
88+
LaneletRoute parse(const std::string & filename);
89+
90+
template <>
91+
PathWithLaneId parse(const std::string & filename);
4492
} // namespace autoware::test_utils
4593

4694
#endif // AUTOWARE_TEST_UTILS__MOCK_DATA_PARSER_HPP_

common/autoware_test_utils/src/autoware_test_utils.cpp

+2-54
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <ament_index_cpp/get_package_share_directory.hpp>
1616
#include <autoware_test_utils/autoware_test_utils.hpp>
17+
#include <autoware_test_utils/mock_data_parser.hpp>
1718
#include <rclcpp/clock.hpp>
1819
#include <rclcpp/executors/single_threaded_executor.hpp>
1920
#include <rclcpp/logging.hpp>
@@ -301,60 +302,7 @@ PathWithLaneId loadPathWithLaneIdInYaml()
301302
{
302303
const auto yaml_path =
303304
get_absolute_path_to_config("autoware_test_utils", "path_with_lane_id_data.yaml");
304-
YAML::Node yaml_node = YAML::LoadFile(yaml_path);
305-
PathWithLaneId path_msg;
306-
307-
// Convert YAML data to PathWithLaneId message
308-
// Fill the header
309-
path_msg.header.stamp.sec = yaml_node["header"]["stamp"]["sec"].as<int>();
310-
path_msg.header.stamp.nanosec = yaml_node["header"]["stamp"]["nanosec"].as<uint32_t>();
311-
path_msg.header.frame_id = yaml_node["header"]["frame_id"].as<std::string>();
312-
313-
// Fill the points
314-
for (const auto & point_node : yaml_node["points"]) {
315-
PathPointWithLaneId point;
316-
// Fill the PathPoint data
317-
point.point.pose.position.x = point_node["point"]["pose"]["position"]["x"].as<double>();
318-
point.point.pose.position.y = point_node["point"]["pose"]["position"]["y"].as<double>();
319-
point.point.pose.position.z = point_node["point"]["pose"]["position"]["z"].as<double>();
320-
point.point.pose.orientation.x = point_node["point"]["pose"]["orientation"]["x"].as<double>();
321-
point.point.pose.orientation.y = point_node["point"]["pose"]["orientation"]["y"].as<double>();
322-
point.point.pose.orientation.z = point_node["point"]["pose"]["orientation"]["z"].as<double>();
323-
point.point.pose.orientation.w = point_node["point"]["pose"]["orientation"]["w"].as<double>();
324-
point.point.longitudinal_velocity_mps =
325-
point_node["point"]["longitudinal_velocity_mps"].as<float>();
326-
point.point.lateral_velocity_mps = point_node["point"]["lateral_velocity_mps"].as<float>();
327-
point.point.heading_rate_rps = point_node["point"]["heading_rate_rps"].as<float>();
328-
point.point.is_final = point_node["point"]["is_final"].as<bool>();
329-
// Fill the lane_ids
330-
for (const auto & lane_id_node : point_node["lane_ids"]) {
331-
point.lane_ids.push_back(lane_id_node.as<int64_t>());
332-
}
333-
334-
path_msg.points.push_back(point);
335-
}
336-
337-
// Fill the left_bound
338-
for (const auto & point_node : yaml_node["left_bound"]) {
339-
Point point;
340-
// Fill the Point data (left_bound)
341-
point.x = point_node["x"].as<double>();
342-
point.y = point_node["y"].as<double>();
343-
point.z = point_node["z"].as<double>();
344305

345-
path_msg.left_bound.push_back(point);
346-
}
347-
348-
// Fill the right_bound
349-
for (const auto & point_node : yaml_node["right_bound"]) {
350-
Point point;
351-
// Fill the Point data
352-
point.x = point_node["x"].as<double>();
353-
point.y = point_node["y"].as<double>();
354-
point.z = point_node["z"].as<double>();
355-
356-
path_msg.right_bound.push_back(point);
357-
}
358-
return path_msg;
306+
return parse<PathWithLaneId>(yaml_path);
359307
}
360308
} // namespace autoware::test_utils

common/autoware_test_utils/src/mock_data_parser.cpp

+102-12
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929

3030
namespace autoware::test_utils
3131
{
32-
Pose parse_pose(const YAML::Node & node)
32+
template <>
33+
Pose parse(const YAML::Node & node)
3334
{
3435
Pose pose;
3536
pose.position.x = node["position"]["x"].as<double>();
@@ -42,7 +43,8 @@ Pose parse_pose(const YAML::Node & node)
4243
return pose;
4344
}
4445

45-
LaneletPrimitive parse_lanelet_primitive(const YAML::Node & node)
46+
template <>
47+
LaneletPrimitive parse(const YAML::Node & node)
4648
{
4749
LaneletPrimitive primitive;
4850
primitive.id = node["id"].as<int64_t>();
@@ -51,43 +53,131 @@ LaneletPrimitive parse_lanelet_primitive(const YAML::Node & node)
5153
return primitive;
5254
}
5355

54-
std::vector<LaneletPrimitive> parse_lanelet_primitives(const YAML::Node & node)
56+
template <>
57+
std::vector<LaneletPrimitive> parse(const YAML::Node & node)
5558
{
5659
std::vector<LaneletPrimitive> primitives;
5760
primitives.reserve(node.size());
5861
std::transform(node.begin(), node.end(), std::back_inserter(primitives), [&](const auto & p) {
59-
return parse_lanelet_primitive(p);
62+
return parse<LaneletPrimitive>(p);
6063
});
6164

6265
return primitives;
6366
}
6467

65-
std::vector<LaneletSegment> parse_segments(const YAML::Node & node)
68+
template <>
69+
std::vector<LaneletSegment> parse(const YAML::Node & node)
6670
{
6771
std::vector<LaneletSegment> segments;
6872
std::transform(node.begin(), node.end(), std::back_inserter(segments), [&](const auto & input) {
6973
LaneletSegment segment;
70-
segment.preferred_primitive = parse_lanelet_primitive(input["preferred_primitive"]);
71-
segment.primitives = parse_lanelet_primitives(input["primitives"]);
74+
segment.preferred_primitive = parse<LaneletPrimitive>(input["preferred_primitive"]);
75+
segment.primitives = parse<std::vector<LaneletPrimitive>>(input["primitives"]);
7276
return segment;
7377
});
7478

7579
return segments;
7680
}
7781

78-
// cppcheck-suppress unusedFunction
79-
LaneletRoute parse_lanelet_route_file(const std::string & filename)
82+
template <>
83+
std::vector<Point> parse(const YAML::Node & node)
84+
{
85+
std::vector<Point> geom_points;
86+
87+
std::transform(
88+
node.begin(), node.end(), std::back_inserter(geom_points), [&](const YAML::Node & input) {
89+
Point point;
90+
point.x = input["x"].as<double>();
91+
point.y = input["y"].as<double>();
92+
point.z = input["z"].as<double>();
93+
return point;
94+
});
95+
96+
return geom_points;
97+
}
98+
99+
template <>
100+
Header parse(const YAML::Node & node)
101+
{
102+
Header header;
103+
104+
if (!node["header"]) {
105+
return header;
106+
}
107+
108+
header.stamp.sec = node["header"]["stamp"]["sec"].as<int>();
109+
header.stamp.nanosec = node["header"]["stamp"]["nanosec"].as<uint32_t>();
110+
header.frame_id = node["header"]["frame_id"].as<std::string>();
111+
112+
return header;
113+
}
114+
115+
template <>
116+
std::vector<PathPointWithLaneId> parse<std::vector<PathPointWithLaneId>>(const YAML::Node & node)
117+
{
118+
std::vector<PathPointWithLaneId> path_points;
119+
120+
if (!node["points"]) {
121+
return path_points;
122+
}
123+
124+
const auto & points = node["points"];
125+
path_points.reserve(points.size());
126+
std::transform(
127+
points.begin(), points.end(), std::back_inserter(path_points), [&](const YAML::Node & input) {
128+
PathPointWithLaneId point;
129+
if (!input["point"]) {
130+
return point;
131+
}
132+
const auto & point_node = input["point"];
133+
point.point.pose = parse<Pose>(point_node["pose"]);
134+
135+
point.point.longitudinal_velocity_mps = point_node["longitudinal_velocity_mps"].as<float>();
136+
point.point.lateral_velocity_mps = point_node["lateral_velocity_mps"].as<float>();
137+
point.point.heading_rate_rps = point_node["heading_rate_rps"].as<float>();
138+
point.point.is_final = point_node["is_final"].as<bool>();
139+
// Fill the lane_ids
140+
for (const auto & lane_id_node : input["lane_ids"]) {
141+
point.lane_ids.push_back(lane_id_node.as<int64_t>());
142+
}
143+
144+
return point;
145+
});
146+
147+
return path_points;
148+
}
149+
150+
template <>
151+
LaneletRoute parse(const std::string & filename)
80152
{
81153
LaneletRoute lanelet_route;
82154
try {
83155
YAML::Node config = YAML::LoadFile(filename);
84156

85-
lanelet_route.start_pose = (config["start_pose"]) ? parse_pose(config["start_pose"]) : Pose();
86-
lanelet_route.goal_pose = (config["goal_pose"]) ? parse_pose(config["goal_pose"]) : Pose();
87-
lanelet_route.segments = parse_segments(config["segments"]);
157+
lanelet_route.start_pose = (config["start_pose"]) ? parse<Pose>(config["start_pose"]) : Pose();
158+
lanelet_route.goal_pose = (config["goal_pose"]) ? parse<Pose>(config["goal_pose"]) : Pose();
159+
lanelet_route.segments = parse<std::vector<LaneletSegment>>(config["segments"]);
88160
} catch (const std::exception & e) {
89161
RCLCPP_DEBUG(rclcpp::get_logger("autoware_test_utils"), "Exception caught: %s", e.what());
90162
}
91163
return lanelet_route;
92164
}
165+
166+
template <>
167+
PathWithLaneId parse(const std::string & filename)
168+
{
169+
PathWithLaneId path;
170+
try {
171+
YAML::Node yaml_node = YAML::LoadFile(filename);
172+
173+
path.header = parse<Header>(yaml_node);
174+
path.points = parse<std::vector<PathPointWithLaneId>>(yaml_node);
175+
path.left_bound = parse<std::vector<Point>>(yaml_node["left_bound"]);
176+
path.right_bound = parse<std::vector<Point>>(yaml_node["right_bound"]);
177+
} catch (const std::exception & e) {
178+
RCLCPP_DEBUG(rclcpp::get_logger("autoware_test_utils"), "Exception caught: %s", e.what());
179+
}
180+
181+
return path;
182+
}
93183
} // namespace autoware::test_utils

0 commit comments

Comments
 (0)