Skip to content

Test MJCF descriptions with Pinocchio #103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft
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
36 changes: 35 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ jobs:
strategy:
matrix:
python-version: ["3.9"]
loader: ["idyntree", "mujoco", "pinocchio", "pybullet", "robomeshcat", "yourdfpy"]
loader: ["idyntree", "mujoco", "pybullet", "robomeshcat", "yourdfpy"]

steps:
- name: "Checkout sources"
Expand All @@ -85,6 +85,40 @@ jobs:
run: |
tox -e loader-${{ matrix.loader }}

loader-pinocchio:
name: "Loader: pinocchio with Python ${{ matrix.python-version }}"
runs-on: ubuntu-latest

strategy:
matrix:
python-version: ["3.9"]

defaults:
run:
# See https://github.com/mamba-org/setup-micromamba?tab=readme-ov-file#about-login-shells
shell: bash -leo pipefail {0}

steps:
- name: "Checkout sources"
uses: actions/checkout@v4

- name: "Install Conda environment with Micromamba"
uses: mamba-org/setup-micromamba@v1
with:
micromamba-version: '1.5.8-0'
environment-name: pinocchio_test_env
create-args: >-
python=${{ matrix.python-version }}
gitpython
pinocchio>=3.1.0
tqdm
cache-environment: true
post-cleanup: 'all'

- name: "Run loader tests"
run: |
python -m unittest tests/loaders/test_pinocchio.py --failfast

ci_success:
name: "CI success"
runs-on: ubuntu-latest
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,15 @@ All notable changes to this project will be documented in this file.

### Changed

- CICD: Isolate loader tests in testing submodules
- CICD: Remove version pin on NumPy < 2
- Update `baxter_common` repository with a commit ID rather than a tag
- Update `talos-data` repository with a commit ID rather than a tag

### Fixed

- CICD: Switch to conda-forge dependencies in Pinocchio loader test environment

## [1.16.0] - 2025-04-09

### Added
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ keywords = ["robot", "description", "urdf", "mjcf"]

[project.optional-dependencies]
opts = [
"idyntree >= 8.0.0",
"idyntree >=8.0.0",
"mujoco >=3.2.0",
"pin >=2.6.10",
"pin >=3.1.0",
"pybullet >=3.2.6",
"robomeshcat >=1.0.4",
"yourdfpy >=0.0.56",
Expand Down
2 changes: 0 additions & 2 deletions tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@
from .test_clone_to_cache import TestCloneToCache
from .test_clone_to_directory import TestCloneToDirectory
from .test_descriptions import TestDescriptions
from .test_loaders import TestLoaders
from .test_progress_bar import TestProgressBar

__all__ = [
"TestCloneToCache",
"TestCloneToDirectory",
"TestDescriptions",
"TestLoaders",
"TestProgressBar",
]
16 changes: 13 additions & 3 deletions tests/loaders/test_idyntree.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,24 @@
import unittest

from robot_descriptions._descriptions import DESCRIPTIONS
from robot_descriptions.loaders.idyntree import (
load_robot_description as load_idyntree,
)

from robot_descriptions.loaders.idyntree import load_robot_description

class TestiDynTree(unittest.TestCase):

"""
Check that all descriptions are loaded properly in iDynTree.
"""

def test_idyntree(self):
self.assertIsNotNone(
load_idyntree(
"upkie_description",
commit="98502d5b175c3d6b60b3cf475b7eeef9fd290c43",
)
)

@staticmethod
def get_test_for_description(description: str):
"""
Expand All @@ -29,10 +38,11 @@ def get_test_for_description(description: str):
"""

def test(self):
load_robot_description(description)
load_idyntree(description)

return test


# Add a test function for each URDF description
for name, description in DESCRIPTIONS.items():
if description.has_urdf:
Expand Down
10 changes: 7 additions & 3 deletions tests/loaders/test_mujoco.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@
import unittest

from robot_descriptions._descriptions import DESCRIPTIONS
from robot_descriptions.loaders.mujoco import load_robot_description
from robot_descriptions.loaders.mujoco import (
load_robot_description as load_mujoco,
)


class TestMuJoCo(unittest.TestCase):

"""
Check that all MJCF descriptions are loaded properly in MuJoCo.
"""

def test_mujoco(self):
self.assertIsNotNone(load_mujoco("cassie_mj_description"))

@staticmethod
def get_test_for_description(description: str):
"""
Expand All @@ -29,7 +33,7 @@ def get_test_for_description(description: str):
"""

def test(self):
load_robot_description(description)
load_mujoco(description)

return test

Expand Down
37 changes: 27 additions & 10 deletions tests/loaders/test_pinocchio.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,24 @@
import unittest

from robot_descriptions._descriptions import DESCRIPTIONS
from robot_descriptions.loaders.pinocchio import load_robot_description
from robot_descriptions.loaders.pinocchio import (
load_robot_description as load_pinocchio,
)


class TestPinocchio(unittest.TestCase):

"""
Check that all descriptions are loaded properly in Pinocchio.
"""

def test_pinocchio(self):
self.assertIsNotNone(
load_pinocchio(
"upkie_description",
commit="98502d5b175c3d6b60b3cf475b7eeef9fd290c43",
)
)

@staticmethod
def get_test_for_description(description: str):
"""
Expand All @@ -29,16 +38,24 @@ def get_test_for_description(description: str):
"""

def test(self):
load_robot_description(description)
load_pinocchio(description)

return test


# Add a test function for each URDF description
# Add a test function for each description
for name, description in DESCRIPTIONS.items():
if description.has_urdf:
setattr(
TestPinocchio,
f"test_{name}",
TestPinocchio.get_test_for_description(name),
)
if name == "a1_mj_description":
# See https://github.com/stack-of-tasks/pinocchio/issues/2613
continue
if name == "aloha_mj_description":
# See https://github.com/stack-of-tasks/pinocchio/issues/2610
continue
if name == "talos_mj_description":
# See https://github.com/stack-of-tasks/pinocchio/issues/2612
continue
setattr(
TestPinocchio,
f"test_{name}",
TestPinocchio.get_test_for_description(name),
)
18 changes: 13 additions & 5 deletions tests/loaders/test_pybullet.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
import pybullet

from robot_descriptions._descriptions import DESCRIPTIONS

from robot_descriptions.loaders.pybullet import load_robot_description
from robot_descriptions.loaders.pybullet import (
load_robot_description as load_pybullet,
)


class TestPyBullet(unittest.TestCase):

"""
Check that all descriptions are loaded properly in PyBullet.
"""
Expand All @@ -31,12 +31,20 @@ def tearDown(self):
"""
pybullet.disconnect()

def test_pybullet(self):
self.assertIsNotNone(
load_pybullet(
"upkie_description",
commit="98502d5b175c3d6b60b3cf475b7eeef9fd290c43",
)
)

def test_value_error_when_no_urdf(self):
"""
Test exception raised when a description has no URDF_PATH.
"""
with self.assertRaises(ValueError):
load_robot_description("_empty_description")
load_pybullet("_empty_description")

@staticmethod
def get_test_for_description(description: str):
Expand All @@ -51,7 +59,7 @@ def get_test_for_description(description: str):
"""

def test(self):
load_robot_description(description)
load_pybullet(description)

return test

Expand Down
15 changes: 12 additions & 3 deletions tests/loaders/test_robomeshcat.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,24 @@
import unittest

from robot_descriptions._descriptions import DESCRIPTIONS
from robot_descriptions.loaders.robomeshcat import load_robot_description
from robot_descriptions.loaders.robomeshcat import (
load_robot_description as load_robomeshcat,
)


class TestRoboMeshCat(unittest.TestCase):

"""
Check that all descriptions are loaded properly in RoboMeshCat.
"""

def test_robomeshcat(self):
self.assertIsNotNone(
load_robomeshcat(
"upkie_description",
commit="98502d5b175c3d6b60b3cf475b7eeef9fd290c43",
)
)

@staticmethod
def get_test_for_description(description: str):
"""
Expand All @@ -29,7 +38,7 @@ def get_test_for_description(description: str):
"""

def test(self):
load_robot_description(description)
load_robomeshcat(description)

return test

Expand Down
15 changes: 12 additions & 3 deletions tests/loaders/test_yourdfpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,24 @@
import unittest

from robot_descriptions._descriptions import DESCRIPTIONS
from robot_descriptions.loaders.yourdfpy import load_robot_description
from robot_descriptions.loaders.yourdfpy import (
load_robot_description as load_yourdfpy,
)


class TestYourdfpy(unittest.TestCase):

"""
Check that all URDF descriptions are loaded properly in yourdfpy.
"""

def test_yourdfpy(self):
self.assertIsNotNone(
load_yourdfpy(
"upkie_description",
commit="98502d5b175c3d6b60b3cf475b7eeef9fd290c43",
)
)

@staticmethod
def get_test_for_description(description: str):
"""
Expand All @@ -29,7 +38,7 @@ def get_test_for_description(description: str):
"""

def test(self):
load_robot_description(description)
load_yourdfpy(description)

return test

Expand Down
18 changes: 18 additions & 0 deletions tests/test_descriptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
import git

from robot_descriptions._descriptions import DESCRIPTIONS
from robot_descriptions.loaders.pinocchio import (
load_robot_description as load_pinocchio,
)


class TestDescriptions(unittest.TestCase):
Expand Down Expand Up @@ -46,6 +49,13 @@ def test_all_descriptions(self):
f"in {description}",
)

def test_cache_path_package_name(self):
"""Check a description with package:// URIs and a custom commit ID."""
load_pinocchio(
"draco3_description",
commit="5afd19733d7b3e9f1135ba93e0aad90ed1a24cc7",
)

def test_invalid_description_commit(self):
invalid_commit = "foobar"
os.environ["ROBOT_DESCRIPTION_COMMIT"] = invalid_commit
Expand All @@ -55,3 +65,11 @@ def test_invalid_description_commit(self):
if description_name in sys.modules:
del sys.modules[description_name]
import_module(description_name)

def test_load_with_commit_then_without(self):
# https://github.com/robot-descriptions/robot_descriptions.py/issues/67
load_pinocchio(
"draco3_description",
commit="5afd19733d7b3e9f1135ba93e0aad90ed1a24cc7",
)
load_pinocchio("baxter_description")
Loading
Loading