Skip to content

l4t infra fixes: aarch64 build args + robot-name resolution - #370

Merged
JohnYanxinLiu merged 1 commit into
developfrom
johnliu/l4t-infra-fixes
Jul 21, 2026
Merged

l4t infra fixes: aarch64 build args + robot-name resolution#370
JohnYanxinLiu merged 1 commit into
developfrom
johnliu/l4t-infra-fixes

Conversation

@JohnYanxinLiu

@JohnYanxinLiu JohnYanxinLiu commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

What features did you add and/or bugs did you address?

  • Which GitHub issue does this address?

    No dedicated issue. This is a foundational infra PR extracted from Johnliu/optitrack emulation #367 (OptiTrack emulation) so the generic real-robot deployment fixes can be reviewed and merged first; Johnliu/optitrack emulation #367 is then rebased on top, shrinking its diff. It also unblocks the upcoming l4t (Jetson) profile work.

  • Additional description if not fully described in the GitHub issue

    Two independent concerns, both generic (nothing OptiTrack-specific):

    1. aarch64 (Jetson/l4t, voxl) image builds

    • Dockerfile.robot: add ARG TARGET_ARCH=x86_64 and use it to parametrize LD_LIBRARY_PATH (.../lib/${TARGET_ARCH}-linux-gnu) so the arm64 images link against the correct arch triplet instead of the hard-coded x86_64.
    • Dockerfile.robot: install ros-${ROS_DISTRO}-mavros-extras (generic MAVROS dependency; also provides the vision_pose plugin used by external-pose deployments).
    • docker-compose.yaml: pass TARGET_ARCH: aarch64 to the voxl and l4t image builds.

    2. Robot name resolution ("robot launches with no name" bug)

    • .bashrc: honor a pre-set ROBOT_NAME (e.g. injected via docker compose) instead of always overriding it from the container/hostname mapping. The bws() flock build lock is retained.
    • default_robot_name_map.yaml: catch-all fallback maps to unknown_robot (a valid ROS namespace token) instead of unknown-robot (a hyphen makes the namespace invalid and launch fails).
  • Please add videos and images to demonstrate the feature.

    N/A — build-arg + shell/config changes, no runtime UI.

How did you implement it?

  • TARGET_ARCH defaults to x86_64, so the desktop/CI build is byte-for-byte unchanged; only the voxl/l4t services opt into aarch64.
  • The name-resolution change is a guard (if [ -z "${ROBOT_NAME:-}" ]; then ... fi) wrapped around the existing container/hostname mapping block — no behavior change when ROBOT_NAME is unset.

How do you run and use it?

  • Desktop (unchanged, sanity check the default arch path still builds):
    AUTOLAUNCH=false airstack up robot-desktop
  • aarch64 image build (on a Jetson / arm64 host):
    airstack image-build --profile l4t robot-l4t
  • Verify a pre-set ROBOT_NAME is honored:
    docker exec -e ROBOT_NAME=robot_1 <container> bash -lc 'echo $ROBOT_NAME'   # -> robot_1

Testing with PyTest

  • No new pytests. This PR is infra/build plumbing; there is no runtime surface with a hermetic test hook. The existing build_packages / build_docker suites exercise the affected Dockerfile/compose.
  • Command (optional, GPU runner): airstack test -m "build_docker or build_packages" -v
  • Expected: robot images build; TARGET_ARCH default keeps the x86 build identical to develop.

Documentation

  • Was mkdocs.yml updated? (y/n) n — no new module or user-facing doc page; changes are within existing docker/config files. CHANGELOG.md updated.
  • Docs scope: existing multi-robot / docker docs remain accurate.
  • Visual media: N/A.

Versioning

  • Yes — bumped .env VERSION 0.19.0-alpha.50.19.0-alpha.6 per semantic versioning (trailing alpha label increment). CHANGELOG [Unreleased] updated.

Generated with Claude Code

Foundational real-robot deployment fixes extracted from the OptiTrack
emulation PR (#367) so they can be reviewed and merged first; #367 will be
rebased on top afterward, shrinking its diff.

Docker / ARM build:
- Add TARGET_ARCH build arg (default x86_64) to Dockerfile.robot and use it to
  parametrize LD_LIBRARY_PATH, so the aarch64 (Jetson/l4t, voxl) images link
  against the correct arch triplet.
- docker-compose.yaml passes TARGET_ARCH: aarch64 to the voxl and l4t image
  builds.
- Install ros-${ROS_DISTRO}-mavros-extras (generic dep; also provides the
  vision_pose plugin used by external-pose deployments).

Robot name resolution:
- .bashrc now honors a pre-set ROBOT_NAME (e.g. injected by docker compose)
  instead of always overriding it from the container/hostname mapping. The
  bws() flock build lock is retained.
- default_robot_name_map.yaml catch-all fallback maps to unknown_robot (valid
  ROS namespace token) instead of unknown-robot.

Version bumped 0.19.0-alpha.5 -> 0.19.0-alpha.6 for the version-increment gate.

Note: the trajectory_controller/trajectory_library robustness fixes originally
listed for extraction are already present on develop (PR #365), so they are not
included here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@JohnYanxinLiu
JohnYanxinLiu marked this pull request as ready for review July 21, 2026 04:47
@JohnYanxinLiu
JohnYanxinLiu merged commit c476db3 into develop Jul 21, 2026
4 of 8 checks passed
JohnYanxinLiu added a commit that referenced this pull request Jul 21, 2026
…e resolution

Parametrize the robot-l4t compose service so a single service covers real
deployments without editing compose:
- AUTONOMY_ROLE and FCU_URL are now ${VAR:-default} overridable (and FCU_URL is
  unquoted so the literal serial path reaches mavros).
- Rosbag output path is BAG_STORAGE_PATH-overridable.

Update the configure-multi-robot skill to reflect the honor-pre-set-ROBOT_NAME
guard (#370): document pinning ROBOT_NAME in an override for a single real robot,
the never-on-the-shared-service caveat, and the unknown_robot fallback fixes by
topology.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
krrishj18 pushed a commit that referenced this pull request Jul 22, 2026
…rdware (#371)

* feat(l4t): make robot-l4t deployment knobs overridable + document name resolution

Parametrize the robot-l4t compose service so a single service covers real
deployments without editing compose:
- AUTONOMY_ROLE and FCU_URL are now ${VAR:-default} overridable (and FCU_URL is
  unquoted so the literal serial path reaches mavros).
- Rosbag output path is BAG_STORAGE_PATH-overridable.

Update the configure-multi-robot skill to reflect the honor-pre-set-ROBOT_NAME
guard (#370): document pinning ROBOT_NAME in an override for a single real robot,
the never-on-the-shared-service caveat, and the unknown_robot fallback fixes by
topology.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(l4t): add site-agnostic l4t-px4-realrobot override template

Deployment override for a single real PX4 robot on a Jetson (aarch64/l4t).
Surfaces the common knobs at the top with sensible defaults: ROBOT_NAME pinned
directly (single-robot shortcut honored by .bashrc), FCU_URL, AUTONOMY_ROLE,
BAG_STORAGE_PATH, and RECORD_BAGS. Mocap-agnostic — NatNet/external-vision
settings are added by a separate optitrack override.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(l4t): entrypoint passthrough + ZED SDK 5.2; document build gotchas

Two real-hardware build fixes for the Jetson profile:
- Dockerfile.l4t-stack-base: overwrite dustynv's /ros_entrypoint.sh with an
  `exec "$@"` passthrough. Its prebuilt source-ROS libs (fastcdr 2.2.5) were
  shadowing the apt Jazzy (2.2.7) that Dockerfile.robot layers on, crashing
  apt-built nodes like mavros with symbol-lookup errors under tmux autolaunch.
- zed/Dockerfile.zed-l4t: bump ZED SDK 4.2 -> 5.2 and move the coupled ROS deps
  together (zed_msgs 5.2.1, point_cloud_transport(_plugins) 4.x, add backward_ros).

Document both gotchas in the docker-build-profiles skill, and correct the stale
unknown-robot -> unknown_robot in the robot_identity reference doc.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: bump version to 0.19.0-alpha.7

Version-increment gate: bump above develop's 0.19.0-alpha.6 and record the l4t
deployment changes in the changelog.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
krrishj18 pushed a commit that referenced this pull request Jul 31, 2026
#372)

* feat(l4t): make robot-l4t deployment knobs overridable + document name resolution

Parametrize the robot-l4t compose service so a single service covers real
deployments without editing compose:
- AUTONOMY_ROLE and FCU_URL are now ${VAR:-default} overridable (and FCU_URL is
  unquoted so the literal serial path reaches mavros).
- Rosbag output path is BAG_STORAGE_PATH-overridable.

Update the configure-multi-robot skill to reflect the honor-pre-set-ROBOT_NAME
guard (#370): document pinning ROBOT_NAME in an override for a single real robot,
the never-on-the-shared-service caveat, and the unknown_robot fallback fixes by
topology.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(l4t): add site-agnostic l4t-px4-realrobot override template

Deployment override for a single real PX4 robot on a Jetson (aarch64/l4t).
Surfaces the common knobs at the top with sensible defaults: ROBOT_NAME pinned
directly (single-robot shortcut honored by .bashrc), FCU_URL, AUTONOMY_ROLE,
BAG_STORAGE_PATH, and RECORD_BAGS. Mocap-agnostic — NatNet/external-vision
settings are added by a separate optitrack override.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(l4t): entrypoint passthrough + ZED SDK 5.2; document build gotchas

Two real-hardware build fixes for the Jetson profile:
- Dockerfile.l4t-stack-base: overwrite dustynv's /ros_entrypoint.sh with an
  `exec "$@"` passthrough. Its prebuilt source-ROS libs (fastcdr 2.2.5) were
  shadowing the apt Jazzy (2.2.7) that Dockerfile.robot layers on, crashing
  apt-built nodes like mavros with symbol-lookup errors under tmux autolaunch.
- zed/Dockerfile.zed-l4t: bump ZED SDK 4.2 -> 5.2 and move the coupled ROS deps
  together (zed_msgs 5.2.1, point_cloud_transport(_plugins) 4.x, add backward_ros).

Document both gotchas in the docker-build-profiles skill, and correct the stale
unknown-robot -> unknown_robot in the robot_identity reference doc.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: bump version to 0.19.0-alpha.7

Version-increment gate: bump above develop's 0.19.0-alpha.6 and record the l4t
deployment changes in the changelog.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(infra): collect co-located unit tests via the package list + integration tier

Unit tests are defined by tests/colcon_unit_test_packages.yaml: conftest.py resolves
each listed package to its <pkg>/test dir and collects the non-linter test_*.py files
under --import-mode=importlib (set in pytest.ini), marking each `unit` by path. ament
lint files are skipped (they run under colcon test). Removes two now-unnecessary files
under tests/robot/; the package test/ dirs are collected directly.

Also add an integration test tier: tests/integration/ + `integration` mark + a shared
robot_autonomy_stack fixture (robot-desktop container, no sim/GPU), slotted into
_MODULE_ORDER between build_packages and the sim tiers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(testing): describe unit tests as co-located and listed in the package YAML

Update the add-unit-tests and run-system-tests skills, AGENTS.md, and the unit-testing
docs: adding a unit test is "list the package in colcon_unit_test_packages.yaml", and the
source lives in the package's own test/ dir. Document the `integration` mark/tier.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: bump version to 0.19.0-alpha.8

Version-increment gate: bump above develop (0.19.0-alpha.6); alpha.7 is taken by the
l4t-deployment-fix PR. Record the test-infra changes in the changelog.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor(tests): split unit-test discovery + session state into tests/harness/

Begin modularizing conftest.py (959 lines) by concern. Extract two self-contained
pieces into a new tests/harness/ package:
- harness/session.py: session-scoped mutable state (results dir, current pytest item,
  last subprocess output, logger) with setter/getter accessors. Hooks write it; helpers
  read it, so helper modules no longer reach into conftest globals.
- harness/discovery.py: unit-test discovery driven by colcon_unit_test_packages.yaml
  (repo_path, load_colcon_unit_test_config, colcon_test_robot_command, unit_test_dirs,
  unit_test_files, _is_unit_item).

conftest.py imports from harness and its hooks delegate to the session accessors; it
re-exports AIRSTACK_ROOT / colcon_test_robot_command / load_colcon_unit_test_config /
logger so existing `from conftest import ...` in the system tests keeps working
unchanged. Behavior-preserving (host-validated): `-m unit` still 14 passed / 152
deselected, 166 collected, same order. Follow-on: the commands/containers/metrics/sim
helpers and collection ordering move out the same way.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor(tests): extract commands/containers/metrics/sim helpers into tests/harness/

Continue modularizing conftest.py. Move the subprocess/ros2 command helpers
(harness/commands.py), docker container + compute-usage + image helpers
(harness/containers.py), MetricsRecorder + get_metrics/current_test_id
(harness/metrics.py), and the sim target configs + ros2 topic sampling
(harness/sim.py) out of conftest.py.

conftest.py drops from 836 to 360 lines and re-exports the harness helper API
(`from harness import *`) so `from conftest import <name>` in the system tests +
sensor_probes keeps working unchanged. Behavior-preserving: -m unit still 14 passed /
152 deselected, 166 collected, same order. Remaining in conftest: pytest hooks,
collection ordering, and the airstack_env / robot_autonomy_stack fixtures.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor(tests): extract collection ordering into tests/harness/collection.py

Final step of the conftest.py modularization: move test ordering — _MODULE_ORDER, the
per-module phase chains, _module_key, and the parametrize-id rewrite — into
harness/collection.py. conftest's pytest_collection_modifyitems hook now delegates to
collection.modify_items(items).

conftest.py is now 246 lines (from 959): pytest hooks + the airstack_env /
robot_autonomy_stack fixtures. All helpers live in tests/harness/ by concern (session,
discovery, commands, containers, metrics, sim, collection). Behavior-preserving: -m unit
still 14 passed / 152 deselected, 166 collected, unit → build → integration → sim order
unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Also sync docs/skills to the tests/harness/ layout (AGENTS.md, tests/README.md,
tests/integration/README.md, run-system-tests + add-unit-tests skills, unit_testing +
end_to_end_testing docs): helpers, MetricsRecorder, the workspace globs, and _MODULE_ORDER
now point at tests/harness/ instead of conftest.py (still re-exported via conftest).

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(robot): pin pytest to 7.4.* so apt launch_pytest stays compatible

The builder-stage pip block pulled pytest >=8 transitively into /usr/local (copied
into the runtime image), shadowing Jazzy's apt python3-pytest 7.4. pytest 8 removed
the `path` argument from pytest_pycollect_makemodule, which apt's launch_pytest plugin
still declares — so every pytest invocation in the robot container aborted at plugin
registration. This broke `colcon test` for ament_python packages (e.g.
lidar_point_cloud_filter in test_colcon_test_robot), while ament_cmake gtest packages
were unaffected.

Pin pytest to Jazzy's version so the container is internally consistent and
launch_testing / launch_pytest remain usable for future launch-based tests. The test
runner (tests/docker) is a separate interpreter and keeps its newer pytest.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(isaac-sim): clear LD_LIBRARY_PATH for PX4 ubuntu.sh so ca-certificates configures

The global ENV LD_LIBRARY_PATH puts isaac-sim's bundled libs
(.../isaacsim.ros2.bridge/jazzy/lib) on the linker path. Its older libcrypto.so.3
shadows the system one, so when the updated ca-certificates (20240203 →
20260601~24.04.1) runs its postinst `openssl`, it fails with
`version 'OPENSSL_3.0.9' not found`, aborting the apt transaction and failing the
isaac-sim image build (PX4 Tools/setup/ubuntu.sh, exit 100).

Clear LD_LIBRARY_PATH for that RUN only so apt/openssl use the system libcrypto;
the global ENV still applies to every other layer. Environmental break (new
ca-certificates × isaac-sim's stale bundled openssl) — not a code regression.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

2 participants