jaxsim 0.2.1.dev69__tar.gz → 0.2.1.dev70__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 (118) hide show
  1. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/.gitignore +1 -1
  2. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/PKG-INFO +1 -1
  3. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/docs/modules/api.rst +5 -0
  4. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/_version.py +2 -2
  5. jaxsim-0.2.1.dev70/src/jaxsim/api/__init__.py +13 -0
  6. jaxsim-0.2.1.dev70/src/jaxsim/api/frame.py +221 -0
  7. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/api/model.py +10 -0
  8. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/parsers/descriptions/link.py +37 -29
  9. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim.egg-info/PKG-INFO +1 -1
  10. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim.egg-info/SOURCES.txt +2 -0
  11. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/tests/conftest.py +19 -7
  12. jaxsim-0.2.1.dev70/tests/test_api_frame.py +144 -0
  13. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/tests/test_api_joint.py +1 -0
  14. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/tests/test_api_link.py +1 -0
  15. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/tests/test_pytree.py +4 -2
  16. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/tests/utils_idyntree.py +7 -0
  17. jaxsim-0.2.1.dev69/src/jaxsim/api/__init__.py +0 -3
  18. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/.devcontainer/Dockerfile +0 -0
  19. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/.devcontainer/devcontainer.json +0 -0
  20. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/.gitattributes +0 -0
  21. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/.github/CODEOWNERS +0 -0
  22. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/.github/workflows/ci_cd.yml +0 -0
  23. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/.github/workflows/read_the_docs.yml +0 -0
  24. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/.github/workflows/style.yml +0 -0
  25. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/.pre-commit-config.yaml +0 -0
  26. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/.readthedocs.yaml +0 -0
  27. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/CONTRIBUTING.md +0 -0
  28. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/LICENSE +0 -0
  29. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/README.md +0 -0
  30. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/docs/Makefile +0 -0
  31. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/docs/conf.py +0 -0
  32. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/docs/guide/install.rst +0 -0
  33. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/docs/index.rst +0 -0
  34. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/docs/make.bat +0 -0
  35. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/docs/modules/index.rst +0 -0
  36. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/docs/modules/integrators.rst +0 -0
  37. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/docs/modules/math.rst +0 -0
  38. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/docs/modules/mujoco.rst +0 -0
  39. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/docs/modules/parsers.rst +0 -0
  40. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/docs/modules/rbda.rst +0 -0
  41. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/docs/modules/typing.rst +0 -0
  42. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/docs/modules/utils.rst +0 -0
  43. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/environment.yml +0 -0
  44. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/examples/.gitattributes +0 -0
  45. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/examples/.gitignore +0 -0
  46. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/examples/PD_controller.ipynb +0 -0
  47. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/examples/Parallel_computing.ipynb +0 -0
  48. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/examples/README.md +0 -0
  49. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/examples/assets/cartpole.urdf +0 -0
  50. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/pixi.lock +0 -0
  51. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/pyproject.toml +0 -0
  52. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/setup.cfg +0 -0
  53. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/setup.py +0 -0
  54. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/__init__.py +0 -0
  55. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/api/com.py +0 -0
  56. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/api/common.py +0 -0
  57. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/api/contact.py +0 -0
  58. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/api/data.py +0 -0
  59. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/api/joint.py +0 -0
  60. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/api/kin_dyn_parameters.py +0 -0
  61. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/api/link.py +0 -0
  62. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/api/ode.py +0 -0
  63. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/api/ode_data.py +0 -0
  64. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/api/references.py +0 -0
  65. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/integrators/__init__.py +0 -0
  66. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/integrators/common.py +0 -0
  67. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/integrators/fixed_step.py +0 -0
  68. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/integrators/variable_step.py +0 -0
  69. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/logging.py +0 -0
  70. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/math/__init__.py +0 -0
  71. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/math/adjoint.py +0 -0
  72. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/math/cross.py +0 -0
  73. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/math/inertia.py +0 -0
  74. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/math/joint_model.py +0 -0
  75. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/math/quaternion.py +0 -0
  76. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/math/rotation.py +0 -0
  77. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/math/skew.py +0 -0
  78. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/math/transform.py +0 -0
  79. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/mujoco/__init__.py +0 -0
  80. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/mujoco/__main__.py +0 -0
  81. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/mujoco/loaders.py +0 -0
  82. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/mujoco/model.py +0 -0
  83. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/mujoco/visualizer.py +0 -0
  84. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/parsers/__init__.py +0 -0
  85. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/parsers/descriptions/__init__.py +0 -0
  86. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/parsers/descriptions/collision.py +0 -0
  87. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/parsers/descriptions/joint.py +0 -0
  88. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/parsers/descriptions/model.py +0 -0
  89. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/parsers/kinematic_graph.py +0 -0
  90. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/parsers/rod/__init__.py +0 -0
  91. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/parsers/rod/parser.py +0 -0
  92. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/parsers/rod/utils.py +0 -0
  93. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/rbda/__init__.py +0 -0
  94. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/rbda/aba.py +0 -0
  95. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/rbda/collidable_points.py +0 -0
  96. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/rbda/crba.py +0 -0
  97. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/rbda/forward_kinematics.py +0 -0
  98. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/rbda/jacobian.py +0 -0
  99. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/rbda/rnea.py +0 -0
  100. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/rbda/soft_contacts.py +0 -0
  101. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/rbda/utils.py +0 -0
  102. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/terrain/__init__.py +0 -0
  103. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/terrain/terrain.py +0 -0
  104. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/typing.py +0 -0
  105. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/utils/__init__.py +0 -0
  106. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/utils/hashless.py +0 -0
  107. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/utils/jaxsim_dataclass.py +0 -0
  108. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim/utils/tracing.py +0 -0
  109. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim.egg-info/dependency_links.txt +0 -0
  110. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim.egg-info/not-zip-safe +0 -0
  111. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim.egg-info/requires.txt +0 -0
  112. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/src/jaxsim.egg-info/top_level.txt +0 -0
  113. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/tests/__init__.py +0 -0
  114. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/tests/test_api_com.py +0 -0
  115. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/tests/test_api_data.py +0 -0
  116. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/tests/test_api_model.py +0 -0
  117. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/tests/test_automatic_differentiation.py +0 -0
  118. {jaxsim-0.2.1.dev69 → jaxsim-0.2.1.dev70}/tests/test_simulations.py +0 -0
@@ -1,5 +1,6 @@
1
1
  # IDEs
2
2
  .idea*
3
+ .vscode/
3
4
 
4
5
  # Matlab
5
6
  *.m~
@@ -141,4 +142,3 @@ src/jaxsim/_version.py
141
142
  .ruff_cache/
142
143
  # pixi environments
143
144
  .pixi
144
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jaxsim
3
- Version: 0.2.1.dev69
3
+ Version: 0.2.1.dev70
4
4
  Home-page: https://github.com/ami-iit/jaxsim
5
5
  Author: Diego Ferigo
6
6
  Author-email: diego.ferigo@iit.it
@@ -38,6 +38,11 @@ Link
38
38
  .. automodule:: jaxsim.api.link
39
39
  :members:
40
40
 
41
+ Frame
42
+ ~~~~~
43
+ .. automodule:: jaxsim.api.frame
44
+ :members:
45
+
41
46
  CoM
42
47
  ~~~
43
48
  .. automodule:: jaxsim.api.com
@@ -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.1.dev69'
16
- __version_tuple__ = version_tuple = (0, 2, 1, 'dev69')
15
+ __version__ = version = '0.2.1.dev70'
16
+ __version_tuple__ = version_tuple = (0, 2, 1, 'dev70')
@@ -0,0 +1,13 @@
1
+ from . import common # isort:skip
2
+ from . import model, data # isort:skip
3
+ from . import (
4
+ com,
5
+ contact,
6
+ frame,
7
+ joint,
8
+ kin_dyn_parameters,
9
+ link,
10
+ ode,
11
+ ode_data,
12
+ references,
13
+ )
@@ -0,0 +1,221 @@
1
+ import functools
2
+ from typing import Sequence
3
+
4
+ import jax
5
+ import jax.numpy as jnp
6
+ import jaxlie
7
+ import numpy as np
8
+
9
+ import jaxsim.api as js
10
+ import jaxsim.math
11
+ import jaxsim.typing as jtp
12
+
13
+ from .common import VelRepr
14
+
15
+ # =======================
16
+ # Index-related functions
17
+ # =======================
18
+
19
+
20
+ def idx_of_parent_link(model: js.model.JaxSimModel, *, frame_idx: jtp.IntLike) -> int:
21
+ """
22
+ Get the index of the link to which the frame is rigidly attached.
23
+
24
+ Args:
25
+ model: The model to consider.
26
+ frame_idx: The index of the frame.
27
+
28
+ Returns:
29
+ The index of the frame's parent link.
30
+ """
31
+
32
+ # Get the intermediate representation parsed from the model description.
33
+ ir = model.description.get()
34
+
35
+ # Extract the indices of the frame and the link it is attached to.
36
+ F = ir.frames[frame_idx - model.number_of_links()]
37
+ L = ir.links_dict[F.parent.name].index
38
+
39
+ return int(L)
40
+
41
+
42
+ def name_to_idx(model: js.model.JaxSimModel, *, frame_name: str) -> int:
43
+ """
44
+ Convert the name of a frame to its index.
45
+
46
+ Args:
47
+ model: The model to consider.
48
+ frame_name: The name of the frame.
49
+
50
+ Returns:
51
+ The index of the frame.
52
+ """
53
+
54
+ frame_names = np.array([frame.name for frame in model.description.get().frames])
55
+
56
+ if frame_name in frame_names:
57
+ idx_in_list = np.argwhere(frame_names == frame_name)
58
+ return int(idx_in_list.squeeze().tolist()) + model.number_of_links()
59
+
60
+ return -1
61
+
62
+
63
+ def idx_to_name(model: js.model.JaxSimModel, *, frame_index: jtp.IntLike) -> str:
64
+ """
65
+ Convert the index of a frame to its name.
66
+
67
+ Args:
68
+ model: The model to consider.
69
+ frame_index: The index of the frame.
70
+
71
+ Returns:
72
+ The name of the frame.
73
+ """
74
+
75
+ return model.description.get().frames[frame_index - model.number_of_links()].name
76
+
77
+
78
+ @functools.partial(jax.jit, static_argnames=["frame_names"])
79
+ def names_to_idxs(
80
+ model: js.model.JaxSimModel, *, frame_names: Sequence[str]
81
+ ) -> jax.Array:
82
+ """
83
+ Convert a sequence of frame names to their corresponding indices.
84
+
85
+ Args:
86
+ model: The model to consider.
87
+ frame_names: The names of the frames.
88
+
89
+ Returns:
90
+ The indices of the frames.
91
+ """
92
+
93
+ return jnp.array(
94
+ [name_to_idx(model=model, frame_name=frame_name) for frame_name in frame_names]
95
+ ).astype(int)
96
+
97
+
98
+ def idxs_to_names(
99
+ model: js.model.JaxSimModel, *, frame_indices: Sequence[jtp.IntLike]
100
+ ) -> tuple[str, ...]:
101
+ """
102
+ Convert a sequence of frame indices to their corresponding names.
103
+
104
+ Args:
105
+ model: The model to consider.
106
+ frame_indices: The indices of the frames.
107
+
108
+ Returns:
109
+ The names of the frames.
110
+ """
111
+
112
+ return tuple(
113
+ idx_to_name(model=model, frame_index=frame_index)
114
+ for frame_index in frame_indices
115
+ )
116
+
117
+
118
+ # ==========
119
+ # Frame APIs
120
+ # ==========
121
+
122
+
123
+ @functools.partial(jax.jit, static_argnames=["frame_index"])
124
+ def transform(
125
+ model: js.model.JaxSimModel,
126
+ data: js.data.JaxSimModelData,
127
+ *,
128
+ frame_index: jtp.IntLike,
129
+ ) -> jtp.Matrix:
130
+ """
131
+ Compute the SE(3) transform from the world frame to the specified frame.
132
+
133
+ Args:
134
+ model: The model to consider.
135
+ data: The data of the considered model.
136
+ frame_index: The index of the frame for which the transform is requested.
137
+
138
+ Returns:
139
+ The 4x4 matrix representing the transform.
140
+ """
141
+
142
+ # Compute the necessary transforms.
143
+ L = idx_of_parent_link(model=model, frame_idx=frame_index)
144
+ W_H_L = js.link.transform(model=model, data=data, link_index=L)
145
+
146
+ # Get the static frame pose wrt the parent link.
147
+ frame = model.description.get().frames[frame_index - model.number_of_links()]
148
+ L_H_F = frame.pose
149
+
150
+ # Combine the transforms computing the frame pose.
151
+ return W_H_L @ L_H_F
152
+
153
+
154
+ @functools.partial(jax.jit, static_argnames=["frame_index", "output_vel_repr"])
155
+ def jacobian(
156
+ model: js.model.JaxSimModel,
157
+ data: js.data.JaxSimModelData,
158
+ *,
159
+ frame_index: jtp.IntLike,
160
+ output_vel_repr: VelRepr | None = None,
161
+ ) -> jtp.Matrix:
162
+ """
163
+ Compute the free-floating jacobian of the frame.
164
+
165
+ Args:
166
+ model: The model to consider.
167
+ data: The data of the considered model.
168
+ frame_index: The index of the frame.
169
+ output_vel_repr:
170
+ The output velocity representation of the free-floating jacobian.
171
+
172
+ Returns:
173
+ The 6×(6+n) free-floating jacobian of the frame.
174
+
175
+ Note:
176
+ The input representation of the free-floating jacobian is the active
177
+ velocity representation.
178
+ """
179
+
180
+ output_vel_repr = (
181
+ output_vel_repr if output_vel_repr is not None else data.velocity_representation
182
+ )
183
+
184
+ # Get the index of the parent link.
185
+ L = idx_of_parent_link(model=model, frame_idx=frame_index)
186
+
187
+ # Compute the Jacobian of the parent link using body-fixed output representation.
188
+ L_J_WL = js.link.jacobian(
189
+ model=model, data=data, link_index=L, output_vel_repr=VelRepr.Body
190
+ )
191
+
192
+ # Adjust the output representation
193
+ match output_vel_repr:
194
+ case VelRepr.Inertial:
195
+ W_H_L = js.link.transform(model=model, data=data, link_index=L)
196
+ W_X_L = jaxlie.SE3.from_matrix(W_H_L).adjoint()
197
+ W_J_WL = W_X_L @ L_J_WL
198
+ O_J_WL_I = W_J_WL
199
+
200
+ case VelRepr.Body:
201
+ W_H_L = js.link.transform(model=model, data=data, link_index=L)
202
+ W_H_F = transform(model=model, data=data, frame_index=frame_index)
203
+ F_H_L = jaxsim.math.Transform.inverse(W_H_F) @ W_H_L
204
+ F_X_L = jaxlie.SE3.from_matrix(F_H_L).adjoint()
205
+ F_J_WL = F_X_L @ L_J_WL
206
+ O_J_WL_I = F_J_WL
207
+
208
+ case VelRepr.Mixed:
209
+ W_H_L = js.link.transform(model=model, data=data, link_index=L)
210
+ W_H_F = transform(model=model, data=data, frame_index=frame_index)
211
+ F_H_L = jaxsim.math.Transform.inverse(W_H_F) @ W_H_L
212
+ FW_H_F = W_H_F.at[0:3, 3].set(jnp.zeros(3))
213
+ FW_H_L = FW_H_F @ F_H_L
214
+ FW_X_L = jaxlie.SE3.from_matrix(FW_H_L).adjoint()
215
+ FW_J_WL = FW_X_L @ L_J_WL
216
+ O_J_WL_I = FW_J_WL
217
+
218
+ case _:
219
+ raise ValueError(output_vel_repr)
220
+
221
+ return O_J_WL_I
@@ -252,6 +252,16 @@ class JaxSimModel(JaxsimDataclass):
252
252
 
253
253
  return self.kin_dyn_parameters.link_names
254
254
 
255
+ def frame_names(self) -> tuple[str, ...]:
256
+ """
257
+ Return the names of the links in the model.
258
+
259
+ Returns:
260
+ The names of the links in the model.
261
+ """
262
+
263
+ return tuple([frame.name for frame in self.description.get().frames])
264
+
255
265
 
256
266
  # =====================
257
267
  # Model post-processing
@@ -1,5 +1,6 @@
1
+ from __future__ import annotations
2
+
1
3
  import dataclasses
2
- from typing import List
3
4
 
4
5
  import jax.numpy as jnp
5
6
  import jax_dataclasses
@@ -16,39 +17,46 @@ class LinkDescription(JaxsimDataclass):
16
17
  In-memory description of a robot link.
17
18
 
18
19
  Attributes:
19
- name (str): The name of the link.
20
- mass (float): The mass of the link.
21
- inertia (jtp.Matrix): The inertia matrix of the link.
22
- index (Optional[int]): An optional index for the link.
23
- parent (Optional[LinkDescription]): The parent link of this link.
24
- pose (jtp.Matrix): The pose transformation matrix of the link.
25
- children (List[LinkDescription]): List of child links.
20
+ name: The name of the link.
21
+ mass: The mass of the link.
22
+ inertia: The inertia tensor of the link.
23
+ index: An optional index for the link (it gets automatically assigned).
24
+ parent: The parent link of this link.
25
+ pose: The pose transformation matrix of the link.
26
+ children: List of child links.
26
27
  """
27
28
 
28
29
  name: Static[str]
29
- mass: float
30
- inertia: jtp.Matrix
30
+ mass: float = dataclasses.field(repr=False)
31
+ inertia: jtp.Matrix = dataclasses.field(repr=False)
31
32
  index: int | None = None
32
- parent: Static["LinkDescription"] = dataclasses.field(default=None, repr=False)
33
+ parent: LinkDescription = dataclasses.field(default=None, repr=False)
33
34
  pose: jtp.Matrix = dataclasses.field(default_factory=lambda: jnp.eye(4), repr=False)
34
- children: Static[List["LinkDescription"]] = dataclasses.field(
35
+
36
+ children: Static[list[LinkDescription]] = dataclasses.field(
35
37
  default_factory=list, repr=False
36
38
  )
37
39
 
38
40
  def __hash__(self) -> int:
39
- return hash(self.__repr__())
40
-
41
- def __eq__(self, other) -> bool:
42
- return (
43
- self.name == other.name
44
- and self.mass == other.mass
45
- and (self.inertia == other.inertia).all()
46
- and self.index == other.index
47
- and self.parent == other.parent
48
- and (self.pose == other.pose).all()
49
- and self.children == other.children
41
+
42
+ return hash(
43
+ (
44
+ hash(self.name),
45
+ hash(float(self.mass)),
46
+ hash(tuple(self.inertia.flatten().tolist())),
47
+ hash(int(self.index)),
48
+ hash(self.parent),
49
+ hash(tuple(hash(c) for c in self.children)),
50
+ )
50
51
  )
51
52
 
53
+ def __eq__(self, other: LinkDescription) -> bool:
54
+
55
+ if not isinstance(other, LinkDescription):
56
+ return False
57
+
58
+ return hash(self) == hash(other)
59
+
52
60
  @property
53
61
  def name_and_index(self) -> str:
54
62
  """
@@ -61,19 +69,19 @@ class LinkDescription(JaxsimDataclass):
61
69
  return f"#{self.index}_<{self.name}>"
62
70
 
63
71
  def lump_with(
64
- self, link: "LinkDescription", lumped_H_removed: jtp.Matrix
65
- ) -> "LinkDescription":
72
+ self, link: LinkDescription, lumped_H_removed: jtp.Matrix
73
+ ) -> LinkDescription:
66
74
  """
67
75
  Combine the current link with another link, preserving mass and inertia.
68
76
 
69
77
  Args:
70
- link (LinkDescription): The link to combine with.
71
- lumped_H_removed (jtp.Matrix): The transformation matrix between the two links.
78
+ link: The link to combine with.
79
+ lumped_H_removed: The transformation matrix between the two links.
72
80
 
73
81
  Returns:
74
- LinkDescription: The combined link.
75
-
82
+ The combined link.
76
83
  """
84
+
77
85
  # Get the 6D inertia of the link to remove
78
86
  I_removed = link.inertia
79
87
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jaxsim
3
- Version: 0.2.1.dev69
3
+ Version: 0.2.1.dev70
4
4
  Home-page: https://github.com/ami-iit/jaxsim
5
5
  Author: Diego Ferigo
6
6
  Author-email: diego.ferigo@iit.it
@@ -51,6 +51,7 @@ src/jaxsim/api/com.py
51
51
  src/jaxsim/api/common.py
52
52
  src/jaxsim/api/contact.py
53
53
  src/jaxsim/api/data.py
54
+ src/jaxsim/api/frame.py
54
55
  src/jaxsim/api/joint.py
55
56
  src/jaxsim/api/kin_dyn_parameters.py
56
57
  src/jaxsim/api/link.py
@@ -105,6 +106,7 @@ tests/__init__.py
105
106
  tests/conftest.py
106
107
  tests/test_api_com.py
107
108
  tests/test_api_data.py
109
+ tests/test_api_frame.py
108
110
  tests/test_api_joint.py
109
111
  tests/test_api_link.py
110
112
  tests/test_api_model.py
@@ -4,6 +4,8 @@ import pathlib
4
4
  import jax
5
5
  import pytest
6
6
  import rod
7
+ import rod.urdf
8
+ import rod.urdf.exporter
7
9
 
8
10
  import jaxsim
9
11
  import jaxsim.api as js
@@ -120,18 +122,26 @@ def jaxsim_model_box() -> js.model.JaxSimModel:
120
122
  rod_model = (
121
123
  rod.builder.primitives.BoxBuilder(x=0.3, y=0.2, z=0.1, mass=1.0, name="box")
122
124
  .build_model()
123
- .add_link()
125
+ .add_link(name="box_link")
124
126
  .add_inertial()
125
127
  .add_visual()
126
128
  .add_collision()
127
129
  .build()
128
130
  )
129
131
 
130
- # Export the URDF string.
131
- urdf_string = rod.urdf.exporter.UrdfExporter.sdf_to_urdf_string(
132
- sdf=rod_model, pretty=True
132
+ rod_model.add_frame(
133
+ rod.Frame(
134
+ name="box_frame",
135
+ attached_to="box_link",
136
+ pose=rod.Pose(relative_to="box_link", pose=[1, 1, 1, 0.5, 0.4, 0.3]),
137
+ )
133
138
  )
134
139
 
140
+ # Export the URDF string.
141
+ urdf_string = rod.urdf.exporter.UrdfExporter(
142
+ pretty=True, gazebo_preserve_fixed_joints=True
143
+ ).to_urdf_string(sdf=rod_model)
144
+
135
145
  return build_jaxsim_model(model_description=urdf_string)
136
146
 
137
147
 
@@ -159,8 +169,8 @@ def jaxsim_model_sphere() -> js.model.JaxSimModel:
159
169
  )
160
170
 
161
171
  # Export the URDF string.
162
- urdf_string = rod.urdf.exporter.UrdfExporter.sdf_to_urdf_string(
163
- sdf=rod_model, pretty=True
172
+ urdf_string = rod.urdf.exporter.UrdfExporter(pretty=True).to_urdf_string(
173
+ sdf=rod_model
164
174
  )
165
175
 
166
176
  return build_jaxsim_model(model_description=urdf_string)
@@ -219,7 +229,9 @@ def jaxsim_model_ergocub_reduced(jaxsim_model_ergocub) -> js.model.JaxSimModel:
219
229
  and "torso" not in j and "elbow" not in j and "shoulder" not in j
220
230
  )
221
231
 
222
- return js.model.reduce(model=model_full, considered_joints=reduced_joints)
232
+ model = js.model.reduce(model=model_full, considered_joints=reduced_joints)
233
+
234
+ return model
223
235
 
224
236
 
225
237
  @pytest.fixture(scope="session")
@@ -0,0 +1,144 @@
1
+ import jax
2
+ import numpy as np
3
+ import pytest
4
+
5
+ import jaxsim.api as js
6
+ from jaxsim import VelRepr
7
+
8
+ from . import utils_idyntree
9
+
10
+
11
+ def test_frame_index(jaxsim_models_types: js.model.JaxSimModel):
12
+
13
+ model = jaxsim_models_types
14
+
15
+ # =====
16
+ # Tests
17
+ # =====
18
+
19
+ frame_indices = tuple(
20
+ frame.index
21
+ for frame in model.description.get().frames
22
+ if frame.index is not None
23
+ )
24
+
25
+ frame_names = np.array([frame.name for frame in model.description.get().frames])
26
+
27
+ for frame_idx, frame_name in zip(frame_indices, frame_names):
28
+ assert js.frame.name_to_idx(model=model, frame_name=frame_name) == frame_idx
29
+ assert js.frame.idx_to_name(model=model, frame_index=frame_idx) == frame_name
30
+ assert (
31
+ js.frame.idx_of_parent_link(model=model, frame_idx=frame_idx)
32
+ < model.number_of_links()
33
+ )
34
+
35
+ assert js.frame.names_to_idxs(
36
+ model=model, frame_names=tuple(frame_names)
37
+ ) == pytest.approx(frame_indices)
38
+
39
+ assert js.frame.idxs_to_names(
40
+ model=model, frame_indices=frame_indices
41
+ ) == pytest.approx(frame_names)
42
+
43
+
44
+ def test_frame_transforms(
45
+ jaxsim_models_types: js.model.JaxSimModel,
46
+ prng_key: jax.Array,
47
+ ):
48
+
49
+ model = jaxsim_models_types
50
+
51
+ key, subkey = jax.random.split(prng_key, num=2)
52
+ data = js.data.random_model_data(
53
+ model=model, key=subkey, velocity_representation=VelRepr.Inertial
54
+ )
55
+
56
+ kin_dyn = utils_idyntree.build_kindyncomputations_from_jaxsim_model(
57
+ model=model, data=data
58
+ )
59
+
60
+ # Get all names of frames in the iDynTree model.
61
+ frame_names = [
62
+ frame.name
63
+ for frame in model.description.get().frames
64
+ if frame.name in kin_dyn.frame_names()
65
+ ]
66
+
67
+ # Skip some entry of models with many frames.
68
+ frame_names = [
69
+ name
70
+ for name in frame_names
71
+ if "skin" not in name or "laser" not in name or "depth" not in name
72
+ ]
73
+
74
+ # Get indices of frames.
75
+ frame_indices = tuple(
76
+ frame.index
77
+ for frame in model.description.get().frames
78
+ if frame.index is not None and frame.name in frame_names
79
+ )
80
+
81
+ # =====
82
+ # Tests
83
+ # =====
84
+
85
+ assert len(frame_indices) == len(frame_names)
86
+
87
+ for frame_name, frame_idx in zip(frame_names, frame_indices):
88
+
89
+ W_H_F_js = js.frame.transform(
90
+ model=model,
91
+ data=data,
92
+ frame_index=js.frame.name_to_idx(model=model, frame_name=frame_name),
93
+ )
94
+ W_H_F_idt = kin_dyn.frame_transform(frame_name=frame_name)
95
+ assert W_H_F_js == pytest.approx(W_H_F_idt, abs=1e-6), frame_name
96
+
97
+
98
+ def test_frame_jacobians(
99
+ jaxsim_models_types: js.model.JaxSimModel,
100
+ velocity_representation: VelRepr,
101
+ prng_key: jax.Array,
102
+ ):
103
+
104
+ model = jaxsim_models_types
105
+
106
+ key, subkey = jax.random.split(prng_key, num=2)
107
+ data = js.data.random_model_data(
108
+ model=model, key=subkey, velocity_representation=velocity_representation
109
+ )
110
+
111
+ kin_dyn = utils_idyntree.build_kindyncomputations_from_jaxsim_model(
112
+ model=model, data=data
113
+ )
114
+
115
+ # Get all names of frames in the iDynTree model.
116
+ frame_names = [
117
+ frame.name
118
+ for frame in model.description.get().frames
119
+ if frame.name in kin_dyn.frame_names()
120
+ ]
121
+
122
+ # Lower the number of frames for models with many frames.
123
+ if model.name().lower() == "ergocub":
124
+ assert any(["sole" in name for name in frame_names])
125
+ frame_names = [name for name in frame_names if "sole" in name]
126
+
127
+ # Get indices of frames.
128
+ frame_indices = tuple(
129
+ frame.index
130
+ for frame in model.description.get().frames
131
+ if frame.index is not None and frame.name in frame_names
132
+ )
133
+
134
+ # =====
135
+ # Tests
136
+ # =====
137
+
138
+ assert len(frame_indices) == len(frame_names)
139
+
140
+ for frame_name, frame_idx in zip(frame_names, frame_indices):
141
+
142
+ J_WL_js = js.frame.jacobian(model=model, data=data, frame_index=frame_idx)
143
+ J_WL_idt = kin_dyn.jacobian_frame(frame_name=frame_name)
144
+ assert J_WL_js == pytest.approx(J_WL_idt, abs=1e-9)
@@ -16,6 +16,7 @@ def test_joint_index(
16
16
 
17
17
  for idx, joint_name in enumerate(model.joint_names()):
18
18
  assert js.joint.name_to_idx(model=model, joint_name=joint_name) == idx
19
+ assert js.joint.idx_to_name(model=model, joint_index=idx) == joint_name
19
20
 
20
21
  assert js.joint.names_to_idxs(
21
22
  model=model, joint_names=model.joint_names()
@@ -20,6 +20,7 @@ def test_link_index(
20
20
 
21
21
  for idx, link_name in enumerate(model.link_names()):
22
22
  assert js.link.name_to_idx(model=model, link_name=link_name) == idx
23
+ assert js.link.idx_to_name(model=model, link_index=idx) == link_name
23
24
 
24
25
  assert js.link.names_to_idxs(
25
26
  model=model, link_names=model.link_names()
@@ -2,6 +2,7 @@ import io
2
2
  from contextlib import redirect_stdout
3
3
 
4
4
  import jax
5
+ import pytest
5
6
  import rod.builder.primitives
6
7
  import rod.urdf.exporter
7
8
 
@@ -9,6 +10,7 @@ import jaxsim.api as js
9
10
 
10
11
 
11
12
  # https://github.com/ami-iit/jaxsim/issues/103
13
+ @pytest.mark.xfail(strict=True)
12
14
  def test_call_jit_compiled_function_passing_different_objects():
13
15
 
14
16
  # Create on-the-fly a ROD model of a box.
@@ -23,8 +25,8 @@ def test_call_jit_compiled_function_passing_different_objects():
23
25
  )
24
26
 
25
27
  # Export the URDF string.
26
- urdf_string = rod.urdf.exporter.UrdfExporter.sdf_to_urdf_string(
27
- sdf=rod_model, pretty=True
28
+ urdf_string = rod.urdf.exporter.UrdfExporter(pretty=True).to_urdf_string(
29
+ sdf=rod_model
28
30
  )
29
31
 
30
32
  model1 = js.model.JaxSimModel.build_from_model_description(
@@ -348,6 +348,13 @@ class KinDynComputations:
348
348
 
349
349
  return H
350
350
 
351
+ def frame_parent_link_name(self, frame_name: str) -> str:
352
+ return self.kin_dyn.model().getLinkName(
353
+ self.kin_dyn.model().getFrameLink(
354
+ self.kin_dyn.model().getFrameIndex(frame_name)
355
+ )
356
+ )
357
+
351
358
  def base_velocity(self) -> npt.NDArray:
352
359
 
353
360
  nu = idt.VectorDynSize()
@@ -1,3 +0,0 @@
1
- from . import common # isort:skip
2
- from . import model, data # isort:skip
3
- from . import com, contact, joint, kin_dyn_parameters, link, ode, ode_data, references
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes