jaxsim 0.4.3.dev271__tar.gz → 0.4.3.dev282__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.
Files changed (129) hide show
  1. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/PKG-INFO +1 -1
  2. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/_version.py +2 -2
  3. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/api/joint.py +5 -2
  4. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/api/ode.py +32 -1
  5. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/math/rotation.py +26 -12
  6. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/parsers/rod/parser.py +3 -2
  7. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim.egg-info/PKG-INFO +1 -1
  8. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/tests/conftest.py +112 -0
  9. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/tests/test_simulations.py +56 -0
  10. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/.devcontainer/Dockerfile +0 -0
  11. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/.devcontainer/devcontainer.json +0 -0
  12. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/.gitattributes +0 -0
  13. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/.github/CODEOWNERS +0 -0
  14. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/.github/dependabot.yml +0 -0
  15. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/.github/workflows/ci_cd.yml +0 -0
  16. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/.github/workflows/read_the_docs.yml +0 -0
  17. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/.github/workflows/update_pixi_lockfile.yml +0 -0
  18. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/.gitignore +0 -0
  19. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/.pre-commit-config.yaml +0 -0
  20. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/.readthedocs.yaml +0 -0
  21. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/CONTRIBUTING.md +0 -0
  22. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/LICENSE +0 -0
  23. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/README.md +0 -0
  24. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/docs/Makefile +0 -0
  25. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/docs/conf.py +0 -0
  26. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/docs/examples.rst +0 -0
  27. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/docs/guide/install.rst +0 -0
  28. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/docs/index.rst +0 -0
  29. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/docs/make.bat +0 -0
  30. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/docs/modules/api.rst +0 -0
  31. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/docs/modules/integrators.rst +0 -0
  32. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/docs/modules/math.rst +0 -0
  33. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/docs/modules/mujoco.rst +0 -0
  34. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/docs/modules/parsers.rst +0 -0
  35. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/docs/modules/rbda.rst +0 -0
  36. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/docs/modules/typing.rst +0 -0
  37. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/docs/modules/utils.rst +0 -0
  38. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/environment.yml +0 -0
  39. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/examples/.gitattributes +0 -0
  40. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/examples/.gitignore +0 -0
  41. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/examples/README.md +0 -0
  42. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/examples/assets/build_cartpole_urdf.py +0 -0
  43. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/examples/assets/cartpole.urdf +0 -0
  44. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/examples/jaxsim_as_multibody_dynamics_library.ipynb +0 -0
  45. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/examples/jaxsim_as_physics_engine.ipynb +0 -0
  46. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/examples/jaxsim_for_robot_controllers.ipynb +0 -0
  47. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/pixi.lock +0 -0
  48. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/pyproject.toml +0 -0
  49. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/setup.cfg +0 -0
  50. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/setup.py +0 -0
  51. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/__init__.py +0 -0
  52. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/api/__init__.py +0 -0
  53. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/api/com.py +0 -0
  54. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/api/common.py +0 -0
  55. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/api/contact.py +0 -0
  56. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/api/data.py +0 -0
  57. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/api/frame.py +0 -0
  58. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/api/kin_dyn_parameters.py +0 -0
  59. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/api/link.py +0 -0
  60. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/api/model.py +0 -0
  61. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/api/ode_data.py +0 -0
  62. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/api/references.py +0 -0
  63. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/exceptions.py +0 -0
  64. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/integrators/__init__.py +0 -0
  65. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/integrators/common.py +0 -0
  66. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/integrators/fixed_step.py +0 -0
  67. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/integrators/variable_step.py +0 -0
  68. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/logging.py +0 -0
  69. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/math/__init__.py +0 -0
  70. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/math/adjoint.py +0 -0
  71. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/math/cross.py +0 -0
  72. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/math/inertia.py +0 -0
  73. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/math/joint_model.py +0 -0
  74. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/math/quaternion.py +0 -0
  75. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/math/skew.py +0 -0
  76. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/math/transform.py +0 -0
  77. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/mujoco/__init__.py +0 -0
  78. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/mujoco/__main__.py +0 -0
  79. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/mujoco/loaders.py +0 -0
  80. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/mujoco/model.py +0 -0
  81. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/mujoco/utils.py +0 -0
  82. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/mujoco/visualizer.py +0 -0
  83. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/parsers/__init__.py +0 -0
  84. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/parsers/descriptions/__init__.py +0 -0
  85. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/parsers/descriptions/collision.py +0 -0
  86. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/parsers/descriptions/joint.py +0 -0
  87. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/parsers/descriptions/link.py +0 -0
  88. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/parsers/descriptions/model.py +0 -0
  89. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/parsers/kinematic_graph.py +0 -0
  90. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/parsers/rod/__init__.py +0 -0
  91. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/parsers/rod/utils.py +0 -0
  92. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/rbda/__init__.py +0 -0
  93. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/rbda/aba.py +0 -0
  94. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/rbda/collidable_points.py +0 -0
  95. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/rbda/contacts/__init__.py +0 -0
  96. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/rbda/contacts/common.py +0 -0
  97. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/rbda/contacts/relaxed_rigid.py +0 -0
  98. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/rbda/contacts/rigid.py +0 -0
  99. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/rbda/contacts/soft.py +0 -0
  100. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/rbda/contacts/visco_elastic.py +0 -0
  101. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/rbda/crba.py +0 -0
  102. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/rbda/forward_kinematics.py +0 -0
  103. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/rbda/jacobian.py +0 -0
  104. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/rbda/rnea.py +0 -0
  105. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/rbda/utils.py +0 -0
  106. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/terrain/__init__.py +0 -0
  107. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/terrain/terrain.py +0 -0
  108. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/typing.py +0 -0
  109. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/utils/__init__.py +0 -0
  110. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/utils/jaxsim_dataclass.py +0 -0
  111. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/utils/tracing.py +0 -0
  112. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim/utils/wrappers.py +0 -0
  113. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim.egg-info/SOURCES.txt +0 -0
  114. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim.egg-info/dependency_links.txt +0 -0
  115. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim.egg-info/requires.txt +0 -0
  116. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/src/jaxsim.egg-info/top_level.txt +0 -0
  117. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/tests/__init__.py +0 -0
  118. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/tests/test_api_com.py +0 -0
  119. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/tests/test_api_contact.py +0 -0
  120. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/tests/test_api_data.py +0 -0
  121. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/tests/test_api_frame.py +0 -0
  122. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/tests/test_api_joint.py +0 -0
  123. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/tests/test_api_link.py +0 -0
  124. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/tests/test_api_model.py +0 -0
  125. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/tests/test_automatic_differentiation.py +0 -0
  126. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/tests/test_contact.py +0 -0
  127. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/tests/test_exceptions.py +0 -0
  128. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/tests/test_pytree.py +0 -0
  129. {jaxsim-0.4.3.dev271 → jaxsim-0.4.3.dev282}/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.dev271
3
+ Version: 0.4.3.dev282
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>
6
6
  Maintainer-email: Diego Ferigo <dgferigo@gmail.com>, Filippo Luca Ferretti <filippo.ferretti@iit.it>
@@ -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.dev271'
16
- __version_tuple__ = version_tuple = (0, 4, 3, 'dev271')
15
+ __version__ = version = '0.4.3.dev282'
16
+ __version_tuple__ = version_tuple = (0, 4, 3, 'dev282')
@@ -122,8 +122,11 @@ def position_limit(
122
122
  The position limits of the joint.
123
123
  """
124
124
 
125
- if model.number_of_joints() <= 1:
126
- return jnp.empty(0).astype(float), jnp.empty(0).astype(float)
125
+ if model.number_of_joints() == 0:
126
+ s_min = model.kin_dyn_parameters.joint_parameters.position_limits_min
127
+ s_max = model.kin_dyn_parameters.joint_parameters.position_limits_max
128
+
129
+ return jnp.atleast_1d(s_min).astype(float), jnp.atleast_1d(s_max).astype(float)
127
130
 
128
131
  exceptions.raise_value_error_if(
129
132
  condition=jnp.array(
@@ -243,9 +243,40 @@ def system_acceleration(
243
243
  # Enforce joint limits
244
244
  # ====================
245
245
 
246
- # TODO: enforce joint limits
247
246
  τ_position_limit = jnp.zeros_like(τ_references).astype(float)
248
247
 
248
+ if model.dofs() > 0:
249
+
250
+ # Stiffness and damper parameters for the joint position limits.
251
+ k_j = jnp.array(
252
+ model.kin_dyn_parameters.joint_parameters.position_limit_spring
253
+ ).astype(float)
254
+ d_j = jnp.array(
255
+ model.kin_dyn_parameters.joint_parameters.position_limit_damper
256
+ ).astype(float)
257
+
258
+ # Compute the joint position limit violations.
259
+ lower_violation = jnp.clip(
260
+ data.state.physics_model.joint_positions
261
+ - model.kin_dyn_parameters.joint_parameters.position_limits_min,
262
+ max=0.0,
263
+ )
264
+
265
+ upper_violation = jnp.clip(
266
+ data.state.physics_model.joint_positions
267
+ - model.kin_dyn_parameters.joint_parameters.position_limits_max,
268
+ min=0.0,
269
+ )
270
+
271
+ # Compute the joint position limit torque.
272
+ τ_position_limit -= jnp.diag(k_j) @ (lower_violation + upper_violation)
273
+
274
+ τ_position_limit -= (
275
+ jnp.positive(τ_position_limit)
276
+ * jnp.diag(d_j)
277
+ @ data.state.physics_model.joint_velocities
278
+ )
279
+
249
280
  # ====================
250
281
  # Joint friction model
251
282
  # ====================
@@ -1,4 +1,3 @@
1
- import jax
2
1
  import jax.numpy as jnp
3
2
  import jaxlie
4
3
 
@@ -8,6 +7,7 @@ from .skew import Skew
8
7
 
9
8
 
10
9
  class Rotation:
10
+
11
11
  @staticmethod
12
12
  def x(theta: jtp.Float) -> jtp.Matrix:
13
13
  """
@@ -19,6 +19,7 @@ class Rotation:
19
19
  Returns:
20
20
  jtp.Matrix: 3D rotation matrix.
21
21
  """
22
+
22
23
  return jaxlie.SO3.from_x_radians(theta=theta).as_matrix()
23
24
 
24
25
  @staticmethod
@@ -32,6 +33,7 @@ class Rotation:
32
33
  Returns:
33
34
  jtp.Matrix: 3D rotation matrix.
34
35
  """
36
+
35
37
  return jaxlie.SO3.from_y_radians(theta=theta).as_matrix()
36
38
 
37
39
  @staticmethod
@@ -45,6 +47,7 @@ class Rotation:
45
47
  Returns:
46
48
  jtp.Matrix: 3D rotation matrix.
47
49
  """
50
+
48
51
  return jaxlie.SO3.from_z_radians(theta=theta).as_matrix()
49
52
 
50
53
  @staticmethod
@@ -53,17 +56,18 @@ class Rotation:
53
56
  Generate a 3D rotation matrix from an axis-angle representation.
54
57
 
55
58
  Args:
56
- vector (jtp.Vector): Axis-angle representation as a 3D vector.
59
+ vector: Axis-angle representation or the rotation as a 3D vector.
57
60
 
58
61
  Returns:
59
- jtp.Matrix: 3D rotation matrix.
60
-
62
+ The SO(3) rotation matrix.
61
63
  """
64
+
62
65
  vector = vector.squeeze()
63
- theta = jnp.linalg.norm(vector)
64
66
 
65
- def theta_is_not_zero(theta_and_v: tuple[jtp.Float, jtp.Vector]) -> jtp.Matrix:
66
- theta, v = theta_and_v
67
+ def theta_is_not_zero(axis: jtp.Vector) -> jtp.Matrix:
68
+
69
+ v = axis
70
+ theta = jnp.linalg.norm(v)
67
71
 
68
72
  s = jnp.sin(theta)
69
73
  c = jnp.cos(theta)
@@ -77,9 +81,19 @@ class Rotation:
77
81
 
78
82
  return R.transpose()
79
83
 
80
- return jax.lax.cond(
81
- pred=(theta == 0.0),
82
- true_fun=lambda operand: jnp.eye(3),
83
- false_fun=theta_is_not_zero,
84
- operand=(theta, vector),
84
+ # Use the double-where trick to prevent JAX problems when the
85
+ # jax.jit and jax.grad transforms are applied.
86
+ return jnp.where(
87
+ jnp.linalg.norm(vector) > 0,
88
+ theta_is_not_zero(
89
+ axis=jnp.where(
90
+ jnp.linalg.norm(vector) > 0,
91
+ vector,
92
+ # The following line is a workaround to prevent division by 0.
93
+ # Considering the outer where, this branch is never executed.
94
+ jnp.ones(3),
95
+ )
96
+ ),
97
+ # Return an identity rotation matrix when the input vector is zero.
98
+ jnp.eye(3),
85
99
  )
@@ -1,4 +1,5 @@
1
1
  import dataclasses
2
+ import os
2
3
  import pathlib
3
4
  from typing import NamedTuple
4
5
 
@@ -273,14 +274,14 @@ def extract_model_data(
273
274
  if j.axis is not None
274
275
  and j.axis.limit is not None
275
276
  and j.axis.limit.dissipation is not None
276
- else 0.0
277
+ else os.environ.get("JAXSIM_JOINT_POSITION_LIMIT_DAMPER", 0.0)
277
278
  ),
278
279
  position_limit_spring=float(
279
280
  j.axis.limit.stiffness
280
281
  if j.axis is not None
281
282
  and j.axis.limit is not None
282
283
  and j.axis.limit.stiffness is not None
283
- else 0.0
284
+ else os.environ.get("JAXSIM_JOINT_POSITION_LIMIT_SPRING", 0.0)
284
285
  ),
285
286
  )
286
287
  for j in sdf_model.joints()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jaxsim
3
- Version: 0.4.3.dev271
3
+ Version: 0.4.3.dev282
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>
6
6
  Maintainer-email: Diego Ferigo <dgferigo@gmail.com>, Filippo Luca Ferretti <filippo.ferretti@iit.it>
@@ -250,6 +250,116 @@ def jaxsim_model_ur10() -> js.model.JaxSimModel:
250
250
  return build_jaxsim_model(model_description=model_urdf_path)
251
251
 
252
252
 
253
+ @pytest.fixture(scope="session")
254
+ def jaxsim_model_single_pendulum() -> js.model.JaxSimModel:
255
+ """
256
+ Fixture providing the JaxSim model of a single pendulum.
257
+ Returns:
258
+ The JaxSim model of a single pendulum.
259
+ """
260
+
261
+ import numpy as np
262
+ import rod.builder.primitives
263
+
264
+ base_height = 2.15
265
+ upper_height = 1.0
266
+
267
+ # ===================
268
+ # Create the builders
269
+ # ===================
270
+
271
+ base_builder = rod.builder.primitives.BoxBuilder(
272
+ name="base",
273
+ mass=1.0,
274
+ x=0.15,
275
+ y=0.15,
276
+ z=base_height,
277
+ )
278
+
279
+ upper_builder = rod.builder.primitives.BoxBuilder(
280
+ name="upper",
281
+ mass=0.5,
282
+ x=0.15,
283
+ y=0.15,
284
+ z=upper_height,
285
+ )
286
+
287
+ # =================
288
+ # Create the joints
289
+ # =================
290
+
291
+ fixed = rod.Joint(
292
+ name="fixed_joint",
293
+ type="fixed",
294
+ parent="world",
295
+ child=base_builder.name,
296
+ )
297
+
298
+ pivot = rod.Joint(
299
+ name="upper_joint",
300
+ type="continuous",
301
+ parent=base_builder.name,
302
+ child=upper_builder.name,
303
+ axis=rod.Axis(
304
+ xyz=rod.Xyz([1, 0, 0]),
305
+ limit=rod.Limit(),
306
+ ),
307
+ )
308
+
309
+ # ================
310
+ # Create the links
311
+ # ================
312
+
313
+ base = (
314
+ base_builder.build_link(
315
+ name=base_builder.name,
316
+ pose=rod.builder.primitives.PrimitiveBuilder.build_pose(
317
+ pos=np.array([0, 0, base_height / 2])
318
+ ),
319
+ )
320
+ .add_inertial()
321
+ .add_visual()
322
+ .add_collision()
323
+ .build()
324
+ )
325
+
326
+ upper_pose = rod.builder.primitives.PrimitiveBuilder.build_pose(
327
+ pos=np.array([0, 0, upper_height / 2])
328
+ )
329
+
330
+ upper = (
331
+ upper_builder.build_link(
332
+ name=upper_builder.name,
333
+ pose=rod.builder.primitives.PrimitiveBuilder.build_pose(
334
+ relative_to=base.name, pos=np.array([0, 0, upper_height])
335
+ ),
336
+ )
337
+ .add_inertial(pose=upper_pose)
338
+ .add_visual(pose=upper_pose)
339
+ .add_collision(pose=upper_pose)
340
+ .build()
341
+ )
342
+
343
+ rod_model = rod.Sdf(
344
+ version="1.10",
345
+ model=rod.Model(
346
+ name="single_pendulum",
347
+ link=[base, upper],
348
+ joint=[fixed, pivot],
349
+ ),
350
+ )
351
+
352
+ rod_model.model.resolve_frames()
353
+
354
+ urdf_string = rod.urdf.exporter.UrdfExporter.sdf_to_urdf_string(
355
+ sdf=rod_model.models()[0]
356
+ )
357
+
358
+ model = build_jaxsim_model(model_description=urdf_string)
359
+
360
+ return model
361
+
362
+
253
363
  # ============================
254
364
  # Collections of JaxSim models
255
365
  # ============================
@@ -280,6 +390,8 @@ def get_jaxsim_model_fixture(
280
390
  return request.getfixturevalue(jaxsim_model_ergocub_reduced.__name__)
281
391
  case "ur10":
282
392
  return request.getfixturevalue(jaxsim_model_ur10.__name__)
393
+ case "single_pendulum":
394
+ return request.getfixturevalue(jaxsim_model_single_pendulum.__name__)
283
395
  case _:
284
396
  raise ValueError(model_name)
285
397
 
@@ -1,5 +1,6 @@
1
1
  import jax
2
2
  import jax.numpy as jnp
3
+ import numpy as np
3
4
  import pytest
4
5
 
5
6
  import jaxsim.api as js
@@ -370,3 +371,58 @@ def test_simulation_with_relaxed_rigid_contacts(
370
371
  assert data_tf.base_position()[2] + max_penetration == pytest.approx(
371
372
  box_height / 2, abs=0.000_100
372
373
  )
374
+
375
+
376
+ def test_joint_limits(
377
+ jaxsim_model_single_pendulum: js.model.JaxSimModel,
378
+ ):
379
+
380
+ model = jaxsim_model_single_pendulum
381
+
382
+ with model.editable(validate=False) as model:
383
+ model.kin_dyn_parameters.joint_parameters.position_limits_max = jnp.atleast_1d(
384
+ jnp.array(1.5708)
385
+ )
386
+ model.kin_dyn_parameters.joint_parameters.position_limits_min = jnp.atleast_1d(
387
+ jnp.array(-1.5708)
388
+ )
389
+ model.kin_dyn_parameters.joint_parameters.position_limit_spring = (
390
+ jnp.atleast_1d(jnp.array(75.0))
391
+ )
392
+ model.kin_dyn_parameters.joint_parameters.position_limit_damper = (
393
+ jnp.atleast_1d(jnp.array(0.1))
394
+ )
395
+
396
+ position_limits_min, position_limits_max = js.joint.position_limits(model=model)
397
+
398
+ data = js.data.JaxSimModelData.build(
399
+ model=model,
400
+ velocity_representation=VelRepr.Inertial,
401
+ )
402
+
403
+ theta = 10 * np.pi / 180
404
+
405
+ # Define a tolerance since the spring-damper model does
406
+ # not guarantee that the joint position will be exactly
407
+ # below the limit.
408
+ tolerance = theta * 0.10
409
+
410
+ # Test minimum joint position limits.
411
+ data_t0 = data.reset_joint_positions(positions=position_limits_min - theta)
412
+
413
+ data_tf = run_simulation(model=model, data_t0=data_t0, dt=0.005, tf=3.0)
414
+
415
+ assert (
416
+ np.min(np.array(data_tf.joint_positions()), axis=0) + tolerance
417
+ >= position_limits_min
418
+ )
419
+
420
+ # Test maximum joint position limits.
421
+ data_t0 = data.reset_joint_positions(positions=position_limits_max - theta)
422
+
423
+ data_tf = run_simulation(model=model, data_t0=data_t0, dt=0.001, tf=3.0)
424
+
425
+ assert (
426
+ np.max(np.array(data_tf.joint_positions()), axis=0) - tolerance
427
+ <= position_limits_max
428
+ )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes