# ai-fange/microduck-build-tutorial architecture

> Architecture diagram of the GitHub repository ai-fange/microduck-build-tutorial, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-29). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/ai-fange/microduck-build-tutorial
- Repository: https://github.com/ai-fange/microduck-build-tutorial

## Overview

Microduck combines Raspberry Pi robot deployment with a MuJoCo/MjLab reinforcement-learning environment. Its main runtime workflow accepts keyboard or gamepad commands, schedules the walking move, reads robot state, and sends motor targets to Dynamixel servos; training produces an ONNX policy for deployment. The tree and README identify additional motion, simulation, monitoring, and training capabilities, but several source files were not sampled, so uncertain internal wiring is omitted.

Main entry points: [`microduck/src/scheduler.py`](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/scheduler.py) (Move scheduler), [`microduck/src/robot_controller.py`](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/robot_controller.py) (Robot controller), [`microduck/src/main.py`](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/main.py) (Runtime entry), [`microduck/src/input/input_source.py`](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/input/input_source.py) (Input selection)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtime["Robot runtime"]
  node_main["Runtime entry<br/>[main.py]"]
  node_input["Input selection<br/>[input_source.py]"]
  node_keyboard["Keyboard input<br/>[keyboard_input.py]"]
  node_gamepad_input["Gamepad input<br/>[gamepad_input.py]"]
  node_daemon["Headless gamepad service<br/>[gamepad_daemon.py]"]
  node_scheduler["Move scheduler<br/>[scheduler.py]"]
  node_walk["Walking move<br/>[walk.py]"]
  node_other_moves["Other moves"]
  node_observer["Robot state observer<br/>[observer.py]"]
  node_stop["Stop control<br/>[stop.py]"]
  node_policy["Walking ONNX policy"]
end

subgraph group_hardware["Robot hardware"]
  node_robot_controller["Robot controller"]
  node_imu["IMU reader<br/>[imu_reader.py]"]
  node_servos{{"Dynamixel servo bus"}}
  node_imu_device{{"BNO08x IMU"}}
  node_voltage["Voltage monitoring<br/>[voltage.py]"]
end

subgraph group_simulation["Simulation tools"]
  node_sim_main["Simulation entry<br/>[sim_main.py]"]
  node_mujoco["MuJoCo controller"]
  node_placo["Placo viewer"]
  node_viewer["Simulation viewer<br/>[viewer_main.py]"]
end

subgraph group_training["Policy training"]
  node_rl_env["Velocity training environment"]
  node_mdp["Rewards and curricula<br/>[mdp.py]"]
  node_export["ONNX export<br/>[export_onnx.py]"]
end

node_operator(("Operator"))
node_gamepad(("Bluetooth gamepad"))

node_operator -->|"starts"| node_main
node_operator -->|"enters commands"| node_keyboard
node_gamepad -->|"sends controls"| node_gamepad_input
node_gamepad -.->|"starts or stops"| node_daemon
node_daemon -.->|"launches control"| node_main
node_main -->|"selects input"| node_input
node_main -->|"initializes hardware"| node_robot_controller
node_main -->|"starts loop"| node_scheduler
node_input -->|"falls back to"| node_keyboard
node_input -->|"selects connected"| node_gamepad_input
node_keyboard -->|"provides commands"| node_scheduler
node_gamepad_input -->|"provides commands"| node_scheduler
node_scheduler -->|"dispatches move"| node_walk
node_scheduler -.->|"dispatches moves"| node_other_moves
node_walk -->|"loads policy"| node_policy
node_walk -->|"reads state and sends targets"| node_robot_controller
node_scheduler -->|"coordinates control"| node_robot_controller
node_observer -.->|"reads robot state"| node_robot_controller
node_robot_controller -->|"reads and writes"| node_servos
node_robot_controller -->|"starts reader"| node_imu
node_imu -->|"reads orientation"| node_imu_device
node_voltage -.->|"reads voltage"| node_robot_controller
node_stop -->|"requests stop"| node_scheduler
node_sim_main -->|"selects simulation"| node_mujoco
node_sim_main -.->|"selects viewer"| node_placo
node_viewer -.->|"opens simulation"| node_mujoco
node_rl_env -->|"uses task terms"| node_mdp
node_export -->|"exports model"| node_policy

click node_main "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/main.py"
click node_input "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/input/input_source.py"
click node_keyboard "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/input/keyboard_input.py"
click node_gamepad_input "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/input/gamepad_input.py"
click node_daemon "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/gamepad_daemon.py"
click node_scheduler "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/scheduler.py"
click node_walk "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/moves/walk.py"
click node_other_moves "https://github.com/ai-fange/microduck-build-tutorial/tree/main/microduck/src/moves"
click node_observer "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/observer.py"
click node_stop "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/stop.py"
click node_robot_controller "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/robot_controller.py"
click node_imu "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/imu_reader.py"
click node_voltage "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/voltage.py"
click node_sim_main "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/sim/sim_main.py"
click node_mujoco "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/sim/mujoco_controller.py"
click node_placo "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/sim/placo_controller.py"
click node_viewer "https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/sim/viewer_main.py"
click node_rl_env "https://github.com/ai-fange/microduck-build-tutorial/blob/main/mjlab_microduck/src/mjlab_microduck/tasks/microduck_velocity_env_cfg.py"
click node_mdp "https://github.com/ai-fange/microduck-build-tutorial/blob/main/mjlab_microduck/src/mjlab_microduck/tasks/mdp.py"
click node_export "https://github.com/ai-fange/microduck-build-tutorial/blob/main/mjlab_microduck/src/mjlab_microduck/scripts/export_onnx.py"
click node_policy "https://github.com/ai-fange/microduck-build-tutorial/tree/main/microduck/src/agents"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_main,node_input,node_keyboard,node_gamepad_input,node_daemon,node_scheduler,node_walk,node_other_moves,node_observer,node_stop,node_policy toneBlue
class node_robot_controller,node_imu,node_servos,node_imu_device,node_voltage toneAmber
class node_sim_main,node_mujoco,node_placo,node_viewer toneMint
class node_rl_env,node_mdp,node_export toneRose
class node_operator,node_gamepad toneIndigo
```

## Components

### Robot runtime

- [Runtime entry](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/main.py): `microduck/src/main.py`
- [Input selection](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/input/input_source.py): `microduck/src/input/input_source.py`
- [Keyboard input](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/input/keyboard_input.py): `microduck/src/input/keyboard_input.py`
- [Gamepad input](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/input/gamepad_input.py): `microduck/src/input/gamepad_input.py`
- [Headless gamepad service](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/gamepad_daemon.py): `microduck/src/gamepad_daemon.py`
- [Move scheduler](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/scheduler.py): `microduck/src/scheduler.py`
- [Walking move](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/moves/walk.py): `microduck/src/moves/walk.py`
- [Other moves](https://github.com/ai-fange/microduck-build-tutorial/tree/main/microduck/src/moves): `microduck/src/moves`
- [Robot state observer](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/observer.py): `microduck/src/observer.py`
- [Stop control](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/stop.py): `microduck/src/stop.py`
- [Walking ONNX policy](https://github.com/ai-fange/microduck-build-tutorial/tree/main/microduck/src/agents): `microduck/src/agents`

### Robot hardware

- [Robot controller](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/robot_controller.py): `microduck/src/robot_controller.py`
- [IMU reader](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/imu_reader.py): `microduck/src/imu_reader.py`
- **Dynamixel servo bus**
- **BNO08x IMU**
- [Voltage monitoring](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/voltage.py): `microduck/src/voltage.py`

### Simulation tools

- [Simulation entry](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/sim/sim_main.py): `microduck/src/sim/sim_main.py`
- [MuJoCo controller](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/sim/mujoco_controller.py): `microduck/src/sim/mujoco_controller.py`
- [Placo viewer](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/sim/placo_controller.py): `microduck/src/sim/placo_controller.py`
- [Simulation viewer](https://github.com/ai-fange/microduck-build-tutorial/blob/main/microduck/src/sim/viewer_main.py): `microduck/src/sim/viewer_main.py`

### Policy training

- [Velocity training environment](https://github.com/ai-fange/microduck-build-tutorial/blob/main/mjlab_microduck/src/mjlab_microduck/tasks/microduck_velocity_env_cfg.py): `mjlab_microduck/src/mjlab_microduck/tasks/microduck_velocity_env_cfg.py`
- [Rewards and curricula](https://github.com/ai-fange/microduck-build-tutorial/blob/main/mjlab_microduck/src/mjlab_microduck/tasks/mdp.py): `mjlab_microduck/src/mjlab_microduck/tasks/mdp.py`
- [ONNX export](https://github.com/ai-fange/microduck-build-tutorial/blob/main/mjlab_microduck/src/mjlab_microduck/scripts/export_onnx.py): `mjlab_microduck/src/mjlab_microduck/scripts/export_onnx.py`

### Other components

- **Operator**
- **Bluetooth gamepad**

## Connections

- Operator → Runtime entry: starts
- Operator → Keyboard input: enters commands
- Bluetooth gamepad → Gamepad input: sends controls
- Bluetooth gamepad → Headless gamepad service: starts or stops
- Headless gamepad service → Runtime entry: launches control
- Runtime entry → Input selection: selects input
- Runtime entry → Robot controller: initializes hardware
- Runtime entry → Move scheduler: starts loop
- Input selection → Keyboard input: falls back to
- Input selection → Gamepad input: selects connected
- Keyboard input → Move scheduler: provides commands
- Gamepad input → Move scheduler: provides commands
- Move scheduler → Walking move: dispatches move
- Move scheduler → Other moves: dispatches moves
- Walking move → Walking ONNX policy: loads policy
- Walking move → Robot controller: reads state and sends targets
- Move scheduler → Robot controller: coordinates control
- Robot state observer → Robot controller: reads robot state
- Robot controller → Dynamixel servo bus: reads and writes
- Robot controller → IMU reader: starts reader
- IMU reader → BNO08x IMU: reads orientation
- Voltage monitoring → Robot controller: reads voltage
- Stop control → Move scheduler: requests stop
- Simulation entry → MuJoCo controller: selects simulation
- Simulation entry → Placo viewer: selects viewer
- Simulation viewer → MuJoCo controller: opens simulation
- Velocity training environment → Rewards and curricula: uses task terms
- ONNX export → Walking ONNX policy: exports model
