rod 0.3.4__tar.gz → 0.3.4.dev2__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.
- {rod-0.3.4 → rod-0.3.4.dev2}/.github/workflows/ci_cd.yml +2 -2
- rod-0.3.4.dev2/.github/workflows/style.yml +53 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/LICENSE +1 -1
- {rod-0.3.4 → rod-0.3.4.dev2}/PKG-INFO +22 -56
- {rod-0.3.4 → rod-0.3.4.dev2}/README.md +3 -15
- rod-0.3.4.dev2/pyproject.toml +20 -0
- rod-0.3.4.dev2/setup.cfg +89 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/builder/primitive_builder.py +5 -6
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/builder/primitives.py +26 -46
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/kinematics/kinematic_tree.py +1 -1
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/kinematics/tree_transforms.py +1 -3
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/pretty_printer.py +1 -1
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/sdf/geometry.py +1 -3
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/sdf/joint.py +11 -10
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/sdf/link.py +0 -41
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/sdf/physics.py +2 -1
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/sdf/sdf.py +26 -19
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/sdf/visual.py +2 -1
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/tree/directed_tree.py +3 -3
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/urdf/exporter.py +2 -2
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/utils/frame_convention.py +4 -2
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/utils/gazebo.py +2 -1
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod.egg-info/PKG-INFO +22 -56
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod.egg-info/SOURCES.txt +3 -2
- rod-0.3.4.dev2/src/rod.egg-info/not-zip-safe +1 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod.egg-info/requires.txt +11 -5
- {rod-0.3.4 → rod-0.3.4.dev2}/tests/test_meshbuilder.py +2 -10
- {rod-0.3.4 → rod-0.3.4.dev2}/tests/test_urdf_parsing.py +0 -22
- rod-0.3.4/.github/CODEOWNERS +0 -1
- rod-0.3.4/.pre-commit-config.yaml +0 -34
- rod-0.3.4/pyproject.toml +0 -166
- rod-0.3.4/setup.cfg +0 -4
- {rod-0.3.4 → rod-0.3.4.dev2}/.gitignore +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/setup.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/__init__.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/builder/__init__.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/kinematics/__init__.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/logging.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/sdf/__init__.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/sdf/collision.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/sdf/common.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/sdf/element.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/sdf/material.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/sdf/model.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/sdf/scene.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/sdf/world.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/tree/__init__.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/tree/tree_elements.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/urdf/__init__.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/utils/__init__.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/utils/resolve_frames.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod/utils/resolve_uris.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod.egg-info/dependency_links.txt +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/src/rod.egg-info/top_level.txt +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/tests/test_urdf_exporter.py +0 -0
- {rod-0.3.4 → rod-0.3.4.dev2}/tests/utils_models.py +0 -0
|
@@ -165,8 +165,6 @@ jobs:
|
|
|
165
165
|
name: Publish to PyPI
|
|
166
166
|
needs: test
|
|
167
167
|
runs-on: ubuntu-latest
|
|
168
|
-
permissions:
|
|
169
|
-
id-token: write
|
|
170
168
|
|
|
171
169
|
steps:
|
|
172
170
|
|
|
@@ -186,4 +184,6 @@ jobs:
|
|
|
186
184
|
(github.event_name == 'release' && github.event.action == 'published'))
|
|
187
185
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
188
186
|
with:
|
|
187
|
+
user: __token__
|
|
188
|
+
password: ${{ secrets.PYPI_TOKEN }}
|
|
189
189
|
skip_existing: true
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: Code Style
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ "**" ]
|
|
6
|
+
tags-ignore: [ "**" ]
|
|
7
|
+
pull_request:
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
|
|
12
|
+
black:
|
|
13
|
+
|
|
14
|
+
name: black
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
|
|
19
|
+
- name: "🔀 Checkout repository"
|
|
20
|
+
uses: actions/checkout@v2
|
|
21
|
+
|
|
22
|
+
- name: '🐍 Initialize Python'
|
|
23
|
+
uses: actions/setup-python@v2
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.10"
|
|
26
|
+
|
|
27
|
+
- name: "📝 Black Code Formatter"
|
|
28
|
+
uses: psf/black@stable
|
|
29
|
+
with:
|
|
30
|
+
options: --check --diff --color
|
|
31
|
+
|
|
32
|
+
isort:
|
|
33
|
+
|
|
34
|
+
name: isort
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
|
|
37
|
+
steps:
|
|
38
|
+
|
|
39
|
+
- name: "🔀 Checkout repository"
|
|
40
|
+
uses: actions/checkout@v2
|
|
41
|
+
|
|
42
|
+
- name: '🐍 Initialize Python'
|
|
43
|
+
uses: actions/setup-python@v2
|
|
44
|
+
with:
|
|
45
|
+
python-version: "3.10"
|
|
46
|
+
|
|
47
|
+
# Workaround for https://github.com/isort/isort-action/issues/70
|
|
48
|
+
- run: pip install colorama
|
|
49
|
+
|
|
50
|
+
- name: "📝 isort"
|
|
51
|
+
uses: isort/isort-action@master
|
|
52
|
+
with:
|
|
53
|
+
configuration: --check --diff --color
|
|
@@ -1,43 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: rod
|
|
3
|
-
Version: 0.3.4
|
|
3
|
+
Version: 0.3.4.dev2
|
|
4
4
|
Summary: The ultimate Python tool for RObot Descriptions processing.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Copyright (c) 2022, Artificial and Mechanical Intelligence
|
|
10
|
-
All rights reserved.
|
|
11
|
-
|
|
12
|
-
Redistribution and use in source and binary forms, with or without
|
|
13
|
-
modification, are permitted provided that the following conditions are met:
|
|
14
|
-
|
|
15
|
-
1. Redistributions of source code must retain the above copyright notice, this
|
|
16
|
-
list of conditions and the following disclaimer.
|
|
17
|
-
|
|
18
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
19
|
-
this list of conditions and the following disclaimer in the documentation
|
|
20
|
-
and/or other materials provided with the distribution.
|
|
21
|
-
|
|
22
|
-
3. Neither the name of the copyright holder nor the names of its
|
|
23
|
-
contributors may be used to endorse or promote products derived from
|
|
24
|
-
this software without specific prior written permission.
|
|
25
|
-
|
|
26
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
27
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
28
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
29
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
30
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
31
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
32
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
33
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
34
|
-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
35
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
36
|
-
|
|
5
|
+
Home-page: https://github.com/ami-iit/rod
|
|
6
|
+
Author: Diego Ferigo
|
|
7
|
+
Author-email: diego.ferigo@iit.it
|
|
8
|
+
License: BSD
|
|
37
9
|
Project-URL: Changelog, https://github.com/ami-iit/rod/releases
|
|
38
10
|
Project-URL: Source, https://github.com/ami-iit/rod
|
|
39
11
|
Project-URL: Tracker, https://github.com/ami-iit/rod/issues
|
|
40
12
|
Keywords: description,gazebo,parser,robot,robotics,ros,sdf,sdformat,simulator,simulation,urdf
|
|
13
|
+
Platform: any
|
|
41
14
|
Classifier: Development Status :: 5 - Production/Stable
|
|
42
15
|
Classifier: Framework :: Robot Framework
|
|
43
16
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -52,7 +25,6 @@ Classifier: Programming Language :: Python :: 3
|
|
|
52
25
|
Classifier: Programming Language :: Python :: 3.10
|
|
53
26
|
Classifier: Programming Language :: Python :: 3.11
|
|
54
27
|
Classifier: Programming Language :: Python :: 3.12
|
|
55
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
56
28
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
57
29
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
58
30
|
Classifier: Topic :: Games/Entertainment :: Simulation
|
|
@@ -68,17 +40,23 @@ Requires-Dist: scipy
|
|
|
68
40
|
Requires-Dist: trimesh
|
|
69
41
|
Requires-Dist: xmltodict
|
|
70
42
|
Provides-Extra: style
|
|
71
|
-
Requires-Dist: black
|
|
43
|
+
Requires-Dist: black; extra == "style"
|
|
72
44
|
Requires-Dist: isort; extra == "style"
|
|
73
45
|
Provides-Extra: pptree
|
|
74
46
|
Requires-Dist: pptree; extra == "pptree"
|
|
75
|
-
Provides-Extra:
|
|
76
|
-
Requires-Dist: idyntree
|
|
77
|
-
Requires-Dist: pytest
|
|
78
|
-
Requires-Dist: pytest-icdiff; extra == "
|
|
79
|
-
Requires-Dist: robot-descriptions; extra == "
|
|
47
|
+
Provides-Extra: test
|
|
48
|
+
Requires-Dist: idyntree; extra == "test"
|
|
49
|
+
Requires-Dist: pytest; extra == "test"
|
|
50
|
+
Requires-Dist: pytest-icdiff; extra == "test"
|
|
51
|
+
Requires-Dist: robot-descriptions; extra == "test"
|
|
80
52
|
Provides-Extra: all
|
|
81
|
-
Requires-Dist:
|
|
53
|
+
Requires-Dist: black; extra == "all"
|
|
54
|
+
Requires-Dist: isort; extra == "all"
|
|
55
|
+
Requires-Dist: pptree; extra == "all"
|
|
56
|
+
Requires-Dist: idyntree; extra == "all"
|
|
57
|
+
Requires-Dist: pytest; extra == "all"
|
|
58
|
+
Requires-Dist: pytest-icdiff; extra == "all"
|
|
59
|
+
Requires-Dist: robot-descriptions; extra == "all"
|
|
82
60
|
|
|
83
61
|
# RObot Description processor
|
|
84
62
|
|
|
@@ -144,7 +122,7 @@ Installing ROD using `conda` is the recommended way to obtain a complete install
|
|
|
144
122
|
conda install rod -c conda-forge
|
|
145
123
|
```
|
|
146
124
|
|
|
147
|
-
This will automatically install `sdformat` and `gz-tools`.
|
|
125
|
+
This will automatically install `sdformat` and `gz-tools`.
|
|
148
126
|
|
|
149
127
|
</details>
|
|
150
128
|
|
|
@@ -324,28 +302,16 @@ print(urdf_string)
|
|
|
324
302
|
|
|
325
303
|
## Contributing
|
|
326
304
|
|
|
327
|
-
Pull requests are welcome.
|
|
305
|
+
Pull requests are welcome.
|
|
328
306
|
For major changes, please open an issue first to discuss what you would like to change.
|
|
329
307
|
|
|
330
|
-
##
|
|
331
|
-
|
|
332
|
-
### Author
|
|
308
|
+
## Maintainers
|
|
333
309
|
|
|
334
310
|
| [<img src="https://github.com/diegoferigo.png" width="40">][df] | [@diegoferigo][df] |
|
|
335
311
|
|:---------------------------------------------------------------:|:------------------:|
|
|
336
312
|
|
|
337
313
|
[df]: https://github.com/diegoferigo
|
|
338
314
|
|
|
339
|
-
### Maintainers
|
|
340
|
-
|
|
341
|
-
| [<img src="https://github.com/flferretti.png" width="40">][ff] | [@flferretti][ff] | [<img src="https://github.com/CarlottaSartore.png" width="40">][cs] | [@CarlottaSartore][cs] |
|
|
342
|
-
|:---------------------------------------------------------------:|:------------------:|:---------------------------------------------------------------:|:------------------:|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
[ff]: https://github.com/flferretti
|
|
347
|
-
[cs]: https://github.com/CarlottaSartore
|
|
348
|
-
|
|
349
315
|
## License
|
|
350
316
|
|
|
351
317
|
[BSD3](https://choosealicense.com/licenses/bsd-3-clause/)
|
|
@@ -62,7 +62,7 @@ Installing ROD using `conda` is the recommended way to obtain a complete install
|
|
|
62
62
|
conda install rod -c conda-forge
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
This will automatically install `sdformat` and `gz-tools`.
|
|
65
|
+
This will automatically install `sdformat` and `gz-tools`.
|
|
66
66
|
|
|
67
67
|
</details>
|
|
68
68
|
|
|
@@ -242,28 +242,16 @@ print(urdf_string)
|
|
|
242
242
|
|
|
243
243
|
## Contributing
|
|
244
244
|
|
|
245
|
-
Pull requests are welcome.
|
|
245
|
+
Pull requests are welcome.
|
|
246
246
|
For major changes, please open an issue first to discuss what you would like to change.
|
|
247
247
|
|
|
248
|
-
##
|
|
249
|
-
|
|
250
|
-
### Author
|
|
248
|
+
## Maintainers
|
|
251
249
|
|
|
252
250
|
| [<img src="https://github.com/diegoferigo.png" width="40">][df] | [@diegoferigo][df] |
|
|
253
251
|
|:---------------------------------------------------------------:|:------------------:|
|
|
254
252
|
|
|
255
253
|
[df]: https://github.com/diegoferigo
|
|
256
254
|
|
|
257
|
-
### Maintainers
|
|
258
|
-
|
|
259
|
-
| [<img src="https://github.com/flferretti.png" width="40">][ff] | [@flferretti][ff] | [<img src="https://github.com/CarlottaSartore.png" width="40">][cs] | [@CarlottaSartore][cs] |
|
|
260
|
-
|:---------------------------------------------------------------:|:------------------:|:---------------------------------------------------------------:|:------------------:|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
[ff]: https://github.com/flferretti
|
|
265
|
-
[cs]: https://github.com/CarlottaSartore
|
|
266
|
-
|
|
267
255
|
## License
|
|
268
256
|
|
|
269
257
|
[BSD3](https://choosealicense.com/licenses/bsd-3-clause/)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"wheel",
|
|
4
|
+
"setuptools>=45",
|
|
5
|
+
"setuptools_scm[toml]>=6.2",
|
|
6
|
+
]
|
|
7
|
+
build-backend = "setuptools.build_meta"
|
|
8
|
+
|
|
9
|
+
[tool.setuptools_scm]
|
|
10
|
+
local_scheme = "dirty-tag"
|
|
11
|
+
|
|
12
|
+
[tool.black]
|
|
13
|
+
line-length = 88
|
|
14
|
+
|
|
15
|
+
[tool.isort]
|
|
16
|
+
profile = "black"
|
|
17
|
+
multi_line_output = 3
|
|
18
|
+
|
|
19
|
+
[tool.cibuildwheel]
|
|
20
|
+
build-frontend = "build"
|
rod-0.3.4.dev2/setup.cfg
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
[metadata]
|
|
2
|
+
name = rod
|
|
3
|
+
description = The ultimate Python tool for RObot Descriptions processing.
|
|
4
|
+
long_description = file: README.md
|
|
5
|
+
long_description_content_type = text/markdown
|
|
6
|
+
author = Diego Ferigo
|
|
7
|
+
author_email = diego.ferigo@iit.it
|
|
8
|
+
license = BSD
|
|
9
|
+
license_files = LICENSE
|
|
10
|
+
platforms = any
|
|
11
|
+
url = https://github.com/ami-iit/rod
|
|
12
|
+
project_urls =
|
|
13
|
+
Changelog = https://github.com/ami-iit/rod/releases
|
|
14
|
+
Source = https://github.com/ami-iit/rod
|
|
15
|
+
Tracker = https://github.com/ami-iit/rod/issues
|
|
16
|
+
keywords =
|
|
17
|
+
description
|
|
18
|
+
gazebo
|
|
19
|
+
parser
|
|
20
|
+
robot
|
|
21
|
+
robotics
|
|
22
|
+
ros
|
|
23
|
+
sdf
|
|
24
|
+
sdformat
|
|
25
|
+
simulator
|
|
26
|
+
simulation
|
|
27
|
+
urdf
|
|
28
|
+
classifiers =
|
|
29
|
+
Development Status :: 5 - Production/Stable
|
|
30
|
+
Framework :: Robot Framework
|
|
31
|
+
Intended Audience :: Science/Research
|
|
32
|
+
Intended Audience :: Developers
|
|
33
|
+
Intended Audience :: Education
|
|
34
|
+
License :: OSI Approved :: BSD License
|
|
35
|
+
Operating System :: OS Independent
|
|
36
|
+
Operating System :: POSIX :: Linux
|
|
37
|
+
Operating System :: MacOS
|
|
38
|
+
Operating System :: Microsoft :: Windows
|
|
39
|
+
Programming Language :: Python :: 3
|
|
40
|
+
Programming Language :: Python :: 3.10
|
|
41
|
+
Programming Language :: Python :: 3.11
|
|
42
|
+
Programming Language :: Python :: 3.12
|
|
43
|
+
Programming Language :: Python :: 3 :: Only
|
|
44
|
+
Programming Language :: Python :: Implementation :: CPython
|
|
45
|
+
Topic :: Games/Entertainment :: Simulation
|
|
46
|
+
|
|
47
|
+
[options]
|
|
48
|
+
zip_safe = False
|
|
49
|
+
packages = find:
|
|
50
|
+
package_dir =
|
|
51
|
+
=src
|
|
52
|
+
python_requires = >=3.10
|
|
53
|
+
install_requires =
|
|
54
|
+
coloredlogs
|
|
55
|
+
mashumaro
|
|
56
|
+
numpy
|
|
57
|
+
packaging
|
|
58
|
+
resolve-robotics-uri-py
|
|
59
|
+
scipy
|
|
60
|
+
trimesh
|
|
61
|
+
xmltodict
|
|
62
|
+
|
|
63
|
+
[options.extras_require]
|
|
64
|
+
style =
|
|
65
|
+
black
|
|
66
|
+
isort
|
|
67
|
+
pptree =
|
|
68
|
+
pptree
|
|
69
|
+
test =
|
|
70
|
+
idyntree
|
|
71
|
+
pytest
|
|
72
|
+
pytest-icdiff
|
|
73
|
+
robot-descriptions
|
|
74
|
+
all =
|
|
75
|
+
%(style)s
|
|
76
|
+
%(pptree)s
|
|
77
|
+
%(test)s
|
|
78
|
+
|
|
79
|
+
[options.packages.find]
|
|
80
|
+
where = src
|
|
81
|
+
|
|
82
|
+
[tool:pytest]
|
|
83
|
+
addopts = -rsxX -v --strict-markers
|
|
84
|
+
testpaths = tests
|
|
85
|
+
|
|
86
|
+
[egg_info]
|
|
87
|
+
tag_build =
|
|
88
|
+
tag_date = 0
|
|
89
|
+
|
|
@@ -12,9 +12,8 @@ from rod import logging
|
|
|
12
12
|
|
|
13
13
|
@dataclasses.dataclass
|
|
14
14
|
class PrimitiveBuilder(abc.ABC):
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
mass: float = dataclasses.field(kw_only=True)
|
|
15
|
+
name: str
|
|
16
|
+
mass: float
|
|
18
17
|
|
|
19
18
|
element: rod.Model | rod.Link | rod.Inertial | rod.Collision | rod.Visual = (
|
|
20
19
|
dataclasses.field(
|
|
@@ -121,7 +120,7 @@ class PrimitiveBuilder(abc.ABC):
|
|
|
121
120
|
pose: rod.Pose | None = None,
|
|
122
121
|
inertial: rod.Inertial | None = None,
|
|
123
122
|
) -> PrimitiveBuilder:
|
|
124
|
-
if not isinstance(self.element, rod.Model
|
|
123
|
+
if not isinstance(self.element, (rod.Model, rod.Link)):
|
|
125
124
|
raise ValueError(type(self.element))
|
|
126
125
|
|
|
127
126
|
if isinstance(self.element, rod.Model):
|
|
@@ -151,7 +150,7 @@ class PrimitiveBuilder(abc.ABC):
|
|
|
151
150
|
pose: rod.Pose | None = None,
|
|
152
151
|
visual: rod.Visual | None = None,
|
|
153
152
|
) -> PrimitiveBuilder:
|
|
154
|
-
if not isinstance(self.element, rod.Model
|
|
153
|
+
if not isinstance(self.element, (rod.Model, rod.Link)):
|
|
155
154
|
raise ValueError(type(self.element))
|
|
156
155
|
|
|
157
156
|
if isinstance(self.element, rod.Model):
|
|
@@ -187,7 +186,7 @@ class PrimitiveBuilder(abc.ABC):
|
|
|
187
186
|
pose: rod.Pose | None = None,
|
|
188
187
|
collision: rod.Collision | None = None,
|
|
189
188
|
) -> PrimitiveBuilder:
|
|
190
|
-
if not isinstance(self.element, rod.Model
|
|
189
|
+
if not isinstance(self.element, (rod.Model, rod.Link)):
|
|
191
190
|
raise ValueError(type(self.element))
|
|
192
191
|
|
|
193
192
|
if isinstance(self.element, rod.Model):
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import dataclasses
|
|
2
2
|
import pathlib
|
|
3
3
|
|
|
4
|
-
import numpy as np
|
|
5
|
-
import numpy.typing as npt
|
|
6
|
-
import resolve_robotics_uri_py
|
|
7
4
|
import trimesh
|
|
5
|
+
from numpy.typing import NDArray
|
|
8
6
|
|
|
9
7
|
import rod
|
|
10
|
-
from rod import logging
|
|
11
8
|
from rod.builder.primitive_builder import PrimitiveBuilder
|
|
12
9
|
|
|
13
10
|
|
|
@@ -65,13 +62,8 @@ class CylinderBuilder(PrimitiveBuilder):
|
|
|
65
62
|
|
|
66
63
|
@dataclasses.dataclass
|
|
67
64
|
class MeshBuilder(PrimitiveBuilder):
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
scale: npt.NDArray = dataclasses.field(default_factory=lambda: np.ones(3))
|
|
72
|
-
|
|
73
|
-
mass: float | None = dataclasses.field(default=None, kw_only=True)
|
|
74
|
-
inertia_tensor: npt.NDArray | None = dataclasses.field(default=None, kw_only=True)
|
|
65
|
+
mesh_path: str | pathlib.Path
|
|
66
|
+
scale: NDArray
|
|
75
67
|
|
|
76
68
|
def __post_init__(self) -> None:
|
|
77
69
|
"""
|
|
@@ -82,46 +74,34 @@ class MeshBuilder(PrimitiveBuilder):
|
|
|
82
74
|
AssertionError: If the scale is not a 3D vector.
|
|
83
75
|
TypeError: If the mesh_path is not a str or pathlib.Path.
|
|
84
76
|
"""
|
|
85
|
-
# Adjust the shape of the scale.
|
|
86
|
-
self.scale = self.scale.squeeze()
|
|
87
|
-
|
|
88
|
-
if self.scale.shape != (3,):
|
|
89
|
-
raise RuntimeError(f"Scale must be a 3D vector, got '{self.scale.shape}'")
|
|
90
|
-
|
|
91
|
-
# Resolve the mesh URI.
|
|
92
|
-
mesh_path = resolve_robotics_uri_py.resolve_robotics_uri(uri=str(self.mesh_uri))
|
|
93
|
-
|
|
94
|
-
# Build the trimesh object from the mesh path.
|
|
95
|
-
self.mesh: trimesh.base.Trimesh = trimesh.load_mesh(file_obj=mesh_path)
|
|
96
|
-
|
|
97
|
-
# Populate the mass from the mesh if it was not provided externally.
|
|
98
|
-
if self.mass is None:
|
|
99
|
-
|
|
100
|
-
if self.mesh.is_watertight:
|
|
101
|
-
self.mass = self.mesh.mass
|
|
102
77
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
78
|
+
mesh_path = (
|
|
79
|
+
self.mesh_path
|
|
80
|
+
if isinstance(self.mesh_path, pathlib.Path)
|
|
81
|
+
else pathlib.Path(self.mesh_path)
|
|
82
|
+
)
|
|
107
83
|
|
|
108
|
-
|
|
109
|
-
|
|
84
|
+
if not mesh_path.is_file():
|
|
85
|
+
raise FileNotFoundError(f"Mesh file not found at {self.mesh_path}")
|
|
110
86
|
|
|
111
|
-
|
|
112
|
-
|
|
87
|
+
self.mesh: trimesh.base.Trimesh = trimesh.load_mesh(
|
|
88
|
+
file_obj=mesh_path,
|
|
89
|
+
)
|
|
113
90
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
self.inertia_tensor = np.eye(3)
|
|
91
|
+
assert self.scale.shape == (
|
|
92
|
+
3,
|
|
93
|
+
), f"Scale must be a 3D vector, got {self.scale.shape}"
|
|
118
94
|
|
|
119
95
|
def _inertia(self) -> rod.Inertia:
|
|
120
|
-
|
|
121
|
-
return rod.Inertia
|
|
96
|
+
inertia = self.mesh.moment_inertia
|
|
97
|
+
return rod.Inertia(
|
|
98
|
+
ixx=inertia[0, 0],
|
|
99
|
+
ixy=inertia[0, 1],
|
|
100
|
+
ixz=inertia[0, 2],
|
|
101
|
+
iyy=inertia[1, 1],
|
|
102
|
+
iyz=inertia[1, 2],
|
|
103
|
+
izz=inertia[2, 2],
|
|
104
|
+
)
|
|
122
105
|
|
|
123
106
|
def _geometry(self) -> rod.Geometry:
|
|
124
|
-
|
|
125
|
-
return rod.Geometry(
|
|
126
|
-
mesh=rod.Mesh(uri=str(self.mesh_uri), scale=self.scale.tolist())
|
|
127
|
-
)
|
|
107
|
+
return rod.Geometry(mesh=rod.Mesh(uri=str(self.mesh_path), scale=self.scale))
|
|
@@ -13,9 +13,7 @@ from rod.tree import TreeFrame
|
|
|
13
13
|
|
|
14
14
|
@dataclasses.dataclass
|
|
15
15
|
class TreeTransforms:
|
|
16
|
-
kinematic_tree: KinematicTree = dataclasses.
|
|
17
|
-
default_factory=dataclasses.dataclass(init=False)
|
|
18
|
-
)
|
|
16
|
+
kinematic_tree: KinematicTree = dataclasses.dataclass(init=False)
|
|
19
17
|
_transform_cache: dict[str, npt.NDArray] = dataclasses.field(default_factory=dict)
|
|
20
18
|
|
|
21
19
|
@staticmethod
|
|
@@ -13,7 +13,7 @@ class DataclassPrettyPrinter(abc.ABC):
|
|
|
13
13
|
if not isinstance(obj, list):
|
|
14
14
|
raise TypeError(obj, type(obj))
|
|
15
15
|
|
|
16
|
-
if all(isinstance(el, numbers.Number
|
|
16
|
+
if all(isinstance(el, (numbers.Number, str)) for el in obj):
|
|
17
17
|
return str(obj)
|
|
18
18
|
|
|
19
19
|
spacing = " " * 4
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import dataclasses
|
|
2
|
+
from typing import Optional
|
|
2
3
|
|
|
3
4
|
import mashumaro
|
|
4
5
|
|
|
@@ -9,32 +10,32 @@ from .element import Element
|
|
|
9
10
|
@dataclasses.dataclass
|
|
10
11
|
class Limit(Element):
|
|
11
12
|
|
|
12
|
-
lower: float
|
|
13
|
+
lower: Optional[float] = dataclasses.field(
|
|
13
14
|
default=None,
|
|
14
15
|
metadata=mashumaro.field_options(serialize=Element.serialize_float),
|
|
15
16
|
)
|
|
16
17
|
|
|
17
|
-
upper: float
|
|
18
|
+
upper: Optional[float] = dataclasses.field(
|
|
18
19
|
default=None,
|
|
19
20
|
metadata=mashumaro.field_options(serialize=Element.serialize_float),
|
|
20
21
|
)
|
|
21
22
|
|
|
22
|
-
effort: float
|
|
23
|
+
effort: Optional[float] = dataclasses.field(
|
|
23
24
|
default=None,
|
|
24
25
|
metadata=mashumaro.field_options(serialize=Element.serialize_float),
|
|
25
26
|
)
|
|
26
27
|
|
|
27
|
-
velocity: float
|
|
28
|
+
velocity: Optional[float] = dataclasses.field(
|
|
28
29
|
default=None,
|
|
29
30
|
metadata=mashumaro.field_options(serialize=Element.serialize_float),
|
|
30
31
|
)
|
|
31
32
|
|
|
32
|
-
stiffness: float
|
|
33
|
+
stiffness: Optional[float] = dataclasses.field(
|
|
33
34
|
default=None,
|
|
34
35
|
metadata=mashumaro.field_options(serialize=Element.serialize_float),
|
|
35
36
|
)
|
|
36
37
|
|
|
37
|
-
dissipation: float
|
|
38
|
+
dissipation: Optional[float] = dataclasses.field(
|
|
38
39
|
default=None,
|
|
39
40
|
metadata=mashumaro.field_options(serialize=Element.serialize_float),
|
|
40
41
|
)
|
|
@@ -50,12 +51,12 @@ class Dynamics(Element):
|
|
|
50
51
|
metadata=mashumaro.field_options(serialize=Element.serialize_float),
|
|
51
52
|
)
|
|
52
53
|
|
|
53
|
-
damping: float
|
|
54
|
+
damping: Optional[float] = dataclasses.field(
|
|
54
55
|
default=None,
|
|
55
56
|
metadata=mashumaro.field_options(serialize=Element.serialize_float),
|
|
56
57
|
)
|
|
57
58
|
|
|
58
|
-
friction: float
|
|
59
|
+
friction: Optional[float] = dataclasses.field(
|
|
59
60
|
default=None,
|
|
60
61
|
metadata=mashumaro.field_options(serialize=Element.serialize_float),
|
|
61
62
|
)
|
|
@@ -65,7 +66,7 @@ class Dynamics(Element):
|
|
|
65
66
|
class Axis(Element):
|
|
66
67
|
xyz: Xyz
|
|
67
68
|
limit: Limit
|
|
68
|
-
dynamics: Dynamics
|
|
69
|
+
dynamics: Optional[Dynamics] = dataclasses.field(default=None)
|
|
69
70
|
|
|
70
71
|
|
|
71
72
|
@dataclasses.dataclass
|
|
@@ -77,4 +78,4 @@ class Joint(Element):
|
|
|
77
78
|
child: str
|
|
78
79
|
|
|
79
80
|
pose: Pose | None = dataclasses.field(default=None)
|
|
80
|
-
axis: Axis
|
|
81
|
+
axis: Optional[Axis] = dataclasses.field(default=None)
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
1
|
import dataclasses
|
|
4
2
|
|
|
5
3
|
import mashumaro
|
|
6
4
|
import numpy as np
|
|
7
5
|
import numpy.typing as npt
|
|
8
6
|
|
|
9
|
-
from rod import logging
|
|
10
|
-
|
|
11
7
|
from .collision import Collision
|
|
12
8
|
from .common import Pose
|
|
13
9
|
from .element import Element
|
|
@@ -16,7 +12,6 @@ from .visual import Visual
|
|
|
16
12
|
|
|
17
13
|
@dataclasses.dataclass
|
|
18
14
|
class Inertia(Element):
|
|
19
|
-
|
|
20
15
|
ixx: float = dataclasses.field(
|
|
21
16
|
default=1.0,
|
|
22
17
|
metadata=mashumaro.field_options(serialize=Element.serialize_float),
|
|
@@ -47,42 +42,6 @@ class Inertia(Element):
|
|
|
47
42
|
metadata=mashumaro.field_options(serialize=Element.serialize_float),
|
|
48
43
|
)
|
|
49
44
|
|
|
50
|
-
@staticmethod
|
|
51
|
-
def from_inertia_tensor(
|
|
52
|
-
inertia_tensor: npt.NDArray, validate: bool = True
|
|
53
|
-
) -> Inertia:
|
|
54
|
-
|
|
55
|
-
inertia_tensor = inertia_tensor.squeeze()
|
|
56
|
-
|
|
57
|
-
if inertia_tensor.shape != (3, 3):
|
|
58
|
-
raise ValueError(f"Expected shape (3, 3), got {inertia_tensor.shape}")
|
|
59
|
-
|
|
60
|
-
# Extract the diagonal terms.
|
|
61
|
-
I1, I2, I3 = np.diag(inertia_tensor)
|
|
62
|
-
|
|
63
|
-
# Check if the inertia tensor meets the triangular inequality.
|
|
64
|
-
valid = True
|
|
65
|
-
valid = valid and I1 + I2 >= I3
|
|
66
|
-
valid = valid and I1 + I3 >= I2
|
|
67
|
-
valid = valid and I2 + I3 >= I1
|
|
68
|
-
|
|
69
|
-
if not valid:
|
|
70
|
-
msg = "Inertia tensor does not meet the triangular inequality"
|
|
71
|
-
|
|
72
|
-
if not validate:
|
|
73
|
-
logging.warning(msg)
|
|
74
|
-
else:
|
|
75
|
-
raise ValueError(msg)
|
|
76
|
-
|
|
77
|
-
return Inertia(
|
|
78
|
-
ixx=float(inertia_tensor[0, 0]),
|
|
79
|
-
ixy=float(inertia_tensor[0, 1]),
|
|
80
|
-
ixz=float(inertia_tensor[0, 2]),
|
|
81
|
-
iyy=float(inertia_tensor[1, 1]),
|
|
82
|
-
iyz=float(inertia_tensor[1, 2]),
|
|
83
|
-
izz=float(inertia_tensor[2, 2]),
|
|
84
|
-
)
|
|
85
|
-
|
|
86
45
|
def matrix(self) -> npt.NDArray:
|
|
87
46
|
return np.array(
|
|
88
47
|
[
|