Skip to content

Low Level (RL Policy) — C++ Example

Source: rbq_sdk/cpp/example/src/rbq_low_level.cpp

Low-level joint control example that subscribes to IMU, joystick, and leg-joint feedback topics, publishes joint position references and ownership commands, and optionally runs a learned walking policy (ONNX).

Behavior overview

The application has a single 500 Hz control loop (2 ms period) and a keyboard-driven state machine with three states:

StateKeyWhat the control loop does
IdleTracks the stack's final reference (rt/rbq/ref/leg_joint/final) and republishes it — acts as a transparent pass-through
Motionx / zInterpolates joints to ready or ground postures using JointControl cosine trajectories
ControlcLoads the ONNX policy, runs inference at 10 Hz (decimation 5 of the 2 ms loop), publishes MotionRef with policy gains

Prerequisites

  • RBQ SDK built and installed — see C++ SDK Overview.
  • onnxruntime library — installed by rbq_sdk/cpp/example/scripts/setup.bash.
  • A policy directory containing info.json and policy.onnx.
  • Robot stack running (simulation or hardware).

Build

From rbq_sdk/cpp/example/:

bash
bash scripts/setup.bash
bash scripts/build.bash

Binary: bin/rbq_low_level

Run

From rbq_sdk/cpp/example/:

bash
# Requires root for RT thread; use without sudo for a normal thread
sudo ./bin/rbq_low_level -p <policyDir>
# Using pre-trained policy from rbq_simulator:
sudo ./bin/rbq_low_level -p ../../rbq_simulator/rbq_gym/policy/rbq10/

The application requires -p. Without it the program exits with an error.

Run with simulation

  1. From RBQ/, start the full stack:
    bash
    bash scripts/sim.bash
  2. In RBQGUI: ConnectAuto Start RobotStance (2).
  3. From rbq_sdk/cpp/example/:
    bash
    sudo ./bin/rbq_low_level -p ../../rbq_simulator/rbq_gym/policy/rbq10/

Keyboard controls

KeyAction
qQuit
zGo to ground posture (folding → ground, ~4.8 s)
xGo to ready posture (ground → folding → ready, ~2.8–5.6 s)
cStart Walk / Control mode (loads policy from -p)

Controls use raw terminal I/O (non-canonical, no echo) so each keypress is acted on immediately without pressing Enter.

Policy directory

The -p directory must contain:

FilePurpose
info.jsonPolicy hyper-parameters (run_name, policy_dt, action_scale, stiffness/damping, observation/action sizes, normalization scales, default joint angles, command ranges)
policy.onnxONNX model exported from the training framework

Supported policy names (from info.json run_name):

NameObservation vectorNotes
rbq10gyro, proj_grav, command, dof_pos, dof_vel, actionSingle-frame
rbq10_trotgyro, proj_grav, command, 4×dof_pos history (0,2,4,6), 4×dof_vel history, action×2, added_mass7-frame history; decimation 5
rbq10_trot_runSame as rbq10_trotFaster run variant

DDS topics

DirectionTopicTypeDescription
Subscribert/rbq/cmd/joy/finalJoy_Joystick axes for velocity commands
Subscribert/rbq/info/imuImu_Angular velocity + orientation quaternion
Subscribert/rbq/info/leg_jointLegJointInfo_Joint position and velocity (12 joints)
Subscribert/rbq/ref/leg_joint/finalMotionRef_Final blended reference (used in Idle)
Publishrt/rbq/ref/leg_joint/owner_20MotionRef_Joint position references with PD gains
Publishrt/rbq/cmd/motion/joint_owner/_20JointOwnershipCmd_Claim ownership of all 12 joints

Joint ordering

Joints are indexed 0–11 in the order:

HR (hind-right): HRR(0), HRP(1), HRK(2)
HL (hind-left): HLR(3), HLP(4), HLK(5)
FR (front-right): FRR(6), FRP(7), FRK(8)
FL (front-left): FLR(9), FLP(10), FLK(11)

Key implementation notes

  • RT thread: When running as root, rbq_sdk::Thread::generate_rt_thread is used for SCHED_FIFO scheduling. Without root the example falls back to a standard std::thread.
  • Ownership: JointOwnershipCmd_ is published once when transitioning into Motion or Control state, claiming all 12 joints (owner_20). The stack respects ownership priority — the example has priority 20.
  • Posture detection: goToMotionReady() checks the four hip-pitch angles against 60° to decide whether the robot is currently grounded (folded), and inserts a folding step if needed.
  • Decimation: The policy runs every 5th control tick (10 Hz from a 500 Hz loop), matching the policy_dt in info.json.

Troubleshooting

ProblemLikely cause
No motion / topics silentStack not running or wrong network interface
Policy, PolicyParams not loaded-p path wrong, info.json missing/invalid, or policy.onnx missing
Thread deadline … over!System too loaded for 2 ms period — run with sudo (RT thread) or reduce load
apt authentication errorsUnrelated host GPG issue; fix separately

See also

This user manual is intended for RBQ users.