Skip to main content
Galaxea A1Z 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 instead.
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.

Before you start: clone the dimos repo

Everything on this page runs from inside a clone of the dimos repository - 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.
First install the system dependencies for your OS with the full setup guide - Ubuntu or macOS - then clone the repo and work from its root:
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:
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:
The equivalent manual dependency sync is:
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:
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.
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

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.
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 above). On the hackathon Mac, OpenCV enumerates the external KS2A418 camera as index 0:
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

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:
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.

Train an ACT policy

Install or verify the complete locked training runtime:
Train an ACT checkpoint from the converted local dataset:
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.
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.

Run a trained checkpoint

After host setup passes, run the trained policy on hardware:
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:
Expose a1z_learned_agent as a runnable blueprint through the normal DimOS blueprint registration process, then start it like any other stack:
The same running blueprint can be driven without the interactive terminal:
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.