jaxsim 0.2.dev366__tar.gz → 0.2.dev388__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 (115) hide show
  1. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/.github/workflows/style.yml +17 -4
  2. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/.gitignore +3 -0
  3. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/.pre-commit-config.yaml +5 -0
  4. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/PKG-INFO +1 -1
  5. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/docs/conf.py +0 -3
  6. jaxsim-0.2.dev388/pyproject.toml +68 -0
  7. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/_version.py +2 -2
  8. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/api/common.py +2 -2
  9. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/api/data.py +4 -4
  10. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/api/model.py +14 -3
  11. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/api/ode.py +0 -1
  12. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/integrators/common.py +2 -2
  13. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/math/transform.py +0 -1
  14. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/mujoco/loaders.py +34 -8
  15. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/mujoco/model.py +45 -2
  16. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/parsers/kinematic_graph.py +1 -1
  17. jaxsim-0.2.dev388/src/jaxsim/terrain/__init__.py +2 -0
  18. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/utils/jaxsim_dataclass.py +0 -1
  19. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim.egg-info/PKG-INFO +1 -1
  20. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/tests/conftest.py +1 -4
  21. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/tests/test_pytree.py +0 -1
  22. jaxsim-0.2.dev366/pyproject.toml +0 -25
  23. jaxsim-0.2.dev366/src/jaxsim/terrain/__init__.py +0 -2
  24. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/.devcontainer/Dockerfile +0 -0
  25. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/.devcontainer/devcontainer.json +0 -0
  26. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/.github/CODEOWNERS +0 -0
  27. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/.github/workflows/ci_cd.yml +0 -0
  28. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/.github/workflows/read_the_docs.yml +0 -0
  29. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/.readthedocs.yaml +0 -0
  30. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/CONTRIBUTING.md +0 -0
  31. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/LICENSE +0 -0
  32. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/README.md +0 -0
  33. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/docs/Makefile +0 -0
  34. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/docs/guide/install.rst +0 -0
  35. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/docs/index.rst +0 -0
  36. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/docs/make.bat +0 -0
  37. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/docs/modules/high_level.rst +0 -0
  38. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/docs/modules/math.rst +0 -0
  39. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/docs/modules/parsers.rst +0 -0
  40. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/docs/modules/physics.rst +0 -0
  41. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/docs/modules/simulation.rst +0 -0
  42. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/docs/modules/typing.rst +0 -0
  43. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/docs/modules/utils.rst +0 -0
  44. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/environment.yml +0 -0
  45. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/examples/.gitattributes +0 -0
  46. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/examples/.gitignore +0 -0
  47. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/examples/PD_controller.ipynb +0 -0
  48. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/examples/Parallel_computing.ipynb +0 -0
  49. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/examples/README.md +0 -0
  50. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/examples/assets/cartpole.urdf +0 -0
  51. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/examples/pixi.lock +0 -0
  52. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/examples/pixi.toml +0 -0
  53. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/setup.cfg +0 -0
  54. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/setup.py +0 -0
  55. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/__init__.py +0 -0
  56. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/api/__init__.py +0 -0
  57. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/api/com.py +0 -0
  58. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/api/contact.py +0 -0
  59. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/api/joint.py +0 -0
  60. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/api/kin_dyn_parameters.py +0 -0
  61. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/api/link.py +0 -0
  62. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/api/ode_data.py +0 -0
  63. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/api/references.py +0 -0
  64. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/integrators/__init__.py +0 -0
  65. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/integrators/fixed_step.py +0 -0
  66. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/integrators/variable_step.py +0 -0
  67. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/logging.py +0 -0
  68. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/math/__init__.py +0 -0
  69. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/math/adjoint.py +0 -0
  70. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/math/cross.py +0 -0
  71. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/math/inertia.py +0 -0
  72. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/math/joint_model.py +0 -0
  73. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/math/quaternion.py +0 -0
  74. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/math/rotation.py +0 -0
  75. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/math/skew.py +0 -0
  76. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/mujoco/__init__.py +0 -0
  77. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/mujoco/__main__.py +0 -0
  78. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/mujoco/visualizer.py +0 -0
  79. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/parsers/__init__.py +0 -0
  80. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/parsers/descriptions/__init__.py +0 -0
  81. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/parsers/descriptions/collision.py +0 -0
  82. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/parsers/descriptions/joint.py +0 -0
  83. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/parsers/descriptions/link.py +0 -0
  84. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/parsers/descriptions/model.py +0 -0
  85. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/parsers/rod/__init__.py +0 -0
  86. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/parsers/rod/parser.py +0 -0
  87. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/parsers/rod/utils.py +0 -0
  88. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/rbda/__init__.py +0 -0
  89. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/rbda/aba.py +0 -0
  90. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/rbda/collidable_points.py +0 -0
  91. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/rbda/crba.py +0 -0
  92. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/rbda/forward_kinematics.py +0 -0
  93. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/rbda/jacobian.py +0 -0
  94. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/rbda/rnea.py +0 -0
  95. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/rbda/soft_contacts.py +0 -0
  96. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/rbda/utils.py +0 -0
  97. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/terrain/terrain.py +0 -0
  98. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/typing.py +0 -0
  99. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/utils/__init__.py +0 -0
  100. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/utils/hashless.py +0 -0
  101. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim/utils/tracing.py +0 -0
  102. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim.egg-info/SOURCES.txt +0 -0
  103. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim.egg-info/dependency_links.txt +0 -0
  104. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim.egg-info/not-zip-safe +0 -0
  105. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim.egg-info/requires.txt +0 -0
  106. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/src/jaxsim.egg-info/top_level.txt +0 -0
  107. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/tests/__init__.py +0 -0
  108. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/tests/test_api_com.py +0 -0
  109. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/tests/test_api_data.py +0 -0
  110. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/tests/test_api_joint.py +0 -0
  111. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/tests/test_api_link.py +0 -0
  112. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/tests/test_api_model.py +0 -0
  113. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/tests/test_automatic_differentiation.py +0 -0
  114. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/tests/test_simulations.py +0 -0
  115. {jaxsim-0.2.dev366 → jaxsim-0.2.dev388}/tests/utils_idyntree.py +0 -0
@@ -17,10 +17,10 @@ jobs:
17
17
  steps:
18
18
 
19
19
  - name: "🔀 Checkout repository"
20
- uses: actions/checkout@v2
20
+ uses: actions/checkout@v4
21
21
 
22
22
  - name: '🐍 Initialize Python'
23
- uses: actions/setup-python@v2
23
+ uses: actions/setup-python@v5
24
24
  with:
25
25
  python-version: "3.8"
26
26
 
@@ -37,10 +37,10 @@ jobs:
37
37
  steps:
38
38
 
39
39
  - name: "🔀 Checkout repository"
40
- uses: actions/checkout@v2
40
+ uses: actions/checkout@v4
41
41
 
42
42
  - name: '🐍 Initialize Python'
43
- uses: actions/setup-python@v2
43
+ uses: actions/setup-python@v5
44
44
  with:
45
45
  python-version: "3.8"
46
46
 
@@ -51,3 +51,16 @@ jobs:
51
51
  uses: isort/isort-action@master
52
52
  with:
53
53
  configuration: --check --diff --color
54
+
55
+ ruff:
56
+
57
+ name: ruff
58
+ runs-on: ubuntu-latest
59
+
60
+ steps:
61
+
62
+ - name: "🔀 Checkout repository"
63
+ uses: actions/checkout@v4
64
+
65
+ - name: "📝 Ruff"
66
+ uses: chartboost/ruff-action@v1
@@ -136,3 +136,6 @@ dmypy.json
136
136
 
137
137
  # setuptools_scm dynamic version
138
138
  src/jaxsim/_version.py
139
+
140
+ # ruff
141
+ .ruff_cache/
@@ -19,3 +19,8 @@ repos:
19
19
  hooks:
20
20
  - id: isort
21
21
  name: isort (python)
22
+
23
+ - repo: https://github.com/astral-sh/ruff-pre-commit
24
+ rev: v0.3.2
25
+ hooks:
26
+ - id: ruff
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jaxsim
3
- Version: 0.2.dev366
3
+ Version: 0.2.dev388
4
4
  Summary: A physics engine in reduced coordinates implemented with JAX.
5
5
  Home-page: https://github.com/ami-iit/jaxsim
6
6
  Author: Diego Ferigo
@@ -1,6 +1,5 @@
1
1
  # Configuration file for the Sphinx documentation builder.
2
2
  import os
3
- import pathlib
4
3
  import sys
5
4
 
6
5
  from pkg_resources import get_distribution
@@ -23,8 +22,6 @@ def _recursive_add_annotations_import():
23
22
  if "READTHEDOCS" in os.environ:
24
23
  _recursive_add_annotations_import()
25
24
 
26
- import jaxsim
27
-
28
25
  # -- Version information
29
26
 
30
27
  sys.path.insert(0, os.path.abspath("."))
@@ -0,0 +1,68 @@
1
+ [build-system]
2
+ build-backend = "setuptools.build_meta"
3
+ requires = [
4
+ "wheel",
5
+ "setuptools>=64",
6
+ "setuptools_scm[toml]>=8",
7
+ ]
8
+
9
+ [tool.setuptools_scm]
10
+ local_scheme = "dirty-tag"
11
+ version_file = "src/jaxsim/_version.py"
12
+
13
+ [tool.black]
14
+ line-length = 88
15
+
16
+ [tool.isort]
17
+ multi_line_output = 3
18
+ profile = "black"
19
+
20
+ [tool.pytest.ini_options]
21
+ addopts = "-rsxX -v --strict-markers"
22
+ minversion = "6.0"
23
+ preview = true
24
+ testpaths = [
25
+ "tests",
26
+ ]
27
+
28
+ target-version = "py311"
29
+
30
+ [tool.ruff]
31
+ exclude = [
32
+ ".git",
33
+ ".pytest_cache",
34
+ ".ruff_cache",
35
+ ".vscode",
36
+ ".devcontainer",
37
+ "__pycache__",
38
+ ]
39
+ preview = true
40
+
41
+ [tool.ruff.lint]
42
+ # https://docs.astral.sh/ruff/rules/
43
+ ignore = [
44
+ "B008", # Function call in default argument
45
+ "B024", # Abstract base class without abstract methods
46
+ "B904", # Raise without from inside exception
47
+ "B905", # Zip without explicit strict
48
+ "E402", # Module level import not at top of file
49
+ "E501", # Line too long
50
+ "E731", # Do not assign a `lambda` expression, use a `def`
51
+ "E741", # Ambiguous variable name
52
+ "F841", # Local variable is assigned to but never used
53
+ "I001", # Import block is unsorted or unformatted
54
+ ]
55
+ select = [
56
+ "B",
57
+ "E",
58
+ "F",
59
+ "I",
60
+ "W",
61
+ "YTT",
62
+ ]
63
+
64
+ [tool.ruff.lint.per-file-ignores]
65
+ # Ignore `E402` (import violations) in all `__init__.py` files
66
+ "**/{tests,docs,tools}/*" = ["E402"]
67
+ "**/{tests}/*" = ["B007"]
68
+ "__init__.py" = ["F401"]
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.2.dev366'
16
- __version_tuple__ = version_tuple = (0, 2, 'dev366')
15
+ __version__ = version = '0.2.dev388'
16
+ __version_tuple__ = version_tuple = (0, 2, 'dev388')
@@ -89,7 +89,7 @@ class ModelDataWithVelocityRepresentation(JaxsimDataclass, abc.ABC):
89
89
  transform: jtp.Matrix,
90
90
  is_force: bool = False,
91
91
  ) -> jtp.Array:
92
- """
92
+ r"""
93
93
  Convert a 6D quantity from inertial-fixed to another representation.
94
94
 
95
95
  Args:
@@ -155,7 +155,7 @@ class ModelDataWithVelocityRepresentation(JaxsimDataclass, abc.ABC):
155
155
  transform: jtp.Matrix,
156
156
  is_force: bool = False,
157
157
  ) -> jtp.Array:
158
- """
158
+ r"""
159
159
  Convert a 6D quantity from another representation to inertial-fixed.
160
160
 
161
161
  Args:
@@ -415,9 +415,9 @@ class JaxSimModelData(common.ModelDataWithVelocityRepresentation):
415
415
 
416
416
  @jax.jit
417
417
  def generalized_position(self) -> tuple[jtp.Matrix, jtp.Vector]:
418
- """
418
+ r"""
419
419
  Get the generalized position
420
- :math:`\mathbf{q} = ({}^W \mathbf{H}_B, \mathbf{s}) \in \text{SO}(3) \times \mathbb{R}^n`.
420
+ :math:`\\mathbf{q} = ({}^W \\mathbf{H}_B, \\mathbf{s}) \\in \text{SO}(3) \times \\mathbb{R}^n`.
421
421
 
422
422
  Returns:
423
423
  A tuple containing the base transform and the joint positions.
@@ -427,9 +427,9 @@ class JaxSimModelData(common.ModelDataWithVelocityRepresentation):
427
427
 
428
428
  @jax.jit
429
429
  def generalized_velocity(self) -> jtp.Vector:
430
- """
430
+ r"""
431
431
  Get the generalized velocity
432
- :math:`\boldsymbol{\nu} = (\boldsymbol{v}_{W,B};\, \boldsymbol{\omega}_{W,B};\, \mathbf{s}) \in \mathbb{R}^{6+n}`
432
+ :math:`\boldsymbol{\nu} = (\boldsymbol{v}_{W,B};\\, \boldsymbol{\\omega}_{W,B};\\, \\mathbf{s}) \\in \\mathbb{R}^{6+n}`
433
433
 
434
434
  Returns:
435
435
  The generalized velocity in the active representation.
@@ -52,6 +52,8 @@ class JaxSimModel(JaxsimDataclass):
52
52
  def build_from_model_description(
53
53
  model_description: str | pathlib.Path | rod.Model,
54
54
  model_name: str | None = None,
55
+ *,
56
+ terrain: jaxsim.terrain.Terrain | None = None,
55
57
  is_urdf: bool | None = None,
56
58
  considered_joints: list[str] | None = None,
57
59
  ) -> JaxSimModel:
@@ -65,6 +67,8 @@ class JaxSimModel(JaxsimDataclass):
65
67
  model_name:
66
68
  The optional name of the model that overrides the one in
67
69
  the description.
70
+ terrain:
71
+ The optional terrain to consider.
68
72
  is_urdf:
69
73
  Whether the model description is a URDF or an SDF. This is
70
74
  automatically inferred if the model description is a path to a file.
@@ -92,7 +96,9 @@ class JaxSimModel(JaxsimDataclass):
92
96
 
93
97
  # Build the model
94
98
  model = JaxSimModel.build(
95
- model_description=intermediate_description, model_name=model_name
99
+ model_description=intermediate_description,
100
+ model_name=model_name,
101
+ terrain=terrain,
96
102
  )
97
103
 
98
104
  # Store the origin of the model, in case downstream logic needs it
@@ -105,6 +111,8 @@ class JaxSimModel(JaxsimDataclass):
105
111
  def build(
106
112
  model_description: jaxsim.parsers.descriptions.ModelDescription,
107
113
  model_name: str | None = None,
114
+ *,
115
+ terrain: jaxsim.terrain.Terrain | None = None,
108
116
  ) -> JaxSimModel:
109
117
  """
110
118
  Build a Model object from an intermediate model description.
@@ -115,6 +123,8 @@ class JaxSimModel(JaxsimDataclass):
115
123
  of the model.
116
124
  model_name:
117
125
  The optional name of the model overriding the physics model name.
126
+ terrain:
127
+ The optional terrain to consider.
118
128
 
119
129
  Returns:
120
130
  The built Model object.
@@ -130,6 +140,7 @@ class JaxSimModel(JaxsimDataclass):
130
140
  kin_dyn_parameters=js.kin_dyn_parameters.KynDynParameters.build(
131
141
  model_description=model_description
132
142
  ),
143
+ terrain=terrain or JaxSimModel.__dataclass_fields__["terrain"].default,
133
144
  )
134
145
 
135
146
  return model
@@ -926,7 +937,7 @@ def inverse_dynamics(
926
937
  def free_floating_gravity_forces(
927
938
  model: JaxSimModel, data: js.data.JaxSimModelData
928
939
  ) -> jtp.Vector:
929
- """
940
+ r"""
930
941
  Compute the free-floating gravity forces :math:`g(\mathbf{q})` of the model.
931
942
 
932
943
  Args:
@@ -976,7 +987,7 @@ def free_floating_bias_forces(
976
987
  model: JaxSimModel, data: js.data.JaxSimModelData
977
988
  ) -> jtp.Vector:
978
989
  """
979
- Compute the free-floating bias forces :math:`h(\mathbf{q}, \boldsymbol{\nu})`
990
+ Compute the free-floating bias forces :math:`h(\\mathbf{q}, \boldsymbol{\nu})`
980
991
  of the model.
981
992
 
982
993
  Args:
@@ -8,7 +8,6 @@ import jaxsim.rbda
8
8
  import jaxsim.typing as jtp
9
9
  from jaxsim.integrators import Time
10
10
  from jaxsim.math import Quaternion
11
- from jaxsim.utils import Mutability
12
11
 
13
12
  from .common import VelRepr
14
13
  from .ode_data import ODEState
@@ -324,7 +324,7 @@ class ExplicitRungeKutta(Integrator[PyTreeType, PyTreeType], Generic[PyTreeType]
324
324
  def post_process_state(
325
325
  cls, x0: State, t0: Time, xf: NextState, dt: TimeStep
326
326
  ) -> NextState:
327
- """
327
+ r"""
328
328
  Post-process the integrated state at :math:`t_f = t_0 + \Delta t`.
329
329
 
330
330
  Args:
@@ -529,7 +529,7 @@ class ExplicitRungeKutta(Integrator[PyTreeType, PyTreeType], Generic[PyTreeType]
529
529
  # Return the index of the row of A providing the fsal derivative (that is the
530
530
  # possibly intermediate kᵢ derivative).
531
531
  # Note that if multiple rows match (it should not), we return the first match.
532
- return True, int(jnp.where(rows_of_A_with_fsal == True)[0].tolist()[0])
532
+ return True, int(jnp.where(rows_of_A_with_fsal)[0].tolist()[0])
533
533
 
534
534
 
535
535
  class ExplicitRungeKuttaSO3Mixin:
@@ -1,4 +1,3 @@
1
- import jax
2
1
  import jax.numpy as jnp
3
2
  import jaxlie
4
3
 
@@ -102,7 +102,7 @@ class RodModelToMjcf:
102
102
 
103
103
  if root.find(f".//joint[@name='{floating_joint_name}']") is not None:
104
104
  msg = f"The URDF already has a floating joint '{floating_joint_name}'"
105
- warnings.warn(msg)
105
+ warnings.warn(msg, stacklevel=2)
106
106
  return ET.tostring(root, pretty_print=True).decode()
107
107
 
108
108
  # Create the "world" link if it doesn't exist.
@@ -129,6 +129,8 @@ class RodModelToMjcf:
129
129
  def convert(
130
130
  rod_model: rod.Model,
131
131
  considered_joints: list[str] | None = None,
132
+ plane_normal: tuple[float, float, float] = (0, 0, 1),
133
+ heightmap: bool | None = None,
132
134
  ) -> tuple[str, dict[str, Any]]:
133
135
  """"""
134
136
 
@@ -198,8 +200,6 @@ class RodModelToMjcf:
198
200
  )
199
201
 
200
202
  urdf_string = ET.tostring(root, pretty_print=True).decode()
201
- # print(urdf_string)
202
- # raise
203
203
 
204
204
  # ------------------------------
205
205
  # Post-process all dummy visuals
@@ -358,6 +358,19 @@ class RodModelToMjcf:
358
358
  texuniform="true",
359
359
  )
360
360
 
361
+ _ = (
362
+ ET.SubElement(
363
+ asset_element,
364
+ "hfield",
365
+ name="terrain",
366
+ nrow="100",
367
+ ncol="100",
368
+ size="5 5 1 1",
369
+ )
370
+ if heightmap
371
+ else None
372
+ )
373
+
361
374
  # ----------------------------------
362
375
  # Populate the scene with the assets
363
376
  # ----------------------------------
@@ -368,12 +381,14 @@ class RodModelToMjcf:
368
381
  worldbody_scene_element,
369
382
  "geom",
370
383
  name="floor",
371
- type="plane",
384
+ type="plane" if not heightmap else "hfield",
372
385
  size="0 0 0.05",
373
386
  material="plane_material",
374
387
  condim="3",
375
388
  contype="1",
376
389
  conaffinity="1",
390
+ zaxis=" ".join(map(str, plane_normal)),
391
+ **({"hfield": "terrain"} if heightmap else {}),
377
392
  )
378
393
 
379
394
  _ = ET.SubElement(
@@ -407,13 +422,14 @@ class RodModelToMjcf:
407
422
  raise RuntimeError("Failed to find the <worldbody> element of the model")
408
423
 
409
424
  # Camera attached to the model
425
+ # It can be manually copied from `python -m mujoco.viewer --mjcf=<URDF_PATH>`
410
426
  _ = ET.SubElement(
411
427
  worldbody_element,
412
428
  "camera",
413
429
  name="track",
414
430
  mode="trackcom",
415
- pos="1 0 5",
416
- zaxis="0 0 1",
431
+ pos="1.930 -2.279 0.556",
432
+ xyaxes="0.771 0.637 0.000 -0.116 0.140 0.983",
417
433
  fovy="60",
418
434
  )
419
435
 
@@ -449,6 +465,8 @@ class UrdfToMjcf:
449
465
  urdf: str | pathlib.Path,
450
466
  considered_joints: list[str] | None = None,
451
467
  model_name: str | None = None,
468
+ plane_normal: tuple[float, float, float] = (0, 0, 1),
469
+ heightmap: bool | None = None,
452
470
  ) -> tuple[str, dict[str, Any]]:
453
471
  """"""
454
472
 
@@ -461,7 +479,10 @@ class UrdfToMjcf:
461
479
 
462
480
  # Convert the ROD model to MJCF.
463
481
  return RodModelToMjcf.convert(
464
- rod_model=rod_model, considered_joints=considered_joints
482
+ rod_model=rod_model,
483
+ considered_joints=considered_joints,
484
+ plane_normal=plane_normal,
485
+ heightmap=heightmap,
465
486
  )
466
487
 
467
488
 
@@ -471,6 +492,8 @@ class SdfToMjcf:
471
492
  sdf: str | pathlib.Path,
472
493
  considered_joints: list[str] | None = None,
473
494
  model_name: str | None = None,
495
+ plane_normal: tuple[float, float, float] = (0, 0, 1),
496
+ heightmap: bool | None = None,
474
497
  ) -> tuple[str, dict[str, Any]]:
475
498
  """"""
476
499
 
@@ -483,5 +506,8 @@ class SdfToMjcf:
483
506
 
484
507
  # Convert the ROD model to MJCF.
485
508
  return RodModelToMjcf.convert(
486
- rod_model=rod_model, considered_joints=considered_joints
509
+ rod_model=rod_model,
510
+ considered_joints=considered_joints,
511
+ plane_normal=plane_normal,
512
+ heightmap=heightmap,
487
513
  )
@@ -1,12 +1,16 @@
1
1
  import functools
2
2
  import pathlib
3
- from typing import Any
3
+ from typing import Any, Callable
4
4
 
5
5
  import mujoco as mj
6
6
  import numpy as np
7
7
  import numpy.typing as npt
8
8
  from scipy.spatial.transform import Rotation
9
9
 
10
+ import jaxsim.typing as jtp
11
+
12
+ HeightmapCallable = Callable[[jtp.FloatLike, jtp.FloatLike], jtp.FloatLike]
13
+
10
14
 
11
15
  class MujocoModelHelper:
12
16
  """
@@ -27,7 +31,9 @@ class MujocoModelHelper:
27
31
 
28
32
  @staticmethod
29
33
  def build_from_xml(
30
- mjcf_description: str | pathlib.Path, assets: dict[str, Any] = None
34
+ mjcf_description: str | pathlib.Path,
35
+ assets: dict[str, Any] = None,
36
+ heightmap: HeightmapCallable | None = None,
31
37
  ) -> "MujocoModelHelper":
32
38
  """"""
33
39
 
@@ -40,6 +46,13 @@ class MujocoModelHelper:
40
46
 
41
47
  # Create the Mujoco model from the XML and, optionally, the assets dictionary
42
48
  model = mj.MjModel.from_xml_string(xml=mjcf_description, assets=assets) # noqa
49
+ data = mj.MjData(model)
50
+
51
+ if heightmap:
52
+ nrow = model.hfield_nrow.item()
53
+ ncol = model.hfield_ncol.item()
54
+ new_hfield = generate_hfield(heightmap, (nrow, ncol))
55
+ model.hfield_data = new_hfield
43
56
 
44
57
  return MujocoModelHelper(model=model, data=mj.MjData(model))
45
58
 
@@ -350,3 +363,33 @@ class MujocoModelHelper:
350
363
  ]
351
364
  ).squeeze()
352
365
  )
366
+
367
+
368
+ def generate_hfield(
369
+ heightmap: HeightmapCallable, size: tuple[int, int] = (10, 10)
370
+ ) -> npt.NDArray:
371
+ """
372
+ Generates a numpy array representing the heightmap of
373
+ The map will have the following format:
374
+ ```
375
+ heightmap[0, 0] heightmap[0, 1] ... heightmap[0, size[1]-1]
376
+ heightmap[1, 0] heightmap[1, 1] ... heightmap[1, size[1]-1]
377
+ ...
378
+ heightmap[size[0]-1, 0] heightmap[size[0]-1, 1] ... heightmap[size[0]-1, size[1]-1]
379
+ ```
380
+
381
+ Args:
382
+ heightmap: A function that takes two arguments (x, y) and returns the height
383
+ at that point.
384
+ size: A tuple of two integers representing the size of the grid.
385
+
386
+ Returns:
387
+ np.ndarray: The terrain heightmap
388
+ """
389
+
390
+ # Generate the grid.
391
+ x = np.linspace(0, 1, size[0])
392
+ y = np.linspace(0, 1, size[1])
393
+
394
+ # Generate the heightmap.
395
+ return np.array([[heightmap(xi, yi) for xi in x] for yi in y]).flatten()
@@ -268,7 +268,7 @@ class KinematicGraph:
268
268
 
269
269
  # Return early if there is no action to take
270
270
  if len(joint_names_to_remove) == 0:
271
- logging.info(f"The kinematic graph doesn't need to be reduced")
271
+ logging.info("The kinematic graph doesn't need to be reduced")
272
272
  return copy.deepcopy(self)
273
273
 
274
274
  # Check if all considered joints are part of the full kinematic graph
@@ -0,0 +1,2 @@
1
+ from . import terrain
2
+ from .terrain import FlatTerrain, PlaneTerrain, Terrain
@@ -1,6 +1,5 @@
1
1
  import abc
2
2
  import contextlib
3
- import copy
4
3
  import dataclasses
5
4
  import functools
6
5
  from collections.abc import Iterator
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jaxsim
3
- Version: 0.2.dev366
3
+ Version: 0.2.dev388
4
4
  Summary: A physics engine in reduced coordinates implemented with JAX.
5
5
  Home-page: https://github.com/ami-iit/jaxsim
6
6
  Author: Diego Ferigo
@@ -2,7 +2,6 @@ import os
2
2
  import pathlib
3
3
 
4
4
  import jax
5
- import jax.numpy as jnp
6
5
  import pytest
7
6
  import rod
8
7
 
@@ -176,14 +175,12 @@ def jaxsim_model_ergocub() -> js.model.JaxSimModel:
176
175
  The JaxSim model of the ErgoCub robot.
177
176
  """
178
177
 
179
- os_environ_original = os.environ.copy()
180
-
181
178
  try:
182
179
  os.environ["ROBOT_DESCRIPTION_COMMIT"] = "v0.7.1"
183
180
 
184
181
  import robot_descriptions.ergocub_description
185
182
  finally:
186
- os.environ = os_environ_original
183
+ _ = os.environ.pop("ROBOT_DESCRIPTION_COMMIT", None)
187
184
 
188
185
  model_urdf_path = pathlib.Path(
189
186
  robot_descriptions.ergocub_description.URDF_PATH.replace(
@@ -2,7 +2,6 @@ import io
2
2
  from contextlib import redirect_stdout
3
3
 
4
4
  import jax
5
- import jax.numpy as jnp
6
5
  import rod.builder.primitives
7
6
  import rod.urdf.exporter
8
7
 
@@ -1,25 +0,0 @@
1
- [build-system]
2
- build-backend = "setuptools.build_meta"
3
- requires = [
4
- "wheel",
5
- "setuptools>=64",
6
- "setuptools_scm[toml]>=8",
7
- ]
8
-
9
- [tool.setuptools_scm]
10
- local_scheme = "dirty-tag"
11
- version_file = "src/jaxsim/_version.py"
12
-
13
- [tool.black]
14
- line-length = 88
15
-
16
- [tool.isort]
17
- profile = "black"
18
- multi_line_output = 3
19
-
20
- [tool.pytest.ini_options]
21
- minversion = "6.0"
22
- addopts = "-rsxX -v --strict-markers"
23
- testpaths = [
24
- "tests",
25
- ]
@@ -1,2 +0,0 @@
1
- from . import terrain
2
- from .terrain import FlatTerrain, Terrain
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