Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
with:
args: format --diff

# Type-check once, on Python 3.8 at the locked versions; newer Warp and NumPy stubs reject valid kernel code.
# Type-check once, on Python 3.8; newer Warp and NumPy stubs reject valid kernel code.
typecheck:
runs-on: ubuntu-latest
steps:
Expand All @@ -40,7 +40,7 @@ jobs:
- run: uv run --group dev --extra pt-cpu pyright

# Test matrices:
# - PR/main: Python 3.8 at the oldest allowed versions and 3.14 at the locked newest, without coverage; PRs skip slow tests.
# - PR/main: Python 3.8 at the oldest allowed versions and 3.14 at the newest, without coverage; PRs skip slow tests.
# - Weekly/manual: every Python at the newest releases, plus the oldest and torch-free rows, coverage, and slow tests.
test:
runs-on: ubuntu-latest
Expand All @@ -59,9 +59,6 @@ jobs:
with:
python-version: ${{ matrix.python }}
enable-cache: true
- name: Upgrade to the newest releases
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
run: uv lock --upgrade
- name: Restore warp kernel cache
id: warp
uses: actions/cache/restore@v4
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,4 @@ best_model_stats/
outputs
out
scripts/benchmark/motion_plan/.results.lock
uv.lock
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ test-all:
uv run --extra $(PT) --extra mj --extra mjwarp pytest -n 8 -m "not slow" .
uv run --extra $(PT) xdoctest robokit

# The oldest allowed versions, as PR CI runs them; resolving them rewrites uv.lock, so restore it afterwards.
# The oldest allowed versions, as PR CI runs them.
test-oldest:
cp uv.lock uv.lock.bak; UV_PROJECT_ENVIRONMENT=.venv-oldest UV_RESOLUTION=lowest-direct uv run --python 3.8 --extra pt-cpu --extra mj --extra mjwarp pytest .; rc=$$?; mv uv.lock.bak uv.lock; exit $$rc
UV_PROJECT_ENVIRONMENT=.venv-oldest UV_RESOLUTION=lowest-direct uv run --python 3.8 --extra pt-cpu --extra mj --extra mjwarp pytest .

install:
uv sync --extra $(PT)
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ Check the paper for benchmark details.
<strong><a href="https://github.com/openrobokit/robokit/blob/main/src/robokit/examples/sim_mpc/04_g1_climb.py">Climbing</a></strong> A G1 climbs a box on hands and knees.
</td>
<td valign="top">
<a href="https://github.com/openrobokit/robokit/blob/main/src/robokit/examples/sim_mpc/10_go2_jump.py"><img src="https://raw.githubusercontent.com/openrobokit/robokit/main/docs/assets/simulation/go2.webp" alt="Jumping" width="100%"></a><br>
<strong><a href="https://github.com/openrobokit/robokit/blob/main/src/robokit/examples/sim_mpc/10_go2_jump.py">Jumping</a></strong> A Go2 lands four 40 cm jumps on target footholds.
<a href="https://github.com/openrobokit/robokit/blob/main/src/robokit/examples/sim_mpc/11_go2_jump.py"><img src="https://raw.githubusercontent.com/openrobokit/robokit/main/docs/assets/simulation/go2.webp" alt="Jumping" width="100%"></a><br>
<strong><a href="https://github.com/openrobokit/robokit/blob/main/src/robokit/examples/sim_mpc/11_go2_jump.py">Jumping</a></strong> A Go2 lands four 40 cm jumps on target footholds.
</td>
</tr>
</table>
Expand Down
7 changes: 3 additions & 4 deletions docs/dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ assert total == 6

The website's **Full** button reveals the complete code; **Copy** always copies it.
`scripts/test_docs.py` executes that code with xdoctest and reports passed, skipped, and failed blocks.
Optional examples use hidden `# xdoctest: +REQUIRES(...)` directives: `ROBOKIT_ASSET_TESTS=1`
for cached assets, `ROBOKIT_BODY_MODELS` for local body models, `ROBOKIT_CUDA_DOCS=1`
Examples that download assets use a hidden `# xdoctest: +SKIP`. Optional examples use hidden
`# xdoctest: +REQUIRES(...)` directives: `ROBOKIT_BODY_MODELS` for local body models, `ROBOKIT_CUDA_DOCS=1`
for CUDA/nvdiffrast, and `ROBOKIT_PARAHOME_DOCS=1` for prepared ParaHome data.
Skipped blocks are still checked for valid Python syntax.
To check the website's copied code after importing and building it, run
Expand Down Expand Up @@ -161,8 +161,7 @@ torch.testing.assert_close(quaternion_multiply(q, q), torch.tensor([0.7071068, 0

### Pytest

Tests use local fixtures; Hugging Face calls are blocked before collection. Opt-in integration tests
(`ROBOKIT_ASSET_TESTS=1`) require locally prepared assets and cannot download missing files.
Tests use local fixtures; Hugging Face calls are blocked before collection.

To test original MANO PKL conversion and CPU engine parity using [locally supplied models](guide/assets.md#user-provided-body-models):

Expand Down
4 changes: 2 additions & 2 deletions docs/guide/assets.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ cached automatically. Use `fetch()` for paths without static symbols:

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
# docs: endhide
from robokit.assets import fetch
from robokit.assets.robots.humanoids import unitree_g1
Expand All @@ -36,7 +36,7 @@ match the symbol to the `SelfCollisionTask` representation you use (`sphere` is

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
from robokit.robo import Robot
from robokit.assets.robots.end_effectors import xhand

Expand Down
8 changes: 4 additions & 4 deletions docs/guide/full_body_retargeting.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ packs one row per frame:

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import trimesh
import warp as wp
Expand Down Expand Up @@ -140,7 +140,7 @@ markers a viewer needs:

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import trimesh
import warp as wp
Expand Down Expand Up @@ -197,7 +197,7 @@ survives. It needs `clip.scene`, and its link names assume G1 + Inspire.

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import trimesh
import warp as wp
Expand Down Expand Up @@ -255,7 +255,7 @@ behavior. Derive a variant with `dataclasses.replace(...)` rather than mutating

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import warp as wp
from robokit.helpers.full_body_retargeting import FullBodyRetargeter

Expand Down
11 changes: 5 additions & 6 deletions docs/guide/hand_retargeting.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ from copy import deepcopy

config = deepcopy(shadow.online)
config.task("smoothness").weight = 0.1
config.task("self_collision").weight = 10.0
config.task("self_collision").margin = 0.005
config.task("rest").weight = 0.01
```

The offline retargeter builds every template in `config.terms` the same way, from
Expand All @@ -82,7 +81,7 @@ cost; later frames are smoothed against the preceding solution. An explicit

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import warp as wp
from robokit.assets.robots.end_effectors import shadow_hand
Expand Down Expand Up @@ -134,7 +133,7 @@ that same world frame:

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import warp as wp
from robokit.assets.robots.end_effectors import shadow_hand
Expand Down Expand Up @@ -184,7 +183,7 @@ Wrist presets use `HandRetargeterOnlineConfig`. Tune tracking with `position_wei

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import warp as wp
from robokit.assets.robots.end_effectors import shadow_hand
Expand Down Expand Up @@ -236,7 +235,7 @@ Contact solves add one contact point and mask per `spec.contact_target_names` en

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import warp as wp
from robokit.assets.robots.end_effectors import shadow_hand
Expand Down
12 changes: 6 additions & 6 deletions docs/guide/humanoid_retargeting.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ and BHL robots.

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
# docs: endhide
from robokit.helpers.humanoid_retargeting.presets.g1_aligned import g1_aligned # G1, aligned SMPL-X
from robokit.helpers.humanoid_retargeting.presets.g1_smplh import g1_smplh # G1, SMPL-H interaction
Expand All @@ -86,7 +86,7 @@ loop:

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import warp as wp
from robokit.helpers.humanoid_retargeting import HumanoidRetargeterOnline
Expand Down Expand Up @@ -140,7 +140,7 @@ The caller owns the `WarpScene`; tasks in `config.terms` enable collision costs:

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import warp as wp
from robokit.helpers.humanoid_retargeting import HumanoidRetargeterOnline
Expand Down Expand Up @@ -185,7 +185,7 @@ scene whose single mesh is the object, and `batch_size=1`. Set the first target

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import trimesh
import warp as wp
Expand Down Expand Up @@ -236,7 +236,7 @@ templates read `HumanoidContext` inputs such as `TARGET_LINKS` and `TARGETS`; th

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import warp as wp
from robokit.helpers.humanoid_retargeting import HumanoidRetargeterOnline
Expand Down Expand Up @@ -281,7 +281,7 @@ lengths:

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import warp as wp
from robokit.helpers.humanoid_retargeting import HumanoidRetargeterOnline
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/ik.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ Load the robot with collision spheres, then add scene and self-collision terms:

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import warp as wp
from robokit.helpers.ik import IKContext, IKSolver, IKSolverConfig, presets
Expand Down
10 changes: 5 additions & 5 deletions docs/guide/motion_planning.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Plan from a start configuration to a hand pose past a box, then sample the plan

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
# docs: endhide
import numpy as np
import warp as wp
Expand Down Expand Up @@ -104,7 +104,7 @@ A joint goal skips goal IK, so it takes a joint preset:

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import warp as wp
from robokit.assets.robots.arms import franka_panda
Expand Down Expand Up @@ -132,7 +132,7 @@ Waypoints between start and goal can be joint arrays or poses:

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import warp as wp
from robokit.assets.robots.arms import franka_panda
Expand Down Expand Up @@ -215,7 +215,7 @@ The planning call itself does not change:

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import warp as wp
from robot_descriptions.loaders.yourdfpy import load_robot_description
Expand Down Expand Up @@ -281,7 +281,7 @@ when the pose target changes and passes that joint goal into each planning updat

```python
# docs: hide
# xdoctest: +REQUIRES(env:ROBOKIT_ASSET_TESTS==1)
# xdoctest: +SKIP
import numpy as np
import warp as wp
from robot_descriptions.loaders.yourdfpy import load_robot_description
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Paths are relative to [`src/robokit/examples`](../../src/robokit/examples/).
| [`grasp`](../../src/robokit/examples/grasp/) | [`01_basic.py`](../../src/robokit/examples/grasp/01_basic.py), [`02_annealed_gd.py`](../../src/robokit/examples/grasp/02_annealed_gd.py) |
| [`geom`](../../src/robokit/examples/geom/) | [`01_basic.py`](../../src/robokit/examples/geom/01_basic.py), [`02_robot.py`](../../src/robokit/examples/geom/02_robot.py), [`03_heterogeneous_batch.py`](../../src/robokit/examples/geom/03_heterogeneous_batch.py), [`04_lod.py`](../../src/robokit/examples/geom/04_lod.py) |
| [`opt`](../../src/robokit/examples/opt/) | [`01_rosenbrock.py`](../../src/robokit/examples/opt/01_rosenbrock.py), [`02_solvers.py`](../../src/robokit/examples/opt/02_solvers.py), [`03_multi_candidate.py`](../../src/robokit/examples/opt/03_multi_candidate.py), [`04_curve_fit.py`](../../src/robokit/examples/opt/04_curve_fit.py), [`05_mpc_pendulum.py`](../../src/robokit/examples/opt/05_mpc_pendulum.py), [`06_mpc_navigation.py`](../../src/robokit/examples/opt/06_mpc_navigation.py) |
| [`sim_mpc`](../../src/robokit/examples/sim_mpc/) | [`01_sharpa_oakink.py`](../../src/robokit/examples/sim_mpc/01_sharpa_oakink.py), [`02_xhand_arctic.py`](../../src/robokit/examples/sim_mpc/02_xhand_arctic.py), [`03_xhand_arctic_articulated.py`](../../src/robokit/examples/sim_mpc/03_xhand_arctic_articulated.py), [`04_g1_climb.py`](../../src/robokit/examples/sim_mpc/04_g1_climb.py), [`05_g1_carry.py`](../../src/robokit/examples/sim_mpc/05_g1_carry.py), [`06_g1_amass.py`](../../src/robokit/examples/sim_mpc/06_g1_amass.py), [`07_leap_cube.py`](../../src/robokit/examples/sim_mpc/07_leap_cube.py), [`08_sharpa_pen.py`](../../src/robokit/examples/sim_mpc/08_sharpa_pen.py), [`09_h1_jog.py`](../../src/robokit/examples/sim_mpc/09_h1_jog.py), [`10_go2_jump.py`](../../src/robokit/examples/sim_mpc/10_go2_jump.py), [`11_fr3_push.py`](../../src/robokit/examples/sim_mpc/11_fr3_push.py), [`12_fr3_balance.py`](../../src/robokit/examples/sim_mpc/12_fr3_balance.py), [`13_batch.py`](../../src/robokit/examples/sim_mpc/13_batch.py), [`14_demo_repair.py`](../../src/robokit/examples/sim_mpc/14_demo_repair.py) |
| [`sim_mpc`](../../src/robokit/examples/sim_mpc/) | [`01_sharpa_oakink.py`](../../src/robokit/examples/sim_mpc/01_sharpa_oakink.py), [`02_xhand_arctic.py`](../../src/robokit/examples/sim_mpc/02_xhand_arctic.py), [`03_xhand_arctic_articulated.py`](../../src/robokit/examples/sim_mpc/03_xhand_arctic_articulated.py), [`04_g1_climb.py`](../../src/robokit/examples/sim_mpc/04_g1_climb.py), [`05_g1_carry.py`](../../src/robokit/examples/sim_mpc/05_g1_carry.py), [`06_g1_amass.py`](../../src/robokit/examples/sim_mpc/06_g1_amass.py), [`07_leap_cube.py`](../../src/robokit/examples/sim_mpc/07_leap_cube.py), [`08_sharpa_pen.py`](../../src/robokit/examples/sim_mpc/08_sharpa_pen.py), [`09_sharpa_cube.py`](../../src/robokit/examples/sim_mpc/09_sharpa_cube.py), [`10_h1_jog.py`](../../src/robokit/examples/sim_mpc/10_h1_jog.py), [`11_go2_jump.py`](../../src/robokit/examples/sim_mpc/11_go2_jump.py), [`12_fr3_push.py`](../../src/robokit/examples/sim_mpc/12_fr3_push.py), [`13_fr3_balance.py`](../../src/robokit/examples/sim_mpc/13_fr3_balance.py), [`14_batch.py`](../../src/robokit/examples/sim_mpc/14_batch.py), [`15_demo_repair.py`](../../src/robokit/examples/sim_mpc/15_demo_repair.py) |

Example usage:

Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ url = "https://download.pytorch.org/whl/cpu"
explicit = true

[tool.uv]
# Lock-only fixes for bad upstream metadata: torch 2.5 and mujoco 3.4-3.5 claim Python versions they ship no wheels for.
constraint-dependencies = ["torch!=2.5.*", "mujoco!=3.4.*,!=3.5.*"]
# uv-only fixes for bad upstream metadata: these claim Python versions they ship no wheels for.
constraint-dependencies = ["torch!=2.5.*", "mujoco!=3.4.*,!=3.5.*", "embreex!=4.4.0.post1"]
required-environments = ["sys_platform == 'linux' and platform_machine == 'x86_64'"]
conflicts = [[{ extra = "pt-cpu" }, { extra = "pt-cu118" }, { extra = "pt-cu126" }, { extra = "pt-cu128" }]]

Expand Down
Loading
Loading