Skip to content

Commit cfafdb9

Browse files
committed
Final optimizations:
Stoppin after finding close enough segment Adaptive search window Tuning parameters. Signed-off-by: silanus23 <berkantali23@outlook.com>
1 parent 3bb2538 commit cfafdb9

3 files changed

Lines changed: 50 additions & 40 deletions

File tree

nav2_bringup/params/nav2_params.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,10 @@ controller_server:
215215
threshold_to_consider: 0.5
216216
offset_from_furthest: 20
217217
use_path_orientations: false
218-
use_geometric_alignment: true
219-
search_window: 1.0
218+
use_geometric_alignment: false
219+
search_window: 0.3
220220
score_arc_length: true
221-
lookahead_distance: 2.0
221+
lookahead_distance: 0.7
222222
PathFollowCritic:
223223
enabled: true
224224
cost_power: 1

nav2_mppi_controller/include/nav2_mppi_controller/critics/path_align_critic.hpp

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -114,42 +114,36 @@ class PathAlignCritic : public CriticFunction
114114
* @note Returns squared distance to avoid sqrt() computation
115115
* @note Handles degenerate (zero-length) segments
116116
*/
117-
inline float distSqToSegment(float px, float py, Eigen::Index seg_idx)
118-
{
119-
const float x1 = path_x_cache_(seg_idx);
120-
const float y1 = path_y_cache_(seg_idx);
121-
const float dx = segment_dx_(seg_idx);
122-
const float dy = segment_dy_(seg_idx);
123-
const float inv_len_sq = segment_inv_len_sq_(seg_idx);
124-
125-
if (inv_len_sq < 1e-6f) {
126-
// Degenerate segment, return distance to point
127-
const float dpx = px - x1;
128-
const float dpy = py - y1;
129-
return dpx * dpx + dpy * dpy;
130-
}
131-
132-
// Project point onto segment, clamped to [0,1]
133-
const float t = std::max(0.0f, std::min(1.0f, ((px - x1) * dx + (py - y1) * dy) * inv_len_sq));
134-
135-
const float closest_x = x1 + t * dx;
136-
const float closest_y = y1 + t * dy;
137-
138-
const float dist_x = px - closest_x;
139-
const float dist_y = py - closest_y;
140-
141-
return dist_x * dist_x + dist_y * dist_y;
117+
inline float distSqToSegment(float px, float py, Eigen::Index seg_idx) const
118+
{
119+
const float dpx = px - path_x_cache_(seg_idx);
120+
const float dpy = py - path_y_cache_(seg_idx);
121+
122+
const float inv_len_sq = segment_inv_len_sq_(seg_idx);
123+
if (inv_len_sq < 1e-6f) [[unlikely]] {
124+
return dpx * dpx + dpy * dpy;
142125
}
143126

127+
const float dx = segment_dx_(seg_idx);
128+
const float dy = segment_dy_(seg_idx);
129+
const float t = std::clamp((dpx * dx + dpy * dy) * inv_len_sq, 0.0f, 1.0f);
130+
131+
const float dist_x = dpx - t * dx;
132+
const float dist_y = dpy - t * dy;
133+
134+
return dist_x * dist_x + dist_y * dist_y;
135+
}
136+
144137
size_t offset_from_furthest_{0};
145138
int trajectory_point_step_{0};
146139
float threshold_to_consider_{0};
147140
float max_path_occupancy_ratio_{0};
148-
bool use_geometric_alignment_{false};
149-
bool score_arc_length_{true};
150-
double search_window_{2.0};
151141
bool use_path_orientations_{false};
152-
float lookahead_distance_{5.0};
142+
bool score_arc_length_{true};
143+
bool use_geometric_alignment_;
144+
double search_window_;
145+
float lookahead_distance_;
146+
float early_termination_distance_;
153147

154148
unsigned int power_{0};
155149
float weight_{0};

nav2_mppi_controller/src/critics/path_align_critic.cpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ void PathAlignCritic::initialize()
3131
getParam(threshold_to_consider_, "threshold_to_consider", 0.5f);
3232
getParam(use_path_orientations_, "use_path_orientations", false);
3333
getParam(use_geometric_alignment_, "use_geometric_alignment", false);
34-
getParam(search_window_, "search_window", 0.5);
3534
getParam(score_arc_length_, "score_arc_length", true);
36-
getParam(lookahead_distance_, "lookahead_distance", 1.0f);
35+
getParam(search_window_, "search_window", 0.3);
36+
getParam(lookahead_distance_, "lookahead_distance", 0.7f);
37+
getParam(early_termination_distance_, "early_termination_distance", 0.025f);
3738

3839
if (!score_arc_length_ && !use_geometric_alignment_) {
3940
RCLCPP_WARN(logger_,
@@ -341,29 +342,44 @@ float PathAlignCritic::computeMinDistanceToPath(float px, float py, Eigen::Index
341342

342343
closest_seg_idx = std::clamp(closest_seg_idx, Eigen::Index(0), num_segments - 1);
343344

344-
// Limit search to window around hint (exploits path locality)
345+
float min_dist_sq = distSqToSegment(px, py, closest_seg_idx);
346+
Eigen::Index best_seg = closest_seg_idx;
347+
348+
// Early termination if already very close
349+
const float good_enough_dist_sq = early_termination_distance_ * early_termination_distance_;
350+
if (min_dist_sq < good_enough_dist_sq) {
351+
return std::sqrt(min_dist_sq);
352+
}
353+
354+
// Adaptive search window - smaller if hint is good
355+
const float adaptive_window = (min_dist_sq < 0.01f) ? search_window_ * 0.5f : search_window_;
356+
345357
const float hint_distance = cumulative_distances_(closest_seg_idx);
346-
const float start_distance = std::max(0.0f, hint_distance - static_cast<float>(search_window_));
347-
const float end_distance = hint_distance + static_cast<float>(search_window_);
358+
const float start_distance = std::max(0.0f, hint_distance - adaptive_window);
359+
const float end_distance = hint_distance + adaptive_window;
348360

349361
const Eigen::Index start_idx = static_cast<Eigen::Index>(
350362
utils::findClosestPathPtBinary(
351363
cumulative_distances_.data(),
352364
path_size_cache_,
353365
start_distance));
354366

355-
float min_dist_sq = std::numeric_limits<float>::max();
356-
Eigen::Index best_seg = closest_seg_idx;
357-
358367
for (Eigen::Index seg_idx = start_idx; seg_idx < num_segments; ++seg_idx) {
359368
if (cumulative_distances_(seg_idx) > end_distance) {break;}
360369
if (segment_len_sq_(seg_idx) < 1e-6f) {continue;}
370+
if (seg_idx == closest_seg_idx) {continue;} // Already checked
361371

362372
const float dist_sq = distSqToSegment(px, py, seg_idx);
363373

364374
if (dist_sq < min_dist_sq) {
365375
min_dist_sq = dist_sq;
366376
best_seg = seg_idx;
377+
378+
// Early exit if found very close match
379+
if (min_dist_sq < good_enough_dist_sq) {
380+
closest_seg_idx = best_seg;
381+
return std::sqrt(min_dist_sq);
382+
}
367383
}
368384
}
369385

0 commit comments

Comments
 (0)