rod 0.2.1.dev33__tar.gz → 0.2.1.dev45__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 (52) hide show
  1. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/.github/workflows/ci_cd.yml +18 -17
  2. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/PKG-INFO +53 -24
  3. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/README.md +50 -20
  4. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/setup.cfg +2 -3
  5. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/__init__.py +35 -6
  6. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod.egg-info/PKG-INFO +53 -24
  7. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/tests/test_meshbuilder.py +35 -20
  8. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/.github/workflows/style.yml +0 -0
  9. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/.gitignore +0 -0
  10. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/LICENSE +0 -0
  11. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/pyproject.toml +0 -0
  12. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/setup.py +0 -0
  13. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/builder/__init__.py +0 -0
  14. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/builder/primitive_builder.py +0 -0
  15. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/builder/primitives.py +0 -0
  16. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/kinematics/__init__.py +0 -0
  17. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/kinematics/kinematic_tree.py +0 -0
  18. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/kinematics/tree_transforms.py +0 -0
  19. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/logging.py +0 -0
  20. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/pretty_printer.py +0 -0
  21. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/sdf/__init__.py +0 -0
  22. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/sdf/collision.py +0 -0
  23. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/sdf/common.py +0 -0
  24. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/sdf/element.py +0 -0
  25. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/sdf/geometry.py +0 -0
  26. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/sdf/joint.py +0 -0
  27. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/sdf/link.py +0 -0
  28. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/sdf/material.py +0 -0
  29. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/sdf/model.py +0 -0
  30. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/sdf/physics.py +0 -0
  31. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/sdf/scene.py +0 -0
  32. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/sdf/sdf.py +0 -0
  33. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/sdf/visual.py +0 -0
  34. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/sdf/world.py +0 -0
  35. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/tree/__init__.py +0 -0
  36. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/tree/directed_tree.py +0 -0
  37. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/tree/tree_elements.py +0 -0
  38. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/urdf/__init__.py +0 -0
  39. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/urdf/exporter.py +0 -0
  40. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/utils/__init__.py +0 -0
  41. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/utils/frame_convention.py +0 -0
  42. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/utils/gazebo.py +0 -0
  43. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/utils/resolve_frames.py +0 -0
  44. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod/utils/resolve_uris.py +0 -0
  45. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod.egg-info/SOURCES.txt +0 -0
  46. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod.egg-info/dependency_links.txt +0 -0
  47. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod.egg-info/not-zip-safe +0 -0
  48. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod.egg-info/requires.txt +0 -0
  49. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/src/rod.egg-info/top_level.txt +0 -0
  50. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/tests/test_urdf_exporter.py +0 -0
  51. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/tests/test_urdf_parsing.py +0 -0
  52. {rod-0.2.1.dev33 → rod-0.2.1.dev45}/tests/utils_models.py +0 -0
@@ -20,12 +20,12 @@ jobs:
20
20
 
21
21
  steps:
22
22
 
23
- - uses: actions/checkout@v3
23
+ - uses: actions/checkout@v4
24
24
  with:
25
25
  fetch-depth: 0
26
26
 
27
27
  - name: Set up Python
28
- uses: actions/setup-python@v4
28
+ uses: actions/setup-python@v5
29
29
  with:
30
30
  python-version: "3.*"
31
31
 
@@ -50,7 +50,7 @@ jobs:
50
50
  python -c "import packaging.version as v; v.Version(\"$(python -m setuptools_scm)\")"
51
51
 
52
52
  - name: Upload artifacts
53
- uses: actions/upload-artifact@v3
53
+ uses: actions/upload-artifact@v4
54
54
  with:
55
55
  path: dist/*
56
56
  name: dist
@@ -73,10 +73,9 @@ jobs:
73
73
  - apt
74
74
  - conda
75
75
  python:
76
- - "3.8"
77
- - "3.9"
78
76
  - "3.10"
79
77
  - "3.11"
78
+ - "3.12"
80
79
  exclude:
81
80
  - os: macos-latest
82
81
  type: apt
@@ -87,15 +86,14 @@ jobs:
87
86
 
88
87
  - name: Set up Python
89
88
  if: matrix.type == 'apt'
90
- uses: actions/setup-python@v4
89
+ uses: actions/setup-python@v5
91
90
  with:
92
91
  python-version: ${{ matrix.python }}
93
92
 
94
- - uses: conda-incubator/setup-miniconda@v2
93
+ - uses: conda-incubator/setup-miniconda@v3
95
94
  if: matrix.type == 'conda'
96
95
  with:
97
96
  python-version: ${{ matrix.python }}
98
- miniforge-variant: Mambaforge
99
97
  miniforge-version: latest
100
98
  channels: conda-forge
101
99
  channel-priority: true
@@ -112,14 +110,16 @@ jobs:
112
110
 
113
111
  - name: Install conda dependencies
114
112
  if: matrix.type == 'conda'
113
+ # Note: pytest-icdiff creates problems on macOS.
115
114
  run: |
116
- mamba install -y \
115
+ conda install -y \
117
116
  coloredlogs \
118
117
  mashumaro \
119
118
  numpy \
120
119
  packaging \
121
120
  resolve-robotics-uri-py \
122
121
  scipy \
122
+ trimesh \
123
123
  xmltodict \
124
124
  black \
125
125
  isort \
@@ -127,12 +127,11 @@ jobs:
127
127
  idyntree \
128
128
  pytest \
129
129
  robot_descriptions \
130
- trimesh
131
- # pytest-icdiff \ # creates problems on macOS
132
- mamba install -y gz-sim7 idyntree
130
+ libgz-tools2 \
131
+ libsdformat13
133
132
 
134
133
  - name: Download Python packages
135
- uses: actions/download-artifact@v3
134
+ uses: actions/download-artifact@v4
136
135
  with:
137
136
  path: dist
138
137
  name: dist
@@ -150,13 +149,15 @@ jobs:
150
149
 
151
150
  - name: Import the package
152
151
  run: python -c "import rod"
152
+ env:
153
+ ROD_LOGGING_LEVEL: DEBUG
153
154
 
154
- - uses: actions/checkout@v3
155
- if: matrix.os != 'windows-latest'
155
+ - uses: actions/checkout@v4
156
156
 
157
157
  - name: Run tests
158
- if: matrix.os != 'windows-latest'
159
158
  run: pytest
159
+ env:
160
+ ROD_LOGGING_LEVEL: DEBUG
160
161
 
161
162
  publish:
162
163
  name: Publish to PyPI
@@ -166,7 +167,7 @@ jobs:
166
167
  steps:
167
168
 
168
169
  - name: Download Python packages
169
- uses: actions/download-artifact@v3
170
+ uses: actions/download-artifact@v4
170
171
  with:
171
172
  path: dist
172
173
  name: dist
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: rod
3
- Version: 0.2.1.dev33
3
+ Version: 0.2.1.dev45
4
4
  Summary: The ultimate Python tool for RObot Descriptions processing.
5
5
  Home-page: https://github.com/ami-iit/rod
6
6
  Author: Diego Ferigo
@@ -22,14 +22,13 @@ Classifier: Operating System :: POSIX :: Linux
22
22
  Classifier: Operating System :: MacOS
23
23
  Classifier: Operating System :: Microsoft :: Windows
24
24
  Classifier: Programming Language :: Python :: 3
25
- Classifier: Programming Language :: Python :: 3.8
26
- Classifier: Programming Language :: Python :: 3.9
27
25
  Classifier: Programming Language :: Python :: 3.10
28
26
  Classifier: Programming Language :: Python :: 3.11
27
+ Classifier: Programming Language :: Python :: 3.12
29
28
  Classifier: Programming Language :: Python :: 3 :: Only
30
29
  Classifier: Programming Language :: Python :: Implementation :: CPython
31
30
  Classifier: Topic :: Games/Entertainment :: Simulation
32
- Requires-Python: >=3.8
31
+ Requires-Python: >=3.10
33
32
  Description-Content-Type: text/markdown
34
33
  License-File: LICENSE
35
34
  Requires-Dist: coloredlogs
@@ -82,39 +81,71 @@ Last but not least, the pose semantics also makes SDF aware of the concept of _f
82
81
 
83
82
  ## Features
84
83
 
85
- - Out-of-the-box support of SDFormat specifications [≥ 1.7][sdformat_spec_17]
86
- - Serialization and deserialization support of SDF files
87
- - In-memory layout based on `dataclasses`
88
- - Syntax highlighting and auto-completion
89
- - Support of programmatic creation of SDF files from Python APIs
90
- - Transitive support of URDF through conversion to SDF[^urdf_to_sdf]
91
- - Type validation of elements and attributes
92
- - Automatic check of missing required elements
93
- - Based on [`Fatal1ty/mashumaro`][mashumaro] for great serialization and deserialization performance
94
- - Support of exporting the in-memory model description to URDF
84
+ - Out-of-the-box support for SDFormat specifications [≥ 1.10][sdformat_spec_110].
85
+ - Serialization and deserialization support for SDF files.
86
+ - In-memory layout based on `dataclasses`.
87
+ - Syntax highlighting and auto-completion.
88
+ - Programmatic creation of SDF files from Python APIs.
89
+ - Transitive support for URDF through conversion to SDF.
90
+ - Type validation of elements and attributes.
91
+ - Automatic check of missing required elements.
92
+ - High-performance serialization and deserialization using [`Fatal1ty/mashumaro`][mashumaro].
93
+ - Export in-memory model description to URDF.
95
94
 
96
95
  [mashumaro]: https://github.com/Fatal1ty/mashumaro
97
96
  [open_robotics]: https://www.openrobotics.org/
98
97
  [pose_semantics]: http://sdformat.org/tutorials?tut=pose_frame_semantics_proposal&cat=pose_semantics_docs&
99
98
  [sdformat]: http://sdformat.org/
100
99
  [sdformat_python]: http://sdformat.org/tutorials?tut=python_bindings&cat=developers&
101
- [sdformat_repo]: https://github.com/gazebosim/sdformat
102
100
  [sdformat_spec]: http://sdformat.org/spec
103
- [sdformat_spec_17]: http://sdformat.org/spec?elem=sdf&ver=1.7
101
+ [sdformat_spec_110]: http://sdformat.org/spec?elem=sdf&ver=1.10
104
102
  [urdf]: http://wiki.ros.org/urdf
105
103
 
106
- [^urdf_to_sdf]: Conversion can be done either using `ign sdf` included in Ignition Gazebo Fortress, or `gz sdf` included in Gazebo Sim starting from Garden.
104
+ [^urdf_to_sdf]: Conversion can be done using the `gz sdf` command included in Gazebo Sim starting from Garden.
107
105
 
108
106
  ## Installation
109
107
 
110
- You can install the project with [`pypa/pip`][pip], preferably in a [virtual environment][venv]:
108
+ > [!TIP]
109
+ > ROD does not support out-of-the-box URDF files.
110
+ > URDF support is obtained by converting URDF files to SDF using the `gz sdf` command provided by [sdformat][sdformat_repo] and [gz-tools][gz-tools_repo].
111
+ > Ensure these tools are installed on your system if URDF support is needed (more information below).
112
+
113
+ [sdformat_repo]: https://github.com/gazebosim/sdformat
114
+ [gz-tools_repo]: https://github.com/gazebosim/gz-tools
115
+
116
+ <details>
117
+ <summary>Using conda (recommended)</summary>
118
+
119
+ Installing ROD using `conda` is the recommended way to obtain a complete installation with out-of-the-box support for both URDF and SDF descriptions:
111
120
 
112
121
  ```bash
113
- pip install git+https://github.com/ami-iit/rod
122
+ conda install rod -c conda-forge
114
123
  ```
115
124
 
125
+ This will automatically install `sdformat` and `gz-tools`.
126
+
127
+ </details>
128
+
129
+ <details>
130
+ <summary>Using pip</summary>
131
+
132
+ You can install ROD from PyPI with [`pypa/pip`][pip], preferably in a [virtual environment][venv]:
133
+
134
+ ```bash
135
+ pip install rod[all]
136
+ ```
137
+
138
+ If you need URDF support, follow the [official instructions][gazebo_sim_docs] to install Gazebo Sim on your operating system,
139
+ making sure to obtain `sdformat ≥ 13.0` and `gz-tools ≥ 2.0`.
140
+
141
+ You don't need to install the entire Gazebo Sim suite.
142
+ For example, on Ubuntu, you can only install the `libsdformat13 gz-tools2` packages.
143
+
116
144
  [pip]: https://github.com/pypa/pip/
117
- [venv]: https://docs.python.org/3.8/tutorial/venv.html
145
+ [venv]: https://docs.python.org/3.10/tutorial/venv.html
146
+ [gazebo_sim_docs]: https://gazebosim.org/docs
147
+
148
+ </details>
118
149
 
119
150
  ## Examples
120
151
 
@@ -225,10 +256,8 @@ print(sdf.serialize(pretty=True))
225
256
 
226
257
  from rod.urdf.exporter import UrdfExporter
227
258
 
228
- urdf_string = UrdfExporter.sdf_to_urdf_string(
229
- sdf=sdf,
230
- pretty=True,
231
- gazebo_preserve_fixed_joints=True,
259
+ urdf_string = UrdfExporter(pretty=True, gazebo_preserve_fixed_joints=True).to_urdf_string(
260
+ sdf=sdf
232
261
  )
233
262
 
234
263
  print(urdf_string)
@@ -21,39 +21,71 @@ Last but not least, the pose semantics also makes SDF aware of the concept of _f
21
21
 
22
22
  ## Features
23
23
 
24
- - Out-of-the-box support of SDFormat specifications [≥ 1.7][sdformat_spec_17]
25
- - Serialization and deserialization support of SDF files
26
- - In-memory layout based on `dataclasses`
27
- - Syntax highlighting and auto-completion
28
- - Support of programmatic creation of SDF files from Python APIs
29
- - Transitive support of URDF through conversion to SDF[^urdf_to_sdf]
30
- - Type validation of elements and attributes
31
- - Automatic check of missing required elements
32
- - Based on [`Fatal1ty/mashumaro`][mashumaro] for great serialization and deserialization performance
33
- - Support of exporting the in-memory model description to URDF
24
+ - Out-of-the-box support for SDFormat specifications [≥ 1.10][sdformat_spec_110].
25
+ - Serialization and deserialization support for SDF files.
26
+ - In-memory layout based on `dataclasses`.
27
+ - Syntax highlighting and auto-completion.
28
+ - Programmatic creation of SDF files from Python APIs.
29
+ - Transitive support for URDF through conversion to SDF.
30
+ - Type validation of elements and attributes.
31
+ - Automatic check of missing required elements.
32
+ - High-performance serialization and deserialization using [`Fatal1ty/mashumaro`][mashumaro].
33
+ - Export in-memory model description to URDF.
34
34
 
35
35
  [mashumaro]: https://github.com/Fatal1ty/mashumaro
36
36
  [open_robotics]: https://www.openrobotics.org/
37
37
  [pose_semantics]: http://sdformat.org/tutorials?tut=pose_frame_semantics_proposal&cat=pose_semantics_docs&
38
38
  [sdformat]: http://sdformat.org/
39
39
  [sdformat_python]: http://sdformat.org/tutorials?tut=python_bindings&cat=developers&
40
- [sdformat_repo]: https://github.com/gazebosim/sdformat
41
40
  [sdformat_spec]: http://sdformat.org/spec
42
- [sdformat_spec_17]: http://sdformat.org/spec?elem=sdf&ver=1.7
41
+ [sdformat_spec_110]: http://sdformat.org/spec?elem=sdf&ver=1.10
43
42
  [urdf]: http://wiki.ros.org/urdf
44
43
 
45
- [^urdf_to_sdf]: Conversion can be done either using `ign sdf` included in Ignition Gazebo Fortress, or `gz sdf` included in Gazebo Sim starting from Garden.
44
+ [^urdf_to_sdf]: Conversion can be done using the `gz sdf` command included in Gazebo Sim starting from Garden.
46
45
 
47
46
  ## Installation
48
47
 
49
- You can install the project with [`pypa/pip`][pip], preferably in a [virtual environment][venv]:
48
+ > [!TIP]
49
+ > ROD does not support out-of-the-box URDF files.
50
+ > URDF support is obtained by converting URDF files to SDF using the `gz sdf` command provided by [sdformat][sdformat_repo] and [gz-tools][gz-tools_repo].
51
+ > Ensure these tools are installed on your system if URDF support is needed (more information below).
52
+
53
+ [sdformat_repo]: https://github.com/gazebosim/sdformat
54
+ [gz-tools_repo]: https://github.com/gazebosim/gz-tools
55
+
56
+ <details>
57
+ <summary>Using conda (recommended)</summary>
58
+
59
+ Installing ROD using `conda` is the recommended way to obtain a complete installation with out-of-the-box support for both URDF and SDF descriptions:
50
60
 
51
61
  ```bash
52
- pip install git+https://github.com/ami-iit/rod
62
+ conda install rod -c conda-forge
53
63
  ```
54
64
 
65
+ This will automatically install `sdformat` and `gz-tools`.
66
+
67
+ </details>
68
+
69
+ <details>
70
+ <summary>Using pip</summary>
71
+
72
+ You can install ROD from PyPI with [`pypa/pip`][pip], preferably in a [virtual environment][venv]:
73
+
74
+ ```bash
75
+ pip install rod[all]
76
+ ```
77
+
78
+ If you need URDF support, follow the [official instructions][gazebo_sim_docs] to install Gazebo Sim on your operating system,
79
+ making sure to obtain `sdformat ≥ 13.0` and `gz-tools ≥ 2.0`.
80
+
81
+ You don't need to install the entire Gazebo Sim suite.
82
+ For example, on Ubuntu, you can only install the `libsdformat13 gz-tools2` packages.
83
+
55
84
  [pip]: https://github.com/pypa/pip/
56
- [venv]: https://docs.python.org/3.8/tutorial/venv.html
85
+ [venv]: https://docs.python.org/3.10/tutorial/venv.html
86
+ [gazebo_sim_docs]: https://gazebosim.org/docs
87
+
88
+ </details>
57
89
 
58
90
  ## Examples
59
91
 
@@ -164,10 +196,8 @@ print(sdf.serialize(pretty=True))
164
196
 
165
197
  from rod.urdf.exporter import UrdfExporter
166
198
 
167
- urdf_string = UrdfExporter.sdf_to_urdf_string(
168
- sdf=sdf,
169
- pretty=True,
170
- gazebo_preserve_fixed_joints=True,
199
+ urdf_string = UrdfExporter(pretty=True, gazebo_preserve_fixed_joints=True).to_urdf_string(
200
+ sdf=sdf
171
201
  )
172
202
 
173
203
  print(urdf_string)
@@ -37,10 +37,9 @@ classifiers =
37
37
  Operating System :: MacOS
38
38
  Operating System :: Microsoft :: Windows
39
39
  Programming Language :: Python :: 3
40
- Programming Language :: Python :: 3.8
41
- Programming Language :: Python :: 3.9
42
40
  Programming Language :: Python :: 3.10
43
41
  Programming Language :: Python :: 3.11
42
+ Programming Language :: Python :: 3.12
44
43
  Programming Language :: Python :: 3 :: Only
45
44
  Programming Language :: Python :: Implementation :: CPython
46
45
  Topic :: Games/Entertainment :: Simulation
@@ -50,7 +49,7 @@ zip_safe = False
50
49
  packages = find:
51
50
  package_dir =
52
51
  =src
53
- python_requires = >=3.8
52
+ python_requires = >=3.10
54
53
  install_requires =
55
54
  coloredlogs
56
55
  mashumaro
@@ -28,7 +28,7 @@ from .utils.frame_convention import FrameConvention
28
28
  # ===============================
29
29
 
30
30
 
31
- def _is_editable():
31
+ def installation_is_editable():
32
32
  """
33
33
  Check if the rod package is installed in editable mode.
34
34
  """
@@ -51,12 +51,41 @@ def _is_editable():
51
51
  return rod_package_dir not in site.getsitepackages()
52
52
 
53
53
 
54
- # Initialize the logging verbosity depending on the installation mode.
55
- logging.configure(
56
- level=logging.LoggingLevel.DEBUG if _is_editable() else logging.LoggingLevel.WARNING
57
- )
54
+ def get_default_logging_level(env_var: str) -> logging.LoggingLevel:
55
+ """
56
+ Get the default logging level.
57
+
58
+ Args:
59
+ env_var: The environment variable to check.
60
+
61
+ Returns:
62
+ The logging level to set.
63
+ """
64
+
65
+ import os
66
+
67
+ # Define the default logging level depending on the installation mode.
68
+ default_logging_level = (
69
+ logging.LoggingLevel.DEBUG
70
+ if installation_is_editable()
71
+ else logging.LoggingLevel.WARNING
72
+ )
73
+
74
+ # Allow to override the default logging level with an environment variable.
75
+ try:
76
+ return logging.LoggingLevel[
77
+ os.environ.get(env_var, default_logging_level.name).upper()
78
+ ]
79
+ except KeyError as exc:
80
+ msg = f"Invalid logging level defined in {env_var}='{os.environ[env_var]}'"
81
+ raise RuntimeError(msg) from exc
82
+
83
+
84
+ # Configure the logger with the default logging level.
85
+ logging.configure(level=get_default_logging_level(env_var="ROD_LOGGING_LEVEL"))
58
86
 
59
- del _is_editable
87
+ del installation_is_editable
88
+ del get_default_logging_level
60
89
 
61
90
  # =====================================
62
91
  # Check for compatible sdformat version
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: rod
3
- Version: 0.2.1.dev33
3
+ Version: 0.2.1.dev45
4
4
  Summary: The ultimate Python tool for RObot Descriptions processing.
5
5
  Home-page: https://github.com/ami-iit/rod
6
6
  Author: Diego Ferigo
@@ -22,14 +22,13 @@ Classifier: Operating System :: POSIX :: Linux
22
22
  Classifier: Operating System :: MacOS
23
23
  Classifier: Operating System :: Microsoft :: Windows
24
24
  Classifier: Programming Language :: Python :: 3
25
- Classifier: Programming Language :: Python :: 3.8
26
- Classifier: Programming Language :: Python :: 3.9
27
25
  Classifier: Programming Language :: Python :: 3.10
28
26
  Classifier: Programming Language :: Python :: 3.11
27
+ Classifier: Programming Language :: Python :: 3.12
29
28
  Classifier: Programming Language :: Python :: 3 :: Only
30
29
  Classifier: Programming Language :: Python :: Implementation :: CPython
31
30
  Classifier: Topic :: Games/Entertainment :: Simulation
32
- Requires-Python: >=3.8
31
+ Requires-Python: >=3.10
33
32
  Description-Content-Type: text/markdown
34
33
  License-File: LICENSE
35
34
  Requires-Dist: coloredlogs
@@ -82,39 +81,71 @@ Last but not least, the pose semantics also makes SDF aware of the concept of _f
82
81
 
83
82
  ## Features
84
83
 
85
- - Out-of-the-box support of SDFormat specifications [≥ 1.7][sdformat_spec_17]
86
- - Serialization and deserialization support of SDF files
87
- - In-memory layout based on `dataclasses`
88
- - Syntax highlighting and auto-completion
89
- - Support of programmatic creation of SDF files from Python APIs
90
- - Transitive support of URDF through conversion to SDF[^urdf_to_sdf]
91
- - Type validation of elements and attributes
92
- - Automatic check of missing required elements
93
- - Based on [`Fatal1ty/mashumaro`][mashumaro] for great serialization and deserialization performance
94
- - Support of exporting the in-memory model description to URDF
84
+ - Out-of-the-box support for SDFormat specifications [≥ 1.10][sdformat_spec_110].
85
+ - Serialization and deserialization support for SDF files.
86
+ - In-memory layout based on `dataclasses`.
87
+ - Syntax highlighting and auto-completion.
88
+ - Programmatic creation of SDF files from Python APIs.
89
+ - Transitive support for URDF through conversion to SDF.
90
+ - Type validation of elements and attributes.
91
+ - Automatic check of missing required elements.
92
+ - High-performance serialization and deserialization using [`Fatal1ty/mashumaro`][mashumaro].
93
+ - Export in-memory model description to URDF.
95
94
 
96
95
  [mashumaro]: https://github.com/Fatal1ty/mashumaro
97
96
  [open_robotics]: https://www.openrobotics.org/
98
97
  [pose_semantics]: http://sdformat.org/tutorials?tut=pose_frame_semantics_proposal&cat=pose_semantics_docs&
99
98
  [sdformat]: http://sdformat.org/
100
99
  [sdformat_python]: http://sdformat.org/tutorials?tut=python_bindings&cat=developers&
101
- [sdformat_repo]: https://github.com/gazebosim/sdformat
102
100
  [sdformat_spec]: http://sdformat.org/spec
103
- [sdformat_spec_17]: http://sdformat.org/spec?elem=sdf&ver=1.7
101
+ [sdformat_spec_110]: http://sdformat.org/spec?elem=sdf&ver=1.10
104
102
  [urdf]: http://wiki.ros.org/urdf
105
103
 
106
- [^urdf_to_sdf]: Conversion can be done either using `ign sdf` included in Ignition Gazebo Fortress, or `gz sdf` included in Gazebo Sim starting from Garden.
104
+ [^urdf_to_sdf]: Conversion can be done using the `gz sdf` command included in Gazebo Sim starting from Garden.
107
105
 
108
106
  ## Installation
109
107
 
110
- You can install the project with [`pypa/pip`][pip], preferably in a [virtual environment][venv]:
108
+ > [!TIP]
109
+ > ROD does not support out-of-the-box URDF files.
110
+ > URDF support is obtained by converting URDF files to SDF using the `gz sdf` command provided by [sdformat][sdformat_repo] and [gz-tools][gz-tools_repo].
111
+ > Ensure these tools are installed on your system if URDF support is needed (more information below).
112
+
113
+ [sdformat_repo]: https://github.com/gazebosim/sdformat
114
+ [gz-tools_repo]: https://github.com/gazebosim/gz-tools
115
+
116
+ <details>
117
+ <summary>Using conda (recommended)</summary>
118
+
119
+ Installing ROD using `conda` is the recommended way to obtain a complete installation with out-of-the-box support for both URDF and SDF descriptions:
111
120
 
112
121
  ```bash
113
- pip install git+https://github.com/ami-iit/rod
122
+ conda install rod -c conda-forge
114
123
  ```
115
124
 
125
+ This will automatically install `sdformat` and `gz-tools`.
126
+
127
+ </details>
128
+
129
+ <details>
130
+ <summary>Using pip</summary>
131
+
132
+ You can install ROD from PyPI with [`pypa/pip`][pip], preferably in a [virtual environment][venv]:
133
+
134
+ ```bash
135
+ pip install rod[all]
136
+ ```
137
+
138
+ If you need URDF support, follow the [official instructions][gazebo_sim_docs] to install Gazebo Sim on your operating system,
139
+ making sure to obtain `sdformat ≥ 13.0` and `gz-tools ≥ 2.0`.
140
+
141
+ You don't need to install the entire Gazebo Sim suite.
142
+ For example, on Ubuntu, you can only install the `libsdformat13 gz-tools2` packages.
143
+
116
144
  [pip]: https://github.com/pypa/pip/
117
- [venv]: https://docs.python.org/3.8/tutorial/venv.html
145
+ [venv]: https://docs.python.org/3.10/tutorial/venv.html
146
+ [gazebo_sim_docs]: https://gazebosim.org/docs
147
+
148
+ </details>
118
149
 
119
150
  ## Examples
120
151
 
@@ -225,10 +256,8 @@ print(sdf.serialize(pretty=True))
225
256
 
226
257
  from rod.urdf.exporter import UrdfExporter
227
258
 
228
- urdf_string = UrdfExporter.sdf_to_urdf_string(
229
- sdf=sdf,
230
- pretty=True,
231
- gazebo_preserve_fixed_joints=True,
259
+ urdf_string = UrdfExporter(pretty=True, gazebo_preserve_fixed_joints=True).to_urdf_string(
260
+ sdf=sdf
232
261
  )
233
262
 
234
263
  print(urdf_string)
@@ -1,5 +1,3 @@
1
- import os
2
- import pathlib
3
1
  import tempfile
4
2
 
5
3
  import numpy as np
@@ -9,53 +7,70 @@ from rod.builder.primitives import MeshBuilder
9
7
 
10
8
 
11
9
  def test_builder_creation():
10
+
11
+ # Create a mesh of a box primitive.
12
12
  mesh = trimesh.creation.box([1, 1, 1])
13
13
 
14
- # Temporary write to file because rod Mesh works with uri
15
- with tempfile.NamedTemporaryFile(suffix=".stl") as fp:
16
- mesh.export(fp.name, file_type="stl")
14
+ # Temporary write to file because rod Mesh works with uri.
15
+ with tempfile.TemporaryDirectory() as tmp:
16
+ with tempfile.NamedTemporaryFile(suffix=".stl", dir=tmp, delete=False) as fp:
17
+
18
+ mesh.export(fp.name, file_type="stl")
19
+ fp.close()
20
+
21
+ builder = MeshBuilder(
22
+ name="test_mesh",
23
+ mesh_path=fp.name,
24
+ mass=1.0,
25
+ scale=np.array([1.0, 1.0, 1.0]),
26
+ )
17
27
 
18
- builder = MeshBuilder(
19
- name="test_mesh",
20
- mesh_path=fp.name,
21
- mass=1.0,
22
- scale=np.array([1.0, 1.0, 1.0]),
23
- )
24
28
  assert (
25
29
  builder.mesh.vertices.shape == mesh.vertices.shape
26
30
  ), f"{builder.mesh.vertices.shape} != {mesh.vertices.shape}"
31
+
27
32
  assert (
28
33
  builder.mesh.faces.shape == mesh.faces.shape
29
34
  ), f"{builder.mesh.faces.shape} != {mesh.faces.shape}"
35
+
30
36
  assert (
31
37
  builder.mesh.moment_inertia.all() == mesh.moment_inertia.all()
32
38
  ), f"{builder.mesh.moment_inertia} != {mesh.moment_inertia}"
39
+
33
40
  assert builder.mesh.volume == mesh.volume, f"{builder.mesh.volume} != {mesh.volume}"
34
41
 
35
42
 
36
43
  def test_builder_creation_custom_mesh():
44
+
37
45
  # Create a custom mesh
38
46
  vertices = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]])
39
47
  faces = np.array([[0, 1, 2], [0, 2, 3]])
40
48
  mesh = trimesh.Trimesh(vertices=vertices, faces=faces)
41
49
 
42
- # Temporary write to file because rod Mesh works with uri
43
- with tempfile.NamedTemporaryFile(suffix=".stl") as fp:
44
- mesh.export(fp.name, file_type="stl")
50
+ # Temporary write to file because rod Mesh works with uri.
51
+ with tempfile.TemporaryDirectory() as tmp:
52
+ with tempfile.NamedTemporaryFile(suffix=".stl", dir=tmp, delete=False) as fp:
53
+
54
+ mesh.export(fp.name, file_type="stl")
55
+ fp.close()
56
+
57
+ builder = MeshBuilder(
58
+ name="test_mesh",
59
+ mesh_path=fp.name,
60
+ mass=1.0,
61
+ scale=np.array([1.0, 1.0, 1.0]),
62
+ )
45
63
 
46
- builder = MeshBuilder(
47
- name="test_mesh",
48
- mesh_path=fp.name,
49
- mass=1.0,
50
- scale=np.array([1.0, 1.0, 1.0]),
51
- )
52
64
  assert (
53
65
  builder.mesh.vertices.shape == mesh.vertices.shape
54
66
  ), f"{builder.mesh.vertices.shape} != {mesh.vertices.shape}"
67
+
55
68
  assert (
56
69
  builder.mesh.faces.shape == mesh.faces.shape
57
70
  ), f"{builder.mesh.faces.shape} != {mesh.faces.shape}"
71
+
58
72
  assert (
59
73
  builder.mesh.moment_inertia.all() == mesh.moment_inertia.all()
60
74
  ), f"{builder.mesh.moment_inertia} != {mesh.moment_inertia}"
75
+
61
76
  assert builder.mesh.volume == mesh.volume, f"{builder.mesh.volume} != {mesh.volume}"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes