Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
8d20b8d
Docs: rewrite install guide and make lerobot a required dependency (#…
yuecideng Apr 12, 2026
d2a8dad
Update cobotmagic arm asset. (#228)
matafela Apr 13, 2026
987d04f
Fix opw solver (#229)
matafela Apr 15, 2026
80368bd
Fix crashing when no grasp pose found. (#232)
matafela Apr 15, 2026
59021a4
add rl benchmark (#231)
matafela Apr 15, 2026
d860435
Enhance workspace analyzer computational efficiency (#230)
yuecideng Apr 15, 2026
d52ea77
Update CobotMagic default safe margin (#235)
matafela Apr 16, 2026
d5bf930
Fix demo action shape normalization and control-part mapping (#237)
yuecideng Apr 16, 2026
3bb2592
Refine URDF assembly component prefixes and name casing policy (#236)
chase6305 Apr 19, 2026
50843a5
Refactor: benchmark (#233)
matafela Apr 20, 2026
e0e16ae
Update pytorch kinematic solver benchmark param (#240)
matafela Apr 20, 2026
0497711
fix plan_trajectory (#242)
yhnsu Apr 22, 2026
ccce98a
docs: add NVIDIA driver guide and mesh loading tutorial (#245)
XuanchaoPENG Apr 23, 2026
386dc66
Add multi-version documentation build support (#234)
yuecideng Apr 24, 2026
9fb2204
Fix README docs link (#246)
yuecideng Apr 24, 2026
06258f1
docs: add AI coding agent skills and cross-reference throughout docum…
yuecideng Apr 28, 2026
72e9731
fix: correct the link of website (#249)
yangchen73 Apr 29, 2026
c824c86
docs: upgrade README badges and add auto-sync to introduction.rst (#250)
yuecideng Apr 29, 2026
8e92c08
upgrade pytorch kinematics (#244)
matafela Apr 30, 2026
72b5bb9
chore: upgrade black to 26.3.1 and fix code style (#251)
yuecideng Apr 30, 2026
fc54598
Improve API reference detail and coverage (#252)
yuecideng May 1, 2026
168f11c
feat: Add atomic action abstraction layer for embodied AI motion gene…
yuecideng May 1, 2026
c5e6f00
Fix pytorch solver qpos mapping (#253)
matafela May 7, 2026
23a1208
docs: Remove AI coding agent skills references (#254)
yuecideng May 7, 2026
076fc65
docs: add data generation tutorial for synthesized data pipeline (#238)
yvvonie May 8, 2026
f81b8a6
Update skills structure and roadmap docs (#257)
yuecideng May 8, 2026
9e34ec1
Adapt dexsim v0.4.0 (#226)
yuecideng May 9, 2026
72ffe43
docs: add uv installation support and update dependencies (#258)
yuecideng May 9, 2026
c6ce00f
Fix PyPI release workflow (#259)
yuecideng May 9, 2026
e11eb4e
docs: improve navigation, cross-references, and guides (#262)
yuecideng May 12, 2026
a251699
Fix multiversion docs overwrite on main branch push (#263)
yuecideng May 12, 2026
6e5f745
docs: add academic publications page (#265)
yuecideng May 12, 2026
c322584
Fix multiversion docs overwrite on main push (#266)
yuecideng May 12, 2026
5cdd9c2
ci: fix docs deployment to use GitHub Actions Pages source
yuecideng May 12, 2026
2a8b56c
ci: fix multiversion docs deployment (#267)
yuecideng May 12, 2026
7f8931d
feat: add RobotDef protocol for robot definition system
yuecideng May 12, 2026
c3d224f
feat: add robot registry for name-based lookup and instantiation
yuecideng May 12, 2026
0a21be9
refactor: migrate CobotMagic to RobotDef protocol with registry
yuecideng May 13, 2026
af09f45
refactor: migrate DexforceW1 to RobotDef protocol with registry
yuecideng May 13, 2026
7d25f55
feat: export RobotDef, registry, and new robot defs from __init__
yuecideng May 13, 2026
5dcc7ce
docs: update add_robot guide for RobotDef protocol
yuecideng May 13, 2026
9ad4934
add design docs
yuecideng May 13, 2026
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
1 change: 1 addition & 0 deletions .claude/skills/add-atomic-action
1 change: 1 addition & 0 deletions .claude/skills/add-functor
1 change: 1 addition & 0 deletions .claude/skills/add-task-env
1 change: 1 addition & 0 deletions .claude/skills/add-test
1 change: 1 addition & 0 deletions .claude/skills/benchmark
1 change: 1 addition & 0 deletions .claude/skills/pr
1 change: 1 addition & 0 deletions .claude/skills/pre-commit-check
177 changes: 122 additions & 55 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
run: |
echo "Workspace: ${GITHUB_WORKSPACE}"
ls
pip install black==24.3.0
pip install black==26.3.1
black --check --diff --color ./
if [ $? -ne 0 ]; then
echo "Code style check failed, please run [black ./] before commit!"
Expand All @@ -45,24 +45,82 @@ jobs:
NVIDIA_DRIVER_CAPABILITIES: all
NVIDIA_VISIBLE_DEVICES: all
NVIDIA_DISABLE_REQUIRE: 1
DOCS_MAX_VERSIONS: 5
container: *container_template
steps:
- uses: actions/checkout@v4

- name: Cache Python dependencies
id: cache-pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-docs-${{ hashFiles('docs/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-docs-

# Restore the full multi-version site from the last successful build.
# The key never matches exactly (run_id is unique), so restore-keys is
# always used to pick up the most recently saved full site.
- name: Restore full multi-version docs site
if: github.event_name == 'push'
uses: actions/cache/restore@v4
with:
path: docs/build/html
key: docs-full-site-${{ github.repository }}-${{ github.run_id }}
restore-keys: |
docs-full-site-${{ github.repository }}-

- name: Build docs
shell: bash
run: |
pip install -e . --extra-index-url http://pyp.open3dv.site:2345/simple/ --trusted-host pyp.open3dv.site
pip install -r docs/requirements.txt
python3 docs/scripts/sync_readme.py
cd ${GITHUB_WORKSPACE}/docs
echo "Start Building docs..."
pip uninstall pymeshlab -y
pip install pymeshlab==2023.12.post3
make html

if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
VERSION="${GITHUB_REF_NAME}"
echo "Building docs for release tag ${VERSION}..."
sphinx-build source build/html/${VERSION}

cd build/html

# Prune old release versions beyond the window
mapfile -t TAG_DIRS < <(ls -d v*/ 2>/dev/null | sort -V)
while [[ ${#TAG_DIRS[@]} -gt ${DOCS_MAX_VERSIONS:-5} ]]; do
echo "Pruning old version: ${TAG_DIRS[0]}"
rm -rf "${TAG_DIRS[0]}"
TAG_DIRS=("${TAG_DIRS[@]:1}")
done

else
echo "Building dev docs for main branch..."
# Only rebuild main/ — all other version dirs come from the cache
rm -rf build/html/main
sphinx-build source build/html/main
cd build/html
fi

# Regenerate versions.json and root index.html from all present dirs
python3 ${GITHUB_WORKSPACE}/docs/scripts/generate_versions_json.py \
--build-dir .

# Save the updated full site so the next run can restore all versions
- name: Save full multi-version docs site
if: github.event_name == 'push'
uses: actions/cache/save@v4
with:
path: docs/build/html
key: docs-full-site-${{ github.repository }}-${{ github.run_id }}

- name: Upload docs artifact
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
if: github.event_name == 'push'
uses: actions/upload-pages-artifact@v3
with:
with:
path: ${{ github.workspace }}/docs/build/html
retention-days: 3

test:
if: github.event_name == 'pull_request'
Expand All @@ -86,62 +144,71 @@ jobs:
pytest tests

publish:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
if: github.event_name == 'push'
needs: build
runs-on: Linux
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
env:
NVIDIA_DRIVER_CAPABILITIES: all
NVIDIA_VISIBLE_DEVICES: all
NVIDIA_DISABLE_REQUIRE: 1
id-token: write
steps:
- name: Deploy GitHub Pages
uses: actions/deploy-pages@v4


release-build:
if: startsWith(github.ref, 'refs/tags/v')
needs: lint
runs-on: Linux

container: *container_template

steps:
- uses: actions/checkout@v4
- name: Download docs artifact
uses: actions/download-artifact@v4
with:
name: github-pages
fetch-depth: 0

- name: Deploy GitHub Pages
uses: actions/deploy-pages@v4
- name: (Release) Install build tools
run: |
python -m pip install --upgrade pip
pip install build

- name: (Release) Build sdist and wheel
run: |
python -m build

# - name: (Release) Create GitHub Release (draft)
# uses: softprops/action-gh-release@v2
# with:
# draft: true
# generate_release_notes: true
# files: |
# dist/*
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: (Release) Upload distributions
uses: actions/upload-artifact@v4
with:
name: python-distributions
path: dist/

release-publish:
if: startsWith(github.ref, 'refs/tags/v')
needs: release-build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/embodichain
permissions:
contents: read
id-token: write # PyPI Trusted Publishing

steps:
- name: (Release) Download distributions
uses: actions/download-artifact@v4
with:
name: python-distributions
path: dist/

# release:
# if: startsWith(github.ref, 'refs/tags/v')
# runs-on: Linux
# permissions:
# contents: write
# id-token: write # PyPI Trusted Publishing

# container: *container_template

# steps:
# - uses: actions/checkout@v4
# with:
# fetch-depth: 0

# - name: (Release) Install build tools
# run: |
# python -m pip install --upgrade pip
# pip install build

# - name: (Release) Build sdist and wheel
# run: |
# python -m build --wheel

# # - name: (Release) Create GitHub Release (draft)
# # uses: softprops/action-gh-release@v2
# # with:
# # draft: true
# # generate_release_notes: true
# # files: |
# # dist/*
# # env:
# # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# - name: (Release) Publish to PyPI
# uses: pypa/gh-action-pypi-publish@release/v1
# with:
# password: ${{ secrets.PYPI_API_TOKEN }}
- name: (Release) Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
157 changes: 157 additions & 0 deletions .github/workflows/tests/test_docs_publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
name: Test docs publish logic

on:
workflow_dispatch:

jobs:
# -----------------------------------------------------------------------
# Scenario A: push to main — existing v0.1.0, v0.2.0 must survive
# Simulates: cache holds v0.1.0 + v0.2.0, build adds/updates main/
# -----------------------------------------------------------------------
test-main-push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up fake "cache" (previous full-site with versioned dirs)
run: |
mkdir -p docs/build/html/v0.1.0 docs/build/html/v0.2.0
echo "<html>v0.1.0</html>" > docs/build/html/v0.1.0/index.html
echo "<html>v0.2.0</html>" > docs/build/html/v0.2.0/index.html

- name: Simulate build step — update main/ only
run: |
GITHUB_REF=refs/heads/main
DOCS_MAX_VERSIONS=4

# Mirrors the workflow: rm -rf build/html/main, then build
rm -rf docs/build/html/main
mkdir -p docs/build/html/main
echo "<html><body>main docs (new build)</body></html>" > docs/build/html/main/index.html

cd docs/build/html
python3 ${GITHUB_WORKSPACE}/docs/scripts/generate_versions_json.py --build-dir .

- name: Assert — v0.1.0 and v0.2.0 still present, main updated
run: |
echo "=== docs/build/html structure ===" && find docs/build/html -maxdepth 1 | sort
[ -d docs/build/html/v0.1.0 ] || (echo "FAIL: v0.1.0 removed!" && exit 1)
[ -d docs/build/html/v0.2.0 ] || (echo "FAIL: v0.2.0 removed!" && exit 1)
grep -q "new build" docs/build/html/main/index.html || (echo "FAIL: main not updated!" && exit 1)
[ -f docs/build/html/versions.json ] || (echo "FAIL: versions.json missing!" && exit 1)
echo "=== versions.json ===" && cat docs/build/html/versions.json
python3 -c "
import json
d = json.load(open('docs/build/html/versions.json'))
names = [v['name'] for v in d['versions']]
assert 'v0.1.0' in names and 'v0.2.0' in names and 'main' in names, f'Missing versions: {names}'
print('PASS: all versions present:', names)
"
echo "PASS: main_push — existing versions preserved"

# -----------------------------------------------------------------------
# Scenario B: tag push v0.3.0 — new version added, old dirs untouched
# -----------------------------------------------------------------------
test-tag-push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up fake "cache" (previous full-site)
run: |
mkdir -p docs/build/html/v0.1.0 docs/build/html/v0.2.0 docs/build/html/main
echo "<html>v0.1.0</html>" > docs/build/html/v0.1.0/index.html
echo "<html>v0.2.0</html>" > docs/build/html/v0.2.0/index.html
echo "<html>main</html>" > docs/build/html/main/index.html

- name: Simulate build step — add v0.3.0
run: |
GITHUB_REF=refs/tags/v0.3.0
DOCS_MAX_VERSIONS=4

mkdir -p docs/build/html/v0.3.0
echo "<html>v0.3.0</html>" > docs/build/html/v0.3.0/index.html

cd docs/build/html
mapfile -t TAG_DIRS < <(ls -d v*/ 2>/dev/null | sort -V)
while [[ ${#TAG_DIRS[@]} -gt ${DOCS_MAX_VERSIONS} ]]; do
echo "Pruning: ${TAG_DIRS[0]}"
rm -rf "${TAG_DIRS[0]}"
TAG_DIRS=("${TAG_DIRS[@]:1}")
done

python3 ${GITHUB_WORKSPACE}/docs/scripts/generate_versions_json.py --build-dir .

- name: Assert — all four dirs present, latest is v0.3.0
run: |
echo "=== docs/build/html structure ===" && find docs/build/html -maxdepth 1 | sort
for d in v0.1.0 v0.2.0 v0.3.0 main; do
[ -d "docs/build/html/$d" ] || (echo "FAIL: $d missing!" && exit 1)
done
echo "=== versions.json ===" && cat docs/build/html/versions.json
python3 -c "
import json
d = json.load(open('docs/build/html/versions.json'))
names = [v['name'] for v in d['versions']]
assert d['latest'] == 'v0.3.0', f'latest should be v0.3.0, got {d[\"latest\"]}'
assert all(n in names for n in ['v0.1.0','v0.2.0','v0.3.0','main']), f'Missing: {names}'
print('PASS: versions.json correct, latest =', d['latest'])
"
echo "PASS: tag_push — new version added, others preserved"

# -----------------------------------------------------------------------
# Scenario C: 5th tag triggers pruning — oldest (v0.1.0) removed
# -----------------------------------------------------------------------
test-prune-old-versions:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up fake "cache" with 4 existing tag dirs (at the limit)
run: |
for v in v0.1.0 v0.2.0 v0.3.0 v0.4.0; do
mkdir -p docs/build/html/${v}
echo "<html>${v}</html>" > docs/build/html/${v}/index.html
done
mkdir -p docs/build/html/main
echo "<html>main</html>" > docs/build/html/main/index.html

- name: Simulate build step — push v0.5.0 triggers prune
run: |
GITHUB_REF=refs/tags/v0.5.0
DOCS_MAX_VERSIONS=4

mkdir -p docs/build/html/v0.5.0
echo "<html>v0.5.0</html>" > docs/build/html/v0.5.0/index.html

cd docs/build/html
mapfile -t TAG_DIRS < <(ls -d v*/ 2>/dev/null | sort -V)
while [[ ${#TAG_DIRS[@]} -gt ${DOCS_MAX_VERSIONS} ]]; do
echo "Pruning: ${TAG_DIRS[0]}"
rm -rf "${TAG_DIRS[0]}"
TAG_DIRS=("${TAG_DIRS[@]:1}")
done

python3 ${GITHUB_WORKSPACE}/docs/scripts/generate_versions_json.py --build-dir .

- name: Assert — v0.1.0 pruned, max 4 tags kept, main untouched
run: |
echo "=== docs/build/html structure ===" && find docs/build/html -maxdepth 1 | sort
[ ! -d docs/build/html/v0.1.0 ] || (echo "FAIL: v0.1.0 should be pruned!" && exit 1)
for d in v0.2.0 v0.3.0 v0.4.0 v0.5.0 main; do
[ -d "docs/build/html/$d" ] || (echo "FAIL: $d was incorrectly removed!" && exit 1)
done
TAG_COUNT=$(ls -d docs/build/html/v*/ 2>/dev/null | wc -l)
[ "${TAG_COUNT}" -le 4 ] || (echo "FAIL: ${TAG_COUNT} tags exceed DOCS_MAX_VERSIONS=4" && exit 1)
echo "=== versions.json ===" && cat docs/build/html/versions.json
python3 -c "
import json
d = json.load(open('docs/build/html/versions.json'))
names = [v['name'] for v in d['versions']]
assert 'v0.1.0' not in names, f'v0.1.0 should be pruned: {names}'
assert d['latest'] == 'v0.5.0', f'latest should be v0.5.0, got {d[\"latest\"]}'
tag_count = sum(1 for v in d['versions'] if v['type'] == 'tag')
assert tag_count <= 4, f'Too many tags: {tag_count}'
print('PASS: pruning correct, latest =', d['latest'], ', tag count =', tag_count)
"
echo "PASS: prune — oldest removed, within limit, main preserved"
Loading
Loading