Quick reference
Dense, scannable lookup for the most common commands, topics, and parameters. The cheat sheet you print or pin to a second monitor. Every link points at the page with the full details.
All commands below assume you've entered the workspace env (e.g.
cd bar_ws && pixi shell) so ros2, colcon, and the BAR console
scripts are on PATH. Looking for one-line aliases (pixi run launch-mujoco, pixi run build, …)? See
How-to → Workspace shortcuts with pixi.
Launch invocations
Grouped by which machine they run on. See Concepts → Architecture → Deployment topology for the split rationale. Launches come from two repos:
bar_ros2ships the Lite + Prime bringups (bar_bringup_lite,bar_bringup_prime), the description viewer (bar_description_lite), and the generic ONNX policy runner (bar_policy).pianist_ros2ships the piano-task launches (pianist_bringupcomposes a Lite + piano MuJoCo scene;pianist_policyruns the piano policy and the USB-MIDI driver).
Single-machine sim / dev (no robot, no tether)
# Drag joints in RViz — no controllers, no physics
ros2 launch bar_description_lite view_lite.launch.py
# MuJoCo sim — full controller stack, /clock from sim time
ros2 launch bar_bringup_lite mujoco.launch.py
# Lite + piano in MuJoCo (pianist_bringup composes the scene, spawns piano_state_bridge)
ros2 launch pianist_bringup mujoco.launch.py
# Calibrate the zero pose (writes ./calibration.yaml on Ctrl+C)
ros2 launch bar_bringup_lite calibrate.launch.py
Robot onboard computer (real bringup)
# Real Lite — both buses, two ros2_control blocks, gamepad + mode_manager
ros2 launch bar_bringup_lite real.launch.py
# Real Lite, no gamepad attached (drive the FSM via /bar/mode/* services)
ros2 launch bar_bringup_lite real.launch.py enable_gamepad:=false
# Gamepad enumerated as js1 (multiple controllers plugged into the Jetson)
ros2 launch bar_bringup_lite real.launch.py joy_dev:=/dev/input/js1
# Real Lite, no FSM (raw debug / calibration)
ros2 launch bar_bringup_lite real.launch.py enable_mode_manager:=false
real.launch.py boots the real-time control plane only — visualisers
and policy runners live on the operator workstation below.
Operator workstation (host side of the tether)
# Live URDF + /lite/joint_states viewer (bar_bringup_lite)
ros2 launch bar_bringup_lite viz.launch.py # viser, http://0.0.0.0:8080
ros2 launch bar_bringup_lite viz.launch.py viewer:=rerun # native rerun window
# Generic tracking-family policy (bar_ros2 → bar_policy)
ros2 launch bar_policy lite_policy.launch.py task:=tracking \
wandb_run_path:=… wandb_checkpoint_name:=model.onnx
# Piano policy (pianist_ros2 → pianist_policy)
ros2 launch pianist_policy piano_policy.launch.py \
wandb_run_path:=… motion_file:=/path/to/song
# USB-MIDI keyboard driver (pianist_ros2 → pianist_policy)
ros2 launch pianist_policy midi_keyboard_driver.launch.py
Both machines must share ROS_DOMAIN_ID. Full surface:
Launch args.
CAN bus setup
# One-time, after USB-to-CAN adapters plug in
sudo ip link set can0 down 2>/dev/null
sudo ip link set can0 up type can bitrate 1000000
sudo ip link set can1 down 2>/dev/null
sudo ip link set can1 up type can bitrate 1000000
# Check state (look for "UP" and "ERROR-ACTIVE")
ip -d link show can0
ip -d link show can1
Diagnostic CLIs
These are the bar (bar_cli) verbs — equivalent ros2 run bar_robstride …
invocations are listed in CLI tools.
# Scan an ID range; read-only, no Enable
bar bus discover --iface can0 --scan-to 32
bar bus discover --iface can1 --scan-to 32
# One-shot GetDeviceId / OperationStatus probe
bar bus ping --iface can0 --id 11
# Per-joint slider window (forward_command_controller frontend)
bar motor slider
# Live URDF + /lite/joint_states viewers (single-machine sim/dev shortcuts;
# on the tethered host, prefer `ros2 launch bar_bringup_lite viz.launch.py`)
bar viz viser # browser at :8080
bar viz rerun # native rerun window
Mode-FSM gamepad bindings (Xbox layout)
| Buttons | Intent | Allowed from | Activates |
|---|---|---|---|
X | DAMP | any state | damping_controller |
L1 + A or L1 + B | LOAD | DAMPING | standby_controller |
R1 + A | START_REMOTE | STANDBY (gated on is_finished) | remote_policy_controller |
R1 + B | START_LOCOMOTION | STANDBY (gated on is_finished) | rl_policy_controller |
BACK | QUIT | ZERO_TORQUE or DAMPING only | rclcpp::shutdown() |
Pair conventionally: L1+A → R1+A for remote-policy, L1+B → R1+B for
locomotion. Combos are identical functionally; the operator's thumb
just stays on one column. See Concepts → Five-mode FSM.
Manual controller switching (no FSM)
These are interactive ros2 control calls:
# ZERO_TORQUE → DAMPING
ros2 control switch_controllers \
--deactivate zero_torque_controller \
--activate damping_controller
# DAMPING → STANDBY (motors will move to piano-ready over ~4 s)
ros2 control switch_controllers \
--deactivate damping_controller \
--activate standby_controller
# Back to safe
ros2 control switch_controllers \
--deactivate <whatever>_controller \
--activate zero_torque_controller
Always end a session with zero_torque_controller active before
Ctrl+C-ing the launch.
Topics you actually echo
| Topic | Type | Rate | When |
|---|---|---|---|
/lite/joint_states | sensor_msgs/JointState | 50 Hz real / 200 Hz sim | always (joint_state_broadcaster, remapped at bringup) |
/imu/data | sensor_msgs/Imu | sensor-rate | always; RELIABLE |
/control_mode | bar_msgs/ControlMode | 50 Hz | always (mode_manager) |
/safety_status | bar_msgs/SafetyStatus | on-change, latched | TRANSIENT_LOCAL; source field per bus |
/standby_controller/state | bar_msgs/StandbyState | active-only | TRANSIENT_LOCAL; watch for is_finished:true before R1+A |
/remote_policy_controller/command | bar_msgs/MITCommand | policy_dt | when bar_policy or pianist_policy runner is up |
/piano/key_state | pianist_msgs/PianoKeyState | sensor / sim rate | piano runs only (RELIABLE + KEEP_LAST(1)) |
/piano/target_keys | pianist_msgs/PianoKeyState | policy_dt | piano runs only; song goal frame for bag-based metrics |
/joy | sensor_msgs/Joy | sensor-rate | when enable_gamepad:=true (default) |
Common one-liners
# Live controller state
ros2 control list_controllers
# Rate of /lite/joint_states (50 Hz real, 200 Hz MuJoCo)
ros2 topic hz /lite/joint_states
# Read the current pose (post-calibration, joint frame)
ros2 topic echo --once /lite/joint_states
# Safety status of every active bus
ros2 topic echo --once /safety_status
# Drive an FSM transition without a gamepad
ros2 service call /bar/mode/damp std_srvs/srv/Trigger
ros2 service call /bar/mode/load std_srvs/srv/Trigger
# Fake an MITCommand publish (when remote_policy_controller is active in MuJoCo)
ros2 topic pub --once /remote_policy_controller/command \
bar_msgs/msg/MITCommand "{header: {stamp: now}, joint_names: [...], ...}"
Services for FSM transitions
std_srvs/Trigger services on /bar/mode/* mirror the gamepad
intents — useful when there's no joystick attached.
| Service | Effect |
|---|---|
/bar/mode/damp | → DAMPING from any state |
/bar/mode/load | DAMPING → STANDBY |
/bar/mode/start_remote | STANDBY → REMOTE (gated on is_finished) |
/bar/mode/start_locomotion | STANDBY → LOCOMOTION (gated on is_finished) |
/bar/mode/quit | exit (only from ZERO_TORQUE or DAMPING) |
The Lite joint table
14 actuated DOFs across two buses. Order is canonical (see Concepts → Frozen schemas).
| Idx | Joint | CAN id | Bus | Model |
|---|---|---|---|---|
| 0 | left_shoulder_pitch | 11 | can0 | rs-02 |
| 1 | left_shoulder_roll | 12 | can0 | rs-00 |
| 2 | left_shoulder_yaw | 13 | can0 | rs-00 |
| 3 | left_elbow_pitch | 14 | can0 | rs-00 |
| 4 | left_wrist_yaw | 15 | can0 | rs-05 |
| 5 | left_wrist_roll | 16 | can0 | rs-05 |
| 6 | left_wrist_pitch | 17 | can0 | rs-05 |
| 7 | right_shoulder_pitch | 21 | can1 | rs-02 |
| 8 | right_shoulder_roll | 22 | can1 | rs-00 |
| 9 | right_shoulder_yaw | 23 | can1 | rs-00 |
| 10 | right_elbow_pitch | 24 | can1 | rs-00 |
| 11 | right_wrist_yaw | 25 | can1 | rs-05 |
| 12 | right_wrist_roll | 26 | can1 | rs-05 |
| 13 | right_wrist_pitch | 27 | can1 | rs-05 |
Full table (effort / current limits / per-joint K/D) in Hardware specs → Joint table.
MIT-mode command convention
Every plugin (Robstride, Sito, MujocoSystem) computes torque as:
τ = K_p · (q_cmd − q) + K_d · (q̇_cmd − q̇) + τ_ff
Five command interfaces per joint: position, velocity, effort,
stiffness, damping. Three state interfaces: position, velocity,
effort. See Concepts → MIT command surface.
Frequent failure modes (one-liners)
| Symptom | First thing to check |
|---|---|
ENOBUFS / Network is down warnings | Motor power off → frames don't ACK → qdisc fills. Power the motors. |
/lite/joint_states shows exactly 0.0 for every joint | Motors un-Enabled (no power, or Enable frame dropped). Check /safety_status flags. |
Launch dies with "joy_dev:=/dev/input/jsN does not exist" | enable_gamepad:=true is the default and the bringup hard-fails when the resolved joystick path is missing. Plug a gamepad in, pass joy_dev:=<actual path> (the error message lists any other /dev/input/js* it found), or pass enable_gamepad:=false. |
mode_manager rejects LOAD from anywhere other than DAMPING | Send DAMP (X) first. See FSM table above. |
ros2 topic echo /safety_status reports flags ≠ 0 | Check Concepts → Safety pipeline for the bit definitions. |
Full guidance: Troubleshooting.