inspect-robots-unitree-g1 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- inspect_robots_unitree_g1-0.1.0/.env.example +5 -0
- inspect_robots_unitree_g1-0.1.0/.github/workflows/canary.yml +46 -0
- inspect_robots_unitree_g1-0.1.0/.github/workflows/ci.yml +183 -0
- inspect_robots_unitree_g1-0.1.0/.github/workflows/release.yml +81 -0
- inspect_robots_unitree_g1-0.1.0/.gitignore +33 -0
- inspect_robots_unitree_g1-0.1.0/.pre-commit-config.yaml +52 -0
- inspect_robots_unitree_g1-0.1.0/CITATION.cff +9 -0
- inspect_robots_unitree_g1-0.1.0/CLAUDE.md +44 -0
- inspect_robots_unitree_g1-0.1.0/LICENSE +21 -0
- inspect_robots_unitree_g1-0.1.0/PKG-INFO +265 -0
- inspect_robots_unitree_g1-0.1.0/README.md +236 -0
- inspect_robots_unitree_g1-0.1.0/plans/0001-g1-gr00t-design.md +436 -0
- inspect_robots_unitree_g1-0.1.0/pyproject.toml +131 -0
- inspect_robots_unitree_g1-0.1.0/src/inspect_robots_unitree_g1/CLAUDE.md +20 -0
- inspect_robots_unitree_g1-0.1.0/src/inspect_robots_unitree_g1/__init__.py +36 -0
- inspect_robots_unitree_g1-0.1.0/src/inspect_robots_unitree_g1/_unitree.py +27 -0
- inspect_robots_unitree_g1-0.1.0/src/inspect_robots_unitree_g1/config.py +347 -0
- inspect_robots_unitree_g1-0.1.0/src/inspect_robots_unitree_g1/embodiment.py +693 -0
- inspect_robots_unitree_g1-0.1.0/src/inspect_robots_unitree_g1/operator.py +60 -0
- inspect_robots_unitree_g1-0.1.0/src/inspect_robots_unitree_g1/packing.py +99 -0
- inspect_robots_unitree_g1-0.1.0/src/inspect_robots_unitree_g1/policy.py +331 -0
- inspect_robots_unitree_g1-0.1.0/src/inspect_robots_unitree_g1/preflight.py +78 -0
- inspect_robots_unitree_g1-0.1.0/src/inspect_robots_unitree_g1/py.typed +0 -0
- inspect_robots_unitree_g1-0.1.0/tests/conftest.py +96 -0
- inspect_robots_unitree_g1-0.1.0/tests/test_api_snapshot.py +30 -0
- inspect_robots_unitree_g1-0.1.0/tests/test_camera.py +42 -0
- inspect_robots_unitree_g1-0.1.0/tests/test_compat.py +73 -0
- inspect_robots_unitree_g1-0.1.0/tests/test_config.py +122 -0
- inspect_robots_unitree_g1-0.1.0/tests/test_conformance.py +16 -0
- inspect_robots_unitree_g1-0.1.0/tests/test_embodiment.py +460 -0
- inspect_robots_unitree_g1-0.1.0/tests/test_embodiment_docs.py +17 -0
- inspect_robots_unitree_g1-0.1.0/tests/test_eval_end_to_end.py +38 -0
- inspect_robots_unitree_g1-0.1.0/tests/test_operator.py +32 -0
- inspect_robots_unitree_g1-0.1.0/tests/test_packing.py +48 -0
- inspect_robots_unitree_g1-0.1.0/tests/test_policy.py +284 -0
- inspect_robots_unitree_g1-0.1.0/tests/test_preflight.py +58 -0
- inspect_robots_unitree_g1-0.1.0/tests/test_unitree.py +49 -0
- inspect_robots_unitree_g1-0.1.0/uv.lock +851 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: Canary
|
|
2
|
+
|
|
3
|
+
# Weekly fresh-resolution test. Regular CI installs from uv.lock, so it can't
|
|
4
|
+
# see that a new release of an allowed dependency breaks us — this job can:
|
|
5
|
+
# it resolves the latest versions the pyproject ranges allow (ignoring the
|
|
6
|
+
# lockfile) and runs the test suite. On failure it opens an issue, like the
|
|
7
|
+
# red-main alert. A green canary is also the signal that it's safe to refresh
|
|
8
|
+
# the lockfile (`uv lock --upgrade`).
|
|
9
|
+
on:
|
|
10
|
+
schedule:
|
|
11
|
+
- cron: "23 5 * * 1" # Mondays 05:23 UTC
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
fresh-deps:
|
|
16
|
+
name: fresh resolution (latest allowed deps)
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
issues: write # open the failure alert
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
with:
|
|
24
|
+
fetch-depth: 0 # hatch-vcs derives the version from git tags
|
|
25
|
+
- name: Install uv
|
|
26
|
+
uses: astral-sh/setup-uv@v5
|
|
27
|
+
- name: Create venv
|
|
28
|
+
run: uv venv --python 3.12
|
|
29
|
+
- name: Install latest allowed deps (unlocked)
|
|
30
|
+
run: uv pip install -e ".[dev]"
|
|
31
|
+
- name: Pytest
|
|
32
|
+
run: uv run --no-sync pytest -q
|
|
33
|
+
- name: Open an issue on failure (unless one is already open)
|
|
34
|
+
if: ${{ failure() }}
|
|
35
|
+
env:
|
|
36
|
+
GH_TOKEN: ${{ github.token }}
|
|
37
|
+
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
38
|
+
run: |
|
|
39
|
+
existing=$(gh issue list -R "$GITHUB_REPOSITORY" --state open --search "Canary in:title" --json number --jq length)
|
|
40
|
+
if [ "$existing" = "0" ]; then
|
|
41
|
+
gh issue create -R "$GITHUB_REPOSITORY" \
|
|
42
|
+
--title "Canary: latest allowed dependencies break the build" \
|
|
43
|
+
--body "The weekly fresh-resolution canary failed: $RUN_URL — a new release of an allowed dependency likely breaks us. Fix: cap the offending dependency in pyproject.toml (then uv lock), or adapt the code and refresh the lock with uv lock --upgrade."
|
|
44
|
+
else
|
|
45
|
+
echo "an open canary issue already exists; not filing another"
|
|
46
|
+
fi
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: ci-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
quality:
|
|
18
|
+
name: lint · type
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
timeout-minutes: 10
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
- name: Install uv
|
|
24
|
+
uses: astral-sh/setup-uv@v5
|
|
25
|
+
with:
|
|
26
|
+
enable-cache: true
|
|
27
|
+
cache-dependency-glob: |
|
|
28
|
+
**/pyproject.toml
|
|
29
|
+
**/uv.lock
|
|
30
|
+
- name: Install from uv.lock (dev extras)
|
|
31
|
+
run: uv sync --locked --python 3.11 --extra dev
|
|
32
|
+
- name: Ruff (lint)
|
|
33
|
+
run: uv run ruff check .
|
|
34
|
+
- name: Ruff (format check)
|
|
35
|
+
run: uv run ruff format --check .
|
|
36
|
+
- name: Mypy (strict)
|
|
37
|
+
run: uv run mypy
|
|
38
|
+
|
|
39
|
+
test:
|
|
40
|
+
name: test (${{ matrix.os }}, py${{ matrix.python-version }})
|
|
41
|
+
runs-on: ${{ matrix.os }}
|
|
42
|
+
timeout-minutes: 15
|
|
43
|
+
strategy:
|
|
44
|
+
fail-fast: false
|
|
45
|
+
matrix:
|
|
46
|
+
os: [ubuntu-latest, macos-latest]
|
|
47
|
+
python-version: ["3.11", "3.12"]
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@v4
|
|
50
|
+
- name: Install uv
|
|
51
|
+
uses: astral-sh/setup-uv@v5
|
|
52
|
+
with:
|
|
53
|
+
enable-cache: true
|
|
54
|
+
cache-dependency-glob: |
|
|
55
|
+
**/pyproject.toml
|
|
56
|
+
**/uv.lock
|
|
57
|
+
- name: Install from uv.lock (dev extras)
|
|
58
|
+
run: uv sync --locked --python ${{ matrix.python-version }} --extra dev
|
|
59
|
+
- name: Pytest (100% coverage)
|
|
60
|
+
run: uv run pytest --cov --cov-report=term-missing
|
|
61
|
+
|
|
62
|
+
import-hygiene:
|
|
63
|
+
name: import with minimal dependencies
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
timeout-minutes: 10
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/checkout@v4
|
|
68
|
+
- name: Install uv
|
|
69
|
+
uses: astral-sh/setup-uv@v5
|
|
70
|
+
with:
|
|
71
|
+
enable-cache: true
|
|
72
|
+
cache-dependency-glob: |
|
|
73
|
+
**/pyproject.toml
|
|
74
|
+
**/uv.lock
|
|
75
|
+
- name: Install package with only locked core pins
|
|
76
|
+
run: |
|
|
77
|
+
uv venv --python 3.12
|
|
78
|
+
uv pip install --no-deps .
|
|
79
|
+
uv export --locked --no-emit-project --no-hashes \
|
|
80
|
+
| grep -E '^(inspect-robots|numpy)==' > /tmp/minimal-locked.txt
|
|
81
|
+
uv pip install -r /tmp/minimal-locked.txt
|
|
82
|
+
- name: Assert integrations absent, then import
|
|
83
|
+
run: |
|
|
84
|
+
.venv/bin/python - <<'PY'
|
|
85
|
+
import importlib.util
|
|
86
|
+
for mod in ("zmq", "msgpack", "msgpack_numpy", "cv2", "unitree_sdk2py", "torch"):
|
|
87
|
+
assert importlib.util.find_spec(mod) is None, f"{mod} unexpectedly installed"
|
|
88
|
+
import inspect_robots_unitree_g1
|
|
89
|
+
print(
|
|
90
|
+
"inspect_robots_unitree_g1",
|
|
91
|
+
inspect_robots_unitree_g1.__version__,
|
|
92
|
+
"imported with minimal deps",
|
|
93
|
+
)
|
|
94
|
+
PY
|
|
95
|
+
|
|
96
|
+
gr00t-seam:
|
|
97
|
+
name: pinned Isaac-GR00T protocol seam
|
|
98
|
+
runs-on: ubuntu-latest
|
|
99
|
+
timeout-minutes: 15
|
|
100
|
+
steps:
|
|
101
|
+
- uses: actions/checkout@v4
|
|
102
|
+
- name: Install uv
|
|
103
|
+
uses: astral-sh/setup-uv@v5
|
|
104
|
+
- name: Fetch and verify pinned protocol files
|
|
105
|
+
env:
|
|
106
|
+
# verified 2026-07-17 against main
|
|
107
|
+
ISAAC_GR00T_REF: 9c7e746b2cd37a810070a98ef41d290a07e806c2
|
|
108
|
+
run: |
|
|
109
|
+
base="https://raw.githubusercontent.com/NVIDIA/Isaac-GR00T/$ISAAC_GR00T_REF"
|
|
110
|
+
curl --fail --silent --show-error "$base/gr00t/policy/server_client.py" -o /tmp/server_client.py
|
|
111
|
+
curl --fail --silent --show-error "$base/gr00t/policy/policy.py" -o /tmp/policy.py
|
|
112
|
+
curl --fail --silent --show-error "$base/gr00t/policy/gr00t_policy.py" -o /tmp/gr00t_policy.py
|
|
113
|
+
curl --fail --silent --show-error "$base/gr00t/configs/data/embodiment_configs.py" -o /tmp/embodiment_configs.py
|
|
114
|
+
python - <<'PY'
|
|
115
|
+
from pathlib import Path
|
|
116
|
+
|
|
117
|
+
checks = {
|
|
118
|
+
"/tmp/server_client.py": [
|
|
119
|
+
'request: dict = {"endpoint": endpoint}',
|
|
120
|
+
'"get_action"',
|
|
121
|
+
"msgpack.packb",
|
|
122
|
+
"msgpack.unpackb",
|
|
123
|
+
"tuple(response)",
|
|
124
|
+
"zmq.error.Again",
|
|
125
|
+
"_init_socket",
|
|
126
|
+
"RCVTIMEO",
|
|
127
|
+
],
|
|
128
|
+
"/tmp/policy.py": ["def get_action", "check_observation"],
|
|
129
|
+
"/tmp/gr00t_policy.py": ["decode_action", '["video", "state", "language"]'],
|
|
130
|
+
"/tmp/embodiment_configs.py": [
|
|
131
|
+
'"unitree_g1_full_body_with_waist_height_nav_cmd"',
|
|
132
|
+
'"annotation.human.task_description"',
|
|
133
|
+
'"ego_view"',
|
|
134
|
+
'"left_leg"',
|
|
135
|
+
],
|
|
136
|
+
}
|
|
137
|
+
for path, needles in checks.items():
|
|
138
|
+
text = Path(path).read_text()
|
|
139
|
+
for needle in needles:
|
|
140
|
+
assert needle in text, f"{path} lost {needle!r}"
|
|
141
|
+
PY
|
|
142
|
+
- name: Import lazy wire dependencies
|
|
143
|
+
run: |
|
|
144
|
+
uv venv --python 3.12
|
|
145
|
+
uv pip install pyzmq msgpack msgpack-numpy
|
|
146
|
+
uv run --no-sync python - <<'PY'
|
|
147
|
+
import msgpack
|
|
148
|
+
import msgpack_numpy
|
|
149
|
+
import zmq
|
|
150
|
+
PY
|
|
151
|
+
|
|
152
|
+
ci-ok:
|
|
153
|
+
name: ci-ok
|
|
154
|
+
if: ${{ always() }}
|
|
155
|
+
needs: [quality, test, import-hygiene, gr00t-seam]
|
|
156
|
+
runs-on: ubuntu-latest
|
|
157
|
+
steps:
|
|
158
|
+
- name: Fail unless every needed job succeeded
|
|
159
|
+
env:
|
|
160
|
+
RESULTS: ${{ toJSON(needs) }}
|
|
161
|
+
run: echo "$RESULTS" | jq -e 'all(.[]; .result == "success")'
|
|
162
|
+
|
|
163
|
+
alert-red-main:
|
|
164
|
+
name: alert on red main
|
|
165
|
+
if: ${{ failure() && github.event_name == 'push' }}
|
|
166
|
+
needs: [quality, test, import-hygiene, gr00t-seam]
|
|
167
|
+
runs-on: ubuntu-latest
|
|
168
|
+
permissions:
|
|
169
|
+
issues: write
|
|
170
|
+
steps:
|
|
171
|
+
- name: Open an issue unless one is already open
|
|
172
|
+
env:
|
|
173
|
+
GH_TOKEN: ${{ github.token }}
|
|
174
|
+
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
175
|
+
run: |
|
|
176
|
+
existing=$(gh issue list -R "$GITHUB_REPOSITORY" --state open --search "CI is red on main in:title" --json number --jq length)
|
|
177
|
+
if [ "$existing" = "0" ]; then
|
|
178
|
+
gh issue create -R "$GITHUB_REPOSITORY" \
|
|
179
|
+
--title "CI is red on main (${GITHUB_SHA:0:8})" \
|
|
180
|
+
--body "CI failed on a push to main: $RUN_URL. Stop the line: fix forward or revert before merging anything else. If the failure is transient, re-run the failed jobs and close this issue."
|
|
181
|
+
else
|
|
182
|
+
echo "an open red-main issue already exists; not filing another"
|
|
183
|
+
fi
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Two ways to release; both publish to PyPI via trusted publishing (OIDC):
|
|
4
|
+
#
|
|
5
|
+
# 1. One-click: Actions -> Release -> "Run workflow" -> pick a version bump.
|
|
6
|
+
# The version is derived from git tags by hatch-vcs, so the cut job only
|
|
7
|
+
# computes the next tag and creates the GitHub release — nothing is
|
|
8
|
+
# committed or pushed to main (main is PR-only). Publish then runs in
|
|
9
|
+
# this same workflow run. (A release created with the built-in
|
|
10
|
+
# GITHUB_TOKEN never re-triggers workflows, which is why publish must
|
|
11
|
+
# live in this run rather than firing on the release event.)
|
|
12
|
+
#
|
|
13
|
+
# 2. Manual: publish a GitHub release by hand — the publish job runs on the
|
|
14
|
+
# release event. The tag must point at a commit that contains this file.
|
|
15
|
+
on:
|
|
16
|
+
release:
|
|
17
|
+
types: [published]
|
|
18
|
+
workflow_dispatch:
|
|
19
|
+
inputs:
|
|
20
|
+
bump:
|
|
21
|
+
description: "Version bump (applied to the latest v* tag)"
|
|
22
|
+
type: choice
|
|
23
|
+
options: [patch, minor, major]
|
|
24
|
+
default: patch
|
|
25
|
+
|
|
26
|
+
concurrency:
|
|
27
|
+
group: release
|
|
28
|
+
cancel-in-progress: false
|
|
29
|
+
|
|
30
|
+
jobs:
|
|
31
|
+
cut:
|
|
32
|
+
if: github.event_name == 'workflow_dispatch'
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
permissions:
|
|
35
|
+
contents: write # create the tag + release
|
|
36
|
+
outputs:
|
|
37
|
+
tag: ${{ steps.bump.outputs.tag }}
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
with:
|
|
41
|
+
fetch-depth: 0 # full tag history to find the latest version
|
|
42
|
+
- name: Compute next tag from latest v* tag
|
|
43
|
+
id: bump
|
|
44
|
+
env:
|
|
45
|
+
BUMP: ${{ inputs.bump }}
|
|
46
|
+
run: |
|
|
47
|
+
latest=$(git tag --list 'v*' --sort=-v:refname | head -1)
|
|
48
|
+
latest=${latest:-v0.0.0}
|
|
49
|
+
IFS=. read -r major minor patch <<< "${latest#v}"
|
|
50
|
+
case "$BUMP" in
|
|
51
|
+
major) major=$((major+1)); minor=0; patch=0 ;;
|
|
52
|
+
minor) minor=$((minor+1)); patch=0 ;;
|
|
53
|
+
patch) patch=$((patch+1)) ;;
|
|
54
|
+
esac
|
|
55
|
+
echo "tag: $latest -> v$major.$minor.$patch"
|
|
56
|
+
echo "tag=v$major.$minor.$patch" >> "$GITHUB_OUTPUT"
|
|
57
|
+
- name: Create GitHub release
|
|
58
|
+
env:
|
|
59
|
+
GH_TOKEN: ${{ github.token }}
|
|
60
|
+
TAG: ${{ steps.bump.outputs.tag }}
|
|
61
|
+
run: gh release create "$TAG" --target "$GITHUB_SHA" --title "$TAG" --generate-notes
|
|
62
|
+
|
|
63
|
+
publish:
|
|
64
|
+
# Directly on manual release events; after cut on workflow_dispatch.
|
|
65
|
+
needs: [cut]
|
|
66
|
+
if: ${{ !cancelled() && (github.event_name == 'release' || needs.cut.result == 'success') }}
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
environment: pypi
|
|
69
|
+
permissions:
|
|
70
|
+
id-token: write # OIDC token for PyPI trusted publishing
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/checkout@v4
|
|
73
|
+
with:
|
|
74
|
+
ref: ${{ needs.cut.outputs.tag || github.ref }}
|
|
75
|
+
fetch-depth: 0 # hatch-vcs derives the version from git tags
|
|
76
|
+
- name: Install uv
|
|
77
|
+
uses: astral-sh/setup-uv@v5
|
|
78
|
+
- name: Build sdist + wheel
|
|
79
|
+
run: uv build
|
|
80
|
+
- name: Publish to PyPI
|
|
81
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
|
|
9
|
+
# Virtualenvs
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
|
|
13
|
+
# Test / coverage
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
.coverage
|
|
16
|
+
coverage.xml
|
|
17
|
+
htmlcov/
|
|
18
|
+
.mypy_cache/
|
|
19
|
+
.ruff_cache/
|
|
20
|
+
.uv-cache/
|
|
21
|
+
|
|
22
|
+
# Secrets / env
|
|
23
|
+
.env
|
|
24
|
+
.env.*
|
|
25
|
+
!.env.example
|
|
26
|
+
|
|
27
|
+
# OS / editor
|
|
28
|
+
.DS_Store
|
|
29
|
+
.idea/
|
|
30
|
+
.vscode/
|
|
31
|
+
|
|
32
|
+
# Agent worktrees
|
|
33
|
+
.worktrees/
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Pre-commit hooks for inspect-robots-unitree-g1. Install once per clone:
|
|
2
|
+
#
|
|
3
|
+
# uv run pre-commit install # sets up both pre-commit and pre-push hooks
|
|
4
|
+
#
|
|
5
|
+
# On commit: file hygiene + ruff (lint & format) + mypy (strict).
|
|
6
|
+
# On push: pytest with the 100% coverage gate.
|
|
7
|
+
#
|
|
8
|
+
# Local hooks run through `uv run` so they use this project's dev environment
|
|
9
|
+
# (matching CI) regardless of whether a virtualenv is activated. Requires uv.
|
|
10
|
+
default_install_hook_types: [pre-commit, pre-push]
|
|
11
|
+
|
|
12
|
+
repos:
|
|
13
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
14
|
+
rev: v5.0.0
|
|
15
|
+
hooks:
|
|
16
|
+
- id: trailing-whitespace
|
|
17
|
+
- id: end-of-file-fixer
|
|
18
|
+
- id: check-yaml
|
|
19
|
+
- id: check-toml
|
|
20
|
+
- id: check-merge-conflict
|
|
21
|
+
- id: check-added-large-files
|
|
22
|
+
|
|
23
|
+
- repo: local
|
|
24
|
+
hooks:
|
|
25
|
+
- id: ruff-check
|
|
26
|
+
name: ruff (lint, autofix)
|
|
27
|
+
entry: uv run ruff check --fix
|
|
28
|
+
language: system
|
|
29
|
+
types_or: [python, pyi]
|
|
30
|
+
require_serial: true
|
|
31
|
+
|
|
32
|
+
- id: ruff-format
|
|
33
|
+
name: ruff (format)
|
|
34
|
+
entry: uv run ruff format
|
|
35
|
+
language: system
|
|
36
|
+
types_or: [python, pyi]
|
|
37
|
+
require_serial: true
|
|
38
|
+
|
|
39
|
+
- id: mypy
|
|
40
|
+
name: mypy (strict)
|
|
41
|
+
entry: uv run mypy
|
|
42
|
+
language: system
|
|
43
|
+
types: [python]
|
|
44
|
+
pass_filenames: false
|
|
45
|
+
|
|
46
|
+
- id: pytest-coverage
|
|
47
|
+
name: pytest (100% coverage gate)
|
|
48
|
+
entry: uv run pytest --cov --cov-report=term-missing
|
|
49
|
+
language: system
|
|
50
|
+
always_run: true
|
|
51
|
+
pass_filenames: false
|
|
52
|
+
stages: [pre-push]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software, please cite it as below."
|
|
3
|
+
title: "Inspect Robots Unitree G1: GR00T adapters for G1 arms"
|
|
4
|
+
authors:
|
|
5
|
+
- name: "Robocurve"
|
|
6
|
+
type: software
|
|
7
|
+
license: MIT
|
|
8
|
+
repository-code: "https://github.com/robocurve/inspect-robots-unitree-g1"
|
|
9
|
+
version: "0.1.0"
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# inspect-robots-unitree-g1 agent guide
|
|
2
|
+
|
|
3
|
+
Inspect Robots adapters for Unitree G1 arms controlled through arm_sdk and
|
|
4
|
+
Isaac-GR00T policy servers.
|
|
5
|
+
|
|
6
|
+
## The one big idea
|
|
7
|
+
|
|
8
|
+
The `g1_arms` embodiment and `gr00t` policy share one absolute 16-D
|
|
9
|
+
`joint_pos` contract. It contains seven left arm radians, one normalized left
|
|
10
|
+
hand, seven right arm radians, and one normalized right hand.
|
|
11
|
+
|
|
12
|
+
## Layout
|
|
13
|
+
|
|
14
|
+
- `src/inspect_robots_unitree_g1/` contains the package.
|
|
15
|
+
- `tests/` contains injected hardware-free tests.
|
|
16
|
+
- `plans/0001-g1-gr00t-design.md` is the accepted binding design.
|
|
17
|
+
|
|
18
|
+
## Working here
|
|
19
|
+
|
|
20
|
+
- Set `UV_CACHE_DIR=$PWD/.uv-cache` for uv commands.
|
|
21
|
+
- Run ruff check, ruff format check, strict mypy, and pytest with coverage.
|
|
22
|
+
- Keep optional SDK, ZMQ, msgpack, and OpenCV imports lazy.
|
|
23
|
+
- Keep 100 percent statement and branch coverage.
|
|
24
|
+
|
|
25
|
+
## Safety invariants
|
|
26
|
+
|
|
27
|
+
- Weight is blended in while holding the measured pose before homing.
|
|
28
|
+
- Every reset reseeds the command baseline from measured arm joints.
|
|
29
|
+
- Every action is hard-clamped and speed-limited in the embodiment.
|
|
30
|
+
- Close opens hands, parks arms, blends weight to zero, then disconnects.
|
|
31
|
+
- Construction performs no hardware, network, camera, signal, or stdin work.
|
|
32
|
+
- Success reaches scoring only through `termination_reason="success"`.
|
|
33
|
+
|
|
34
|
+
## CI and releases
|
|
35
|
+
|
|
36
|
+
- CI installs from `uv.lock`.
|
|
37
|
+
- `ci-ok` needs every blocking job.
|
|
38
|
+
- Versions come from git tags through hatch-vcs.
|
|
39
|
+
|
|
40
|
+
## Writing style
|
|
41
|
+
|
|
42
|
+
- Do not use em dashes in prose.
|
|
43
|
+
- Do not use decorative emoji.
|
|
44
|
+
- Use plain headers without trailing colons.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 RoboCurve
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|