You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
l4t deployment fixes: make the Jetson profile build + boot on real hardware (#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>
If you need a non-default name (custom hostname scheme on a physical robot, or you want `drone_alpha` instead of `robot_1`), write a new mapping YAML in `robot/docker/robot_name_map/` and point `ROBOT_NAME_MAP_CONFIG_FILE` at it. Do **not** hardcode `ROBOT_NAME=...` in compose unless you know what you are doing — it bypasses the resolver and you lose `ROS_DOMAIN_ID` co-assignment.
103
+
If you need a non-default name (custom hostname scheme on a physical robot, or you want `drone_alpha` instead of `robot_1`), you have two options:
104
+
105
+
1. **Write a mapping YAML** in `robot/docker/robot_name_map/` and point `ROBOT_NAME_MAP_CONFIG_FILE` at it. Preferred when the name should be derived from the machine (hostname/container) — keeps the resolver in charge of `ROS_DOMAIN_ID` co-assignment.
106
+
2. **Pin `ROBOT_NAME` directly** in a per-deployment override env file. `.bashrc` honors a pre-set `ROBOT_NAME` (guard: `if [ -z "${ROBOT_NAME:-}" ]`) and skips the map lookup. This is the clean shortcut for a **single real robot** whose hostname doesn't match `robot-<n>` (see [Real robots and the `unknown_robot` fallback](#real-robots-and-the-unknown_robot-fallback) below):
107
+
108
+
```bash
109
+
# overrides/<deployment>.env — single robot, named directly
110
+
ROBOT_NAME=robot_1
111
+
ROS_DOMAIN_ID=1 # set alongside — pinning ROBOT_NAME skips the map's domain co-assignment
112
+
```
113
+
114
+
**Only pin `ROBOT_NAME` in an *override env file*, never on the shared `robot-desktop`/`robot-l4t` *service* in compose.** The service is reused for every replica; a hardcoded `ROBOT_NAME` there collapses all robots onto one name/domain and silently breaks multi-robot. And when you pin it, set `ROS_DOMAIN_ID` too — the resolver is what normally co-assigns the domain, and skipping it leaves the domain at whatever the environment defaults to.
101
115
102
116
For a one-off override (e.g. ad hoc debugging):
103
117
@@ -286,7 +300,7 @@ Without `allow_substs="true"`, the substitution string is loaded literally and t
286
300
If two robots share a domain, every topic collides — both `/robot_1/odometry` publishers will be visible to both subscribers, and DDS will sometimes deliver crossed data. The default `robot_name_map` derives the domain from the robot index, so this only happens if you:
287
301
288
302
- Hardcode `ROS_DOMAIN_ID` in compose to the same value for two replicas
289
-
- Use a hostname that doesn't match any rule and falls through to the catch-all (both robots get `unknown-robot`, domain `0`)
303
+
- Use a hostname that doesn't match any rule and falls through to the catch-all (both robots get `unknown_robot`, domain `0`)
290
304
291
305
Always verify after starting:
292
306
@@ -329,9 +343,21 @@ This is a common foot-gun:
329
343
330
344
Either keep the remap relative (`to="odometry"`) so it joins the namespace, or write the full path explicitly (`to="/$(env ROBOT_NAME)/odometry"`).
331
345
332
-
### 9. Hostname doesn't match any rule on real robots
346
+
### 9. Real robots and the `unknown_robot` fallback
347
+
348
+
On VOXL/Jetson the service uses `ROBOT_NAME_SOURCE=hostname`, so the **OS hostname** is what gets mapped — not a compose replica index. The stock `default_robot_name_map.yaml` only matches `robot-<n>`, so a device named `airlab-jetson-42` falls through to the catch-all and comes up as **`ROBOT_NAME=unknown_robot`, domain `0`** (with a map that has *no* catch-all, the resolver instead exits non-zero and `ROBOT_NAME` is left unset — same confusing "empty namespace" symptom). This is the usual "why is my real robot `unknown_robot`?" report.
333
349
334
-
On VOXL/Jetson with `ROBOT_NAME_SOURCE=hostname`, the device hostname must match a rule in the mapping YAML. If `hostname` returns `airlab-jetson-42` and your config only matches `robot-N`, the resolver exits non-zero and `ROBOT_NAME` is unset — the autonomy stack will then launch with empty namespaces and break in confusing ways. Either rename the device or extend the mapping config.
350
+
Pick whichever fix matches your topology (see [Configuring a Single Robot](#configuring-a-single-robot)):
351
+
352
+
- **One robot, quickest:** pin `ROBOT_NAME=robot_1` + `ROS_DOMAIN_ID=1` in the deployment's override env file. The `.bashrc` guard honors it and skips the lookup — no hostname change, no map file.
353
+
- **One robot, machine-derived:** rename the device hostname to `robot-1` so the default map resolves it automatically.
354
+
- **A fleet:** name each machine `robot-<n>` (default map handles it) **or** ship a mapping YAML that matches your hostnames and point `ROBOT_NAME_MAP_CONFIG_FILE` at it. Do **not** pin a single `ROBOT_NAME` on the shared service — every robot would collide on it.
Copy file name to clipboardExpand all lines: .agents/skills/docker-build-profiles/SKILL.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -49,6 +49,8 @@ Troubleshooting notes
49
49
- YAML quirk: unquoted `3.10` may be parsed as float `3.1` — this changes path strings and breaks imports (e.g., `python3.1` instead of `python3.10`).
50
50
- Jetson/L4T builds may require `network: host` during the build to avoid kernel iptables/raw table missing-module errors.
51
51
- Jetson **`robot-l4t`** builds from **`robot-l4t-stack-base`** (`robot/docker/Dockerfile.l4t-stack-base`), not raw dustynv, so **`Dockerfile.robot` stays Ubuntu-shaped.**`airstack image-build --profile l4t robot-l4t` triggers **`robot-l4t-stack-base`** first (`airstack.sh`); bare `compose build robot-l4t` can still parallelize badly, so list stack-base explicitly if not using AirStack CLI.
52
+
-**dustynv `/ros_entrypoint.sh` shadows the apt Jazzy runtime (mavros symbol-lookup crash).** The dustynv base sources a prebuilt *source* ROS at `$ROS_ROOT/install` from PID 1, prepending its older libs (e.g. `fastcdr` 2.2.5) ahead of the apt Jazzy (2.2.7) that `Dockerfile.robot` layers on top — apt-built nodes like mavros then die with symbol-lookup errors under tmux autolaunch. `Dockerfile.l4t-stack-base` neutralizes it by overwriting `/ros_entrypoint.sh` with a `exec "$@"` passthrough; shells get ROS from `/opt/ros/jazzy/setup.bash` via `.bashrc`. If a Jetson node suddenly can't resolve symbols after a base-image bump, check whether the entrypoint passthrough is still in place.
53
+
-**ZED SDK version is pinned across `zed/Dockerfile.zed-l4t`** — the `ZED_SDK_URL` (e.g. `.../zedsdk/5.2/...`) and the ROS dep args (`ZED_MSGS_VERSION`, `POINTCLOUD_TRANSPORT*_VERSION`, `BACKWARD_ROS_VERSION`) must move together; a mismatched `zed_msgs` vs SDK breaks the driver build. Bumping the SDK is camera-firmware-coupled, so confirm the target camera runs that SDK line before merging.
52
54
53
55
Examples of agent prompts
54
56
- "Check `robot/docker/docker-compose.yaml` for `PYTHON_VERSION` entries and quote any unquoted numeric values; open a PR with the fixes and include a test log from a builder-stage build."
Copy file name to clipboardExpand all lines: CHANGELOG.md
+7Lines changed: 7 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,11 +12,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
12
12
- Battery and telemetry display in GCS RQT control panel (voltage and percentage per robot when MAVROS battery topic is bridged)
13
13
-`TARGET_ARCH` build arg (default `x86_64`) in `Dockerfile.robot` to arch-parametrize `LD_LIBRARY_PATH`; `docker-compose.yaml` passes `TARGET_ARCH: aarch64` to the `voxl` and `l4t` real-robot image builds
14
14
-`ros-${ROS_DISTRO}-mavros-extras` in the robot image (provides the vision_pose plugin used for external-pose deployments)
15
+
-`overrides/l4t-px4-realrobot.env` — site-agnostic deployment override for a single real PX4 robot on a Jetson (aarch64/l4t)
16
+
17
+
### Changed
18
+
19
+
-`robot-l4t` compose service knobs are now env-overridable (`AUTONOMY_ROLE`, `FCU_URL`, and the rosbag path via `BAG_STORAGE_PATH`); `FCU_URL` unquoted so the literal serial path reaches MAVROS
20
+
-`zed-l4t` image: ZED SDK 4.2 → 5.2 with the coupled ROS deps (`zed_msgs` 5.2.1, `point_cloud_transport(_plugins)` 4.x, add `backward_ros`)
15
21
16
22
### Fixed
17
23
18
24
- Robot name resolution now honors a pre-set `ROBOT_NAME` (e.g. injected via docker compose) instead of always overriding it from the container/hostname mapping (`robot/docker/.bashrc`)
19
25
- Robot name-map catch-all fallback now maps to `unknown_robot` (valid ROS namespace token) instead of `unknown-robot` (`default_robot_name_map.yaml`)
26
+
- l4t robot image: replace dustynv's `/ros_entrypoint.sh` with a passthrough so its prebuilt source-ROS libs (older `fastcdr`) no longer shadow the apt Jazzy runtime and crash apt-built nodes like MAVROS
0 commit comments