jaxsim 0.2.dev376__tar.gz → 0.2.dev394__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 (114) hide show
  1. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/.github/workflows/style.yml +17 -4
  2. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/.gitignore +3 -0
  3. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/.pre-commit-config.yaml +5 -0
  4. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/PKG-INFO +1 -1
  5. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/docs/conf.py +0 -3
  6. jaxsim-0.2.dev394/pyproject.toml +68 -0
  7. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/_version.py +2 -2
  8. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/api/common.py +2 -2
  9. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/api/data.py +4 -4
  10. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/api/link.py +24 -0
  11. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/api/model.py +207 -2
  12. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/api/ode.py +0 -1
  13. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/integrators/common.py +2 -2
  14. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/math/transform.py +0 -1
  15. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/mujoco/loaders.py +1 -1
  16. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/mujoco/model.py +2 -0
  17. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/parsers/kinematic_graph.py +1 -1
  18. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/utils/jaxsim_dataclass.py +0 -1
  19. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim.egg-info/PKG-INFO +1 -1
  20. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/tests/conftest.py +1 -4
  21. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/tests/test_api_link.py +32 -0
  22. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/tests/test_api_model.py +7 -0
  23. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/tests/test_pytree.py +0 -1
  24. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/tests/utils_idyntree.py +9 -0
  25. jaxsim-0.2.dev376/pyproject.toml +0 -25
  26. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/.devcontainer/Dockerfile +0 -0
  27. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/.devcontainer/devcontainer.json +0 -0
  28. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/.github/CODEOWNERS +0 -0
  29. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/.github/workflows/ci_cd.yml +0 -0
  30. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/.github/workflows/read_the_docs.yml +0 -0
  31. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/.readthedocs.yaml +0 -0
  32. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/CONTRIBUTING.md +0 -0
  33. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/LICENSE +0 -0
  34. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/README.md +0 -0
  35. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/docs/Makefile +0 -0
  36. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/docs/guide/install.rst +0 -0
  37. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/docs/index.rst +0 -0
  38. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/docs/make.bat +0 -0
  39. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/docs/modules/high_level.rst +0 -0
  40. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/docs/modules/math.rst +0 -0
  41. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/docs/modules/parsers.rst +0 -0
  42. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/docs/modules/physics.rst +0 -0
  43. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/docs/modules/simulation.rst +0 -0
  44. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/docs/modules/typing.rst +0 -0
  45. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/docs/modules/utils.rst +0 -0
  46. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/environment.yml +0 -0
  47. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/examples/.gitattributes +0 -0
  48. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/examples/.gitignore +0 -0
  49. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/examples/PD_controller.ipynb +0 -0
  50. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/examples/Parallel_computing.ipynb +0 -0
  51. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/examples/README.md +0 -0
  52. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/examples/assets/cartpole.urdf +0 -0
  53. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/examples/pixi.lock +0 -0
  54. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/examples/pixi.toml +0 -0
  55. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/setup.cfg +0 -0
  56. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/setup.py +0 -0
  57. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/__init__.py +0 -0
  58. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/api/__init__.py +0 -0
  59. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/api/com.py +0 -0
  60. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/api/contact.py +0 -0
  61. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/api/joint.py +0 -0
  62. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/api/kin_dyn_parameters.py +0 -0
  63. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/api/ode_data.py +0 -0
  64. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/api/references.py +0 -0
  65. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/integrators/__init__.py +0 -0
  66. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/integrators/fixed_step.py +0 -0
  67. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/integrators/variable_step.py +0 -0
  68. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/logging.py +0 -0
  69. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/math/__init__.py +0 -0
  70. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/math/adjoint.py +0 -0
  71. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/math/cross.py +0 -0
  72. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/math/inertia.py +0 -0
  73. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/math/joint_model.py +0 -0
  74. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/math/quaternion.py +0 -0
  75. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/math/rotation.py +0 -0
  76. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/math/skew.py +0 -0
  77. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/mujoco/__init__.py +0 -0
  78. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/mujoco/__main__.py +0 -0
  79. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/mujoco/visualizer.py +0 -0
  80. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/parsers/__init__.py +0 -0
  81. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/parsers/descriptions/__init__.py +0 -0
  82. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/parsers/descriptions/collision.py +0 -0
  83. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/parsers/descriptions/joint.py +0 -0
  84. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/parsers/descriptions/link.py +0 -0
  85. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/parsers/descriptions/model.py +0 -0
  86. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/parsers/rod/__init__.py +0 -0
  87. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/parsers/rod/parser.py +0 -0
  88. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/parsers/rod/utils.py +0 -0
  89. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/rbda/__init__.py +0 -0
  90. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/rbda/aba.py +0 -0
  91. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/rbda/collidable_points.py +0 -0
  92. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/rbda/crba.py +0 -0
  93. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/rbda/forward_kinematics.py +0 -0
  94. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/rbda/jacobian.py +0 -0
  95. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/rbda/rnea.py +0 -0
  96. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/rbda/soft_contacts.py +0 -0
  97. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/rbda/utils.py +0 -0
  98. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/terrain/__init__.py +0 -0
  99. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/terrain/terrain.py +0 -0
  100. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/typing.py +0 -0
  101. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/utils/__init__.py +0 -0
  102. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/utils/hashless.py +0 -0
  103. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim/utils/tracing.py +0 -0
  104. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim.egg-info/SOURCES.txt +0 -0
  105. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim.egg-info/dependency_links.txt +0 -0
  106. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim.egg-info/not-zip-safe +0 -0
  107. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim.egg-info/requires.txt +0 -0
  108. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/src/jaxsim.egg-info/top_level.txt +0 -0
  109. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/tests/__init__.py +0 -0
  110. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/tests/test_api_com.py +0 -0
  111. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/tests/test_api_data.py +0 -0
  112. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/tests/test_api_joint.py +0 -0
  113. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/tests/test_automatic_differentiation.py +0 -0
  114. {jaxsim-0.2.dev376 → jaxsim-0.2.dev394}/tests/test_simulations.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.dev376
3
+ Version: 0.2.dev394
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.dev376'
16
- __version_tuple__ = version_tuple = (0, 2, 'dev376')
15
+ __version__ = version = '0.2.dev394'
16
+ __version_tuple__ = version_tuple = (0, 2, 'dev394')
@@ -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.
@@ -335,3 +335,27 @@ def velocity(
335
335
 
336
336
  # Compute the link velocity in the output velocity representation.
337
337
  return O_J_WL_I @ I_ν
338
+
339
+
340
+ @jax.jit
341
+ def bias_acceleration(
342
+ model: js.model.JaxSimModel,
343
+ data: js.data.JaxSimModelData,
344
+ *,
345
+ link_index: jtp.IntLike,
346
+ ) -> jtp.Vector:
347
+ """
348
+ Compute the bias acceleration of the link.
349
+
350
+ Args:
351
+ model: The model to consider.
352
+ data: The data of the considered model.
353
+ link_index: The index of the link.
354
+
355
+ Returns:
356
+ The 6D bias acceleration of the link.
357
+ """
358
+
359
+ # Compute the bias acceleration of all links in the active representation.
360
+ O_v̇_WL = js.model.link_bias_accelerations(model=model, data=data)[link_index]
361
+ return O_v̇_WL
@@ -937,7 +937,7 @@ def inverse_dynamics(
937
937
  def free_floating_gravity_forces(
938
938
  model: JaxSimModel, data: js.data.JaxSimModelData
939
939
  ) -> jtp.Vector:
940
- """
940
+ r"""
941
941
  Compute the free-floating gravity forces :math:`g(\mathbf{q})` of the model.
942
942
 
943
943
  Args:
@@ -987,7 +987,7 @@ def free_floating_bias_forces(
987
987
  model: JaxSimModel, data: js.data.JaxSimModelData
988
988
  ) -> jtp.Vector:
989
989
  """
990
- 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})`
991
991
  of the model.
992
992
 
993
993
  Args:
@@ -1243,6 +1243,211 @@ def average_velocity_jacobian(
1243
1243
  # ========================
1244
1244
 
1245
1245
 
1246
+ @jax.jit
1247
+ def link_bias_accelerations(
1248
+ model: JaxSimModel,
1249
+ data: js.data.JaxSimModelData,
1250
+ ) -> jtp.Vector:
1251
+ r"""
1252
+ Compute the bias accelerations of the links of the model.
1253
+
1254
+ Args:
1255
+ model: The model to consider.
1256
+ data: The data of the considered model.
1257
+
1258
+ Returns:
1259
+ The bias accelerations of the links of the model.
1260
+
1261
+ Note:
1262
+ This function computes the component of the total 6D acceleration not due to
1263
+ the joint or base acceleration.
1264
+ It is often called :math:`\dot{J} \boldsymbol{\nu}`.
1265
+ """
1266
+
1267
+ # ================================================
1268
+ # Compute the body-fixed zero base 6D acceleration
1269
+ # ================================================
1270
+
1271
+ # Compute the base transform.
1272
+ W_H_B = jaxlie.SE3.from_rotation_and_translation(
1273
+ rotation=jaxlie.SO3.from_quaternion_xyzw(
1274
+ xyzw=jaxsim.math.Quaternion.to_xyzw(wxyz=data.base_orientation())
1275
+ ),
1276
+ translation=data.base_position(),
1277
+ ).as_matrix()
1278
+
1279
+ def other_representation_to_inertial(
1280
+ C_v̇_WB: jtp.Vector, C_v_WB: jtp.Vector, W_H_C: jtp.Matrix, W_v_WC: jtp.Vector
1281
+ ) -> jtp.Vector:
1282
+ """
1283
+ Helper to convert the active representation of the base acceleration C_v̇_WB
1284
+ expressed in a generic frame C to the inertial-fixed representation W_v̇_WB.
1285
+ """
1286
+
1287
+ W_X_C = jaxlie.SE3.from_matrix(W_H_C).adjoint()
1288
+ C_X_W = jaxlie.SE3.from_matrix(W_H_C).inverse().adjoint()
1289
+
1290
+ # In Mixed representation, we need to include a cross product in ℝ⁶.
1291
+ # In Inertial and Body representations, the cross product is always zero.
1292
+ return W_X_C @ (C_v̇_WB + jaxsim.math.Cross.vx(C_X_W @ W_v_WC) @ C_v_WB)
1293
+
1294
+ # Here we initialize a zero 6D acceleration in the active representation, and
1295
+ # convert it to inertial-fixed. This is a useful intermediate representation
1296
+ # because the apparent acceleration W_v̇_WB is equal to the intrinsic acceleration
1297
+ # W_a_WB, and intrinsic accelerations can be expressed in different frames through
1298
+ # a simple C_X_W 6D transform.
1299
+ match data.velocity_representation:
1300
+ case VelRepr.Inertial:
1301
+ W_H_C = W_H_W = jnp.eye(4)
1302
+ W_v_WC = W_v_WW = jnp.zeros(6)
1303
+ with data.switch_velocity_representation(VelRepr.Inertial):
1304
+ C_v_WB = W_v_WB = data.base_velocity()
1305
+
1306
+ case VelRepr.Body:
1307
+ W_H_C = W_H_B
1308
+ with data.switch_velocity_representation(VelRepr.Inertial):
1309
+ W_v_WC = W_v_WB = data.base_velocity()
1310
+ with data.switch_velocity_representation(VelRepr.Body):
1311
+ C_v_WB = B_v_WB = data.base_velocity()
1312
+
1313
+ case VelRepr.Mixed:
1314
+ W_H_BW = W_H_B.at[0:3, 0:3].set(jnp.eye(3))
1315
+ W_H_C = W_H_BW
1316
+ with data.switch_velocity_representation(VelRepr.Mixed):
1317
+ W_ṗ_B = data.base_velocity()[0:3]
1318
+ W_v_WC = W_v_W_BW = jnp.zeros(6).at[0:3].set(W_ṗ_B)
1319
+ with data.switch_velocity_representation(VelRepr.Mixed):
1320
+ C_v_WB = BW_v_WB = data.base_velocity()
1321
+ case _:
1322
+ raise ValueError(data.velocity_representation)
1323
+
1324
+ # Convert a zero 6D acceleration from the active representation to inertial-fixed.
1325
+ W_v̇_WB = other_representation_to_inertial(
1326
+ C_v̇_WB=jnp.zeros(6), C_v_WB=C_v_WB, W_H_C=W_H_C, W_v_WC=W_v_WC
1327
+ )
1328
+
1329
+ # ===================================
1330
+ # Initialize buffers and prepare data
1331
+ # ===================================
1332
+
1333
+ # Get the parent array λ(i).
1334
+ # Note: λ(0) must not be used, it's initialized to -1.
1335
+ λ = model.kin_dyn_parameters.parent_array
1336
+
1337
+ # Compute 6D transforms of the base velocity.
1338
+ B_X_W = jaxsim.math.Adjoint.from_transform(transform=W_H_B, inverse=True)
1339
+
1340
+ # Compute the parent-to-child adjoints and the motion subspaces of the joints.
1341
+ # These transforms define the relative kinematics of the entire model, including
1342
+ # the base transform for both floating-base and fixed-base models.
1343
+ i_X_λi, S = model.kin_dyn_parameters.joint_transforms_and_motion_subspaces(
1344
+ joint_positions=data.joint_positions(), base_transform=W_H_B
1345
+ )
1346
+
1347
+ # Allocate the buffer to store the body-fixed link velocities.
1348
+ L_v_WL = jnp.zeros(shape=(model.number_of_links(), 6))
1349
+
1350
+ # Store the base velocity.
1351
+ with data.switch_velocity_representation(VelRepr.Body):
1352
+ B_v_WB = data.base_velocity()
1353
+ L_v_WL = L_v_WL.at[0].set(B_v_WB)
1354
+
1355
+ # Get the joint velocities.
1356
+ ṡ = data.joint_velocities(model=model, joint_names=model.joint_names())
1357
+
1358
+ # Allocate the buffer to store the body-fixed link accelerations,
1359
+ # and initialize the base acceleration.
1360
+ L_v̇_WL = jnp.zeros(shape=(model.number_of_links(), 6))
1361
+ L_v̇_WL = L_v̇_WL.at[0].set(B_X_W @ W_v̇_WB)
1362
+
1363
+ # ======================================
1364
+ # Propagate accelerations and velocities
1365
+ # ======================================
1366
+
1367
+ # The computation of the bias forces is similar to the forward pass of RNEA,
1368
+ # this time with zero base and joint accelerations. Furthermore, here we do
1369
+ # not remove gravity during the propagation.
1370
+
1371
+ # Initialize the loop.
1372
+ Carry = tuple[jtp.MatrixJax, jtp.MatrixJax]
1373
+ carry0: Carry = (L_v_WL, L_v̇_WL)
1374
+
1375
+ def propagate_accelerations(carry: Carry, i: jtp.Int) -> tuple[Carry, None]:
1376
+ # Initialize index and unpack the carry.
1377
+ ii = i - 1
1378
+ v, a = carry
1379
+
1380
+ # Get the motion subspace of the joint.
1381
+ Si = S[i].squeeze()
1382
+
1383
+ # Project the joint velocity into its motion subspace.
1384
+ vJ = Si * ṡ[ii]
1385
+
1386
+ # Propagate the link body-fixed velocity.
1387
+ v_i = i_X_λi[i] @ v[λ[i]] + vJ
1388
+ v = v.at[i].set(v_i)
1389
+
1390
+ # Propagate the link body-fixed acceleration considering zero joint acceleration.
1391
+ s̈ = 0.0
1392
+ a_i = i_X_λi[i] @ a[λ[i]] + Si * s̈ + jaxsim.math.Cross.vx(v[i]) @ vJ
1393
+ a = a.at[i].set(a_i)
1394
+
1395
+ return (v, a), None
1396
+
1397
+ # Compute the body-fixed velocity and body-fixed apparent acceleration of the links.
1398
+ (L_v_WL, L_v̇_WL), _ = (
1399
+ jax.lax.scan(
1400
+ f=propagate_accelerations,
1401
+ init=carry0,
1402
+ xs=jnp.arange(start=1, stop=model.number_of_links()),
1403
+ )
1404
+ if model.number_of_links() > 1
1405
+ else [(L_v_WL, L_v̇_WL), None]
1406
+ )
1407
+
1408
+ # ===================================================================
1409
+ # Convert the body-fixed 6D acceleration to the active representation
1410
+ # ===================================================================
1411
+
1412
+ def body_to_other_representation(
1413
+ L_v̇_WL: jtp.Vector, L_v_WL: jtp.Vector, C_H_L: jtp.Matrix, L_v_CL: jtp.Vector
1414
+ ) -> jtp.Vector:
1415
+ """
1416
+ Helper to convert the body-fixed apparent acceleration L_v̇_WL to
1417
+ another representation C_v̇_WL expressed in a generic frame C.
1418
+ """
1419
+
1420
+ # In Mixed representation, we need to include a cross product in ℝ⁶.
1421
+ # In Inertial and Body representations, the cross product is always zero.
1422
+ C_X_L = jaxsim.math.Adjoint.from_transform(transform=C_H_L)
1423
+ return C_X_L @ (L_v̇_WL + jaxsim.math.Cross.vx(L_v_CL) @ L_v_WL)
1424
+
1425
+ match data.velocity_representation:
1426
+ case VelRepr.Body:
1427
+ C_H_L = L_H_L = jnp.stack([jnp.eye(4)] * model.number_of_links())
1428
+ L_v_CL = L_v_LL = jnp.zeros(shape=(model.number_of_links(), 6))
1429
+
1430
+ case VelRepr.Inertial:
1431
+ C_H_L = W_H_L = js.model.forward_kinematics(model=model, data=data)
1432
+ L_v_CL = L_v_WL
1433
+
1434
+ case VelRepr.Mixed:
1435
+ W_H_L = js.model.forward_kinematics(model=model, data=data)
1436
+ LW_H_L = jax.vmap(lambda W_H_L: W_H_L.at[0:3, 3].set(jnp.zeros(3)))(W_H_L)
1437
+ C_H_L = LW_H_L
1438
+ L_v_CL = L_v_LW_L = jax.vmap(lambda v: v.at[0:3].set(jnp.zeros(3)))(L_v_WL)
1439
+
1440
+ case _:
1441
+ raise ValueError(data.velocity_representation)
1442
+
1443
+ # Convert from body-fixed to the active representation.
1444
+ O_v̇_WL = jax.vmap(body_to_other_representation)(
1445
+ L_v̇_WL=L_v̇_WL, L_v_WL=L_v_WL, C_H_L=C_H_L, L_v_CL=L_v_CL
1446
+ )
1447
+
1448
+ return O_v̇_WL
1449
+
1450
+
1246
1451
  @jax.jit
1247
1452
  def link_contact_forces(
1248
1453
  model: js.model.JaxSimModel, data: js.data.JaxSimModelData
@@ -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.
@@ -7,6 +7,8 @@ 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
+
10
12
  HeightmapCallable = Callable[[jtp.FloatLike, jtp.FloatLike], jtp.FloatLike]
11
13
 
12
14
 
@@ -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
@@ -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.dev376
3
+ Version: 0.2.dev394
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(
@@ -157,3 +157,35 @@ def test_link_jacobians(
157
157
  v_WL_idt = kin_dyn.frame_velocity(frame_name=link_name)
158
158
  v_WL_js = js.link.velocity(model=model, data=data, link_index=link_idx)
159
159
  assert v_WL_js == pytest.approx(v_WL_idt), link_name
160
+
161
+
162
+ def test_link_bias_acceleration(
163
+ jaxsim_models_types: js.model.JaxSimModel,
164
+ velocity_representation: VelRepr,
165
+ prng_key: jax.Array,
166
+ ):
167
+
168
+ model = jaxsim_models_types
169
+
170
+ key, subkey = jax.random.split(prng_key, num=2)
171
+ data = js.data.random_model_data(
172
+ model=model,
173
+ key=subkey,
174
+ velocity_representation=velocity_representation,
175
+ )
176
+
177
+ kin_dyn = utils_idyntree.build_kindyncomputations_from_jaxsim_model(
178
+ model=model, data=data
179
+ )
180
+
181
+ # =====
182
+ # Tests
183
+ # =====
184
+
185
+ for name, index in zip(
186
+ model.link_names(),
187
+ js.link.names_to_idxs(model=model, link_names=model.link_names()),
188
+ ):
189
+ Jν_idt = kin_dyn.frame_bias_acc(frame_name=name)
190
+ Jν_js = js.link.bias_acceleration(model=model, data=data, link_index=index)
191
+ assert pytest.approx(Jν_idt) == Jν_js
@@ -161,6 +161,13 @@ def test_model_rbda(
161
161
  )
162
162
  assert pytest.approx(HH_idt) == HH_js
163
163
 
164
+ # Bias accelerations
165
+ Jν_js = js.model.link_bias_accelerations(model=model, data=data)
166
+ Jν_idt = jnp.stack(
167
+ [kin_dyn.frame_bias_acc(frame_name=name) for name in model.link_names()]
168
+ )
169
+ assert pytest.approx(Jν_idt) == Jν_js
170
+
164
171
 
165
172
  def test_model_jacobian(
166
173
  jaxsim_models_types: js.model.JaxSimModel,
@@ -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
 
@@ -290,6 +290,15 @@ class KinDynComputations:
290
290
 
291
291
  return v_WF.toNumPy()
292
292
 
293
+ def frame_bias_acc(self, frame_name: str) -> npt.NDArray:
294
+
295
+ if self.kin_dyn.getFrameIndex(frame_name) < 0:
296
+ raise ValueError(f"Frame '{frame_name}' does not exist")
297
+
298
+ J̇ν = self.kin_dyn.getFrameBiasAcc(frame_name)
299
+
300
+ return J̇ν.toNumPy()
301
+
293
302
  def com_position(self) -> npt.NDArray:
294
303
 
295
304
  W_p_G = self.kin_dyn.getCenterOfMassPosition()
@@ -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
- ]
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