> Documentation index: https://nao-rs.lukaloehr.com/llms.txt, a list of every page in this documentation.

# Architecture

> The processes, threads and crates of nao-rs, and how they map onto what Aldebaran's HAL and LoLA did.

## Processes

```text
computer (brain, tools)
   │ TCP 7700: robot API              UDP 7701: stop
   ▼                                   ▼
hulk ── links the nao-rs runtime    nao-rs-guard ── watches the runtime
   │  (one process, real-time cycle)    │  (takes the chest board over on a hang)
   │                                    │
   ├─ USB ─▶ chest board ─▶ 13 motor boards, 2 foot boards, IMU, sonar, battery, chest button
   ├─ I2C ─▶ head: 6 LED drivers, touch, power monitor, temperature
   └─ /dev/cgos ─▶ board controller: CPU temperature, head fan
            both map /run/nao-rs/deathswitch
```

On the original stack, HAL, LoLA and HULA are three processes linked by shared
memory and two sockets. With nao-rs, `hulk` links the runtime as a library, so
the controller and the drivers share one process. The only other process
that touches the hardware is the guard, and it does so only after it has
killed the runtime.

## Threads of the runtime

| Thread | Priority (`SCHED_FIFO`) | Period | Job |
| --- | --- | --- | --- |
| `robot-cycle` | 30, pinned to CPU 3, memory locked | 12 ms | Chest board exchange in HAL's order, death switch check before each frame, triggers, heartbeat |
| `robot-head` | 20 | 12 ms | One I2C transaction per cycle: LEDs out, touch, power and temperature in (about 6 ms on the bus) |
| `robot-fan` | normal | 10 s | The fan curve, the CPU alert and halt |
| guard (own process) | 40 | 2 ms poll | Heartbeat check, UDP stop, takeover |

The head runs on its own thread because one I2C transaction takes about 6 ms;
the cycle thread only reads the latest head state from it (the three head pads
feed the death switch triggers). The controller's commands and the head state
reach the cycle thread through lock-free "latest value" slots, so reading them
never blocks; the cycle publishes its state for the controller under a short
lock.

## One cycle

1. Take the newest commands from the controller.
2. **Check the death switch**, one atomic load. Tripped means the frame is
   all-off.
3. Exchange the frame with the chest board and decode the answer
   ([in HAL's order](https://nao-rs.lukaloehr.com/architecture/cycle.md)).
4. Look at the triggers: chest button, the three head pads, joint
   temperatures. Trip the switch when one fires.
5. Write the heartbeat for the guard and publish the state.

If the cycle falls more than three periods behind, the runtime trips the
switch: the controller can't have seen the robot for that long.

## State and commands

The runtime's state and commands use **LoLA's layout**: the same arrays, in the
same order and units, as LoLA's RoboCup messages. Software written for LoLA,
such as HULKs' `hulk`, keeps its conversions unchanged. The joint order is:

```text
HeadYaw HeadPitch
LShoulderPitch LShoulderRoll LElbowYaw LElbowRoll LWristYaw
LHipYawPitch LHipRoll LHipPitch LKneePitch LAnklePitch LAnkleRoll
RHipRoll RHipPitch RKneePitch RAnklePitch RAnkleRoll
RShoulderPitch RShoulderRoll RElbowYaw RElbowRoll RWristYaw
LHand RHand
```

There is one hip yaw-pitch joint for both legs (`LHipYawPitch`): the NAO's
two hips share one motor.

## Crates

| Crate | What it does |
| --- | --- |
| `usbfs` | Linux usbfs without libusb: configuration, claim, control and bulk transfers |
| `chestlink` | The USB link to the chest board: start-up and the write, acknowledge, read exchange |
| `chestboard` | Chest board frames: messages, length table, CRC |
| `chestprefs` | The body preferences stored in the chest board: serial numbers, calibration |
| `motorboard` | The motor boards' configuration table |
| `body` | HAL's body start-up, the motor board handshake, the cycle requests and the all-off frame |
| `sensors` | Body sensors from the chest board's answers, in LoLA's units and order |
| `head` | The head I2C bus: LED drivers, touch, power monitor, temperature |
| `fan` | The head fan through the board controller, and alfand's control law |
| `deathswitch` | The latched switch page, the guard's rules, the UDP stop |
| `safety` | HAL's safety rules as pure logic: controller lost, cycle stall, battery over-current, how the stiffness factors combine; applied to every frame by the runtime |
| `chesttools` | The chest board tools: version, mode, power-off |
| `rt` | Real-time helpers: FIFO priority, locked memory, absolute-deadline ticker, lock-free latest value |
| `robot` | The runtime that ties them together, and the guard |

Tools: `naoctl` (on the robot, see [Command-line tools](https://nao-rs.lukaloehr.com/reference/cli.md)), and
the recording, replay and comparison tools used for
[verification](https://nao-rs.lukaloehr.com/verification.md).

## Related topics

- [The cycle in HAL's order](https://nao-rs.lukaloehr.com/architecture/cycle.md)
- [Boot time](https://nao-rs.lukaloehr.com/architecture/boot.md)
- Previous: [Party mode](https://nao-rs.lukaloehr.com/brain/party-mode.md)
- Next: [The cycle in HAL's order](https://nao-rs.lukaloehr.com/architecture/cycle.md)
