jaxsim 0.4.3.dev362__py3-none-any.whl → 0.4.3.dev365__py3-none-any.whl
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/_version.py +2 -2
- jaxsim/parsers/descriptions/__init__.py +7 -1
- jaxsim/parsers/descriptions/collision.py +19 -0
- jaxsim/parsers/rod/meshes.py +104 -0
- jaxsim/parsers/rod/parser.py +12 -0
- jaxsim/parsers/rod/utils.py +53 -0
- {jaxsim-0.4.3.dev362.dist-info → jaxsim-0.4.3.dev365.dist-info}/METADATA +2 -1
- {jaxsim-0.4.3.dev362.dist-info → jaxsim-0.4.3.dev365.dist-info}/RECORD +11 -10
- {jaxsim-0.4.3.dev362.dist-info → jaxsim-0.4.3.dev365.dist-info}/LICENSE +0 -0
- {jaxsim-0.4.3.dev362.dist-info → jaxsim-0.4.3.dev365.dist-info}/WHEEL +0 -0
- {jaxsim-0.4.3.dev362.dist-info → jaxsim-0.4.3.dev365.dist-info}/top_level.txt +0 -0
jaxsim/_version.py
CHANGED
@@ -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
|
jaxsim/parsers/rod/parser.py
CHANGED
@@ -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,
|
jaxsim/parsers/rod/utils.py
CHANGED
@@ -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>
|
@@ -69,6 +69,7 @@ Requires-Dist: pptree
|
|
69
69
|
Requires-Dist: optax>=0.2.3
|
70
70
|
Requires-Dist: qpax
|
71
71
|
Requires-Dist: rod>=0.3.3
|
72
|
+
Requires-Dist: trimesh
|
72
73
|
Requires-Dist: typing-extensions; python_version < "3.12"
|
73
74
|
Provides-Extra: all
|
74
75
|
Requires-Dist: jaxsim[style,testing,viz]; extra == "all"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
jaxsim/__init__.py,sha256=opgtbhhd1kDsHI4H1vOd3loMPDRi884yQ3tohfFGfNc,3382
|
2
|
-
jaxsim/_version.py,sha256=
|
2
|
+
jaxsim/_version.py,sha256=MAn1zPonARBalCehiaTUL7_k9OAe5L1w_cFS6kmRIWI,428
|
3
3
|
jaxsim/exceptions.py,sha256=vSoScaRD4nvh6jltgK9Ry5pKnE0O5hb4_yI_pk_fvR8,2175
|
4
4
|
jaxsim/logging.py,sha256=STI-D_upXZYX-ZezLrlJJ0UlD5YspST0vZ_DcIwkzO4,1553
|
5
5
|
jaxsim/typing.py,sha256=2HXy9hgazPXjofi1vLQ09ZubPtgVmg80U9NKmZ6NYiI,761
|
@@ -37,14 +37,15 @@ jaxsim/mujoco/utils.py,sha256=vZ8afASNOSxnxVW9p_1U1J_n-9nVhnBDqlV5k8c1GkM,8256
|
|
37
37
|
jaxsim/mujoco/visualizer.py,sha256=nD6SNWmn-nxjjjIY9oPAHvL2j8q93DJDjZeepzke_DQ,6988
|
38
38
|
jaxsim/parsers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
39
39
|
jaxsim/parsers/kinematic_graph.py,sha256=MJkJ7AW1TdLZmxibuiVrTfn6jHjh3OVhEF20DqwsCnM,34748
|
40
|
-
jaxsim/parsers/descriptions/__init__.py,sha256=
|
41
|
-
jaxsim/parsers/descriptions/collision.py,sha256=
|
40
|
+
jaxsim/parsers/descriptions/__init__.py,sha256=N_hp8cGI5FyEFiuNx9a-CAGCr0F0QpYEpdMHvwB7_1g,261
|
41
|
+
jaxsim/parsers/descriptions/collision.py,sha256=mLcwj61of16MVJf64I95E5SiQZST3uyTEfS0ImhGBSI,4419
|
42
42
|
jaxsim/parsers/descriptions/joint.py,sha256=2KWLP4ILPMV8q1X0J7aS3GGFeZn4zXan0dqGOWc7XuQ,4365
|
43
43
|
jaxsim/parsers/descriptions/link.py,sha256=Eh0W5qL7_Uw0GV-BkNKXhm9Q2dRTfIWCX5D-87zQkxA,3711
|
44
44
|
jaxsim/parsers/descriptions/model.py,sha256=I2Vsbv8Josl4Le7b5rIvhqA2k9Bbv5JxMqwytayxds0,9833
|
45
45
|
jaxsim/parsers/rod/__init__.py,sha256=G2vqlLajBLUc4gyzXwsEI2Wsi4TMOIF9bLDFeT6KrGU,92
|
46
|
-
jaxsim/parsers/rod/
|
47
|
-
jaxsim/parsers/rod/
|
46
|
+
jaxsim/parsers/rod/meshes.py,sha256=a5qUFkHe3gPXMKRnvPx3BDvlEHT2vEJqcLYLXhJFCdA,2847
|
47
|
+
jaxsim/parsers/rod/parser.py,sha256=OJdKM2hVyED9nw7iRpxCRFZx9Z6rKmVflhkItGTzRns,14499
|
48
|
+
jaxsim/parsers/rod/utils.py,sha256=-bVIbO8AOnImkVbf8XA3XOweoTny7m85ACLkR0d_p2E,7505
|
48
49
|
jaxsim/rbda/__init__.py,sha256=kmy4G9aMkrqPNGdLSaSV3k15dpF52vBEUQXDFDuKIxU,337
|
49
50
|
jaxsim/rbda/aba.py,sha256=w7ciyxB0IsmueatT0C7PcBQEl9dyiH9oqJgIi3xeTUE,8983
|
50
51
|
jaxsim/rbda/collidable_points.py,sha256=0PFLzxWKtRg8-JtfNhGlSjBMv1J98tiLymOdvlvAak4,5325
|
@@ -65,8 +66,8 @@ jaxsim/utils/__init__.py,sha256=Y5zyoRevl3EMVQadhZ4EtSwTEkDt2vcnFoRhPJjKTZ0,215
|
|
65
66
|
jaxsim/utils/jaxsim_dataclass.py,sha256=TGmTQV2Lq7Q-2nLoAEaeNtkPa_qj0IKkdBm4COj46Os,11312
|
66
67
|
jaxsim/utils/tracing.py,sha256=eEY28MZW0Lm_jJNt1NkFqZz0ek01tvhR46OXZYCo7tc,532
|
67
68
|
jaxsim/utils/wrappers.py,sha256=ZY7olSORzZRvSzkdeNLj8yjwUIAt9L0Douwl7wItjpk,4008
|
68
|
-
jaxsim-0.4.3.
|
69
|
-
jaxsim-0.4.3.
|
70
|
-
jaxsim-0.4.3.
|
71
|
-
jaxsim-0.4.3.
|
72
|
-
jaxsim-0.4.3.
|
69
|
+
jaxsim-0.4.3.dev365.dist-info/LICENSE,sha256=eaYdFmdeMbiIoIiPzEK0MjP1S9wtFXjXNR5er49uLR0,1546
|
70
|
+
jaxsim-0.4.3.dev365.dist-info/METADATA,sha256=_oydr6ibnTCcmb-aQwfcEFX1ZlVSnnj7N-rUzv2-C50,17536
|
71
|
+
jaxsim-0.4.3.dev365.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
|
72
|
+
jaxsim-0.4.3.dev365.dist-info/top_level.txt,sha256=LxGMA8FLtXjQ6oI7N5gd_R_oSUHxpXxUEOfT1xS_ni0,7
|
73
|
+
jaxsim-0.4.3.dev365.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|