Repository navigation
navmap_planner: weighted A*, replan hysteresis, cheaper plans and multi-floor fixes - #178
Conversation
fmrico
left a comment
There was a problem hiding this comment.
Thanks for splitting this out of #177. The direction looks good, and with the defaults the behaviour doesn't change. I especially like the epoch-stamped buffers and reading the uint8 layer without copying it; those help even without LOD maps. Weighted A* without re-opening is also the right choice for large maps.
I found a couple of issues before we can merge:
Bugs
-
Stale
closed_stamp_after a map size change. When N changes,ensure_graph_cachereallocatesg_,parent_andg_stamp_and resetsepoch_to 0, but it leavesclosed_stamp_alone. The weighted search only reassigns it whenclosed_stamp_.size() != N. So this sequence breaks: a weighted plan on a map of size N1, a re-mesh to N2, then back to N1.epoch_starts again at 1 whileclosed_stamp_still holds the old stamps, and NavCels show up as closed without being expanded. LOD maps change size all the time, so this will happen. Fix:closed_stamp_.clear()in the same branch that reallocatesg_. -
The hysteresis check ignores obstacles on non-uint8 cost layers.
choose_pathusesdynamic_pointer_cast<LayerView<std::uint8_t>>. When the cast returns null, every cell counts asFREE_SPACE. With afloatinflated_obstacleslayer (the case the rewritten test uses), the followed path is kept even when a new obstacle blocks it. It should read costs the same waya_star_pathdoes (layer_get<std::uint8_t>).
Minor
- Please replace the magic numbers with named constants, or parameters where it makes sense:
best < 2.0, the 1 mnearband, and the0.5fheight tolerance. The0.5fappears in three places (path_smoother,locate_near, end of the shortcut check), so a single shared constant would help. - When
freshis empty and the old path is still valid up to the horizon, the old path is kept, even though A* just found no path. Please add at least a comment or a debug log for this case. - The kept path starts at
followed_[from], not at the robot. Can you confirm the controller handles that first segment well? - Some of the comments are long paragraphs (
choose_path,a_star_path). Could you shorten them to one or two lines each?
Before merging
- The description still contains the
NavMap#<NUMBER>placeholder. Please link the actual PR. That fix needs to be merged first, or the CI here may fail. - Please add tests for: (a) weighted A* while the map alternates between sizes, which covers bug 1; (b) hysteresis with a
floatcost layer and an obstacle on the followed path, which covers bug 2.
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
…hysteresis; named constants; tests
|
Thanks for the careful review. Pushed a commit that addresses everything: Bugs
Tests (both fail without the fix and pass with it)
Minor
The package passes all its tests with these changes, lint included. Regarding the dependency on NavMap: EasyNavigation/NavMap#42, which needs to be merged first. |
|
LGTM!!! Merging 🚀 |
Split out of #177, as suggested.
What
Changes to
easynav_navmap_planner, motivated by planning on level-of-detail NavMaps (fine near the robot, coarse far away) and on buildings with several floors:heuristic_weight, default1.0, which keeps A* admissible and the previous behaviour). A larger weight expands fewer NavCels at the cost of paths up to that factor longer; each NavCel is expanded once.replan_hysteresis,replan_hysteresis_horizon, both0.0by default = off). Keeps the path being followed while it stays traversable, unless a new one is shorter by a given fraction. This avoids the oscillation of replanning on a map that changes with the robot's position. The horizon limits the check to the part of the path near the robot, because the far part of a LOD map is coarse and changes with every re-mesh.All new parameters are documented in the README. With the defaults, behaviour is unchanged.
Tests
New tests in
navmap_planner_tests.cppandnavmap_planner_terrain_tests.cpp. One existing test was rewritten to use afloatinflated_obstacleslayer.Dependencies
This package reads cost layers whose type may not be
uint8. The planner tests need theNavMap::operator=fix from EasyNavigation/NavMap#42; without it a test can crash on a retyped layer.