docs(plans): BEAST-01 cockpit parity & command surfaces plan - #156
docs(plans): BEAST-01 cockpit parity & command surfaces plan#156Coldaine wants to merge 1 commit into
Conversation
🤖 CodeAnt AI — Review Status
|
Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
📝 WalkthroughWalkthroughThe PR adds a detailed plan for BEAST cockpit parity. It covers deployment, motion safety, bridge connectivity, control surfaces, OAK-D overlays, exclusions, risks, validation, and open implementation questions. ChangesBEAST cockpit parity and surfaces
Estimated code review effort: 1 (Trivial) | ~5 minutes Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds a new planning doc for bringing BEAST-01’s Hangar /cockpit to parity with the stock Waveshare UI and then extending it, including a Phase 0 Jetson monorepo cutover + rosbridge/WSS bring-up and a Phase 1 e-stop redesign toward robot-side latched motion authority.
Changes:
- Introduces a phased implementation plan covering deployment cutover, cockpit parity (drive/lights/gimbal/cameras/voltage), and UI surface extensions.
- Documents updated ground truth about repo topology, current robot deployment state, and motion-enabled startup behavior.
- Specifies intended safety/control semantics (ARMED/DISARMED/LOCKED) and validation steps for each phase.
Suppressed comments (1)
docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md:99
- This phase-0 step suggests adding
/ugv/set_allow_motiontoservices_glob, but the current cockpit bridge configuration setsSERVICES_GLOB = '[]'and thecockpit_rosbridgewrapper removes service/action ops entirely. If the plan’s DISARM/RE-ARM path stays service-based, this step should explicitly call out the required bridge/protocol change (or an alternate relay), not just aservices_globedit.
4. Author the rosbridge glob whitelist in `rosbridge.launch.py`: exactly the topics/services in
`client.ts` `ROS_SUBSCRIPTIONS`/`ROS_PUBLICATIONS` plus service `/ugv/set_allow_motion`
(`services_glob`). The bridge fault rail in the UI will confirm refusals.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| 1. **E-stop = robot-side latched service.** The cockpit DISARM button calls | ||
| `/ugv/set_allow_motion` (`{data: false}`); re-arm calls `{data: true}`. Rendered state comes | ||
| only from `/ugv/allow_motion` + `/cockpit/status` interlock fields — never from local | ||
| intent. The 2 Hz heartbeat, intent latching, beforeunload trap, and keep-socket-alive | ||
| machinery in `client.ts` are deleted. Rationale: twist_mux lock topics are VOLATILE and | ||
| don't survive mux restart (documented in `twist_mux.yaml`); the service flag lives in | ||
| `ugv_bringup` below the mux, gates the serial write itself, and covers every command source. |
| **Check the systemd unit's launch args during cutover** — it currently passes | ||
| `allow_motion:=false`; the new code defaults `true`. Decide the unit's args deliberately | ||
| (recommend: let the new default stand; interlocks still disarm). |
| ## Phase 1 — Parity: drive, lights, gimbal, cameras + e-stop rewire | ||
|
|
||
| **Verify-then-fix each control end-to-end** (robot untethered, pack ≥ 10.5 V, supervised): | ||
| 1. Drive: WASD + hold-pad at 10 Hz lands on `/cmd_vel`; release → watchdog stop ≤ 0.5 s. |
There was a problem hiding this comment.
Actionable comments posted: 8
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md`:
- Around line 203-208: The Validation section must verify the rosbridge service
whitelist, not just topics_glob. Inspect services_glob and use the actual WSS
client to execute both DISARM and RE-ARM for /ugv/set_allow_motion, recording
successful responses, timeout behavior, and denial of an unwhitelisted service;
retain the existing topic and ROS checks.
- Around line 53-63: Add freshness requirements to the motion-state contract
covering `/ugv/allow_motion` and `/cockpit/status`: track each stream’s age,
render UNKNOWN or UNCONFIRMED when either exceeds the defined threshold, and
prevent RE-ARM until both streams are fresh again. Update the motion-state and
RE-ARM behavior in the plan while preserving the existing ARMED, DISARMED, and
LOCKED semantics for fresh data.
- Around line 79-80: Resolve the rosbridge address inconsistency across the “WSS
via Tailscale Serve” description and the LAN fallback URL: either configure
rosbridge to bind to the controlled LAN interface, documenting the required
firewall rules, or replace the 192.168.0.187:9090 fallback with a local
forwarding path. Before Phase 0 completion, test the exact fallback connection
and document the selected behavior consistently.
- Around line 90-94: Update the cutover plan to make the beast-ros-base.service
launch-argument change mandatory: remove or change allow_motion:=false so the
new true default produces the intended ARMED-at-boot behavior. Add explicit
post-restart verification of the effective launch argument and
/ugv/allow_motion, while retaining the existing safety interlock checks.
- Around line 32-38: Update the motion/interlock design around the robot-side
safety state and related sections to specify that clearing ETHERNET_LOCK or
CHARGING_LOCK does not automatically re-arm motion: allow_motion remains false
until an explicit operator RE-ARM, while preserving the existing 2-second RE-ARM
hold. Add robot tests covering both interlock-clear transitions and requiring
explicit RE-ARM before motion is restored.
- Around line 97-105: Update the rosbridge and deployment plan around
ROS_SUBSCRIPTIONS, ROS_PUBLICATIONS, services_glob, Tailscale Serve, and
BEAST_COCKPIT_WS_URL to define endpoint authorization controls, including an
operator/device allowlist, restricted Tailscale access, and disabling the LAN
fallback except on an isolated bench. Add verification that unauthorized clients
cannot publish, actuate, or call /ugv/set_allow_motion.
- Around line 156-160: Update the depthimage_to_laserscan plan entry to document
that /camera/scan uses /oak/stereo/image_raw with /oak/stereo/camera_info,
including the source camera-topic remap. Add a pre-enable validation requiring
non-zero P.D0 values and valid camera range data, and retain the existing USB
bandwidth checks.
- Around line 167-169: Update the “Threat-horizon ribbon” plan to use a
depth-preserving transport or server-side metric depth topic instead of relying
on the JPEG compressed image. Document the metric topic contract, including byte
order, scale, and clipping values, with depths below 0.3 m clipped consistently
for ribbon and HUD thresholds.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 7c47553c-a372-4f03-912e-7ac1be533e81
📒 Files selected for processing (1)
docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md
| **Boot/arm design changed: motion-enabled startup (PR #155, merged 2026-08-03).** | ||
| `bringup_lidar.launch.py` now declares `allow_motion` with `default_value='true'`. The robot | ||
| boots **motion-enabled**; `ugv_safety_monitor` disarms only when an interlock (Ethernet | ||
| carrier / charging) is observed, calling `/ugv/set_allow_motion` (`std_srvs/SetBool`) — still | ||
| the sole motion authority in `ugv_bringup`. `interlock_override` exists as a startup-only | ||
| maintenance escape hatch (never a service, never default true). **There is no boot-ARM gate | ||
| to design around — the earlier "boots disarmed" assumption is dead.** |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate target file =="
fd -a '2026-08-03-beast-cockpit-parity-and-surfaces\.md' . || true
echo "== target excerpt =="
if [ -f docs/plans/2026-08-03-beast-cookpit-parity-and-surfaces.md ]; then
rm -f docs/plans/2026-08-03-beast-cookpit-parity-and-surfaces.md 2>/dev/null || true
fi
cat -n docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md | sed -n '1,120p'
echo "== related searches =="
rg -n "RE-ARM|re-arm|REARM|hold|2[- ]?second|allow_motion|ugv_safety_monitor|set_allow_motion|interlock|charging|Ethernet|motion_enabled|bringup_lidar|2026-08-03" docs . --glob '!*.git' --glob '!build/**' --glob '!dist/**' | head -n 300Repository: Coldaine/RobotOverview
Length of output: 50381
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
p=Path('docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md')
print('target_path_exists=', p.exists())
if p.exists():
text=p.read_text()
for needle in ["interlock", "RE-ARM", "re-ARM", "REARM", "operator", "allow_motion", "motion-enable", "charging", "Ethernet"]:
print(f'{needle}:', text.count(needle), [i for i,l in enumerate(text.splitlines(),1) if needle.lower() in l.lower()][:20])
PYRepository: Coldaine/RobotOverview
Length of output: 561
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate implementation candidates =="
fd -i 'safety_monitor|bringup_lidar|ugv_bringup|cockpit/status|command.*rail|client\.ts|beast_status' . | sed -n '1,120p'
echo "== focused safety/status/arm files =="
for f in $(fd -i 'safety_monitor|cockpit_status|bringup_lidar|command.*rail|client\.ts|beast_status' . | sed -n '1,40p'); do
echo "--- $f ($(wc -l < "$f") lines) ---"
rg -n "allow_motion|set_allow_motion|ETHERNET|CHARGING|charging|RE-ARM|re-arm|hold|2 s|2s|interlock|LOCKED|LOCK" "$f" || true
done
echo "== structural calls to safety/status status =="
rg -n "safety/status|allow_motion|set_allow_motion|ETHERNET_LOCK|CHARGING_LOCK" robot/docs/src src public . --glob '!**/.git/**' --glob '!docs/plans/**' --glob '!src/data/**' | head -n 300Repository: Coldaine/RobotOverview
Length of output: 50378
Specify explicit motion recovery after Ethernet or charging clears.
The robot-side logic does not re-arm after an interlock state clears. This does not change the 2-second RE-ARM hold; it only documents the missing transition. State that clearing ETHERNET_LOCK or CHARGING_LOCK leaves allow_motion=false until an explicit operator RE-ARM, and cover this behavior in the robot tests.
Also applies to: 53-63
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md` around lines 32 -
38, Update the motion/interlock design around the robot-side safety state and
related sections to specify that clearing ETHERNET_LOCK or CHARGING_LOCK does
not automatically re-arm motion: allow_motion remains false until an explicit
operator RE-ARM, while preserving the existing 2-second RE-ARM hold. Add robot
tests covering both interlock-clear transitions and requiring explicit RE-ARM
before motion is restored.
| 1. **E-stop = robot-side latched service.** The cockpit DISARM button calls | ||
| `/ugv/set_allow_motion` (`{data: false}`); re-arm calls `{data: true}`. Rendered state comes | ||
| only from `/ugv/allow_motion` + `/cockpit/status` interlock fields — never from local | ||
| intent. The 2 Hz heartbeat, intent latching, beforeunload trap, and keep-socket-alive | ||
| machinery in `client.ts` are deleted. Rationale: twist_mux lock topics are VOLATILE and | ||
| don't survive mux restart (documented in `twist_mux.yaml`); the service flag lives in | ||
| `ugv_bringup` below the mux, gates the serial write itself, and covers every command source. | ||
| 2. **Motion states shown in the UI:** ARMED (default at boot) / DISARMED (operator or | ||
| interlock) / LOCKED (hardware interlock observed: Ethernet or charging). No ARM-from-boot | ||
| flow exists — PR #155 removed it. DISARM is one click, immediate; RE-ARM requires a 2 s | ||
| hold-to-confirm so a dropped click never re-enables motion. |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Add freshness handling to the motion-state contract.
Rendering state from /ugv/allow_motion and /cockpit/status is safe only when both streams are fresh. The plan defines a failed service-call state, but not a stale-telemetry state. A cached true can leave the UI showing ARMED after status delivery stops. Add age thresholds, render UNKNOWN or UNCONFIRMED for stale data, and block RE-ARM until fresh state returns.
Also applies to: 126-131
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md` around lines 53 -
63, Add freshness requirements to the motion-state contract covering
`/ugv/allow_motion` and `/cockpit/status`: track each stream’s age, render
UNKNOWN or UNCONFIRMED when either exceeds the defined threshold, and prevent
RE-ARM until both streams are fresh again. Update the motion-state and RE-ARM
behavior in the plan while preserving the existing ARMED, DISARMED, and LOCKED
semantics for fresh data.
| WSS via Tailscale Serve → rosbridge :9090 (loopback on Jetson) | ||
| Robot guarantees that do NOT depend on the UI: |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Resolve the rosbridge bind-address contradiction.
Lines 79-80 describe rosbridge as loopback-only. Lines 103-105 use ws://192.168.0.187:9090 as a LAN fallback. If rosbridge binds only to 127.0.0.1, this fallback cannot connect. Either bind rosbridge to a controlled LAN interface and document the firewall rules, or replace the fallback with a local forwarding path. Test the exact fallback URL before Phase 0 is complete.
Also applies to: 103-105
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md` around lines 79 -
80, Resolve the rosbridge address inconsistency across the “WSS via Tailscale
Serve” description and the LAN fallback URL: either configure rosbridge to bind
to the controlled LAN interface, documenting the required firewall rules, or
replace the 192.168.0.187:9090 fallback with a local forwarding path. Before
Phase 0 completion, test the exact fallback connection and document the selected
behavior consistently.
| **Check the systemd unit's launch args during cutover** — it currently passes | ||
| `allow_motion:=false`; the new code defaults `true`. Decide the unit's args deliberately | ||
| (recommend: let the new default stand; interlocks still disarm). | ||
| 2. Verify ground truth post-cutover: `/scan` ~10 Hz / 480 ranges, `/ugv/allow_motion` true, | ||
| watchdog armed, `ETHERNET_LOCK` appears on `/ugv/safety/status` when the cable is in. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Make the effective boot state explicit.
beast-ros-base.service currently passes allow_motion:=false. That argument overrides the new launch default true, so the ARMED-at-boot contract and validation step will not occur if the unit is deployed unchanged. Make the systemd unit update mandatory, or change the plan to expect DISARMED at boot. Verify the effective launch argument and /ugv/allow_motion after restart.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md` around lines 90 -
94, Update the cutover plan to make the beast-ros-base.service launch-argument
change mandatory: remove or change allow_motion:=false so the new true default
produces the intended ARMED-at-boot behavior. Add explicit post-restart
verification of the effective launch argument and /ugv/allow_motion, while
retaining the existing safety interlock checks.
| 4. Author the rosbridge glob whitelist in `rosbridge.launch.py`: exactly the topics/services in | ||
| `client.ts` `ROS_SUBSCRIPTIONS`/`ROS_PUBLICATIONS` plus service `/ugv/set_allow_motion` | ||
| (`services_glob`). The bridge fault rail in the UI will confirm refusals. | ||
| 5. Tailscale Serve: proxy HTTPS:443 → `localhost:9090` on `beast-01`; verify | ||
| `wss://beast-01.<tailnet>.ts.net` upgrades a WebSocket from the workstation. | ||
|
|
||
| **Hangar:** | ||
| 6. Doppler `homelab`/`dev` (+`prd`): `BEAST_COCKPIT_WS_URL=wss://beast-01.<tailnet>.ts.net`. | ||
| Keep a documented LAN fallback (`ws://192.168.0.187:9090`) for bench bring-up. |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Repo files around target:"
git ls-files | rg 'docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces\.md|rosbridge|client\.ts|tailnet|Tailscale|doppler|serve|lan|fallback' || true
echo
echo "Target plan excerpt:"
sed -n '1,160p' docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md
echo
echo "Search for auth/allowlist/service definitions:"
rg -n --hidden --glob '!*.lock' 'rosbridge|--allow-(topics|services)|allowed-(topics|services)|services_glob|ROS_SUBSCRIPTIONS|ROS_PUBLICATIONS|allow_motion|Tailscale|serve|doppler|BEAST_COCKPIT_WS_URL|fallback|acl|allowlist|authentication|auth' . | sed -n '1,240p'Repository: Coldaine/RobotOverview
Length of output: 50381
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Relevant documents and files:"
printf '\n--- docs/deploy.md excerpt ---\n'
sed -n '45,70p' docs/deploy.md || true
printf '\n--- .claude/skills/beast-paces/SKILL.md excerpts ---\n'
sed -n '34,38p;53,56p' .claude/skills/beast-paces/SKILL.md || true
printf '\nSearch only for rosbridge launch args/services_glob/allow_topics/topics_glob/auth-related terms:\n'
rg -n \
'rosbridge\.launch\.py|services_glob|topics_glob|allow_topics|topics_whitelist|topics_blacklist|allow_auth|auth|Tailscale|TAILSCALE|serve|ts\.net|acl|allowlist|whitelist|DENY|DISALLOW|allow_motion:=' \
docs .claude package.json package-lock.json src robot/beast/ros2_ws/src/ugv_main/ugv_cockpit/launch/rosbridge.launch.py 2>/dev/null || true
printf '\nRosebridge launch file excerpt:\n'
sed -n '1,220p' robot/beast/ros2_ws/src/ugv_main/ugv_cockpit/launch/rosbridge.launch.py || trueRepository: Coldaine/RobotOverview
Length of output: 50381
Define authorization access controls for the rosbridge endpoint.
ROS_SUBSCRIPTIONS/ROS_PUBLICATIONS and rosbridge service globs only limit ROS names. Tailscale Serve and the documented LAN fallback also enable drive, actuator, and /ugv/set_allow_motion calls. Add explicit controls such as a Tailscale ACL/operator or device allowlist, disable the LAN URL outside an isolated bench, and verify that unauthorized clients cannot publish or call the service.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md` around lines 97 -
105, Update the rosbridge and deployment plan around ROS_SUBSCRIPTIONS,
ROS_PUBLICATIONS, services_glob, Tailscale Serve, and BEAST_COCKPIT_WS_URL to
define endpoint authorization controls, including an operator/device allowlist,
restricted Tailscale access, and disabling the LAN fallback except on an
isolated bench. Add verification that unauthorized clients cannot publish,
actuate, or call /ugv/set_allow_motion.
| 1. Add `depthimage_to_laserscan` (`ros-humble-depthimage-to-laserscan`) on | ||
| `/oak/stereo/image_raw` → `/camera/scan` (squashes 3D overhangs to a 2D forward arc). | ||
| Note USB3 cable is PENDING — on USB2 verify bandwidth with RGB + depth + scan live before | ||
| enabling all three; degrade depth rate first. | ||
| 2. Verify `/cockpit/depth/compressed` + `/cockpit/overhead_clearance` live (nodes exist, unverified). |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 5 \
'depthimage_to_laserscan|oak/stereo/(image_raw|camera_info)|camera_info' \
robot/beast/ros2_wsRepository: Coldaine/RobotOverview
Length of output: 14438
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== files =="
git ls-files docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md robotics robot/beast/ros2_ws/src/ugv_main/ugv_gazebo/config/ros_gz_bridge.yaml robot/beast/ros2_ws/src/ugv_main/ugv_main/ugv_vision/launch/oak_d_lite.launch.py robot/beast/ros2_ws/src/ugv_main/ugv_vision/config/params.yaml robot/beast/ros2_ws/src/ugv_main/ugv_vision/config/camera_info.yaml robot/beast/ros2_ws/deploy/storage/mission.topics | sed -n '1,120p'
echo "== plan context =="
cat -n docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md | sed -n '130,175p'
echo "== rtabmap launch =="
cat -n robot/beast/ros2_ws/src/ugv_main/ugv_slam/launch/rtabmap.launch.py | sed -n '1,90p'
echo "== localization launch =="
cat -n robot/beast/ros2_ws/src/ugv_main/ugv_nav/launch/nav_bringup/localization_launch.py | sed -n '70,100p'
echo "== gazebo bridge =="
cat -n robot/beast/ros2_ws/src/ugv_main/ugv_gazebo/config/ros_gz_bridge.yaml | sed -n '30,50p'
echo "== camera config =="
cat -n robot/beast/ros2_ws/src/ugv_main/ugv_vision/config/params.yaml | sed -n '1,25p'
if [ -f robot/beast/ros2_ws/src/ugv_main/ugv_vision/config/camera_info.yaml ]; then
cat -n robot/beast/ros2_ws/src/ugv_main/ugv_vision/config/camera_info.yaml
fi
echo "== topic file =="
cat -n robot/beast/ros2_ws/deploy/storage/mission.topics | sed -n '1,30p'
echo "== laser scan references in repo =="
rg -n -C 3 'depthimage_to_laserscan|depth.*laserscan|CameraInfo|camera_info_url|min_distance|max_distance|/camera/scan|/oak/stereo/camera_info' .Repository: Coldaine/RobotOverview
Length of output: 50378
Document the /oak/stereo/camera_info contract for /camera/scan.
/oak/stereo/image_raw has a matching /oak/stereo/camera_info entry, but the OAK-D static calibration is populated from RGB camera metadata. Add the scan’s source camera topic/remap and the accepted non-zero P.D0/range validation before enabling /camera/scan.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md` around lines 156
- 160, Update the depthimage_to_laserscan plan entry to document that
/camera/scan uses /oak/stereo/image_raw with /oak/stereo/camera_info, including
the source camera-topic remap. Add a pre-enable validation requiring non-zero
P.D0 values and valid camera range data, and retain the existing USB bandwidth
checks.
| 5. **Threat-horizon ribbon**: absolute-positioned canvas strip over the OAK RGB feed, nearest | ||
| depth per column mapped blue→red (source: `/cockpit/depth/compressed` frame, downsampled | ||
| in-browser; reuse `depth_ops.py` stats if a lighter topic exists). |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Files:"
git ls-files | rg '(^|/)(docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces\.md|depth_colorizer\.py|depth_ops\.py|depth\.py|.*depth.*\.py)$|cockpit' || true
echo
echo "Doc excerpt:"
if [ -f docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md ]; then
nl -ba docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md | sed -n '150,185p'
fi
echo
echo "Search depth_colorizer/deep_ops/cockpit depth:"
rg -n --hidden --glob '!*.png' --glob '!*.jpg' --glob '!*.jpeg' --glob '!*.gif' --glob '!*.bmp' 'depth_colorizer|depth_ops|/cockpit/depth/compressed|depth/compressed|topic_name|depth_colorize|depth_ops' . || trueRepository: Coldaine/RobotOverview
Length of output: 3038
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Doc excerpt:"
awk 'NR>=150 && NR<=185 { printf "%5d\t%s\n", NR, $0 }' docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md || true
echo
echo "Definitions/usages around cockpit depth topics:"
rg -n --hidden --glob '!*.png' --glob '!*.jpg' --glob '!*.jpeg' --glob '!*.gif' --glob '!*.bmp' \
'("|\x27|)(/cockpit/depth/compressed|/cockpit/depth|depth_colorizer|depth_ops|compressed|compressed_image|metric|metric_metric|meters|unit|cm|width|height|msg|depth)("\x27|)' \
docs robot src || true
echo
echo "Inspect depth_colorizer.py outline and relevant code:"
wc -l robot/beast/ros2_ws/src/ugv_main/ugv_cockpit/ugv_cockpit/depth_colorizer.py robot/beast/ros2_ws/src/ugv_main/ugv_cockpit/ugv_cockpit/depth_ops.py
sed -n '1,260p' robot/beast/ros2_ws/src/ugv_main/ugv_cockpit/ugv_cockpit/depth_colorizer.py
sed -n '1,260p' robot/beast/ros2_ws/src/ugv_main/ugv_cockpit/ugv_cockpit/depth_ops.pyRepository: Coldaine/RobotOverview
Length of output: 50379
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Focused topic/config references:"
rg -n --hidden --glob '!src/**' --glob '!robot/beast/ros2_ws/src/ugv_else/**/*.map' --glob '!*.png' --glob '!*.jpg' --glob '!*.jpeg' --glob '!*.gif' --glob '!*.bmp' \
'/cockpit/depth/compressed|/cockpit/depth|depth_colorizer|depth_ops|compressed_topic|sensor_msgs/msg/Image|compressed_image|depth_topic|depth_metric|metric' \
docs robot/src robot/beast/ros2_ws/src/ugv_main robot/beast/ros2_ws/launch robot/beast/ros2_ws/src/ugv_main/ugv_cockpit || true
echo
echo "Plan excerpt:"
awk 'NR>=150 && NR<=185 { printf "%5d\t%s\n", NR, $0 }' docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md || true
echo
echo "Python files relevant excerpt with context:"
for f in robot/beast/ros2_ws/src/ugv_main/ugv_cockpit/ugv_cockpit/depth_colorizer.py robot/beast/ros2_ws/src/ugv_main/ugv_cockpit/ugv_cockpit/depth_ops.py robot/beast/ros2_ws/src/ugv_main/ugv_cockpit/ugv_cockpit/cockpit_rosbridge.py robot/beast/ros2_ws/src/ugv_main/ugv_cockpit/ugv_cockpit/overhead_clearance.py; do
if [ -f "$f" ]; then
echo "===== $f ($(wc -l < "$f") lines) ====="
rg -n 'class |def |topic_name|publish|Image|encode|depth_ops|depth_histogram|compress|topic' "$f" -C 3 || true
fi
doneRepository: Coldaine/RobotOverview
Length of output: 26378
Define the metric depth topic contract for the threat ribbon.
/cockpit/depth/compressed is documented and implemented as a JPEG sensor_msgs/msg/CompressedImage; the raw millimetre metric values are lost when downsampled in-browser. Add a depth-preserving transport or publish a server-side metric topic, then document byte order, scale, and the 0.3 m clipping behavior so the ribbon and HUD thresholds are reliable.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md` around lines 167
- 169, Update the “Threat-horizon ribbon” plan to use a depth-preserving
transport or server-side metric depth topic instead of relying on the JPEG
compressed image. Document the metric topic contract, including byte order,
scale, and clipping values, with depths below 0.3 m clipped consistently for
ribbon and HUD thresholds.
| ## Validation | ||
|
|
||
| - Robot (post-cutover): `ros2 topic hz /scan` (~10 Hz, 480 ranges), | ||
| `ros2 topic echo /ugv/allow_motion --once`, | ||
| `ros2 service call /ugv/set_allow_motion std_srvs/srv/SetBool "{data: false}"` round-trip, | ||
| `ros2 param get /rosbridge_websocket topics_glob` shows the whitelist. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Validate the service whitelist through rosbridge.
Phase 0 configures services_glob, but validation checks only topics_glob. The ROS CLI call in Line 207 bypasses rosbridge, so validation can pass while the browser cannot call /ugv/set_allow_motion. Inspect services_glob and execute DISARM and RE-ARM through the actual WSS client, including response, timeout, and denied-service cases.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/plans/2026-08-03-beast-cockpit-parity-and-surfaces.md` around lines 203
- 208, The Validation section must verify the rosbridge service whitelist, not
just topics_glob. Inspect services_glob and use the actual WSS client to execute
both DISARM and RE-ARM for /ugv/set_allow_motion, recording successful
responses, timeout behavior, and denial of an unwhitelisted service; retain the
existing topic and ROS checks.
| @@ -0,0 +1,224 @@ | |||
| # Plan: BEAST-01 Cockpit Parity & Command Surfaces | |||
There was a problem hiding this comment.
WARNING: This plan supersedes earlier planning content (the July 31 command deck plan and the Aug 1 cockpit roadmap) but does not reference or mark those files as superseded. The docs/plans/ directory has accumulated many dated plan documents that are stale or superseded, and the plans README convention states "Executed plans are deleted, not archived" — yet superseded plans remain in the directory. Consider deleting or explicitly marking the superseded plans (2026-07-31-beast-command-deck-plan.md, 2026-07-31-beast-command-deck-spec.md, 2026-08-01-beast-cockpit-future-roadmap.md) and updating docs/plans/README.md.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| @@ -0,0 +1,224 @@ | |||
| # Plan: BEAST-01 Cockpit Parity & Command Surfaces | |||
|
|
|||
| **TL;DR** | |||
There was a problem hiding this comment.
SUGGESTION: The plans README (docs/plans/README.md) was not updated to include this new plan or to remove superseded entries. The README's "Live work orders" table should list this plan and remove the command deck plan and cockpit roadmap it supersedes.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
Code Review SummaryStatus: 2 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (1 file)
Fix these issues in Kilo Cloud Reviewed by ling-3.0-flash:free · Input: 248.4K · Output: 31K · Cached: 532.7K |
|
Merged into main via commit 3faeb68. |
User description
Corrected master plan for the human-driven command deck, written against current main after the monorepo cutover.
What this plan is:
Ground truth corrections baked in:
obot/beast/ros2_ws/\ in this repo (PR Consolidate BEAST ROS workspace into RobotOverview #153); Coldaine/ugv_ws is archived
Out of scope (next plan): LLM/agent layer, Nav2 goals, SLAM, UPS I2C bench session.
CodeAnt-AI Description
Define the implementation plan for cockpit parity and robot command surfaces
What Changed
Impact
✅ Clearer robot motion safety states✅ Verified cockpit drive and camera parity✅ Safer, confirmed emergency disarm behavior💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.
Summary
Adds the corrected BEAST cockpit implementation plan after the monorepo cutover.
Plan coverage
The plan documents the corrected ROS workspace location, preserved LD19 and OAK-D Lite pipelines, motion-enabled startup, interlock-on-detection, robot-side latched e-stop authority, and Tailscale WSS bridge exposure.
LLM and VLM features, Nav2 goals, SLAM, and UPS I2C work remain out of scope. It also supersedes stale planning content from PR
#152.