> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cadenzalabs.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Robots

> The go1, g1, and arm controllers: script actions, scale them, run them concurrently.

The robot controllers are the friendliest way to drive a robot: call action
methods to get descriptors, collect them in a list, and `run()`. Nothing
executes until `run()`.

```python theme={null}
import cadenza_lab as cadenza

go1 = cadenza.go1()            # Unitree Go1 quadruped
g1  = cadenza.g1()             # Unitree G1 humanoid
arm = cadenza.arm()            # Cadenza 6-axis articulated arm
```

Cadenza ships three robots. The legged robots (`go1`, `g1`) are gait-driven and
return **`Step`** descriptors; the **`arm`** is a fixed-base manipulator that is
Cartesian (poses and grasps) and returns **`ArmAction`** descriptors. Everything
below up to [Arm](#arm-6-axis-manipulator) describes the legged `Step` model.

## How it works

Each action method (`go1.jump()`, `go1.walk_forward()`, …) returns a lightweight
`Step`, a name plus modifiers. `run()` normalizes the list, looks each name up
in the [action library](/sdk/actions), applies your `speed`/`extension`
overrides, and executes it on the simulator. A **nested list** runs as one
concurrent, merged gait.

```mermaid theme={null}
flowchart LR
    M["go1.walk_forward(speed=1.5)"] --> S[Step]
    S --> SEQ["sequence = [Step, Step, [Step, Step]]"]
    SEQ --> R[go1.run]
    R --> N[normalize + scale]
    N --> LIB[(Action library)]
    LIB --> SIM[Sim · MuJoCo viewer]
    SIM -->|next Step| R
```

## The `Step` descriptor

```python theme={null}
Step(name, speed=1.0, extension=1.0, repeat=1, distance_m=0.0, rotation_rad=0.0)
```

| Field          | Meaning                                                                          |
| -------------- | -------------------------------------------------------------------------------- |
| `speed`        | For gaits: command-speed multiplier. For phase actions: motion-speed multiplier. |
| `extension`    | Scales joint displacement from the stand pose (phase) or step height (gait).     |
| `repeat`       | Run the action N times.                                                          |
| `distance_m`   | Target travel distance for locomotion (`0` = action default).                    |
| `rotation_rad` | Target rotation for turns (`0` = action default).                                |

You rarely build `Step` directly. The action methods do it for you.

## Go1 action methods

Each returns a `Step`. Pass `speed`, `extension`, `distance_m`, `rotation_rad`,
or `repeat` where they apply.

| Group              | Methods                                                                                                |
| ------------------ | ------------------------------------------------------------------------------------------------------ |
| Posture            | `stand` · `stand_up` · `sit` · `lie_down` · `crouch` · `deep_crouch` · `rear_up`                       |
| Locomotion         | `walk_forward` · `walk_backward` · `trot_forward` · `crawl_forward` · `pace_forward` · `bound_forward` |
| Turning / strafing | `turn_left` · `turn_right` · `side_step_left` · `side_step_right`                                      |
| Skills             | `jump` · `climb_step` · `shake_hand` · `rear_kick`                                                     |
| Escape hatch       | `action(name, **kwargs)` for any library action by name                                                |

```python theme={null}
go1 = cadenza.go1()
go1.walk_forward(speed=1.5, distance_m=2.0)   # -> Step("walk_forward", speed=1.5, distance_m=2.0)
go1.turn_left(rotation_rad=1.57)              # quarter turn
go1.action("trot_forward", speed=1.2, repeat=2)
```

## G1 action methods

The G1 humanoid scripted runner currently executes `stand`, `crouch`,
`walk_forward`, `jump`, and `hold`:

```python theme={null}
g1 = cadenza.g1()
g1.run([g1.stand(), g1.crouch(), g1.walk_forward(distance_m=1.0), g1.stand(), g1.jump()])
```

<Note>
  The full G1 [action library](/sdk/actions) has 20 actions (arms, turns, etc.).
  Reach the rest through `Sim`, `GymAdapter`, or the
  [stack](/sdk/inference-stack). The scripted `g1.run([...])` path is the
  balance-stabilized subset.
</Note>

## `run()`

```python theme={null}
run(sequence=None, *, goal=None, scene=None, target=None, on=None,
    model=None, sense=None, max_iterations=250, headless=False,
    verbose=True, streaming=False)
```

Two shapes:

<Tabs>
  <Tab title="Scripted">
    ```python theme={null}
    go1 = cadenza.go1()
    go1.run([
        go1.stand(),
        go1.walk_forward(speed=1.5, distance_m=2.0),
        go1.jump(),
    ])
    ```
  </Tab>

  <Tab title="Goal-driven">
    ```python theme={null}
    # Hand the loop to a world model (see the Inference stack guide)
    go1.setup(model=MyVLA(), sense=[MyDepth()])
    go1.run(goal="reach the beacon and sit", scene="stairs", target=(-5.5, 0.0))
    ```
  </Tab>
</Tabs>

When `goal=` is given, `run()` forwards to [`cadenza.stack.run`](/sdk/inference-stack).
Otherwise it executes the `sequence` in the viewer.

## Concurrency

Nest a list inside the sequence to fuse those actions into a single gait. Their
velocity / yaw / step-height commands are merged:

```python theme={null}
go1.run([
    go1.stand(),
    [go1.turn_left(), go1.walk_forward()],   # turn while walking (one arc)
    go1.sit(),
])
```

## Inference at construction

Attach a [VLA orchestration strategy](/sdk/inference-orchestration) so each step
is run "think-and-act" instead of open-loop:

```python theme={null}
from cadenza.inference import Sequential

go1 = cadenza.go1(inference=Sequential())
go1.run([go1.walk_forward(distance_m=5.0)])
```

## Bundled assets

```python theme={null}
cadenza.Go1.model()             # path to the bundled Go1 scene XML
cadenza.Go1.terrain("terrain")  # path to a bundled terrain XML (use as xml_path)
go1 = cadenza.go1(xml_path=cadenza.Go1.terrain("terrain"))
```

## Demo: a full Go1 routine

```python theme={null}
"""demo_robot.py: open the viewer and run a short Go1 routine.
Needs a display (opens a MuJoCo window). Close the window to exit.
"""
import cadenza_lab as cadenza

go1 = cadenza.go1()
go1.run([
    go1.stand(),
    go1.walk_forward(speed=1.3, distance_m=1.5),
    [go1.turn_left(), go1.walk_forward()],   # arc left
    go1.shake_hand(),
    go1.jump(speed=1.8, extension=1.2),
    go1.sit(),
])
```

```bash theme={null}
python demo_robot.py
```

<Card title="Send it to a real robot" icon="tower-broadcast" href="/sdk/deploy">
  The same `Step` list deploys to a physical Go1 / G1 over DDS, SSH, or a bridge.
</Card>

## Arm (6-axis manipulator)

The **arm** is Cadenza's third robot: a fixed-base 6-DOF articulated arm with a
parallel two-finger gripper. Unlike the legged robots, it has no gaits — its
primitives are **Cartesian** (go to a pose, grasp the thing at a location), so
motion is driven by closed-form inverse kinematics and "grasping" is a weld the
controller activates when the gripper closes on an object.

```python theme={null}
import cadenza_lab as cadenza

arm = cadenza.arm()
arm.run([
    arm.home(),
    arm.pick((0.5, 0.0, 0.43)),     # grab the cube on the table
    arm.place((0.4, 0.22, 0.43)),   # set it down to the side
    arm.home(),
])
```

Each method returns an **`ArmAction`** descriptor (the manipulator's analogue of
`Step`); nothing runs until `arm.run(...)`.

### Arm action methods

| Method             | Kind      | What it does                                                    |
| ------------------ | --------- | --------------------------------------------------------------- |
| `home()`           | discrete  | Return to the neutral folded pose, gripper open.                |
| `move_to(x, y, z)` | cartesian | Move the gripper to a point, approaching top-down.              |
| `open_gripper()`   | discrete  | Open the parallel fingers.                                      |
| `close_gripper()`  | discrete  | Close the parallel fingers.                                     |
| `pick(x, y, z)`    | cartesian | Approach from above, descend, grasp, and lift the object there. |
| `place(x, y, z)`   | cartesian | Carry the held object to a point, lower, release, and retract.  |

Cartesian targets are in **metres, in the arm's base frame**, and accept either
spelling:

```python theme={null}
arm.move_to(0.5, 0.0, 0.55)     # x, y, z
arm.move_to((0.5, 0.0, 0.55))   # or a single (x, y, z) tuple

arm.actions()   # ['home', 'move_to', 'open_gripper', 'close_gripper', 'pick', 'place']
```

### `run()`

```python theme={null}
arm.run(sequence, *, headless=False, realtime=True, verbose=True)
```

Opens the MuJoCo viewer and executes the `ArmAction` list. Pass
`headless=True` for tests / CI (no window):

```python theme={null}
arm.run([arm.pick((0.5, 0, 0.43)), arm.place((0.4, 0.22, 0.43))], headless=True)
```

### How it stays controlled

<Note>
  The controller keeps the hand **above the work surface at all times**: every
  target is clamped to a no-go floor and the IK solution is checked so the
  fingertips never dip below the table, and the arm bodies are gravity-compensated
  so the position servos track without sag. The result is a controlled pick/place
  that hits the table and stops, instead of phasing through it.
</Note>

* **Top-down IK** — damped-least-squares solving for the gripper to reach a
  point pointing straight down. `move_to`/`pick`/`place` all use it.
* **Grasp = weld** — when the gripper closes on the object, the controller welds
  it to the palm for a rigid lift, and releases it on `place`.

### Demo: a pick-and-place routine

```python theme={null}
"""demo_arm.py: open the viewer and relocate a cube on the table.
Needs a display (opens a MuJoCo window). Close the window to exit.
"""
import cadenza_lab as cadenza

arm = cadenza.arm()
arm.run([
    arm.home(),
    arm.pick((0.50, 0.00, 0.43)),   # in-feed location
    arm.place((0.40, 0.22, 0.43)),  # drop-off location
    arm.home(),
])
```

```bash theme={null}
python demo_arm.py
```
