Skip to content

System architecture: from battery to policy

Stage 1 · Foundations · ~30 min · Before this: 01 Degrees of freedom, 02 Balance · numbers from the repository as of 2026-11-02

A walking humanoid is a stack of machines inside one another: a battery feeds small motor controllers that correct each joint thousands of times a second, a computer runs a neural-network “policy” (the learned controller) fifty times a second, and a training computer elsewhere produced that policy in simulation. This page lays the whole stack out, then follows one control tick (one 20 ms round of sense, decide, act) from a gyro sample to motor torque and asks whether it fits.

Think of the robot as a company with managers at different speeds. A slow, clever manager (a vision-language-action model, VLA: a large AI model that looks through the camera and reads an instruction, or a person with a gamepad) decides what to do: “walk to the table”, “pick up the cup”. A quick, practised supervisor (the policy, a small neural network) turns that into joint targets for every joint, 50 times a second, while keeping the robot balanced. Fast workers on the shop floor (the motor drivers) hold each joint at its target thousands of times a second by pushing current through the motor windings. Underneath it all is the plant: a battery, wires, a frame and 27 powered joints.

Each level only works if the level below is much faster than itself. The policy can treat “set the knee to 20°” as almost instant because the motor driver’s loop settles in a few milliseconds; the VLA can treat “walk forward” as instant because the policy handles every step. This is the classic control hierarchy, and learned humanoids use it too: in an open research humanoid the policy runs at 50 Hz and the joint controller at 25 kHz on the motor driver.[12]

Why a newcomer should care. When a robot wobbles or falls, the cause can sit in any layer: a weak motor, a slow sensor, an overloaded data cable, a badly trained policy. Knowing the layers tells you where to look, and which later page to read.

Words you will meet on this page
  • PD control (proportional-derivative): each motor pushes towards its target angle in proportion to how far off it is (P) and resists moving too fast (D), like a spring with a shock absorber. Page 15.
  • IMU (inertial measurement unit): a chip with a gyro (how fast the body is turning) and an accelerometer (which way is down). Marvin Bot’s sits in the pelvis. An AHRS (attitude and heading reference system) is an IMU sold with its own filtering built in.
  • CAN (Controller Area Network): a shared two-wire data cable, invented for cars, that the computer uses to talk to a chain of motors. A frame is one message on it; a bus is one such cable with its motors.
  • ROS 2 (Robot Operating System 2): not an operating system but a widely used set of software libraries that let robot programs pass messages to each other.
  • ONNX (Open Neural Network Exchange): a standard file format for a trained neural network, so it can be run by software other than the one that trained it.
  • ms = millisecond (a thousandth of a second); µs = microsecond (a millionth). Latency = delay; jitter = how much that delay varies from one time to the next.

Click any block for what it does, how fast it runs, the repository file or decision behind it, and the page that covers it. The buttons beside the diagram highlight one path through the stack; start with One control tick.

How to read this picture: each horizontal band is one layer, slowest and furthest from the hardware at the top (training) down to the metal frame at the bottom. Arrows show which way data or power flows. Bright blocks are on the highlighted path; dimmed ones are not. On a phone, swipe the diagram sideways.

Highlight a path

Rates in the stack

LoopRatePeriod
VLA (GR00T N1.7)~1–4 Hz250 ms+
Policy50 Hz20 ms
Leg CAN commands500 Hz2 ms
Arm CAN commands250 Hz4 ms
IMU≥500 Hz≤2 ms
Driver PD, currentkHz<1 ms
From docs/requirements.md R42–R43 and description/robot.yaml. The driver loop rate is not in the RobStride manuals; it is a bench-test item.

A gyro notices the pelvis tipping. How long until a motor pushes back? Each stage below adds a delay. Press Marvin Bot today first, then change one slider at a time. “Average” uses half of each waiting period (an event lands at a random moment); “worst case” uses whole periods. The dot replays the chain in slow motion.

How to read this picture: time runs left to right in milliseconds; each coloured block is one delay, in order, and the vertical lines mark the start of each 20 ms policy tick. Readout values turn green when comfortably inside the range the policy was trained with (or the bus limit), amber near its edge and red outside it.

Presets

Loop rates

How often the policy runs. Sets the tick length (1/rate).
How often the controller sends each motor a frame (legs 500 Hz, arms 250 Hz).
Each takes a command and a reply frame of up to 160 bits at 1 Mbit/s.
Requirement R42: at least 500 Hz.

Delays

IMU filtering, USB or serial transfer and driver buffering before the reading is usable.
Building the observation (the list of numbers fed to the network) and running the network. A small network like Marvin Bot's takes well under 1 ms.
How many thousand times a second each motor's own controller corrects the joint. Not published for RobStride; open-source drivers run 10–40 kHz.
Event to torque
–
Tick start to torque vs tick
–
Sensor-side delay (trained 0–20 ms)
–
Action-side delay (trained 0–10 ms)
–
CAN bus load (limit 0.6)
–

The body is a machined 6061 aluminium frame (7075 at the most loaded flanges) with printed shells, carrying 27 powered joints: 6 per leg, 6 per arm, waist yaw and two neck joints. Each big joint is a RobStride quasi-direct-drive actuator: a motor, a 9:1 or 10:1 planetary gearbox, an absolute encoder (14-bit on the RS04[10]) and a driver board in one housing. The small joints (neck, wrist pitch) and the fingers are serial-bus servos.

Energy comes from a 48 V nominal 13S3P lithium-ion pack (about 630 Wh). It passes through a Class-T fuse, a precharge circuit and a contactor that the e-stop opens. DC-DC converters make 19–20 V for the computer (taken before the contactor, so an e-stop never reboots it), 12 V for the serial servos, and 5 V at each wrist for the hand servos. A small keep-alive battery holds the computer up during a pack swap.

CAN (Controller Area Network) is a two-wire bus (the two wires carry opposite signals, which cancels electrical noise) where every node hears every frame and a number at the start of each message, its identifier, decides which goes first when two talk at once.[11] RobStride actuators use classic CAN 2.0B at 1 Mbit/s with 29-bit identifiers.[10] A frame with 8 data bytes takes at most 160 bits on the wire (131 bits plus up to 29 extra “stuff” bits the hardware inserts to keep the receivers in step; description/robot.yaml), so 160 µs. Every motor needs a command and a reply each cycle, so the bus load is

load = nmotors × 2 frames × 160 bits × fcycle ÷ 1 000 000 bit/s

where n is the number of motors on the bus and f the command rate. Three leg motors at 500 Hz give 3 × 2 × 160 × 500 / 106 = 0.48, which is the repo’s 48%. A load of 0.48 means the wires are busy 48% of the time. Marvin Bot keeps every bus at or below 0.6 so that resent messages and timing wobble have room. Page 10 goes deeper.

The policy only sees what the robot can measure: the pelvis IMU (gyro and accelerometer, giving angular velocity and the direction of gravity), every joint’s position and velocity from the actuators’ encoders, and, for perception, the head’s Orbbec Gemini 335L depth camera. Page 11 covers them.

The computer is a Jetson AGX Orin 64 GB developer kit, a palm-sized NVIDIA board built for robots: a 12-core Arm Cortex-A78AE CPU and a 2048-core Ampere GPU sharing 64 GB of memory, 15–60 W.[1] It runs JetPack 7.2, NVIDIA’s Linux and driver bundle for Jetson.[2] On top of that the software splits in two:

  • A real-time control process, outside ROS. One program owns the CAN buses, reads the IMU, runs the policy at 50 Hz, applies the safety layer (joint, velocity and torque clamps, a command timeout, fall detection into a damping mode, where the motors only resist motion so the robot slumps instead of thrashing) and sends joint targets. Keeping it outside ROS keeps the hard-timed path short and easy to reason about.
  • ROS 2 Jazzy around it for everything that can tolerate a few milliseconds of jitter: the camera driver, logging, teleoperation and later the VLA bridge.[4] Isaac ROS 4.6 adds NVIDIA’s GPU-accelerated ROS 2 packages; 4.6 is the release that brought JetPack 7.2 support to Orin.[3]

The common ROS alternative is ros2_control, where a controller manager calls a hardware interface’s read and write functions in a real-time loop and loads controllers as plugins.[5] It is a reasonable design; the repo chose a plain process first because the loop is small (read, infer, clamp, write) and the bench tests must show the CAN timing before anything else is layered on.

  1. High level, about 1–4 Hz. A vision-language-action model (GR00T N1.7, NVIDIA’s open model: one part reasons slowly about images and words, a second part outputs short chunks of motion[15]) or a human teleoperator (a person steering it remotely) sets goals: a walking velocity, arm targets. On an AGX Orin with TensorRT (NVIDIA’s tool for running networks fast on its chips), one 16-step action chunk took about 0.28 s in one published deployment,[16] so the VLA runs on the desktop GPU first.
  2. Policy, 50 Hz. A small multilayer perceptron, MLP, the simplest kind of neural network (layers of 256, 128 and 128 “hidden units” for flat walking, 512-256-128 with the terrain map) maps the observation (gyro, gravity direction, command, joint positions and velocities, last action, and on rough ground a height map) to joint position targets for the 12 leg joints. Its output is a target, not a torque.
  3. Joint PD, in the motor driver. PD stands for proportional-derivative. Each driver computes τ = kp(qtarget − q) + kd(0 − q̇) many times per millisecond, where q is joint angle, q̇ its velocity, and kp, kd the stiffness and damping gains sent with the command. Page 15 explains the gains.
  4. Current loop, tens of kHz. The torque request becomes a current request (τ = Kt × I × gear ratio, Kt the torque constant), and field-oriented control (FOC) switches the driver’s transistors on and off thousands of times a second to hold that current. Open-source quasi-direct-drive drivers run this loop in the tens of kilohertz.[19]

A policy trained in simulation learned to act on observations of a certain age. If the real robot’s observations are older, the policy reacts to a pelvis tilt that has already grown; feedback with extra delay starts to overcorrect and oscillate, like adjusting a shower whose hot water takes too long to arrive. Latency was one of the first identified causes of the sim-to-real gap for legged robots, and modelling it in training fixed walking that otherwise failed.[14][13] Marvin Bot’s walking tasks give every simulated robot a random delay of 0–20 ms on its IMU and joint readings and 0–10 ms on its motor commands, so the policy is robust across that range. Playground 2 checks whether the real chain stays inside it:

sensor side = IMU sample hold + transport delay
action side = inference + wait for CAN slot + frames on the bus + driver loop
event to torque = sensor side + wait for policy tick + action side

The “sensor side” is how old the reading is when the policy sees it; the “action side” is how long the policy’s answer takes to become torque. In the average case each wait is half its period (½ × 1/f, where f is that loop’s rate); in the worst case a whole period.

The training side and sim-to-real at a glance

Section titled “The training side and sim-to-real at a glance”

Policies are trained on a desktop graphics card (GPU), never on the Orin. The tools have many names; what matters at this stage is what each one does (pages 14, 16 and 17 explain them):

  • Walking and stairs: Isaac Lab 3.0, NVIDIA’s robot-learning simulator (running on the Newton or PhysX physics engines), runs thousands of copies of the robot at once, and a learning method called PPO (proximal policy optimisation, from the rsl_rl library) improves the policy by trial and error.[6]
  • Human-like motion: ProtoMotions, on Newton, trains a motion-tracking policy to copy human movements, which are generated from text with Kimodo and fitted to Marvin Bot’s body with PyRoki, following the BeyondMimic method.[7][18]
  • Cross-check: every exported policy is replayed in MuJoCo, a different physics engine, with sensor noise: if it only works in the simulator it was trained in, it has learned that simulator’s quirks.[8]

As of the latest repo update, flat-ground policy v9, retrained on the current 1.41 m body, passes that cross-check, and the stair policy (rough v9, still trained on the earlier 1.29 m body) passes all 25 stair runs.

The exported network is an ONNX file plus a JSON file describing joint order, default pose, action scale and observation layout; on the robot, ONNX Runtime or TensorRT runs it.[9] Sim-to-real is then a loop: measure the real actuators on the bench (phase 2), fit the simulated motor model, retrain, and repeat. Page 20 covers it.

Choice Picked Alternatives considered Why
Onboard computer Jetson AGX Orin 64 GB dev kit Jetson Thor T4000 (same module price in 2026) Already available; Thor is noted for a second robot (docs/decisions.md).
Real-time loop Own process outside ROS ros2_control hardware interface Short, auditable timed path; ROS 2 kept for jitter-tolerant work.
Isaac ROS version 4.6 on Jazzy 5.0 5.0 skipped for now because of reported regressions on Orin.
CAN interfaces On-board CAN plus isolated USB-CAN (gs_usb, SocketCAN) Microcontroller bridge; five single-channel adapters Cheapest path; the bench timing test decides.
VLA placement Desktop GPU first, Orin with TensorRT later Onboard from the start A few hertz on Orin at best; the policy must keep its 50 Hz regardless (open item 10).
Whole-body control RL lower body plus IK arms, then motion tracking A large pretrained whole-body controller Published checkpoints target another robot and need far more compute to retrain.
  • IMU connection: a ready-made USB IMU is quicker to set up; a small microcontroller board reading the IMU chip directly (over serial or SPI) is more work but keeps the sensor side well inside 0–20 ms in the worst case, not just on average.
  • CAN adapters: plug-in USB-CAN adapters are cheap and simple; a microcontroller bridge costs design time but gives steadier timing. The bench latency test decides.
  • Policy rate: running faster than 50 Hz shortens the wait for the next tick, but the policy must be retrained at that rate and the computer works harder.
  • Policy size: a bigger network (a transformer that remembers recent history, for example) may walk better, but each extra millisecond of thinking time eats into the 0–10 ms action-side range the policy was trained with.
Your decision note

Built from your settings above. Paste it into an issue, a design discussion or an AI assistant session.

Where this leads. This page is the map of the machine; the rest of the guide zooms in. Stage 2 starts at the bottom of the diagram with the motors (page 04) and the loads they carry (page 05); the buses, sensors and power get their own pages in stage 3.

  1. NVIDIA, Jetson AGX Orin product page and technical brief — used for: CPU, GPU, memory and 15–60 W power range.
  2. NVIDIA, JetPack SDK — used for: what JetPack is.
  3. NVIDIA, Isaac ROS release notes — used for: 4.6 (August 2026) added Jetson Orin and JetPack 7.2 support; 5.0 moves to ROS 2 Lyrical.
  4. Open Robotics, ROS 2 Jazzy documentation — used for: ROS 2 as the middleware for camera, logging and teleoperation.
  5. ros2_control documentation (Jazzy) — used for: controller manager, hardware interface and real-time loop concepts.
  6. NVIDIA, Isaac Lab documentation — used for: parallel simulation for training on the desktop.
  7. NVIDIA, ProtoMotions — used for: the motion-tracking training framework.
  8. Google DeepMind, MuJoCo documentation — used for: the second physics engine used for cross-checks.
  9. ONNX Runtime documentation — used for: running exported ONNX policies on the robot.
  10. RobStride, Product_Information (RS04 user manual) — used for: CAN 2.0B at 1 Mbit/s, 29-bit identifiers, 14-bit absolute encoder.
  11. CAN in Automation, CAN knowledge — used for: how CAN arbitration and frames work.
  12. Liao et al., Berkeley Humanoid: A Research Platform for Learning-based Control, 2024 — used for: policy at 50 Hz, PD at 25 kHz on the motor driver.
  13. Hwangbo et al., Learning agile and dynamic motor skills for legged robots, Science Robotics 2019 — used for: modelling actuator dynamics and delays for transfer.
  14. Tan et al., Sim-to-Real: Learning Agile Locomotion For Quadruped Robots, RSS 2018 — used for: latency as a cause of the sim-to-real gap.
  15. NVIDIA, GR00T N1: An Open Foundation Model for Generalist Humanoid Robots, 2025 — used for: the dual-system VLA design.
  16. Seeed Studio wiki, GR00T N1.7 with TensorRT on AGX Orin (JetPack 7.2) — used for: about 0.28 s per 16-action chunk on AGX Orin.
  17. Radosavovic et al., Real-World Humanoid Locomotion with Reinforcement Learning, 2023 — used for: further reading on learned humanoid controllers (a transformer over observation history).
  18. Liao et al., BeyondMimic: From Motion Tracking to Versatile Humanoid Control via Guided Diffusion, 2025 — used for: the motion-tracking recipe the repo follows.
  19. Katz, A low cost modular actuator for dynamic robots, MIT thesis, 2018 — used for: current and PD loops in an open-source quasi-direct-drive driver running at tens of kHz.