15 #ifndef NAV2_REGULATED_PURE_PURSUIT_CONTROLLER__DYNAMIC_WINDOW_PURE_PURSUIT_FUNCTIONS_HPP_
16 #define NAV2_REGULATED_PURE_PURSUIT_CONTROLLER__DYNAMIC_WINDOW_PURE_PURSUIT_FUNCTIONS_HPP_
25 #include "rclcpp/rclcpp.hpp"
26 #include "geometry_msgs/msg/twist.hpp"
28 namespace nav2_regulated_pure_pursuit_controller
31 namespace dynamic_window_pure_pursuit
36 double max_linear_vel;
37 double min_linear_vel;
38 double max_angular_vel;
39 double min_angular_vel;
58 const geometry_msgs::msg::Twist & current_speed,
59 const double & max_linear_vel,
60 const double & min_linear_vel,
61 const double & max_angular_vel,
62 const double & min_angular_vel,
63 const double & max_linear_accel,
64 const double & max_linear_decel,
65 const double & max_angular_accel,
66 const double & max_angular_decel,
71 constexpr
double Eps = 1e-3;
74 auto compute_window = [&](
const double & current_vel,
const double & max_vel,
75 const double & min_vel,
const double & max_accel,
const double & max_decel)
77 double candidate_max_vel = 0.0;
78 double candidate_min_vel = 0.0;
80 if (current_vel > Eps) {
82 candidate_max_vel = current_vel + max_accel * dt;
83 candidate_min_vel = current_vel + max_decel * dt;
84 }
else if (current_vel < -Eps) {
86 candidate_max_vel = current_vel - max_decel * dt;
87 candidate_min_vel = current_vel - max_accel * dt;
90 candidate_max_vel = current_vel + max_accel * dt;
91 candidate_min_vel = current_vel - max_accel * dt;
95 double dynamic_window_max_vel = std::min(candidate_max_vel, max_vel);
96 double dynamic_window_min_vel = std::max(candidate_min_vel, min_vel);
97 return std::make_tuple(dynamic_window_max_vel, dynamic_window_min_vel);
101 std::tie(dynamic_window.max_linear_vel, dynamic_window.min_linear_vel) =
102 compute_window(current_speed.linear.x, max_linear_vel, min_linear_vel,
103 max_linear_accel, max_linear_decel);
106 std::tie(dynamic_window.max_angular_vel, dynamic_window.min_angular_vel) =
107 compute_window(current_speed.angular.z, max_angular_vel, min_angular_vel,
108 max_angular_accel, max_angular_decel);
110 return dynamic_window;
118 inline void applyRegulationToDynamicWindow(
119 const double & regulated_linear_vel,
120 DynamicWindowBounds & dynamic_window)
123 double v_reg_min = std::min(0.0, regulated_linear_vel);
124 double v_reg_max = std::max(0.0, regulated_linear_vel);
127 dynamic_window.min_linear_vel = std::max(dynamic_window.min_linear_vel, v_reg_min);
128 dynamic_window.max_linear_vel = std::min(dynamic_window.max_linear_vel, v_reg_max);
131 if (dynamic_window.min_linear_vel > dynamic_window.max_linear_vel) {
132 if (dynamic_window.min_linear_vel > v_reg_max) {
133 dynamic_window.max_linear_vel = dynamic_window.min_linear_vel;
135 dynamic_window.min_linear_vel = dynamic_window.max_linear_vel;
147 inline std::tuple<double, double> computeOptimalVelocityWithinDynamicWindow(
148 const DynamicWindowBounds & dynamic_window,
149 const double & curvature,
153 double optimal_linear_vel;
154 double optimal_angular_vel;
162 if (abs(curvature) < 1e-3) {
166 optimal_linear_vel = dynamic_window.max_linear_vel;
169 optimal_linear_vel = dynamic_window.min_linear_vel;
174 if (dynamic_window.min_angular_vel <= 0.0 && 0.0 <= dynamic_window.max_angular_vel) {
175 optimal_angular_vel = 0.0;
178 if (std::abs(dynamic_window.min_angular_vel) <= std::abs(dynamic_window.max_angular_vel)) {
179 optimal_angular_vel = dynamic_window.min_angular_vel;
181 optimal_angular_vel = dynamic_window.max_angular_vel;
184 return std::make_tuple(optimal_linear_vel, optimal_angular_vel);
191 std::pair<double, double> candidates[] = {
192 {dynamic_window.min_linear_vel, curvature * dynamic_window.min_linear_vel},
193 {dynamic_window.max_linear_vel, curvature * dynamic_window.max_linear_vel},
194 {dynamic_window.min_angular_vel / curvature, dynamic_window.min_angular_vel},
195 {dynamic_window.max_angular_vel / curvature, dynamic_window.max_angular_vel}
198 double best_linear_vel = -std::numeric_limits<double>::max() * sign;
199 double best_angular_vel = 0.0;
201 for (
auto [linear_vel, angular_vel] : candidates) {
203 if (linear_vel >= dynamic_window.min_linear_vel &&
204 linear_vel <= dynamic_window.max_linear_vel &&
205 angular_vel >= dynamic_window.min_angular_vel &&
206 angular_vel <= dynamic_window.max_angular_vel)
209 if (linear_vel * sign > best_linear_vel * sign) {
210 best_linear_vel = linear_vel;
211 best_angular_vel = angular_vel;
217 if (best_linear_vel != -std::numeric_limits<double>::max() * sign) {
218 optimal_linear_vel = best_linear_vel;
219 optimal_angular_vel = best_angular_vel;
220 return std::make_tuple(optimal_linear_vel, optimal_angular_vel);
228 const std::array<std::array<double, 2>, 4> corners = {{
229 {dynamic_window.min_linear_vel, dynamic_window.min_angular_vel},
230 {dynamic_window.min_linear_vel, dynamic_window.max_angular_vel},
231 {dynamic_window.max_linear_vel, dynamic_window.min_angular_vel},
232 {dynamic_window.max_linear_vel, dynamic_window.max_angular_vel}
237 const double denom = std::sqrt(curvature * curvature + 1.0);
238 auto compute_dist = [&](
const std::array<double, 2> & corner) ->
double {
239 return std::abs(curvature * corner[0] - corner[1]) / denom;
242 double closest_dist = std::numeric_limits<double>::max();
243 best_linear_vel = -std::numeric_limits<double>::max() * sign;
244 best_angular_vel = 0.0;
246 for (
const auto & corner : corners) {
247 const double dist = compute_dist(corner);
250 if (dist < closest_dist ||
251 (std::abs(dist - closest_dist) <= 1e-3 && corner[0] * sign > best_linear_vel * sign))
254 best_linear_vel = corner[0];
255 best_angular_vel = corner[1];
259 optimal_linear_vel = best_linear_vel;
260 optimal_angular_vel = best_angular_vel;
262 return std::make_tuple(optimal_linear_vel, optimal_angular_vel);
282 inline std::tuple<double, double> computeDynamicWindowVelocities(
283 const geometry_msgs::msg::Twist & current_speed,
284 const double & max_linear_vel,
285 const double & min_linear_vel,
286 const double & max_angular_vel,
287 const double & min_angular_vel,
288 const double & max_linear_accel,
289 const double & max_linear_decel,
290 const double & max_angular_accel,
291 const double & max_angular_decel,
292 const double & regulated_linear_vel,
293 const double & curvature,
299 DynamicWindowBounds dynamic_window = computeDynamicWindow(
300 current_speed, max_linear_vel, min_linear_vel, max_angular_vel, min_angular_vel,
301 max_linear_accel, max_linear_decel, max_angular_accel, max_angular_decel, dt);
304 applyRegulationToDynamicWindow(regulated_linear_vel, dynamic_window);
307 auto [linear_vel, angular_vel] = computeOptimalVelocityWithinDynamicWindow(
308 dynamic_window, curvature, sign);
310 return std::make_tuple(linear_vel, angular_vel);