Metadata-Version: 2.4
Name: lerobot_robot_galaxea_a1
Version: 0.2.1
Summary: LeRobot Robot plugin for the Galaxea A1 runtime
Author: PengYue
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/pengyue-polaron/lerobot-robot-galaxea-a1
Project-URL: Repository, https://github.com/pengyue-polaron/lerobot-robot-galaxea-a1
Project-URL: Issues, https://github.com/pengyue-polaron/lerobot-robot-galaxea-a1/issues
Keywords: lerobot,galaxea,a1,robotics
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: <3.13,>=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: embodied-ops[grpc]<0.3,>=0.2
Requires-Dist: lerobot<0.7,>=0.6.0
Dynamic: license-file

# LeRobot Robot plugin for Galaxea A1

This package provides the auto-discovered LeRobot robot type `galaxea_a1`.
It is a thin client of an [`embodied-ops`](https://github.com/pengyue-polaron/embodied-ops)
Unix-socket service and deliberately contains no ROS node, vendor driver, process
supervisor, System config parser, or host motor publisher.

## Safety model

- Constructing `GalaxeaA1` does not connect to ROS, hardware, or the runtime service.
- `connect()` attaches to a separately supervised A1 runtime and must not move the arm.
- `send_action()` accepts six absolute joints in radians plus a continuous normalized
  gripper target and returns the command actually accepted by the runtime.
- Limits are declared by the runtime manifest and validated without hidden rewriting.
- `disconnect()` closes its exclusive command lease so the runtime locks/disables
  motion; it never opens the gripper or moves the robot home.

The production service is provided by
[`galaxea-a1-runtime`](https://github.com/pengyue-polaron/galaxea-a1-runtime).
That runtime retains exclusive ownership of ROS, the staged joint tracker, the locked
fail-closed relay, cameras, System config, and process lifecycle. This package never
imports `galaxea_a1_runtime`.

## Install

```bash
python -m pip install lerobot_robot_galaxea_a1
```

LeRobot discovers the package from its exact `lerobot_robot_` distribution prefix:

```bash
lerobot-teleoperate \
  --robot.type=galaxea_a1 \
  --robot.id=a1 \
  --robot.endpoint=unix:///run/my-runtime/embodied-ops.sock
```

The generic LeRobot 0.6 CLI currently installs identity teleoperation processors.
Do **not** pair the raw A1 SO leader with this command: leader values are degrees while
the robot contract is radians. Use `make_galaxea_a1_processors()` through LeRobot's
programmatic `teleoperate`/`record` APIs until upstream supports third-party pair
processor resolution.

## Recording boundary

This Robot is deliberately a control adapter: its observation contains the six measured
joints and normalized gripper required by the verified Teleop processor. It does not make
joint control depend on EEF tracking, and it does not reopen cameras owned by another
process. Consequently, a generic `lerobot-record` invocation is not the canonical Galaxea
dataset recorder.

The `galaxea-a1-runtime` collection workflow composes this control path with read-only EEF
feedback and the sole-owner Camera Bridge, then writes the standard LeRobotDataset v3
feature contract. This split keeps the pip plugin useful with any conforming service while
leaving robot-specific synchronization, provenance, atomic episode commit, and safety
lifecycle in the Runtime composition root.

## Canonical action contract

```text
joint_1_rad ... joint_6_rad  absolute radians
gripper_normalized           continuous 0..1
```

The supplied `GalaxeaA1RelativeAnchorProcessorStep` preserves the verified A1 mapping:
leader deltas are anchored to the A1 startup pose, converted from degrees, transformed
by explicit sign/scale/bias vectors, and bounded by explicit tracked joint limits.

## Development

```bash
uv venv --python 3.12
uv pip install -e . pytest ruff build
uv run --no-project pytest
uv run --no-project ruff check .
uv run --no-project ruff format --check .
uv build
```

All CI tests use a fake runtime service on a temporary Unix socket and never import ROS
or touch hardware.

## License

Apache-2.0
