Skip to content

Commit 9033141

Browse files
committed
♻️ refactor dwpp function to improve readability
Signed-off-by: Decwest <[email protected]>
1 parent e85780a commit 9033141

File tree

1 file changed

+67
-69
lines changed

1 file changed

+67
-69
lines changed

nav2_regulated_pure_pursuit_controller/src/regulated_pure_pursuit_controller.cpp

Lines changed: 67 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -269,106 +269,104 @@ void RegulatedPurePursuitController::computeOptimalVelocityUsingDynamicWindow(
269269
dynamic_window_max_angular_vel,
270270
dynamic_window_min_angular_vel);
271271

272-
// Reflect regulated v (tighten upper limit)
272+
// clip dynamic window's max linear velocity to regulated linear velocity
273273
if (dynamic_window_max_linear_vel > regulated_linear_vel) {
274274
dynamic_window_max_linear_vel = std::max(dynamic_window_min_linear_vel, regulated_linear_vel);
275275
}
276276

277-
const double k = curvature;
277+
// consider linear_vel - angular_vel space (horizontal and vertical axes respectively)
278+
// Select the closest point to the line angular_vel = curvature * linear_vel within the dynamic window.
279+
// If multiple points are equally close, select the one with the highest linear_vel.
278280

279-
// ---- Curvature is 0 (w = 0) ----
280-
if (abs(k) < 1e-3) {
281-
// If w=0 is within DW, then the maximum linear speed is adopted as it is.
281+
// When curvature == 0, the line is angular_vel = 0
282+
if (abs(curvature) < 1e-3) {
283+
// If the line angular_vel = 0 intersects the dynamic window, select (dynamic_window_max_linear_vel, 0)
282284
if (dynamic_window_min_angular_vel <= 0.0 && 0.0 <= dynamic_window_max_angular_vel) {
283-
optimal_linear_vel = dynamic_window_max_linear_vel; // Always maximum v
285+
optimal_linear_vel = dynamic_window_max_linear_vel;
284286
optimal_angular_vel = 0.0;
285-
return;
287+
} else {
288+
// If not, select (dynamic_window_max_linear_vel, angular vel within dynamic window closest to 0)
289+
optimal_linear_vel = dynamic_window_max_linear_vel;
290+
if (std::abs(dynamic_window_min_angular_vel) <= std::abs(dynamic_window_max_angular_vel)) {
291+
optimal_angular_vel = dynamic_window_min_angular_vel;
292+
} else {
293+
optimal_angular_vel = dynamic_window_max_angular_vel;
294+
}
286295
}
287-
// If w=0 is outside, choose the side closer to w=0 and with smaller |w|.
288-
const double w_choice = (std::abs(dynamic_window_min_angular_vel) <=
289-
std::abs(dynamic_window_max_angular_vel)) ? dynamic_window_min_angular_vel :
290-
dynamic_window_max_angular_vel;
291-
optimal_linear_vel = dynamic_window_max_linear_vel; // Always maximum v
292-
optimal_angular_vel = w_choice;
293296
return;
294297
}
295298

296-
// ---- 2) Select 'max v' from the candidates in the DW among the intersections. ----
297-
double best_v = -std::numeric_limits<double>::infinity(); // Initial value for maximization
298-
double best_w = 0.0;
299-
300-
// Intersection with vertical edges
301-
{
302-
const double v1 = dynamic_window_min_linear_vel;
303-
const double w1 = k * v1;
304-
if (w1 >= dynamic_window_min_angular_vel && w1 <= dynamic_window_max_angular_vel) {
305-
if (v1 > best_v) {best_v = v1; best_w = w1;}
306-
}
307-
}
308-
{
309-
const double v2 = dynamic_window_max_linear_vel;
310-
const double w2 = k * v2;
311-
if (w2 >= dynamic_window_min_angular_vel && w2 <= dynamic_window_max_angular_vel) {
312-
if (v2 > best_v) {best_v = v2; best_w = w2;}
313-
}
314-
}
315-
316-
// Intersection with horizontal edge (k ! = 0)
317-
{
318-
const double v3 = dynamic_window_min_angular_vel / k;
319-
if (v3 >= dynamic_window_min_linear_vel && v3 <= dynamic_window_max_linear_vel) {
320-
const double w3 = dynamic_window_min_angular_vel;
321-
if (v3 > best_v) {best_v = v3; best_w = w3;}
322-
}
323-
}
324-
{
325-
const double v4 = dynamic_window_max_angular_vel / k;
326-
if (v4 >= dynamic_window_min_linear_vel && v4 <= dynamic_window_max_linear_vel) {
327-
const double w4 = dynamic_window_max_angular_vel;
328-
if (v4 > best_v) {best_v = v4; best_w = w4;}
299+
// When the dynamic window and the line angular_vel = curvature * linear_vel intersect,
300+
// select the intersection point that yields the highest linear velocity.
301+
302+
// List the four candidate intersection points
303+
std::pair<double, double> candidates[] = {
304+
{dynamic_window_min_linear_vel, curvature * dynamic_window_min_linear_vel},
305+
{dynamic_window_max_linear_vel, curvature * dynamic_window_max_linear_vel},
306+
{dynamic_window_min_angular_vel / curvature, dynamic_window_min_angular_vel},
307+
{dynamic_window_max_angular_vel / curvature, dynamic_window_max_angular_vel}
308+
};
309+
310+
double best_linear_vel = -std::numeric_limits<double>::infinity();
311+
double best_angular_vel = 0.0;
312+
313+
for (auto [linear_vel, angular_vel] : candidates) {
314+
// Check whether the candidate lies within the dynamic window
315+
if (linear_vel >= dynamic_window_min_linear_vel &&
316+
linear_vel <= dynamic_window_max_linear_vel &&
317+
angular_vel >= dynamic_window_min_angular_vel &&
318+
angular_vel <= dynamic_window_max_angular_vel)
319+
{
320+
// Update if this candidate has the highest linear velocity so far
321+
if (linear_vel > best_linear_vel) {
322+
best_linear_vel = linear_vel;
323+
best_angular_vel = angular_vel;
324+
}
329325
}
330326
}
331327

332-
if (best_v > -std::numeric_limits<double>::infinity()) {
333-
// Intersection found → Adopt max. v
334-
optimal_linear_vel = best_v;
335-
optimal_angular_vel = best_w;
328+
// If best_linear_vel was updated, it means that a valid intersection exists
329+
if (best_linear_vel > -std::numeric_limits<double>::infinity()) {
330+
optimal_linear_vel = best_linear_vel;
331+
optimal_angular_vel = best_angular_vel;
336332
return;
337333
}
338334

339-
// ---- 3) If no intersection exists: Select the one with the smallest
340-
// Euclidean distance to the line w = k v among the 4 corners
335+
// When the dynamic window and the line angular_vel = curvature * linear_vel have no intersection,
336+
// select the point within the dynamic window that is closest to the line.
337+
338+
// Because the dynamic window is a convex region, the closest point must be one of its four corners.
341339
const std::array<std::array<double, 2>, 4> corners = {{
342340
{dynamic_window_min_linear_vel, dynamic_window_min_angular_vel},
343341
{dynamic_window_min_linear_vel, dynamic_window_max_angular_vel},
344342
{dynamic_window_max_linear_vel, dynamic_window_min_angular_vel},
345343
{dynamic_window_max_linear_vel, dynamic_window_max_angular_vel}
346344
}};
347345

348-
const double denom = std::sqrt(k * k + 1.0); // Just sqrt once
349-
350-
auto euclid_dist = [&](const std::array<double, 2> & corner) -> double {
351-
// Distance from point (v, w) to line w - k v = 0
352-
return std::abs(k * corner[0] - corner[1]) / denom;
346+
// Compute the distance from a point (linear_vel, angular_vel) to the line angular_vel = curvature * linear_vel
347+
const double denom = std::sqrt(curvature * curvature + 1.0);
348+
auto compute_dist = [&](const std::array<double, 2> & corner) -> double {
349+
return std::abs(curvature * corner[0] - corner[1]) / denom;
353350
};
354351

355-
double best_dist = std::numeric_limits<double>::infinity();
356-
best_v = corners[0][0];
357-
best_w = corners[0][1];
352+
double closest_dist = std::numeric_limits<double>::infinity();
353+
best_linear_vel = -std::numeric_limits<double>::infinity();
354+
best_angular_vel = 0.0;
358355

359356
for (const auto & corner : corners) {
360-
const double d = euclid_dist(corner);
361-
// 1) Smaller distance → Adopted
362-
// 2) If distances are equal (~1e-12) → Choose the one with larger v (acceleration policy)
363-
if (d < best_dist || (std::abs(d - best_dist) <= 1e-3 && corner[0] > best_v)) {
364-
best_dist = d;
365-
best_v = corner[0];
366-
best_w = corner[1];
357+
const double dist = compute_dist(corner);
358+
// Update if this corner is closer to the line, or equally close but has a higher linear velocity
359+
if (dist < closest_dist ||
360+
(std::abs(dist - closest_dist) <= 1e-3 && corner[0] > best_linear_vel))
361+
{
362+
closest_dist = dist;
363+
best_linear_vel = corner[0];
364+
best_angular_vel = corner[1];
367365
}
368366
}
369367

370-
optimal_linear_vel = best_v;
371-
optimal_angular_vel = best_w;
368+
optimal_linear_vel = best_linear_vel;
369+
optimal_angular_vel = best_angular_vel;
372370
}
373371

374372
geometry_msgs::msg::TwistStamped RegulatedPurePursuitController::computeVelocityCommands(

0 commit comments

Comments
 (0)