Autoware.Auto
motion_common.hpp
Go to the documentation of this file.
1 // Copyright 2019 Christopher Ho
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 #ifndef MOTION_COMMON__MOTION_COMMON_HPP_
15 #define MOTION_COMMON__MOTION_COMMON_HPP_
16 
18 #include <autoware_auto_msgs/msg/control_diagnostic.hpp>
19 #include <autoware_auto_msgs/msg/trajectory.hpp>
20 #include <autoware_auto_msgs/msg/vehicle_control_command.hpp>
21 #include <autoware_auto_msgs/msg/vehicle_kinematic_state.hpp>
22 #include <geometry_msgs/msg/transform_stamped.hpp>
24 
25 #include <algorithm>
26 #include <cmath>
27 
28 namespace motion
29 {
30 namespace motion_common
31 {
32 // Use same representation as message type
35 using Diagnostic = autoware_auto_msgs::msg::ControlDiagnostic;
38 using Heading = decltype(decltype(State::state)::heading);
39 using Index = decltype(Trajectory::points)::size_type;
40 using Point = decltype(Trajectory::points)::value_type;
41 
43 MOTION_COMMON_PUBLIC bool is_past_point(const Point & state, const Point & pt) noexcept;
46 MOTION_COMMON_PUBLIC bool is_past_point(
47  const Point & state, const Point & current_pt, const Point & next_pt) noexcept;
49 MOTION_COMMON_PUBLIC
50 bool is_past_point(const Point & state, const Point & pt, Real nx, Real ny) noexcept;
51 
53 MOTION_COMMON_PUBLIC
54 bool is_aligned(Heading a, Heading b, Real dot_threshold);
55 
57 template<typename IsPastPointF>
59  const Trajectory & traj,
60  const State & state,
61  Index start_idx,
62  IsPastPointF is_past_point)
63 {
64  // Invariant: m_reference_trajectory.points.size > 0U
65  if (traj.points.empty()) {
66  return 0U;
67  }
68  auto next_idx = start_idx;
69  for (auto idx = start_idx; idx < traj.points.size() - 1U; ++idx) {
70  const auto current_pt = traj.points[idx];
71  const auto next_pt = traj.points[idx + 1U];
72 
73  // If I'm not past the next point, then I'm done
74  if (!is_past_point(state, current_pt, next_pt, traj)) {
75  break;
76  }
77  // Otherwise, update
78  next_idx = idx + 1U;
79  }
80  return next_idx;
81 }
82 
84 MOTION_COMMON_PUBLIC bool heading_ok(const Trajectory & traj);
85 
87 // Operations relating to algebraic manipulation of VehicleKinematicState and TrajectoryPoint
88 
90 MOTION_COMMON_PUBLIC void doTransform(
91  const Point & t_in,
92  Point & t_out,
93  const geometry_msgs::msg::TransformStamped & transform) noexcept;
95 MOTION_COMMON_PUBLIC void doTransform(
96  const State & t_in,
97  State & t_out,
98  const geometry_msgs::msg::TransformStamped & transform) noexcept;
99 
101 MOTION_COMMON_PUBLIC Real to_angle(Heading heading) noexcept;
102 
104 template<typename RealT>
105 Heading from_angle(RealT angle) noexcept
106 {
107  static_assert(std::is_floating_point<RealT>::value, "angle must be floating point");
108  Heading ret{};
109  ret.real = static_cast<decltype(ret.real)>(std::cos(angle * RealT{0.5}));
110  ret.imag = static_cast<decltype(ret.imag)>(std::sin(angle * RealT{0.5}));
111  return ret;
112 }
113 
118 template<typename QuatT>
119 Heading from_quat(QuatT quat) noexcept
120 {
121  Heading ret{};
122  ret.real = static_cast<decltype(ret.real)>(quat.w);
123  ret.imag = static_cast<decltype(ret.imag)>(quat.z);
124  return ret;
125 }
126 
131 template<typename QuatT>
132 QuatT to_quat(Heading heading) noexcept
133 {
134  QuatT quat{};
135  quat.w = static_cast<decltype(quat.w)>(heading.real);
136  quat.z = static_cast<decltype(quat.z)>(heading.imag);
137  return quat;
138 }
139 
141 template<typename T>
142 T clamp(T val, T min, T max)
143 {
144  if (max < min) {
145  throw std::domain_error{"max < min"};
146  }
147  return std::min(max, std::max(min, val));
148 }
149 
151 template<typename T, typename RealT = double>
152 T interpolate(T a, T b, RealT t)
153 {
154  static_assert(std::is_floating_point<RealT>::value, "t must be floating point");
155  t = clamp(t, RealT{0.0}, RealT{1.0});
156  const auto del = b - a;
157  return static_cast<T>(t * static_cast<RealT>(del)) + a;
158 }
159 
162 MOTION_COMMON_PUBLIC Heading nlerp(Heading a, Heading b, Real t);
163 // TODO(c.ho) proper slerp implementation
164 
166 template<typename SlerpF>
167 Point interpolate(Point a, Point b, Real t, SlerpF slerp_fn)
168 {
169  Point ret{rosidl_runtime_cpp::MessageInitialization::ALL};
170  {
171  const auto dt0 = time_utils::from_message(a.time_from_start);
172  const auto dt1 = time_utils::from_message(b.time_from_start);
173  ret.time_from_start = time_utils::to_message(time_utils::interpolate(dt0, dt1, t));
174  }
175  ret.x = interpolate(a.x, b.x, t);
176  ret.y = interpolate(a.y, b.y, t);
177  ret.heading = slerp_fn(a.heading, b.heading, t);
178  ret.longitudinal_velocity_mps =
179  interpolate(a.longitudinal_velocity_mps, b.longitudinal_velocity_mps, t);
180  ret.lateral_velocity_mps = interpolate(a.lateral_velocity_mps, b.lateral_velocity_mps, t);
181  ret.acceleration_mps2 = interpolate(a.acceleration_mps2, b.acceleration_mps2, t);
182  ret.heading_rate_rps = interpolate(a.heading_rate_rps, b.heading_rate_rps, t);
183  ret.front_wheel_angle_rad = interpolate(a.front_wheel_angle_rad, b.front_wheel_angle_rad, t);
184  ret.rear_wheel_angle_rad = interpolate(a.rear_wheel_angle_rad, b.rear_wheel_angle_rad, t);
185 
186  return ret;
187 }
188 
190 MOTION_COMMON_PUBLIC Point interpolate(Point a, Point b, Real t);
191 
193 template<typename SlerpF>
194 void sample(
195  const Trajectory & in,
196  Trajectory & out,
197  std::chrono::nanoseconds period,
198  SlerpF slerp_fn)
199 {
200  out.points.clear();
201  out.header = in.header;
202  if (in.points.empty()) {
203  return;
204  }
205  // Determine number of points
207  const auto last_time = from_message(in.points.back().time_from_start);
208  auto count_ = last_time / period;
209  // should round down
210  using SizeT = typename decltype(in.points)::size_type;
211  const auto count =
212  static_cast<SizeT>(std::min(count_, static_cast<decltype(count_)>(in.CAPACITY)));
213  out.points.reserve(count);
214  // Insert first point
215  out.points.push_back(in.points.front());
216  // Add remaining points
217  auto ref_duration = period;
218  auto after_current_ref_idx = SizeT{1};
219  for (auto idx = SizeT{1}; idx < count; ++idx) {
220  // Determine next reference index
221  for (auto jdx = after_current_ref_idx; jdx < in.points.size(); ++jdx) {
222  const auto & pt = in.points[jdx];
223  if (from_message(pt.time_from_start) > ref_duration) {
224  after_current_ref_idx = jdx;
225  break;
226  }
227  }
228  // Interpolate
229  {
230  const auto & curr_pt = in.points[after_current_ref_idx - 1U];
231  const auto & next_pt = in.points[after_current_ref_idx];
232  const auto dt = std::chrono::duration_cast<std::chrono::duration<Real>>(
233  from_message(next_pt.time_from_start) - from_message(curr_pt.time_from_start));
234  const auto dt_ = std::chrono::duration_cast<std::chrono::duration<Real>>(
235  ref_duration - from_message(curr_pt.time_from_start));
236  const auto t = dt_.count() / dt.count();
237  out.points.push_back(interpolate(curr_pt, next_pt, t, slerp_fn));
238  }
239  ref_duration += period;
240  }
241 }
242 
244 MOTION_COMMON_PUBLIC void sample(
245  const Trajectory & in,
246  Trajectory & out,
247  std::chrono::nanoseconds period);
248 
250 MOTION_COMMON_PUBLIC
251 void error(const Point & state, const Point & ref, Diagnostic & out) noexcept;
252 } // namespace motion_common
253 } // namespace motion
254 
256 {
257 namespace msg
258 {
259 // TODO(c.ho) these should go into some autoware_auto_msgs package
261 MOTION_COMMON_PUBLIC Complex32 operator+(Complex32 a, Complex32 b) noexcept;
263 MOTION_COMMON_PUBLIC Complex32 operator-(Complex32 a) noexcept;
265 MOTION_COMMON_PUBLIC Complex32 operator-(Complex32 a, Complex32 b) noexcept;
266 } // namespace msg
267 } // namespace autoware_auto_msgs
268 #endif // MOTION_COMMON__MOTION_COMMON_HPP_
QuatT to_quat(Heading heading) noexcept
Converts a simple heading representation into a quaternion-like object.
Definition: motion_common.hpp:132
MOTION_COMMON_PUBLIC Complex32 operator-(Complex32 a, Complex32 b) noexcept
Difference operator.
Definition: motion_common.cpp:244
autoware_auto_msgs::msg::VehicleKinematicState VehicleKinematicState
Definition: trajectory_spoofer.hpp:44
Heading from_angle(RealT angle) noexcept
Basic conversion.
Definition: motion_common.hpp:105
geometry_msgs::msg::TransformStamped TransformStamped
Definition: motion_testing_publisher.hpp:37
T
Definition: catr_diff.py:22
MOTION_COMMON_PUBLIC void doTransform(const Point &t_in, Point &t_out, const geometry_msgs::msg::TransformStamped &transform) noexcept
Apply transform to TrajectoryPoint.
Definition: motion_common.cpp:91
decltype(autoware_auto_msgs::msg::TrajectoryPoint::x) Real
Definition: motion_common.hpp:33
Index update_reference_index(const Trajectory &traj, const State &state, Index start_idx, IsPastPointF is_past_point)
Advance to the first trajectory point past state according to criterion is_past_point.
Definition: motion_common.hpp:58
TIME_UTILS_PUBLIC builtin_interfaces::msg::Time to_message(std::chrono::system_clock::time_point t)
Convert from std::chrono::time_point to time message.
Definition: time_utils.cpp:67
TIME_UTILS_PUBLIC std::chrono::nanoseconds interpolate(std::chrono::nanoseconds a, std::chrono::nanoseconds b, float t) noexcept
Standard interpolation.
Definition: time_utils.cpp:97
T interpolate(T a, T b, RealT t)
Standard linear interpolation.
Definition: motion_common.hpp:152
MOTION_COMMON_PUBLIC Heading nlerp(Heading a, Heading b, Real t)
Definition: motion_common.cpp:163
MOTION_COMMON_PUBLIC bool is_past_point(const Point &state, const Point &pt) noexcept
Check if a state is past a given trajectory point, assuming heading is correct.
Definition: motion_common.cpp:26
autoware_auto_msgs::msg::ControlDiagnostic Diagnostic
Definition: motion_common.hpp:35
decltype(Trajectory::points)::value_type Point
Definition: motion_common.hpp:40
autoware_auto_msgs::msg::Complex32 Complex32
Definition: trajectory_spoofer.hpp:40
autoware_auto_msgs::msg::Trajectory Trajectory
Definition: motion_common.hpp:37
Definition: motion_common.hpp:255
w
Definition: catr_diff.py:22
MOTION_COMMON_PUBLIC bool heading_ok(const Trajectory &traj)
Check that all heading values in a trajectory are normalized 2D quaternions.
Definition: motion_common.cpp:77
t
Definition: catr_diff.py:22
decltype(Trajectory::points)::size_type Index
Definition: motion_common.hpp:39
MOTION_COMMON_PUBLIC void error(const Point &state, const Point &ref, Diagnostic &out) noexcept
Diagnostic header stuff.
Definition: motion_common.cpp:198
TIME_UTILS_PUBLIC std::chrono::system_clock::time_point from_message(builtin_interfaces::msg::Time t) noexcept
Convert from std::chrono::time_point from time message.
Definition: time_utils.cpp:80
a
Definition: catr_diff.py:22
DifferentialState x
Definition: kinematic_bicycle.snippet.hpp:28
MOTION_COMMON_PUBLIC Complex32 operator+(Complex32 a, Complex32 b) noexcept
Addition operator.
Definition: motion_common.cpp:223
autoware_auto_msgs::msg::VehicleControlCommand VehicleControlCommand
Definition: pure_pursuit.hpp:41
T clamp(T val, T min, T max)
Standard clamp implementation.
Definition: motion_common.hpp:142
Definition: controller_base.hpp:30
MOTION_COMMON_PUBLIC Real to_angle(Heading heading) noexcept
Converts 2D quaternion to simple heading representation.
Definition: motion_common.cpp:145
void sample(const Trajectory &in, Trajectory &out, std::chrono::nanoseconds period, SlerpF slerp_fn)
Sample a trajectory using interpolation; does not extrapolate.
Definition: motion_common.hpp:194
autoware_auto_msgs::msg::VehicleKinematicState State
Definition: motion_common.hpp:36
Heading from_quat(QuatT quat) noexcept
Converts a quaternion-like object to a simple heading representation.
Definition: motion_common.hpp:119
autoware_auto_msgs::msg::VehicleControlCommand Command
Definition: motion_common.hpp:34
decltype(decltype(State::state)::heading) Heading
Definition: motion_common.hpp:38
MOTION_COMMON_PUBLIC bool is_aligned(Heading a, Heading b, Real dot_threshold)
Check if cosine angle is less than some dot product threshold.
Definition: motion_common.cpp:64