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

# Galaxea A1Z

> The complete A1Z guide: bring-up on macOS and Linux, teach mode, replay, LeRobot export, ACT training, running checkpoints, and a multi-policy agent

<img src="https://mintcdn.com/dimensionalos/nen8HmtUow2GjeTj/platforms/arms/assets/a1z.png?fit=max&auto=format&n=nen8HmtUow2GjeTj&q=85&s=55a7b8f4fc1da8e63e46512f08458b0c" alt="Galaxea A1Z" width="1600" height="1000" data-path="platforms/arms/assets/a1z.png" />

The Galaxea A1Z is a 6-DOF CAN-bus arm with the G1Z gripper (CAN motor 7). DimOS drives it over native Linux SocketCAN using the vendor's 250 Hz MIT position-control loop, with gravity compensation from the G1Z URDF. It is the teach-and-learn platform: drag the arm through a task in zero-gravity teach mode, record episodes with camera, export straight to a LeRobot dataset, train a policy, and run that policy back on the arm — optionally behind a language agent.

This page is the authoritative, end-to-end A1Z reference. If you only need the higher-level demonstration → dataset → training → deployment story across all arms, read [the learning loop](/capabilities/manipulation/collect-and-train) instead.

<Warning>
  The A1Z has **no brakes and no e-stop button** - only the PSU power switch. When motors disable, the arm goes limp and falls. Support the arm and keep the workspace clear before starting any hardware blueprint. Enabling the G1Z also initializes the gripper. Never leave it energized unattended.
</Warning>

## Before you start: clone the dimos repo

<Info>
  **Everything on this page runs from inside a clone of the [dimos repository](https://github.com/dimensionalOS/dimos)** - the setup scripts, `uv sync`, and every `uv run dimos` command below assume the repo root is your working directory. The quickstart's `pip install dimos` alone is **not** enough for the A1Z; without the repo checkout, none of the commands on this page will work.
</Info>

First install the system dependencies for your OS with the full setup guide - [Ubuntu](/installation/ubuntu) or [macOS](/installation/osx) - then clone the repo and work from its root:

```bash theme={null}
# fetch large files on-demand instead of pulling all of them immediately
export GIT_LFS_SKIP_SMUDGE=1
git clone https://github.com/dimensionalOS/dimos.git
cd dimos

# A1Z support currently lives on the adventure_x branch
git checkout adventure_x
```

All commands in the rest of this guide are run from this directory. Make sure you are on the `adventure_x` branch - the A1Z setup scripts and commands below are not on `main` yet.

## Host setup

The G1Z requires the vendor SDK's `gripper` branch - vendor `main` does not accept `with_gripper` and cannot actuate CAN motor 7. The one-command setup pins the correct SDK for you.

Run it as your normal user. On both platforms it installs the pinned vendor SDK from the locked `galaxea-a1z` dependency group; on macOS it also installs the PyUSB/gs-usb transport and Homebrew `libusb`. Linux then configures SocketCAN; macOS verifies the attached HHS adapter without enabling the arm:

```bash theme={null}
./dimos/robot/manipulators/galaxea_a1z/scripts/setup_a1z.sh
```

Add `--with-lerobot` to install the dataset, training, and live-policy runtime in the same environment. Use `--sdk-only` to synchronize and verify Python dependencies without checking or configuring attached CAN hardware:

```bash theme={null}
./dimos/robot/manipulators/galaxea_a1z/scripts/setup_a1z.sh --with-lerobot
./dimos/robot/manipulators/galaxea_a1z/scripts/setup_a1z.sh --sdk-only
```

The equivalent manual dependency sync is:

```bash theme={null}
uv sync --locked --inexact \
  --group galaxea-a1z \
  --extra learning \
  --extra lerobot
```

Always include `--group galaxea-a1z` in later exact syncs, or just rerun the setup script. That group keeps the non-PyPI vendor SDK and the macOS transport pinned inside `uv.lock`, so no manual `uv pip install` step is ever needed.

### CAN bring-up (Linux)

DimOS deliberately has **no Linux userspace-CAN fallback**. After a boot or after reconnecting the HHS adapter, rerun the full setup script, or invoke the CAN portion directly to bind the adapter to the kernel driver, configure the stable `a1zcan` SocketCAN interface, and verify transmission:

```bash theme={null}
sudo ./dimos/robot/manipulators/galaxea_a1z/scripts/setup_a1z_can.sh
```

<Warning>
  Do not start DimOS unless the script prints `A1Z CAN setup passed`. Galaxea's HHS USB-CANFD adapter is incompatible with the `gs_usb` driver in some Linux kernels: the interface comes up looking normal and `UP`, but silently drops every transmission. The setup script detects that misleading state and prints your supported-kernel and exact-kernel patch options. Galaxea recommends kernel 6.8.0-124 or newer; Jetsons and other pinned-kernel hosts need a persistent driver patch built for their exact kernel.
</Warning>

Known hardware quirk: the HHS adapter can wedge its RX queue after a crashed session. If the bus behaves strangely after a crash, physically replug the adapter and rerun the CAN check.

### Camera access (macOS)

The teach command uses a standard UVC camera through DimOS's generic `Webcam` and `CameraModule`. On Linux, index N normally maps to `/dev/videoN`. On macOS, grant the terminal application Camera access in **System Settings → Privacy & Security → Camera**, then select the AVFoundation device with `--camera-index N`. Use the index reported by **OpenCV, not `ffmpeg`** - their AVFoundation device ordering can differ.

## Run the arm

```bash theme={null}
uv run dimos run coordinator-galaxea-a1z
```

Startup is deliberately conservative: connecting opens the bus with motors unpowered, and activation does a **safe-start** - zero-gain enable, wait for all motors, verify the pose is within joint limits and nearly still, then hold at the measured pose. The arm never snaps to a commanded pose on enable.

Joint limits (rad): j1 ±2.094, j2 \[0, 3.142], j3 \[-3.142, 0], j4/j5 ±1.484, j6 ±2.007. The vendor firmware emergency-disables motors if a limit is crossed - including during teach mode, which drops the arm. Keep demonstrations comfortably inside the limits.

## Teach mode: record episodes by hand

Teach mode puts the arm in gravity-compensated zero-force mode: you drag it through the task by hand while DimOS records. Each saved episode contains 640x480 RGB camera frames at 15 Hz plus the six measured arm joints and the gripper position.

```bash theme={null}
uv run dimos a1z teach --task "pick up the object"
```

The `--task` text is stored with the episodes - write a real task description, since downstream language-conditioned policies train on it. Keep yourself out of the camera frame while dragging.

Select the camera with `--camera-index N` (see [camera access on macOS](#camera-access-macos) above). On the hackathon Mac, OpenCV enumerates the external KS2A418 camera as index 0:

```bash theme={null}
uv run --no-sync dimos a1z teach --camera-index 0 --task "pick up the object"
```

While recording, press `SPACE` to save the current episode or `d` to discard it. While idle, press `d` to discard the most recently saved episode; replay and dataset export will exclude it.

The command prints the Memory2 `.db` path.

## Replay an episode

```bash theme={null}
uv run dimos a1z replay ~/.local/state/dimos/recordings/a1z_teach_<timestamp>.db
```

The latest saved episode plays by default; pick one with `--episode` and adjust speed with `--speed`. The arm physically re-executes the taught motion - same safety rules as any motion command. Replaying is the fastest way to confirm a recording captured what you demonstrated before you spend time on datasets and training.

## Export to a LeRobot dataset

Convert a teach recording into a LeRobot v3 dataset with synchronized video, seven-element observation state (six joints + gripper), and seven-element action:

```bash theme={null}
uv run dimos dataprep build \
  --source ~/.local/state/dimos/recordings/a1z_teach_<timestamp>.db \
  --output ./a1z_lerobot_dataset \
  --format lerobot \
  --config dimos/learning/dataprep/galaxea_a1z_state_config.json

uv run dimos dataprep inspect ./a1z_lerobot_dataset
```

The output stores images as `observation.images.image`, the measured arm and gripper state as `observation.state`, and the next measured state as `action` - ready for imitation-learning training. For the config fields and the general demonstration → dataset story, see [the learning loop](/capabilities/manipulation/collect-and-train).

## Train an ACT policy

Install or verify the complete locked training runtime:

```bash theme={null}
./dimos/robot/manipulators/galaxea_a1z/scripts/setup_a1z.sh \
  --sdk-only \
  --with-lerobot
```

Train an ACT checkpoint from the converted local dataset:

```bash theme={null}
uv run lerobot-train \
  --dataset.repo_id=galaxea_a1z \
  --dataset.root=./a1z_lerobot_dataset \
  --policy.type=act \
  --policy.device=mps \
  --policy.push_to_hub=false \
  --output_dir=outputs/a1z_act \
  --job_name=a1z_act \
  --wandb.enable=false
```

Use `--policy.device=cuda` on an NVIDIA training host. Apple-silicon Macs use `mps`; CPU-only hosts can use `cpu` for a slow smoke test.

<Note>
  ACT is the tested A1Z policy type, but the runtime uses LeRobot's policy factory rather than hard-coding ACT. Another LeRobot policy type works as long as its checkpoint exposes the same single RGB image input, seven-value state input, and seven-value action output.
</Note>

## Run a trained checkpoint

After host setup passes, run the trained policy on hardware:

```bash theme={null}
uv run dimos a1z run-policy \
  outputs/a1z_act/checkpoints/last/pretrained_model \
  --camera-index 0 \
  --device mps \
  --task "pick up the object" \
  --duration 20
```

This is the one-checkpoint hardware test path. Loading and hardware initialization require confirmation, and inference starts only after live RGB and seven-joint observations are ready. Under the hood it installs the checkpoint in the policy catalog under the name `default`, starts the same camera/coordinator/policy module stack a full blueprint uses, and invokes `execute_learned_policy("default")`.

## Turn trained policies into an agentic robot

Once individual checkpoints pass `run-policy`, put them in one catalog and give each behavior a stable, meaningful skill name. Checkpoints load on first use and are cached, so one running robot can execute several trained behaviors without restarting. The complete blueprint stays small:

```python theme={null}
from dimos.agents.annotation import skill
from dimos.agents.capabilities import CAP_MOVEMENT
from dimos.agents.mcp.mcp_client import McpClient
from dimos.agents.mcp.mcp_server import McpServer
from dimos.core.coordination.blueprints import autoconnect
from dimos.learning.lerobot_policy import LeRobotPolicyConfig, LeRobotPolicyModule
from dimos.robot.manipulators.galaxea_a1z.blueprints.basic import (
    make_a1z_learned_policy_blueprint,
)


class HackathonPolicies(LeRobotPolicyModule):
    @skill(uses=[CAP_MOVEMENT], lifecycle="background")
    def pick_up_cup(self) -> str:
        """Pick up the wooden cup from the table."""
        return self.start_configured_policy("pick_up_cup", tool_name="pick_up_cup")

    @skill(uses=[CAP_MOVEMENT], lifecycle="background")
    def place_cup(self) -> str:
        """Place the held wooden cup on the table."""
        return self.start_configured_policy("place_cup", tool_name="place_cup")


a1z_policies = make_a1z_learned_policy_blueprint(
    policies={
        "pick_up_cup": LeRobotPolicyConfig(
            policy_path="outputs/pick_up_cup/checkpoints/last/pretrained_model",
            task="pick up the wooden cup",
            device="mps",
            default_duration=20.0,
        ),
        "place_cup": LeRobotPolicyConfig(
            policy_path="outputs/place_cup/checkpoints/last/pretrained_model",
            task="place the wooden cup on the table",
            device="mps",
            default_duration=20.0,
        ),
    },
    policy_module=HackathonPolicies,
    camera_index=0,
)

A1Z_AGENT_PROMPT = """You control a Galaxea A1Z manipulation arm.
Use the available learned manipulation skills to carry out the user's request.
Call only one movement skill at a time and report failures clearly.
"""

a1z_learned_agent = autoconnect(
    a1z_policies,
    McpServer.blueprint(),
    McpClient.blueprint(system_prompt=A1Z_AGENT_PROMPT),
)
```

Expose `a1z_learned_agent` as a runnable blueprint through the normal DimOS blueprint registration process, then start it like any other stack:

```bash theme={null}
uv run dimos run a1z-learned-agent --daemon
uv run dimos humancli
```

The same running blueprint can be driven without the interactive terminal:

```bash theme={null}
uv run dimos agent-send "pick up the wooden cup, then place it back down"
uv run dimos mcp list-tools
uv run dimos mcp call pick_up_cup
```

The composition is standard DimOS: the A1Z helper supplies the hardware, servo coordinator, camera, and one multi-policy module; `McpServer` exposes the named skills; and `McpClient` lets the language agent select and sequence them. Adding a trained behavior means adding one catalog entry and one small `@skill` wrapper - no new executor module, no changes to DimOS core.

## If something goes wrong

* **Kill switch:** the PSU power switch is the only hardware kill. Stopping the DimOS stack calls `deactivate()` (`write_enable(False)`), which disables the motors - and, since the arm has no brakes, drops it. Support the arm first, either way.
* **Gripper stays energized after shutdown:** the vendor protocol sends the gripper-disable frame only once and it can be lost. The DimOS adapter retries this automatically; if the gripper is still stiff, use the kill switch.
* **CAN interface up but nothing responds:** the broken-`gs_usb` kernel case above. Rerun `setup_a1z_can.sh` and read its output.
* **Policy behaving strangely:** work backwards through the loop. Run `dimos dataprep inspect` to check shapes and episode counts, and `dimos a1z replay` to check the recorded motion looks like what you demonstrated. A bad policy is usually a dataset problem; a dataset problem is usually a recording problem.
