Environment: Jetson Orin Nano, JetPack 6.2.1, repo @ b646f5e, Unitree Go2, robot name set to robotdog during install.sh
Summary
The installer offers an optional robot name, which becomes a ROS2 namespace for all nodes (e.g. /robotdog/front_camera). When set, the web dashboard is broken: battery stays at 0%, cameras are stuck on "Initializing camera...", and the Health page shows every node as unknown. With an empty robot name everything works — so the bug is invisible to most users, but anyone who fills in the optional name gets a non-functional system.
There are two independent root causes.
Root cause 1 — bot_state_machine uses absolute lifecycle names (fix available)
lifecycle_manager.cpp::create_comms() builds its lifecycle clients/subscriptions with absolute names:
"/" + n.name + "/transition_event"
"/" + n.name + "/change_state"
"/" + n.name + "/get_state"
The leading / bypasses the node's namespace. The state machine itself is correctly namespaced by its launch file (from robot_config.yaml), so it looks for /front_camera/get_state while the real service is at /robotdog/front_camera/get_state. Every get_state fails, all statuses stay unknown, and coordinated bringup never activates anything.
Log signature (repeated for every managed node):
[LifecycleManager] bring_down: missing state for front_camera (get_state failed?)
Fix: drop the leading / so the names resolve relative to the state machine's own namespace. Behavior is unchanged for unnamed robots (namespace / produces identical names). Verified on the hardware above: with the fix and a namespaced stack, 21/22 nodes activate correctly.
Root cause 2 — frontend has no namespace support
Even with the state machine fixed, the web UI hardcodes root-level topic/service paths. getRosTopic() in frontend/src/utils/ros/topics-and-services.tsx returns '/' + topic:
export function getRosTopic(typeKey, isDummy = false): string {
const topic = topicsMessages[typeKey];
return `${isDummy ? '/dummy' : ''}/${topic}`;
}
So the frontend subscribes to /battery, /compressed_camera, /compressed_back_camera, … which have zero publishers when the stack runs under a namespace. Battery, cameras and controls are all dead. Fixing this properly means threading a namespace prefix through topics-and-services.tsx, topics-and-services-v2.tsx and the ~25 hooks/components that consume them.
Reproduction
- Run
sudo ./install.sh and set any non-empty robot name (e.g. robotdog)
- Boot the stack and open the dashboard, connect to the robot
- Battery stays 0%, cameras never initialize, Health page shows all nodes
unknown
Workaround
Set robot_name: "" in botbrain_ws/robot_config.yaml and restart the stack — all nodes relaunch at the root namespace and the UI works.
Suggestion
Until the frontend supports namespaces, either warn in the installer that setting a robot name breaks the web UI, or hide the option. I'm opening a PR with the bot_state_machine fix (root cause 1); root cause 2 needs a maintainer decision on how the namespace should reach the frontend (e.g. stored per-robot in the robots table alongside the address).
Environment: Jetson Orin Nano, JetPack 6.2.1, repo @
b646f5e, Unitree Go2, robot name set torobotdogduringinstall.shSummary
The installer offers an optional robot name, which becomes a ROS2 namespace for all nodes (e.g.
/robotdog/front_camera). When set, the web dashboard is broken: battery stays at 0%, cameras are stuck on "Initializing camera...", and the Health page shows every node asunknown. With an empty robot name everything works — so the bug is invisible to most users, but anyone who fills in the optional name gets a non-functional system.There are two independent root causes.
Root cause 1 —
bot_state_machineuses absolute lifecycle names (fix available)lifecycle_manager.cpp::create_comms()builds its lifecycle clients/subscriptions with absolute names:The leading
/bypasses the node's namespace. The state machine itself is correctly namespaced by its launch file (fromrobot_config.yaml), so it looks for/front_camera/get_statewhile the real service is at/robotdog/front_camera/get_state. Everyget_statefails, all statuses stayunknown, and coordinated bringup never activates anything.Log signature (repeated for every managed node):
Fix: drop the leading
/so the names resolve relative to the state machine's own namespace. Behavior is unchanged for unnamed robots (namespace/produces identical names). Verified on the hardware above: with the fix and a namespaced stack, 21/22 nodes activate correctly.Root cause 2 — frontend has no namespace support
Even with the state machine fixed, the web UI hardcodes root-level topic/service paths.
getRosTopic()infrontend/src/utils/ros/topics-and-services.tsxreturns'/' + topic:So the frontend subscribes to
/battery,/compressed_camera,/compressed_back_camera, … which have zero publishers when the stack runs under a namespace. Battery, cameras and controls are all dead. Fixing this properly means threading a namespace prefix throughtopics-and-services.tsx,topics-and-services-v2.tsxand the ~25 hooks/components that consume them.Reproduction
sudo ./install.shand set any non-empty robot name (e.g.robotdog)unknownWorkaround
Set
robot_name: ""inbotbrain_ws/robot_config.yamland restart the stack — all nodes relaunch at the root namespace and the UI works.Suggestion
Until the frontend supports namespaces, either warn in the installer that setting a robot name breaks the web UI, or hide the option. I'm opening a PR with the
bot_state_machinefix (root cause 1); root cause 2 needs a maintainer decision on how the namespace should reach the frontend (e.g. stored per-robot in therobotstable alongside the address).