Skip to content

Fix: Select hangar_sim nav2 params by ROS distro so Jazzy navigation starts - #863

Draft
dv-picknik wants to merge 1 commit into
v9.4from
fix/21729-hangar-nav2-jazzy-v9.4
Draft

Fix: Select hangar_sim nav2 params by ROS distro so Jazzy navigation starts#863
dv-picknik wants to merge 1 commit into
v9.4from
fix/21729-hangar-nav2-jazzy-v9.4

Conversation

@dv-picknik

@dv-picknik dv-picknik commented Aug 19, 2026

Copy link
Copy Markdown
Member

[written by AI]

needs: moveit_pro/#21807

Problem

hangar_sim navigation cannot start on Jazzy on the v9.4 line. Two pre-Jazzy patterns in nav2_params.yaml:

  • Pre-Jazzy pluginlib lookup names (:370, :392-400). Jazzy's nav2 exports these plugins with no name attribute, so the lookup name is the pkg::Class type. planner_server aborts bringup with class nav2_navfn_planner/NavfnPlanner ... does not exist, before bt_navigator is reached.
  • An explicit plugin_lib_names list (:56-104) duplicating what Jazzy's bt_navigator loads implicitly. The parameter is additive since Jazzy, so it double-registers and configure fails with ID [ComputePathToPose] already registered, killing nav2_container.

And one more, found during review — outside those files but squarely in "navigation doesn't work on Jazzy":

  • objectives/navigate_to_clicked_point_with_replanning.xml hardcoded /opt/ros/humble/share/nav2_bt_navigator/.../navigate_to_pose_w_replanning_and_recovery.xml. /opt/ros/humble does not exist on the Jazzy image at all, and this is the only hangar_sim objective that drives NavigateToPoseAction. Without this, nav2 would come up and the one navigation objective would still fail.

#809 fixed the first two on main and explicitly says "Do not backport" — correctly, since the slash form is right on Humble. main is Jazzy-only (ARG ROS_DISTRO=jazzy); 9.4 publishes both v9.4-humble-amd64 and v9.4-jazzy-amd64. Upstream confirms the forms are mutually exclusive: Humble's global_planner_plugin.xml declares name="nav2_navfn_planner/NavfnPlanner"; Jazzy's declares no name. A straight cherry-pick fixes Jazzy and silently regresses Humble — and this repo's v9.4 CI is jazzy-only (ACTIVE_DISTRO = 'jazzy'), so nothing would catch it.

Approach

One parameter file per distro, chosen at launch:

  • params/nav2_params.yamlbyte-identical to v9.4, still serving Humble.
  • params/nav2_params_jazzy.yaml — generated from it, differing only where Jazzy requires it: the 6 plugin names in :: form, no plugin_lib_names, and 3 parameters Jazzy renamedprogress_checker_plugins (Jazzy takes a list), and behavior_server's local_costmap_topic / local_footprint_topic (Jazzy split these into local_/global_ pairs).
  • robot_drivers_to_persist_sim.launch.py picks by $ROS_DISTRO, defaults to the Humble file, and logs the resolved path — the wrong branch reproduces the very bug this avoids, and its only symptom would be a component container aborting. It logs the params_file actually in effect, so an override cannot make the line lie.
  • The objective's behavior_tree_path becomes "", so nav2 falls back to default_nav_to_pose_bt_xml and no distro string appears in the path. A comment records that this resolves to each distro's own default tree, which are not identical (Jazzy backs up faster and gates recovery on error codes).

Those 3 renamed parameters matter even though they are inert today. Their Humble spellings are undeclared on Jazzy, so they are silently ignored rather than rejected, and the values only coincide with Jazzy's defaults — which is exactly what would hide a divergence the moment anyone renames the progress-checker id or namespaces the costmaps. costmap_topic also feeds the collision check guarding Spin/BackUp. Verified on a running stack: before the rename progress_checker_plugin and costmap_topic read back Parameter not set on Jazzy while nav2's own spellings carried the defaults; after, they read back with the configured values. On Humble the singular/unprefixed spellings are genuinely declared, which is why the split is per-distro rather than a blanket rename.

The selection lives in one place: that launch file is the only one resolving the params path against hangar_sim's share directory, and it passes params_file to slam_launch.py, localization_launch.py, navigation_launch.py, and the nav2_container node. The other launch files' own defaults point at nav2_bringup's stock params and are dead here, so they are untouched.

A build-time alternative was weighed — branch in CMakeLists.txt on $ENV{ROS_DISTRO} and install one file under a single name. That removes the runtime env dependency entirely (the image that builds is the image that runs), but it makes the installed share tree differ from the source tree, which is worse to debug on a frozen release branch. The runtime read is reversible and visible in the log; the build-time trick is neither.

Two parallel files is the cost, so test/nav2_params_distro_parity_test.py pins the complete set of allowed differences — the 6 renames, plus the Humble-only and Jazzy-only key sets — and that both filenames the launch file names exist. Any other divergence fails. It rejects the pkg/Class form generally, not just today's six. Verified it fails on injected drift, not just passes.

Verification

Full stack on both published v9.4 images, hangar_sim, overlay built per distro, both runs at this branch's final commit. Jazzy runs on top of #21807's image, without which bt_navigator crashes regardless of this change. (The Jazzy column was first produced against #21671 and re-run against #21807 after that PR was narrowed and closed; the results are identical -- 5.88 m in 41.8 s either way.)

v9.4-humble-amd64 v9.4-jazzy-amd64
params file selected (from the log) .../params/nav2_params.yaml .../params/nav2_params_jazzy.yaml
bt_navigator / planner_server / controller_server all active [3] all active [3]
distro-renamed params read back progress_checker_plugin set (Humble spelling is real here) progress_checker_plugins, local_costmap_topic, local_footprint_topic all set
NavigateToPose with old hardcoded path accepted, drives ABORTED (status 6)
NavigateToPose with behavior_tree="" accepted, drives accepted, drives

On Jazzy a 6 m goal completes: done=True elapsed=41.8s traveled=5.89 m. Before this change, bringup aborted at planner_server; with names fixed but the list still present, nav2_container died (exit -6).

The Humble column is the half CI cannot produce — v9.4 integration is jazzy-only, and the suite does not observe nav2 bringup anyway (both navigate objectives are in skip_objectives, and wait_for_robot_tf only waits on world → grasp_link). It was run by hand for this reason.

colcon test on hangar_sim: 17/17 pass, including the new parity test through the ament/ctest harness and the copyright and lint_cmake targets. pre-commit passes on all changed files.

MPPI still commands ~0.176 m/s against vx_max: 0.5 on Jazzy. That is the separate upstream regression tracked by PickNikRobotics/moveit_pro#21730 and is out of scope here.

Merge order

Land after PickNikRobotics/moveit_pro#21807 (the narrowed replacement for the closed #21671). The needs: line above points CI at that PR's image so integration runs against a coherent BT.CPP/nav2 pair.

Closes PickNikRobotics/moveit_pro#21729

@dv-picknik dv-picknik added this to the 9.4.2 milestone Aug 19, 2026
@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1a326e61-3ec4-4c1e-94e9-d584f9fb839f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@dv-picknik dv-picknik self-assigned this Aug 19, 2026
@dv-picknik
dv-picknik force-pushed the fix/21729-hangar-nav2-jazzy-v9.4 branch from 724ce97 to 335086b Compare August 19, 2026 20:19
@github-actions

Copy link
Copy Markdown

MoveIt Pro Example WS - Objectives Integration Test Report

@dv-picknik
dv-picknik force-pushed the fix/21729-hangar-nav2-jazzy-v9.4 branch from 335086b to c4ce908 Compare August 19, 2026 20:38
@github-actions

Copy link
Copy Markdown

MoveIt Pro Example WS - Objectives Integration Test Report

@github-actions

Copy link
Copy Markdown

MoveIt Pro Example WS - Objectives Integration Test Report

Nav2's pluginlib lookup names are mutually exclusive between Humble
(pkg/Class) and Jazzy (pkg::Class), and Jazzy's bt_navigator loads its
default BT plugin libraries implicitly. Ship a Jazzy parameter file
alongside the Humble one and pick between them at launch, so hangar_sim
navigation starts on both distros the 9.4 line publishes.

Closes #21729

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@dv-picknik
dv-picknik force-pushed the fix/21729-hangar-nav2-jazzy-v9.4 branch from c4ce908 to d54824e Compare August 19, 2026 20:57
@dv-picknik

Copy link
Copy Markdown
Member Author

[written by AI]

Review gate

Agents run sequentially on this branch, findings applied between each. Final tree is d54824e3.

Agent Result
code-reviewer 1 High (missing BSD-3-Clause header on the new test — ament_copyright runs at colcon-test time, not in pre-commit, so the PR's original "pre-commit passes" claim did not cover it), 3 P2. Applied.
documentation-bot No documentation impact. The hangar_sim architecture doc never names nav2_params.yaml; repo-wide markdown grep for nav2_params returns zero hits.
platform-architect-bot 1 High, 1 Medium, 4 Low. Applied — see the objective and logging changes below.
roboticist-bot 1 Required (three parameters renamed in Jazzy's nav2 were silently ignored), 3 suggestions applied, rest deferred with cause.
test-runner Build clean; 17/17 tests pass, including the new parity test through the colcon test / ament harness (not just bare pytest).
frontend-noah-bot, security-auditor, licensing-privacy-bot Not run — no frontend, security-sensitive, or licensing/privacy surface in this diff.
compatibility-bot Not run — the API-boundary doc lives in moveit_pro, and this diff is additive (a new params file plus a distro branch); the params_file launch argument keeps its name and semantics.

Findings worth surfacing rather than burying:

  • The hardcoded /opt/ros/humble/... behavior-tree path in navigate_to_clicked_point_with_replanning.xml was outside the original diff but inside the PR's problem statement — it is the only hangar_sim objective driving NavigateToPoseAction, and /opt/ros/humble does not exist on the Jazzy image. Without it this PR would have fixed bringup and left the one navigation objective broken. CI could not have caught it: both navigate objectives are in skip_objectives.
  • Three parameters were silently ignored on Jazzy in the new file — progress_checker_plugin (Jazzy takes the plural vector) and behavior_server's costmap_topic / footprint_topic (Jazzy split these into local_/global_ pairs). Confirmed on a running stack: the Humble spellings read back Parameter not set while Jazzy's own forms carried the defaults. Inert today only because those defaults match the configured values — which is precisely what would hide a later divergence, and costmap_topic feeds the collision check guarding Spin/BackUp. Renamed, and the parity test grew a JAZZY_ONLY_KEYS set (it previously forbade the fix). Re-verified: the parameters now read back with our values and a 6 m goal still completes.
  • main carries the same three ignored keys (nav2_params.yaml:92,363,364). Pre-existing there and out of scope for this backport, but it should be tracked separately.

Deferred with cause: fail-closed Shutdown on an unrecognized ROS_DISTRO (adding a new hard-stop bringup failure mode to a frozen release branch is worse than the warning it replaces); MPPI acceleration constraints, the behavior_server velocity-smoother bypass, and motion_model: DiffDrive on a holonomic base (all inherited from the existing Humble config, unchanged by this PR, and not safe to retune on a release branch without measurement); PyYAML/pytest declaration was applied, but the pre-existing ament_flake8 vs ament_cmake_flake8 naming mismatch in package.xml — which means flake8 never registers as a ctest target — is left alone as out of scope.

@github-actions

Copy link
Copy Markdown

MoveIt Pro Example WS - Objectives Integration Test Report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant