Skip to content

Commit 289376b

Browse files
purewater0901boyali
authored andcommitted
feat(motion_utils): add resampling function to motion utils (tier4#1374)
* feat(interpolation): add zero order hold interpolation Signed-off-by: yutaka <purewater0901@gmail.com> * feat(motion_utils): add resample path function Signed-off-by: yutaka <purewater0901@gmail.com> * change file name Signed-off-by: yutaka <purewater0901@gmail.com> * add tests Signed-off-by: yutaka <purewater0901@gmail.com> * add more tests Signed-off-by: yutaka <purewater0901@gmail.com> * fix some tests Signed-off-by: yutaka <purewater0901@gmail.com> * add explanation Signed-off-by: yutaka <purewater0901@gmail.com>
1 parent fa37378 commit 289376b

File tree

4 files changed

+681
-0
lines changed

4 files changed

+681
-0
lines changed

common/motion_utils/include/motion_utils/motion_utils.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define MOTION_UTILS__MOTION_UTILS_HPP_
1717

1818
#include "motion_utils/marker/marker_helper.hpp"
19+
#include "motion_utils/resample/path.hpp"
1920
#include "motion_utils/trajectory/tmp_conversion.hpp"
2021
#include "motion_utils/trajectory/trajectory.hpp"
2122
#include "motion_utils/vehicle/vehicle_state_checker.hpp"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
// Copyright 2022 TIER IV, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef MOTION_UTILS__RESAMPLE__PATH_HPP_
16+
#define MOTION_UTILS__RESAMPLE__PATH_HPP_
17+
18+
#include "interpolation/interpolation_utils.hpp"
19+
#include "interpolation/linear_interpolation.hpp"
20+
#include "interpolation/spline_interpolation.hpp"
21+
#include "interpolation/zero_order_hold.hpp"
22+
#include "motion_utils/trajectory/trajectory.hpp"
23+
#include "tier4_autoware_utils/geometry/geometry.hpp"
24+
#include "tier4_autoware_utils/geometry/pose_deviation.hpp"
25+
#include "tier4_autoware_utils/math/constants.hpp"
26+
27+
#include "autoware_auto_planning_msgs/msg/path.hpp"
28+
29+
#include <boost/optional.hpp>
30+
31+
#include <algorithm>
32+
#include <limits>
33+
#include <stdexcept>
34+
#include <vector>
35+
36+
namespace motion_utils
37+
{
38+
/**
39+
* @brief A resampling function for a path. Note that in a default setting, position xy are
40+
* resampled by spline interpolation, position z are resampled by linear interpolation, longitudinal
41+
* and lateral velocity are resampled by zero_order_hold, and heading rate is resampled by linear
42+
* interpolation. Orientation of the resampled path are calculated by a forward difference method
43+
* based on the interpolated position x and y.
44+
* @param input_path input path to resample
45+
* @param resampled_arclength arclength that contains length of each resampling points from initial
46+
* point
47+
* @param use_lerp_for_xy If this is true, it uses linear interpolation to resample position x and
48+
* y. Otherwise, it uses spline interpolation
49+
* @param use_lerp_for_z If this is true, it uses linear interpolation to resample position z.
50+
* Otherwise, it uses spline interpolation
51+
* @param use_zero_order_hold_for_v If this is true, it uses zero_order_hold to resample
52+
* longitudinal and lateral velocity. Otherwise, it uses linear interpolation
53+
* @return resampled path
54+
*/
55+
inline autoware_auto_planning_msgs::msg::Path resamplePath(
56+
const autoware_auto_planning_msgs::msg::Path & input_path,
57+
const std::vector<double> & resampled_arclength, const bool use_lerp_for_xy = false,
58+
const bool use_lerp_for_z = true, const bool use_zero_order_hold_for_v = true)
59+
{
60+
// Check vector size and if out_arclength have the end point of the path
61+
const double input_path_len = motion_utils::calcArcLength(input_path.points);
62+
if (
63+
input_path.points.size() < 2 || resampled_arclength.size() < 2 ||
64+
input_path_len < resampled_arclength.back()) {
65+
std::cerr
66+
<< "[motion_utils]: input path size, input path length or resampled arclength is wrong"
67+
<< std::endl;
68+
return input_path;
69+
}
70+
71+
// Input Path Information
72+
std::vector<double> input_arclength(input_path.points.size());
73+
std::vector<double> x(input_path.points.size());
74+
std::vector<double> y(input_path.points.size());
75+
std::vector<double> z(input_path.points.size());
76+
std::vector<double> v_lon(input_path.points.size());
77+
std::vector<double> v_lat(input_path.points.size());
78+
std::vector<double> heading_rate(input_path.points.size());
79+
80+
input_arclength.front() = 0.0;
81+
x.front() = input_path.points.front().pose.position.x;
82+
y.front() = input_path.points.front().pose.position.y;
83+
z.front() = input_path.points.front().pose.position.z;
84+
v_lon.front() = input_path.points.front().longitudinal_velocity_mps;
85+
v_lat.front() = input_path.points.front().lateral_velocity_mps;
86+
heading_rate.front() = input_path.points.front().heading_rate_rps;
87+
for (size_t i = 1; i < input_path.points.size(); ++i) {
88+
const auto & prev_pt = input_path.points.at(i - 1);
89+
const auto & curr_pt = input_path.points.at(i);
90+
const double ds =
91+
tier4_autoware_utils::calcDistance2d(prev_pt.pose.position, curr_pt.pose.position);
92+
input_arclength.at(i) = ds + input_arclength.at(i - 1);
93+
x.at(i) = curr_pt.pose.position.x;
94+
y.at(i) = curr_pt.pose.position.y;
95+
z.at(i) = curr_pt.pose.position.z;
96+
v_lon.at(i) = curr_pt.longitudinal_velocity_mps;
97+
v_lat.at(i) = curr_pt.lateral_velocity_mps;
98+
heading_rate.at(i) = curr_pt.heading_rate_rps;
99+
}
100+
101+
// Interpolate
102+
const auto lerp = [&](const auto & input) {
103+
return interpolation::lerp(input_arclength, input, resampled_arclength);
104+
};
105+
const auto slerp = [&](const auto & input) {
106+
return interpolation::slerp(input_arclength, input, resampled_arclength);
107+
};
108+
const auto zoh = [&](const auto & input) {
109+
return interpolation::zero_order_hold(input_arclength, input, resampled_arclength);
110+
};
111+
112+
const auto interpolated_x = use_lerp_for_xy ? lerp(x) : slerp(x);
113+
const auto interpolated_y = use_lerp_for_xy ? lerp(y) : slerp(y);
114+
const auto interpolated_z = use_lerp_for_z ? lerp(z) : slerp(z);
115+
const auto interpolated_v_lon = use_zero_order_hold_for_v ? zoh(v_lon) : lerp(v_lon);
116+
const auto interpolated_v_lat = use_zero_order_hold_for_v ? zoh(v_lat) : lerp(v_lat);
117+
const auto interpolated_heading_rate = lerp(heading_rate);
118+
119+
autoware_auto_planning_msgs::msg::Path interpolated_path;
120+
interpolated_path.header = input_path.header;
121+
interpolated_path.drivable_area = input_path.drivable_area;
122+
interpolated_path.points.resize(interpolated_x.size());
123+
124+
// Insert Position, Velocity and Heading Rate
125+
for (size_t i = 0; i < interpolated_path.points.size(); ++i) {
126+
autoware_auto_planning_msgs::msg::PathPoint path_point;
127+
path_point.pose.position.x = interpolated_x.at(i);
128+
path_point.pose.position.y = interpolated_y.at(i);
129+
path_point.pose.position.z = interpolated_z.at(i);
130+
path_point.longitudinal_velocity_mps = interpolated_v_lon.at(i);
131+
path_point.lateral_velocity_mps = interpolated_v_lat.at(i);
132+
path_point.heading_rate_rps = interpolated_heading_rate.at(i);
133+
interpolated_path.points.at(i) = path_point;
134+
}
135+
136+
// Insert Orientation
137+
for (size_t i = 0; i < interpolated_path.points.size() - 1; ++i) {
138+
const auto & src_point = interpolated_path.points.at(i).pose.position;
139+
const auto & dst_point = interpolated_path.points.at(i + 1).pose.position;
140+
const double pitch = tier4_autoware_utils::calcElevationAngle(src_point, dst_point);
141+
const double yaw = tier4_autoware_utils::calcAzimuthAngle(src_point, dst_point);
142+
interpolated_path.points.at(i).pose.orientation =
143+
tier4_autoware_utils::createQuaternionFromRPY(0.0, pitch, yaw);
144+
if (i == interpolated_path.points.size() - 2) {
145+
// Terminal Orientation is same as the point before it
146+
interpolated_path.points.at(i + 1).pose.orientation =
147+
interpolated_path.points.at(i).pose.orientation;
148+
}
149+
}
150+
151+
return interpolated_path;
152+
}
153+
} // namespace motion_utils
154+
155+
#endif // MOTION_UTILS__RESAMPLE__PATH_HPP_

common/motion_utils/package.xml

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<depend>autoware_auto_vehicle_msgs</depend>
1616
<depend>builtin_interfaces</depend>
1717
<depend>geometry_msgs</depend>
18+
<depend>interpolation</depend>
1819
<depend>libboost-dev</depend>
1920
<depend>rclcpp</depend>
2021
<depend>tf2</depend>

0 commit comments

Comments
 (0)