Metadata-Version: 2.4
Name: trainnr
Version: 0.1.0
Summary: The physical AI platform for robot learning, run from your coding agent: telemetry, real-to-sim identification, simulation, RL and imitation, evaluation, sim-to-real deployment.
Author: Prakhar Aggarwal
License-Expression: FSL-1.1-ALv2
Project-URL: Homepage, https://github.com/Trainnr-AI/trainnr
Project-URL: Repository, https://github.com/Trainnr-AI/trainnr
Project-URL: Documentation, https://github.com/Trainnr-AI/trainnr/tree/main/docs
Project-URL: Issues, https://github.com/Trainnr-AI/trainnr/issues
Project-URL: Changelog, https://github.com/Trainnr-AI/trainnr/blob/main/CHANGELOG.md
Keywords: physical-ai,robotics,robot-learning,reinforcement-learning,imitation-learning,sim-to-real,system-identification,mujoco,simulation,telemetry,mcp
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Scientific/Engineering :: Physics
Classifier: Typing :: Typed
Requires-Python: <3.14,>=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: LICENSES/Apache-2.0.txt
License-File: NOTICE
Requires-Dist: onnx>=1.22.0
Requires-Dist: onnxruntime>=1.24.3
Requires-Dist: typing-extensions>=4.6; python_version < "3.12"
Provides-Extra: sim
Requires-Dist: mujoco[sysid]~=3.11.0; extra == "sim"
Requires-Dist: gymnasium<2,>=1.1.1; extra == "sim"
Provides-Extra: train
Requires-Dist: lerobot[dataset,smolvla,training]>=0.6.1; python_version >= "3.12" and extra == "train"
Provides-Extra: gpu
Requires-Dist: mujoco-warp~=3.11.0; sys_platform != "darwin" and extra == "gpu"
Provides-Extra: mjx
Requires-Dist: mujoco-mjx[warp]~=3.11.0; extra == "mjx"
Provides-Extra: viz
Requires-Dist: rerun-sdk>=0.20; extra == "viz"
Requires-Dist: tensorboard>=2.15; extra == "viz"
Provides-Extra: viz-query
Requires-Dist: rerun-sdk[datafusion]>=0.20; extra == "viz-query"
Provides-Extra: scene
Requires-Dist: open3d>=0.19; extra == "scene"
Requires-Dist: coacd>=1.0; extra == "scene"
Provides-Extra: deploy
Provides-Extra: mcp
Requires-Dist: mcp~=2.1; extra == "mcp"
Requires-Dist: psutil>=5.9; extra == "mcp"
Provides-Extra: usd
Requires-Dist: newton[importers]~=1.6.0; extra == "usd"
Dynamic: license-file

# trainnr

<!-- mcp-name: io.github.trainnr-ai/trainnr -->

The Python package of trainnr, **the physical AI platform for robot
learning, run from your coding agent.** It identifies a robot's dynamics
from its telemetry, generates datasets, trains policies, evaluates them
with exact confidence intervals, exports and gates them for deployment in
simulation, and checks new telemetry for drift. Every step is an MCP tool
and every result is a hash-stamped record the next step cites. What runs
today, and where, is in the repository's
[README](https://github.com/Trainnr-AI/trainnr#status).

The premise: **the robot is an artifact, not an import.** A robot enters
as a bundle `name@hash` (canonical MJCF or a USD asset read by Newton,
measured dynamics with intervals, provenance), and every stage codes
against that bundle, never against an embodiment.

The architecture and its decisions:
[`docs/22-pipeline-architecture.md`](https://github.com/Trainnr-AI/trainnr/blob/main/docs/22-pipeline-architecture.md);
the loop this package serves: [`docs/76-the-loop.md`](https://github.com/Trainnr-AI/trainnr/blob/main/docs/76-the-loop.md).

## Layout

Subpackages under `trainnr/trainnr/`, lowest layer first.

| Package | What it holds |
|---|---|
| `stats` | The honesty layer: exact binomial intervals, rank-correlation intervals, top-pick probability, per-factor main effects by Fisher's exact test. Standard library only, so a signed report is recomputable anywhere. |
| `bundles` | Hash-stamped artifact identity (`name@hash`, `require_stamp`) and where bundles live (`TRAINNR_ROBOTS_DIR`). Nothing is nameable without its hash. |
| `protocol.py` | The vocabulary every layer shares: `EpisodeProtocol`, milestones, `Placement`, `CameraSpec`. Standard library only, so a third-party task package imports this and nothing heavier. |
| `physics` | Engines by name (`trainnr.engines` entry points): CPU MuJoCo as the metrology reference and MJX-Warp as the batched throughput instrument; start-state validation on the model's own geometry; the rollout contract and `instrument_stamp`. |
| `robot` | The robot as a measured artifact: onboarding from MJCF or USD with an import audit, fail-loudly model gates, system identification over `mujoco.sysid` with fit records, intervals and pinned / NOT PINNED verdicts, identification methods by name. |
| `robots` | How a real robot's telemetry enters: recording adapters (`wire`, `lerobot`, `mcap`, `rosbag2`, Unitree DDS capture), joint-order maps, the public-log registry. |
| `collect` | Recordings become datasets with provenance: the demonstration press, shards, LeRobot v3 export, datasheets. |
| `tasks` | Scenes built as programs over the robot bundle, with their episode protocols and scripted experts, self-registering through `trainnr.tasks` entry points; task declaration as data (`Task.stamp`), overlays, the acceptance critic. |
| `evaluate` | The judge: paired trials with milestone chains, per-trial records and their fold, variations drawn by trial index, camera rigs as data, certificates, finding records, figures. |
| `envs` | The ecosystem's door: every registered task as a gymnasium env, the LeRobot `EnvConfig` (`--env.type=trainnr`), LeRobot's policy loader, an openpi chunk policy over its own client. |
| `deploy` | A policy exported as ONNX with a manifest a runtime drives it from; the sim-to-sim gate on plain MuJoCo and on Unitree's simulator over DDS; attribution of a failed gate to its cause; pre-flight; the deployment mirror into the viewer. |
| `fleet` | After deployment: drift judged against the robot's identified intervals from fresh telemetry. |
| `scenes` | Captured scenes: the Gaussian splat the cameras see, the collision proxy the solver touches, and the record of the gap between them. |
| `rl` | Learning on top of certified policies: SmoothRL's objective transcribed, the residual and replay pieces. |
| `project` | One directory per effort: the manifest, the artifact index the Studio reads, the presenter, the Studio's control files, previews. |
| `cloud` | Rented GPUs behind one seam: the provider contract and registry, RunPod first, the transfer rules (never `.env`, never private files). |
| `mcp_server.py`, `mcp_actions.py`, `mcp_jobs.py` | The MCP surface: the describe tools, the acting tools (each spawns the CLI that owns the work), and job handles for the long-running ones. |
| `cli.py` | The `trainnr` command. |
| `plugins.py`, `paths.py`, `viz.py` | The plugin door both registries share; where the checkout is; the mesh-true Rerun mirror of any MuJoCo model. |

The layer rule, pinned by `tests/test_layers.py` inside the package and by
`tools/check-layers.py` across packages: `stats` ← `bundles`, `protocol` ←
`evaluate` ← `physics`, `tasks`, `collect`, `robot` ← `envs` ← tools. This
package never imports `trainnr_mjlab` or the Studio.

## Tasks

Registered task families (`list_task_families` lists them):

| Family | Robot | What it is |
|---|---|---|
| `trainnr/lift-study` | SO-101 | the lift at a declared randomization span, the study's unit |
| `trainnr/kitting` | ALOHA 2 | parts into tray slots, with the scripted expert that presses demonstrations |
| `trainnr/gripper-pick` | Robotiq 2F-85 (USD-born) | a pick with the acceptance ladder's rungs |
| `trainnr/go2-walk` | Unitree Go2 | mjlab's velocity task on the onboarded Go2, trained through `trainnr-mjlab` |
| `trainnr/microduck-walk` | microduck | the biped's walk through the certified actuator stack |
| `trainnr/go1-walk` | Unitree Go1 | mjlab's own Go1 task with the study's span knob |

The SO-101 reach, lift, block-stack and tool-insert scenes and the ALOHA 2
transfer-cube scene are task builders in the same registry.

## The command and the plugin doors

```sh
trainnr mcp        # serve the tools over stdio (what an agent's config runs)
trainnr studio     # launch the Studio on the current project
trainnr version    # the installed version
```

Six entry-point groups let a third party extend the platform from its own
package, without a fork:

| Group | What registers | Built-in example |
|---|---|---|
| `trainnr.tasks` | a task module | `so101`, `aloha2` |
| `trainnr.engines` | a physics engine over the same MJCF | `mujoco`, `mjx-warp` |
| `trainnr.gpu_providers` | a rented-GPU vendor | `runpod` |
| `trainnr.robot_adapters` | a telemetry format | `wire`, `lerobot`, `mcap`, `rosbag2` |
| `trainnr.model_sources` | a robot model format for onboarding | `usd` |
| `trainnr.identification_methods` | a system-identification method | `drivetrain-ratio` |

A seventh, `trainnr.mcp_tools`, lets another package add tools to the MCP
server (`register_plugin_tools`).

## Develop

Everything runs through [uv](https://docs.astral.sh/uv/), which provisions
the interpreter too.

```sh
cd trainnr
uv run python -m unittest discover -s tests   # the suite; heavy parts skip without their extra
uvx ruff format --check . && uvx ruff check . # the same gate pre-commit runs
```

The base install is light on purpose: onnx and ONNX Runtime, which the
deployment tools (export, gate, pre-flight) need with nothing else
installed, and no more. The statistics and bundle layers are standard
library only, so they are recomputable anywhere a report is audited. The
stages that need more are extras (`pyproject.toml`,
`[project.optional-dependencies]`):

| Extra | What it brings |
|---|---|
| `sim` | MuJoCo with its `sysid` module (compatible-release pinned to 3.11: the engine version is part of the identified artifact) and gymnasium |
| `train` | LeRobot with dataset, SmolVLA and training support; Python 3.12 or newer |
| `mjx` | MJX with the Warp implementation, the batched second engine; CPU anywhere, fast on NVIDIA |
| `gpu` | MuJoCo Warp itself; skipped on macOS |
| `viz` | the Rerun SDK and TensorBoard's event reader (the presenter reads the file the trainer writes) |
| `viz-query` | reading a saved viewer recording back as columns (Rerun with DataFusion) |
| `scene` | Open3D and CoACD for captured scenes: the surface-to-proxy audit and collision proxies |
| `deploy` | nothing: kept as a name for commands that pass `--extra deploy`; onnx and ONNX Runtime are in the base install |
| `mcp` | the MCP SDK and psutil (the Studio's process liveness) |
| `usd` | Newton's importers for USD assets |

Two more sets are dependency groups, not extras: their sources are a git
URL or not on PyPI, so they are not published with the package and are
installed from a checkout only (`[dependency-groups]`):

| Group | What it brings | Install |
|---|---|---|
| `remote` | openpi's websocket client, pinned to a commit | `uv sync --group remote` |
| `dds` | cyclonedds, evdev and Unitree's `unitree_sdk2py`, for the DDS gate against Unitree's simulator (Linux) | `CYCLONEDDS_HOME=/usr/local uv sync --group dds` |

`mjx` and `usd` conflict (Newton's release and our engine pin disagree on
mujoco-warp); a USD import happens once, at onboarding, and the bundle it
writes runs on every extra. LeRobot wants Python 3.12 while `sim` is
measured on 3.11, so training commonly lives in a second environment
(`.venv-train`) beside the sim one.

On WSL2 the GPU routing and headless rendering variables live in one file,
`wsl.env` (`uv run --env-file wsl.env …` or `../tools/wsl-run.sh`); its
header says what each line does. Harmless on native Linux, unnecessary on
macOS and Windows.
