jaxsim 0.4.3.dev362__tar.gz → 0.4.3.dev365__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.
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/PKG-INFO +2 -1
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/environment.yml +1 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/examples/jaxsim_for_robot_controllers.ipynb +16 -11
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/pyproject.toml +2 -1
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/_version.py +2 -2
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/parsers/descriptions/__init__.py +7 -1
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/parsers/descriptions/collision.py +19 -0
- jaxsim-0.4.3.dev365/src/jaxsim/parsers/rod/meshes.py +104 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/parsers/rod/parser.py +12 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/parsers/rod/utils.py +53 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim.egg-info/PKG-INFO +2 -1
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim.egg-info/SOURCES.txt +2 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim.egg-info/requires.txt +1 -0
- jaxsim-0.4.3.dev365/tests/test_meshes.py +100 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/.devcontainer/Dockerfile +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/.devcontainer/devcontainer.json +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/.gitattributes +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/.github/CODEOWNERS +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/.github/dependabot.yml +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/.github/workflows/ci_cd.yml +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/.github/workflows/pixi.yml +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/.github/workflows/read_the_docs.yml +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/.gitignore +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/.pre-commit-config.yaml +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/.readthedocs.yaml +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/CONTRIBUTING.md +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/LICENSE +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/README.md +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/docs/Makefile +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/docs/conf.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/docs/examples.rst +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/docs/guide/install.rst +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/docs/index.rst +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/docs/make.bat +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/docs/modules/api.rst +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/docs/modules/integrators.rst +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/docs/modules/math.rst +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/docs/modules/mujoco.rst +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/docs/modules/parsers.rst +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/docs/modules/rbda.rst +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/docs/modules/typing.rst +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/docs/modules/utils.rst +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/examples/.gitattributes +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/examples/.gitignore +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/examples/README.md +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/examples/assets/build_cartpole_urdf.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/examples/assets/cartpole.urdf +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/examples/jaxsim_as_multibody_dynamics_library.ipynb +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/examples/jaxsim_as_physics_engine.ipynb +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/pixi.lock +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/setup.cfg +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/setup.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/__init__.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/api/__init__.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/api/com.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/api/common.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/api/contact.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/api/data.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/api/frame.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/api/joint.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/api/kin_dyn_parameters.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/api/link.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/api/model.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/api/ode.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/api/ode_data.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/api/references.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/exceptions.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/integrators/__init__.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/integrators/common.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/integrators/fixed_step.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/integrators/variable_step.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/logging.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/math/__init__.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/math/adjoint.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/math/cross.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/math/inertia.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/math/joint_model.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/math/quaternion.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/math/rotation.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/math/skew.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/math/transform.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/mujoco/__init__.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/mujoco/__main__.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/mujoco/loaders.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/mujoco/model.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/mujoco/utils.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/mujoco/visualizer.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/parsers/__init__.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/parsers/descriptions/joint.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/parsers/descriptions/link.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/parsers/descriptions/model.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/parsers/kinematic_graph.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/parsers/rod/__init__.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/rbda/__init__.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/rbda/aba.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/rbda/collidable_points.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/rbda/contacts/__init__.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/rbda/contacts/common.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/rbda/contacts/relaxed_rigid.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/rbda/contacts/rigid.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/rbda/contacts/soft.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/rbda/contacts/visco_elastic.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/rbda/crba.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/rbda/forward_kinematics.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/rbda/jacobian.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/rbda/rnea.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/rbda/utils.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/terrain/__init__.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/terrain/terrain.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/typing.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/utils/__init__.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/utils/jaxsim_dataclass.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/utils/tracing.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim/utils/wrappers.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim.egg-info/dependency_links.txt +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/src/jaxsim.egg-info/top_level.txt +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/tests/__init__.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/tests/conftest.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/tests/test_api_com.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/tests/test_api_contact.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/tests/test_api_data.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/tests/test_api_frame.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/tests/test_api_joint.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/tests/test_api_link.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/tests/test_api_model.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/tests/test_automatic_differentiation.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/tests/test_contact.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/tests/test_exceptions.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/tests/test_pytree.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/tests/test_simulations.py +0 -0
- {jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/tests/utils_idyntree.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: jaxsim
|
3
|
-
Version: 0.4.3.
|
3
|
+
Version: 0.4.3.dev365
|
4
4
|
Summary: A differentiable physics engine and multibody dynamics library for control and robot learning.
|
5
5
|
Author-email: Diego Ferigo <dgferigo@gmail.com>, Filippo Luca Ferretti <filippoluca.ferretti@outlook.com>
|
6
6
|
Maintainer-email: Filippo Luca Ferretti <filippo.ferretti@iit.it>, Alessandro Croci <alessandro.croci@iit.it>
|
@@ -70,6 +70,7 @@ Requires-Dist: optax>=0.2.3
|
|
70
70
|
Requires-Dist: qpax
|
71
71
|
Requires-Dist: rod>=0.3.3
|
72
72
|
Requires-Dist: typing_extensions; python_version < "3.12"
|
73
|
+
Requires-Dist: trimesh
|
73
74
|
Provides-Extra: style
|
74
75
|
Requires-Dist: black[jupyter]~=24.0; extra == "style"
|
75
76
|
Requires-Dist: isort; extra == "style"
|
@@ -90,6 +90,17 @@
|
|
90
90
|
"[sdformat_github]: https://github.com/gazebosim/sdformat"
|
91
91
|
]
|
92
92
|
},
|
93
|
+
{
|
94
|
+
"cell_type": "code",
|
95
|
+
"execution_count": null,
|
96
|
+
"metadata": {},
|
97
|
+
"outputs": [],
|
98
|
+
"source": [
|
99
|
+
"import os\n",
|
100
|
+
"\n",
|
101
|
+
"os.path.abspath(\"\")"
|
102
|
+
]
|
103
|
+
},
|
93
104
|
{
|
94
105
|
"cell_type": "code",
|
95
106
|
"execution_count": null,
|
@@ -98,18 +109,12 @@
|
|
98
109
|
},
|
99
110
|
"outputs": [],
|
100
111
|
"source": [
|
101
|
-
"# @title
|
102
|
-
"\n",
|
103
|
-
"import requests\n",
|
104
|
-
"\n",
|
105
|
-
"url = \"https://raw.githubusercontent.com/ami-iit/jaxsim/main/examples/assets/cartpole.urdf\"\n",
|
106
|
-
"\n",
|
107
|
-
"response = requests.get(url)\n",
|
112
|
+
"# @title Load the URDF model\n",
|
113
|
+
"import pathlib\n",
|
108
114
|
"\n",
|
109
|
-
"
|
110
|
-
"
|
111
|
-
"
|
112
|
-
" raise RuntimeError(\"Failed to fetch data.\")"
|
115
|
+
"model_urdf_string = pathlib.Path(\n",
|
116
|
+
" os.path.abspath(\"\") + \"/assets/cartpole.urdf\"\n",
|
117
|
+
").read_text()"
|
113
118
|
]
|
114
119
|
},
|
115
120
|
{
|
@@ -55,6 +55,7 @@ dependencies = [
|
|
55
55
|
"qpax",
|
56
56
|
"rod >= 0.3.3",
|
57
57
|
"typing_extensions ; python_version < '3.12'",
|
58
|
+
"trimesh",
|
58
59
|
]
|
59
60
|
|
60
61
|
[project.optional-dependencies]
|
@@ -67,7 +68,7 @@ testing = [
|
|
67
68
|
"idyntree >= 12.2.1",
|
68
69
|
"pytest >=6.0",
|
69
70
|
"pytest-icdiff",
|
70
|
-
"robot-descriptions"
|
71
|
+
"robot-descriptions"
|
71
72
|
]
|
72
73
|
viz = [
|
73
74
|
"lxml",
|
@@ -12,5 +12,5 @@ __version__: str
|
|
12
12
|
__version_tuple__: VERSION_TUPLE
|
13
13
|
version_tuple: VERSION_TUPLE
|
14
14
|
|
15
|
-
__version__ = version = '0.4.3.
|
16
|
-
__version_tuple__ = version_tuple = (0, 4, 3, '
|
15
|
+
__version__ = version = '0.4.3.dev365'
|
16
|
+
__version_tuple__ = version_tuple = (0, 4, 3, 'dev365')
|
@@ -1,4 +1,10 @@
|
|
1
|
-
from .collision import
|
1
|
+
from .collision import (
|
2
|
+
BoxCollision,
|
3
|
+
CollidablePoint,
|
4
|
+
CollisionShape,
|
5
|
+
MeshCollision,
|
6
|
+
SphereCollision,
|
7
|
+
)
|
2
8
|
from .joint import JointDescription, JointGenericAxis, JointType
|
3
9
|
from .link import LinkDescription
|
4
10
|
from .model import ModelDescription
|
@@ -154,3 +154,22 @@ class SphereCollision(CollisionShape):
|
|
154
154
|
return False
|
155
155
|
|
156
156
|
return hash(self) == hash(other)
|
157
|
+
|
158
|
+
|
159
|
+
@dataclasses.dataclass
|
160
|
+
class MeshCollision(CollisionShape):
|
161
|
+
center: jtp.VectorLike
|
162
|
+
|
163
|
+
def __hash__(self) -> int:
|
164
|
+
return hash(
|
165
|
+
(
|
166
|
+
hash(tuple(self.center.tolist())),
|
167
|
+
hash(self.collidable_points),
|
168
|
+
)
|
169
|
+
)
|
170
|
+
|
171
|
+
def __eq__(self, other: MeshCollision) -> bool:
|
172
|
+
if not isinstance(other, MeshCollision):
|
173
|
+
return False
|
174
|
+
|
175
|
+
return hash(self) == hash(other)
|
@@ -0,0 +1,104 @@
|
|
1
|
+
import numpy as np
|
2
|
+
import trimesh
|
3
|
+
|
4
|
+
VALID_AXIS = {"x": 0, "y": 1, "z": 2}
|
5
|
+
|
6
|
+
|
7
|
+
def extract_points_vertices(mesh: trimesh.Trimesh) -> np.ndarray:
|
8
|
+
"""
|
9
|
+
Extracts the vertices of a mesh as points.
|
10
|
+
"""
|
11
|
+
return mesh.vertices
|
12
|
+
|
13
|
+
|
14
|
+
def extract_points_random_surface_sampling(mesh: trimesh.Trimesh, n) -> np.ndarray:
|
15
|
+
"""
|
16
|
+
Extracts N random points from the surface of a mesh.
|
17
|
+
|
18
|
+
Args:
|
19
|
+
mesh: The mesh from which to extract points.
|
20
|
+
n: The number of points to extract.
|
21
|
+
|
22
|
+
Returns:
|
23
|
+
The extracted points (N x 3 array).
|
24
|
+
"""
|
25
|
+
|
26
|
+
return mesh.sample(n)
|
27
|
+
|
28
|
+
|
29
|
+
def extract_points_uniform_surface_sampling(
|
30
|
+
mesh: trimesh.Trimesh, n: int
|
31
|
+
) -> np.ndarray:
|
32
|
+
"""
|
33
|
+
Extracts N uniformly sampled points from the surface of a mesh.
|
34
|
+
|
35
|
+
Args:
|
36
|
+
mesh: The mesh from which to extract points.
|
37
|
+
n: The number of points to extract.
|
38
|
+
|
39
|
+
Returns:
|
40
|
+
The extracted points (N x 3 array).
|
41
|
+
"""
|
42
|
+
|
43
|
+
return trimesh.sample.sample_surface_even(mesh=mesh, count=n)[0]
|
44
|
+
|
45
|
+
|
46
|
+
def extract_points_select_points_over_axis(
|
47
|
+
mesh: trimesh.Trimesh, axis: str, direction: str, n: int
|
48
|
+
) -> np.ndarray:
|
49
|
+
"""
|
50
|
+
Extracts N points from a mesh along a specified axis. The points are selected based on their position along the axis.
|
51
|
+
|
52
|
+
Args:
|
53
|
+
mesh: The mesh from which to extract points.
|
54
|
+
axis: The axis along which to extract points.
|
55
|
+
direction: The direction along the axis from which to extract points. Valid values are "higher" and "lower".
|
56
|
+
n: The number of points to extract.
|
57
|
+
|
58
|
+
Returns:
|
59
|
+
The extracted points (N x 3 array).
|
60
|
+
"""
|
61
|
+
|
62
|
+
dirs = {"higher": np.s_[-n:], "lower": np.s_[:n]}
|
63
|
+
arr = mesh.vertices
|
64
|
+
|
65
|
+
# Sort rows lexicographically first, then columnar.
|
66
|
+
arr.sort(axis=0)
|
67
|
+
sorted_arr = arr[dirs[direction]]
|
68
|
+
return sorted_arr
|
69
|
+
|
70
|
+
|
71
|
+
def extract_points_aap(
|
72
|
+
mesh: trimesh.Trimesh,
|
73
|
+
axis: str,
|
74
|
+
upper: float | None = None,
|
75
|
+
lower: float | None = None,
|
76
|
+
) -> np.ndarray:
|
77
|
+
"""
|
78
|
+
Extracts points from a mesh along a specified axis within a specified range. The points are selected based on their position along the axis.
|
79
|
+
|
80
|
+
Args:
|
81
|
+
mesh: The mesh from which to extract points.
|
82
|
+
axis: The axis along which to extract points.
|
83
|
+
upper: The upper bound of the range.
|
84
|
+
lower: The lower bound of the range.
|
85
|
+
|
86
|
+
Returns:
|
87
|
+
The extracted points (N x 3 array).
|
88
|
+
|
89
|
+
Raises:
|
90
|
+
AssertionError: If the lower bound is greater than the upper bound.
|
91
|
+
"""
|
92
|
+
|
93
|
+
# Check bounds.
|
94
|
+
upper = upper if upper is not None else np.inf
|
95
|
+
lower = lower if lower is not None else -np.inf
|
96
|
+
assert lower < upper, "Invalid bounds for axis-aligned plane"
|
97
|
+
|
98
|
+
# Logic.
|
99
|
+
points = mesh.vertices[
|
100
|
+
(mesh.vertices[:, VALID_AXIS[axis]] >= lower)
|
101
|
+
& (mesh.vertices[:, VALID_AXIS[axis]] <= upper)
|
102
|
+
]
|
103
|
+
|
104
|
+
return points
|
@@ -334,6 +334,18 @@ def extract_model_data(
|
|
334
334
|
|
335
335
|
collisions.append(sphere_collision)
|
336
336
|
|
337
|
+
if collision.geometry.mesh is not None and int(
|
338
|
+
os.environ.get("JAXSIM_COLLISION_MESH_ENABLED", "0")
|
339
|
+
):
|
340
|
+
logging.warning("Mesh collision support is still experimental.")
|
341
|
+
mesh_collision = utils.create_mesh_collision(
|
342
|
+
collision=collision,
|
343
|
+
link_description=links_dict[link.name],
|
344
|
+
method=utils.meshes.extract_points_vertices,
|
345
|
+
)
|
346
|
+
|
347
|
+
collisions.append(mesh_collision)
|
348
|
+
|
337
349
|
return SDFData(
|
338
350
|
model_name=sdf_model.name,
|
339
351
|
link_descriptions=links,
|
@@ -1,12 +1,21 @@
|
|
1
1
|
import os
|
2
|
+
import pathlib
|
3
|
+
from collections.abc import Callable
|
4
|
+
from typing import TypeVar
|
2
5
|
|
3
6
|
import numpy as np
|
4
7
|
import numpy.typing as npt
|
5
8
|
import rod
|
9
|
+
import trimesh
|
10
|
+
from rod.utils.resolve_uris import resolve_local_uri
|
6
11
|
|
7
12
|
import jaxsim.typing as jtp
|
13
|
+
from jaxsim import logging
|
8
14
|
from jaxsim.math import Adjoint, Inertia
|
9
15
|
from jaxsim.parsers import descriptions
|
16
|
+
from jaxsim.parsers.rod import meshes
|
17
|
+
|
18
|
+
MeshMappingMethod = TypeVar("MeshMappingMethod", bound=Callable[..., npt.NDArray])
|
10
19
|
|
11
20
|
|
12
21
|
def from_sdf_inertial(inertial: rod.Inertial) -> jtp.Matrix:
|
@@ -202,3 +211,47 @@ def create_sphere_collision(
|
|
202
211
|
return descriptions.SphereCollision(
|
203
212
|
collidable_points=collidable_points, center=center_wrt_link
|
204
213
|
)
|
214
|
+
|
215
|
+
|
216
|
+
def create_mesh_collision(
|
217
|
+
collision: rod.Collision,
|
218
|
+
link_description: descriptions.LinkDescription,
|
219
|
+
method: MeshMappingMethod = None,
|
220
|
+
) -> descriptions.MeshCollision:
|
221
|
+
|
222
|
+
file = pathlib.Path(resolve_local_uri(uri=collision.geometry.mesh.uri))
|
223
|
+
_file_type = file.suffix.replace(".", "")
|
224
|
+
mesh = trimesh.load_mesh(file, file_type=_file_type)
|
225
|
+
|
226
|
+
if mesh.is_empty:
|
227
|
+
raise RuntimeError(f"Failed to process '{file}' with trimesh")
|
228
|
+
|
229
|
+
mesh.apply_scale(collision.geometry.mesh.scale)
|
230
|
+
logging.info(
|
231
|
+
msg=f"Loading mesh {collision.geometry.mesh.uri} with scale {collision.geometry.mesh.scale}, file type '{_file_type}'"
|
232
|
+
)
|
233
|
+
|
234
|
+
if method is None:
|
235
|
+
method = meshes.VertexExtraction()
|
236
|
+
logging.debug("Using default Vertex Extraction method for mesh wrapping")
|
237
|
+
else:
|
238
|
+
logging.debug(f"Using method {method} for mesh wrapping")
|
239
|
+
|
240
|
+
points = method(mesh=mesh)
|
241
|
+
logging.debug(f"Extracted {len(points)} points from mesh")
|
242
|
+
|
243
|
+
W_H_L = collision.pose.transform() if collision.pose is not None else np.eye(4)
|
244
|
+
|
245
|
+
# Extract translation from transformation matrix
|
246
|
+
W_p_L = W_H_L[:3, 3]
|
247
|
+
mesh_points_wrt_link = points @ W_H_L[:3, :3].T + W_p_L
|
248
|
+
collidable_points = [
|
249
|
+
descriptions.CollidablePoint(
|
250
|
+
parent_link=link_description,
|
251
|
+
position=point,
|
252
|
+
enabled=True,
|
253
|
+
)
|
254
|
+
for point in mesh_points_wrt_link
|
255
|
+
]
|
256
|
+
|
257
|
+
return descriptions.MeshCollision(collidable_points=collidable_points, center=W_p_L)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: jaxsim
|
3
|
-
Version: 0.4.3.
|
3
|
+
Version: 0.4.3.dev365
|
4
4
|
Summary: A differentiable physics engine and multibody dynamics library for control and robot learning.
|
5
5
|
Author-email: Diego Ferigo <dgferigo@gmail.com>, Filippo Luca Ferretti <filippoluca.ferretti@outlook.com>
|
6
6
|
Maintainer-email: Filippo Luca Ferretti <filippo.ferretti@iit.it>, Alessandro Croci <alessandro.croci@iit.it>
|
@@ -70,6 +70,7 @@ Requires-Dist: optax>=0.2.3
|
|
70
70
|
Requires-Dist: qpax
|
71
71
|
Requires-Dist: rod>=0.3.3
|
72
72
|
Requires-Dist: typing_extensions; python_version < "3.12"
|
73
|
+
Requires-Dist: trimesh
|
73
74
|
Provides-Extra: style
|
74
75
|
Requires-Dist: black[jupyter]~=24.0; extra == "style"
|
75
76
|
Requires-Dist: isort; extra == "style"
|
@@ -88,6 +88,7 @@ src/jaxsim/parsers/descriptions/joint.py
|
|
88
88
|
src/jaxsim/parsers/descriptions/link.py
|
89
89
|
src/jaxsim/parsers/descriptions/model.py
|
90
90
|
src/jaxsim/parsers/rod/__init__.py
|
91
|
+
src/jaxsim/parsers/rod/meshes.py
|
91
92
|
src/jaxsim/parsers/rod/parser.py
|
92
93
|
src/jaxsim/parsers/rod/utils.py
|
93
94
|
src/jaxsim/rbda/__init__.py
|
@@ -122,6 +123,7 @@ tests/test_api_model.py
|
|
122
123
|
tests/test_automatic_differentiation.py
|
123
124
|
tests/test_contact.py
|
124
125
|
tests/test_exceptions.py
|
126
|
+
tests/test_meshes.py
|
125
127
|
tests/test_pytree.py
|
126
128
|
tests/test_simulations.py
|
127
129
|
tests/utils_idyntree.py
|
@@ -0,0 +1,100 @@
|
|
1
|
+
import trimesh
|
2
|
+
|
3
|
+
from jaxsim.parsers.rod import meshes
|
4
|
+
|
5
|
+
|
6
|
+
def test_mesh_wrapping_vertex_extraction():
|
7
|
+
"""
|
8
|
+
Test the vertex extraction method on different meshes.
|
9
|
+
1. A simple box
|
10
|
+
2. A sphere
|
11
|
+
"""
|
12
|
+
|
13
|
+
# Test 1: A simple box.
|
14
|
+
# First, create a box with origin at (0,0,0) and extents (3,3,3),
|
15
|
+
# i.e. points span from -1.5 to 1.5 on the axis.
|
16
|
+
mesh = trimesh.creation.box(
|
17
|
+
extents=[3.0, 3.0, 3.0],
|
18
|
+
)
|
19
|
+
points = meshes.extract_points_vertices(mesh=mesh)
|
20
|
+
assert len(points) == len(mesh.vertices)
|
21
|
+
|
22
|
+
# Test 2: A sphere.
|
23
|
+
# The sphere is centered at the origin and has a radius of 1.0.
|
24
|
+
mesh = trimesh.creation.icosphere(subdivisions=4, radius=1.0)
|
25
|
+
points = meshes.extract_points_vertices(mesh=mesh)
|
26
|
+
assert len(points) == len(mesh.vertices)
|
27
|
+
|
28
|
+
|
29
|
+
def test_mesh_wrapping_aap():
|
30
|
+
"""
|
31
|
+
Test the AAP wrapping method on different meshes.
|
32
|
+
1. A simple box
|
33
|
+
1.1: Remove all points above x=0.0
|
34
|
+
1.2: Remove all points below y=0.0
|
35
|
+
2. A sphere
|
36
|
+
"""
|
37
|
+
|
38
|
+
# Test 1.1: Remove all points above x=0.0.
|
39
|
+
# The expected result is that the number of points is halved.
|
40
|
+
# First, create a box with origin at (0,0,0) and extents (3,3,3),
|
41
|
+
# i.e. points span from -1.5 to 1.5 on the axis.
|
42
|
+
mesh = trimesh.creation.box(extents=[3.0, 3.0, 3.0])
|
43
|
+
points = meshes.extract_points_aap(mesh=mesh, axis="x", lower=0.0)
|
44
|
+
assert len(points) == len(mesh.vertices) // 2
|
45
|
+
assert all(points[:, 0] > 0.0)
|
46
|
+
|
47
|
+
# Test 1.2: Remove all points below y=0.0.
|
48
|
+
# The expected result is that the number of points is halved.
|
49
|
+
points = meshes.extract_points_aap(mesh=mesh, axis="y", upper=0.0)
|
50
|
+
assert len(points) == len(mesh.vertices) // 2
|
51
|
+
assert all(points[:, 1] < 0.0)
|
52
|
+
|
53
|
+
# Test 2: A sphere.
|
54
|
+
# The sphere is centered at the origin and has a radius of 1.0.
|
55
|
+
# Points are expected to be halved.
|
56
|
+
mesh = trimesh.creation.icosphere(subdivisions=4, radius=1.0)
|
57
|
+
|
58
|
+
# Remove all points above y=0.0.
|
59
|
+
points = meshes.extract_points_aap(mesh=mesh, axis="y", lower=0.0)
|
60
|
+
assert all(points[:, 1] >= 0.0)
|
61
|
+
assert len(points) < len(mesh.vertices)
|
62
|
+
|
63
|
+
|
64
|
+
def test_mesh_wrapping_points_over_axis():
|
65
|
+
"""
|
66
|
+
Test the points over axis method on different meshes.
|
67
|
+
1. A simple box
|
68
|
+
1.1: Select 10 points from the lower end of the x-axis
|
69
|
+
1.2: Select 10 points from the higher end of the y-axis
|
70
|
+
2. A sphere
|
71
|
+
"""
|
72
|
+
|
73
|
+
# Test 1.1: Remove 10 points from the lower end of the x-axis.
|
74
|
+
# First, create a box with origin at (0,0,0) and extents (3,3,3),
|
75
|
+
# i.e. points span from -1.5 to 1.5 on the axis.
|
76
|
+
mesh = trimesh.creation.box(extents=[3.0, 3.0, 3.0])
|
77
|
+
points = meshes.extract_points_select_points_over_axis(
|
78
|
+
mesh=mesh, axis="x", direction="lower", n=4
|
79
|
+
)
|
80
|
+
assert len(points) == 4
|
81
|
+
assert all(points[:, 0] < 0.0)
|
82
|
+
|
83
|
+
# Test 1.2: Select 10 points from the higher end of the y-axis.
|
84
|
+
points = meshes.extract_points_select_points_over_axis(
|
85
|
+
mesh=mesh, axis="y", direction="higher", n=4
|
86
|
+
)
|
87
|
+
assert len(points) == 4
|
88
|
+
assert all(points[:, 1] > 0.0)
|
89
|
+
|
90
|
+
# Test 2: A sphere.
|
91
|
+
# The sphere is centered at the origin and has a radius of 1.0.
|
92
|
+
mesh = trimesh.creation.icosphere(subdivisions=4, radius=1.0)
|
93
|
+
sphere_n_vertices = len(mesh.vertices)
|
94
|
+
|
95
|
+
# Select 10 points from the higher end of the z-axis.
|
96
|
+
points = meshes.extract_points_select_points_over_axis(
|
97
|
+
mesh=mesh, axis="z", direction="higher", n=sphere_n_vertices // 2
|
98
|
+
)
|
99
|
+
assert len(points) == sphere_n_vertices // 2
|
100
|
+
assert all(points[:, 2] >= 0.0)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{jaxsim-0.4.3.dev362 → jaxsim-0.4.3.dev365}/examples/jaxsim_as_multibody_dynamics_library.ipynb
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|