mujoco-truss-gen 0.1.0__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 (29) hide show
  1. mujoco_truss_gen-0.1.0/LICENSE +28 -0
  2. mujoco_truss_gen-0.1.0/PKG-INFO +433 -0
  3. mujoco_truss_gen-0.1.0/README.md +369 -0
  4. mujoco_truss_gen-0.1.0/pyproject.toml +107 -0
  5. mujoco_truss_gen-0.1.0/setup.cfg +4 -0
  6. mujoco_truss_gen-0.1.0/src/generate_mujoco_model.py +7 -0
  7. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/__init__.py +30 -0
  8. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/base_env.py +254 -0
  9. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/generate_mujoco_model.py +122 -0
  10. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/mujoco_model/__init__.py +32 -0
  11. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/mujoco_model/bodies.py +254 -0
  12. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/mujoco_model/builders.py +203 -0
  13. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/mujoco_model/constants.py +10 -0
  14. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/mujoco_model/constraints.py +59 -0
  15. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/mujoco_model/geometry.py +54 -0
  16. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/mujoco_model/io_viewer.py +42 -0
  17. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/mujoco_model/model.py +304 -0
  18. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/mujoco_model/model_types.py +7 -0
  19. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/mujoco_model/presets.py +21 -0
  20. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/mujoco_model/tendons.py +94 -0
  21. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/relative_observation_env.py +76 -0
  22. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen/velocity_command_env.py +37 -0
  23. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen.egg-info/PKG-INFO +433 -0
  24. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen.egg-info/SOURCES.txt +27 -0
  25. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen.egg-info/dependency_links.txt +1 -0
  26. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen.egg-info/entry_points.txt +2 -0
  27. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen.egg-info/requires.txt +14 -0
  28. mujoco_truss_gen-0.1.0/src/mujoco_truss_gen.egg-info/top_level.txt +2 -0
  29. mujoco_truss_gen-0.1.0/tests/test_envs.py +100 -0
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Isaac Sudweeks
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,433 @@
1
+ Metadata-Version: 2.4
2
+ Name: mujoco-truss-gen
3
+ Version: 0.1.0
4
+ Summary: Tools for generating MuJoCo models and Gym-style environments for isoperimetric truss robots.
5
+ Author-email: Isaac Sudweeks <isuds@byu.edu>
6
+ Maintainer-email: Isaac Sudweeks <isuds@byu.edu>
7
+ License: BSD 3-Clause License
8
+
9
+ Copyright (c) 2026, Isaac Sudweeks
10
+
11
+ Redistribution and use in source and binary forms, with or without
12
+ modification, are permitted provided that the following conditions are met:
13
+
14
+ 1. Redistributions of source code must retain the above copyright notice, this
15
+ list of conditions and the following disclaimer.
16
+
17
+ 2. Redistributions in binary form must reproduce the above copyright notice,
18
+ this list of conditions and the following disclaimer in the documentation
19
+ and/or other materials provided with the distribution.
20
+
21
+ 3. Neither the name of the copyright holder nor the names of its
22
+ contributors may be used to endorse or promote products derived from
23
+ this software without specific prior written permission.
24
+
25
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
+ DAMAGES INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER
32
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33
+ OR TORT INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE
34
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
+
36
+ Project-URL: Homepage, https://github.com/isaa-sudweeks/mujoco-truss-gen
37
+ Project-URL: Repository, https://github.com/isaa-sudweeks/mujoco-truss-gen
38
+ Project-URL: Issues, https://github.com/isaa-sudweeks/mujoco-truss-gen/issues
39
+ Keywords: mujoco,robotics,truss,simulation,gymnasium
40
+ Classifier: Development Status :: 2 - Pre-Alpha
41
+ Classifier: Intended Audience :: Science/Research
42
+ Classifier: License :: OSI Approved :: BSD License
43
+ Classifier: Programming Language :: Python :: 3
44
+ Classifier: Programming Language :: Python :: 3.10
45
+ Classifier: Programming Language :: Python :: 3.11
46
+ Classifier: Programming Language :: Python :: 3.12
47
+ Classifier: Topic :: Scientific/Engineering
48
+ Requires-Python: >=3.10
49
+ Description-Content-Type: text/markdown
50
+ License-File: LICENSE
51
+ Requires-Dist: gymnasium>=0.29
52
+ Requires-Dist: mujoco>=3.0
53
+ Requires-Dist: numpy>=1.24
54
+ Requires-Dist: scipy>=1.10
55
+ Provides-Extra: dev
56
+ Requires-Dist: build>=1.2; extra == "dev"
57
+ Requires-Dist: mypy>=1.8; extra == "dev"
58
+ Requires-Dist: pytest>=8.0; extra == "dev"
59
+ Requires-Dist: ruff>=0.4; extra == "dev"
60
+ Requires-Dist: twine>=5.0; extra == "dev"
61
+ Provides-Extra: test
62
+ Requires-Dist: pytest>=8.0; extra == "test"
63
+ Dynamic: license-file
64
+
65
+ # mujoco-truss-gen
66
+
67
+ `mujoco-truss-gen` is a Python package for generating MuJoCo models and
68
+ Gymnasium-style environments for triangle-based isoperimetric truss robots.
69
+
70
+ The package is intended for members of the isoperimetric robot research workflow
71
+ who need a shared, installable source of MuJoCo robot models instead of copying
72
+ model-generation code between reinforcement learning, planning, simulation, and
73
+ optimization projects.
74
+
75
+ ## Project Status
76
+
77
+ This repository is an internal lab prototype. It has a working installable
78
+ package, a small public API, a built-in octahedron preset, and tests that verify
79
+ basic model generation and environment stepping. The API may still change before
80
+ the package is treated as stable research infrastructure.
81
+
82
+ Current scope:
83
+
84
+ - Generate MuJoCo `MjSpec` models for triangle-based truss structures.
85
+ - Generate a built-in octahedron robot preset.
86
+ - Build either an abstract per-node slide-joint model or a more realistic
87
+ triangle-body model with connector balls for shared nodes.
88
+ - Add tendon actuators and perimeter constraints.
89
+ - Save generated MuJoCo XML.
90
+ - Wrap generated models in Gymnasium-compatible environments.
91
+ - Provide base, relative-observation, and velocity-command environment variants.
92
+
93
+ Known limitations:
94
+
95
+ - Only the `"octahedron"` named preset is included.
96
+ - Custom robot definitions are supported through dictionaries, but there is not
97
+ yet a registry of named robot presets.
98
+ - The default rewards are research defaults, not task-independent objectives.
99
+ - The environment classes are starting points. Most RL, planning, or
100
+ optimization tasks should subclass or wrap them for task-specific observations,
101
+ rewards, resets, and termination logic.
102
+ - The human viewer requires a Python environment where `mujoco.viewer` is
103
+ available.
104
+
105
+ ## Installation
106
+
107
+ After a release has been published to PyPI:
108
+
109
+ ```bash
110
+ python -m pip install mujoco-truss-gen
111
+ ```
112
+
113
+ To upgrade to the newest published version:
114
+
115
+ ```bash
116
+ python -m pip install --upgrade mujoco-truss-gen
117
+ ```
118
+
119
+ For local development from a clone:
120
+
121
+ ```bash
122
+ git clone https://github.com/isaa-sudweeks/mujoco-truss-gen.git
123
+ cd mujoco-truss-gen
124
+ python -m pip install -e ".[dev]"
125
+ ```
126
+
127
+ The package requires Python 3.10 or newer and installs these runtime
128
+ dependencies:
129
+
130
+ - `gymnasium`
131
+ - `mujoco`
132
+ - `numpy`
133
+ - `scipy`
134
+
135
+ ## Quick Start
136
+
137
+ Generate the built-in octahedron model:
138
+
139
+ ```python
140
+ from mujoco_truss_gen import get_mujoco_spec
141
+
142
+ spec = get_mujoco_spec("octahedron", realistic=False)
143
+ model = spec.compile()
144
+ ```
145
+
146
+ Save the generated XML:
147
+
148
+ ```python
149
+ from mujoco_truss_gen import get_mujoco_spec, save_xml
150
+
151
+ spec = get_mujoco_spec("octahedron", realistic=False)
152
+ xml_path = save_xml(spec, "octahedron.xml")
153
+ ```
154
+
155
+ Run one Gymnasium step:
156
+
157
+ ```python
158
+ import numpy as np
159
+
160
+ from mujoco_truss_gen import MujocoRelativeObsEnv, TrussEnvConfig, get_mujoco_spec
161
+
162
+ spec = get_mujoco_spec("octahedron", realistic=False)
163
+ env = MujocoRelativeObsEnv(
164
+ TrussEnvConfig(
165
+ model_source=spec,
166
+ max_steps=1_000,
167
+ nsubsteps=4,
168
+ speed=0.01,
169
+ )
170
+ )
171
+
172
+ obs, info = env.reset(seed=0)
173
+ action = np.zeros(env.action_space.shape, dtype=np.float32)
174
+ obs, reward, terminated, truncated, info = env.step(action)
175
+ env.close()
176
+ ```
177
+
178
+ Open the passive MuJoCo viewer:
179
+
180
+ ```bash
181
+ python -m mujoco_truss_gen.generate_mujoco_model
182
+ ```
183
+
184
+ ## Defining a Custom Truss
185
+
186
+ Custom trusses are represented with two dictionaries.
187
+
188
+ `node_dict` maps node names to 3D positions:
189
+
190
+ ```python
191
+ node_dict = {
192
+ "node_1": [0.0, 0.0, 0.2],
193
+ "node_2": [0.8, 0.0, 0.2],
194
+ "node_3": [0.4, 0.7, 0.2],
195
+ }
196
+ ```
197
+
198
+ `triangle_dict` maps triangle names to four node names:
199
+
200
+ ```python
201
+ triangle_dict = {
202
+ "triangle_1": ["node_1", "node_2", "node_3", "node_1"],
203
+ }
204
+ ```
205
+
206
+ The first three names are the triangle vertices. The fourth name is the passive
207
+ node for that triangle's perimeter constraint and must be one of the first three
208
+ vertex names.
209
+
210
+ Build a model from those dictionaries:
211
+
212
+ ```python
213
+ from mujoco_truss_gen import get_mujoco_spec
214
+
215
+ spec = get_mujoco_spec(node_dict, triangle_dict, realistic=False)
216
+ model = spec.compile()
217
+ ```
218
+
219
+ `get_mujoco_spec()` and `build_triangle()` treat caller-provided dictionaries as
220
+ read-only inputs. The realistic builder clones shared nodes internally, but it
221
+ does not mutate the original `node_dict` or `triangle_dict` passed by the caller.
222
+
223
+ ## Model Generation Contract
224
+
225
+ Public generation helpers:
226
+
227
+ - `build_world()` creates a base `mujoco.MjSpec` containing a ground plane and
228
+ top light.
229
+ - `build_triangle(spec, node_dict, triangle_dict, realistic=False)` adds truss
230
+ bodies, sites, tendons, actuators, and perimeter constraints to an existing
231
+ spec.
232
+ - `get_mujoco_spec("octahedron", realistic=False)` builds the built-in
233
+ octahedron preset.
234
+ - `get_mujoco_spec(node_dict, triangle_dict, realistic=False)` builds a custom
235
+ dictionary-defined truss.
236
+ - `get_octahedron_definition()` returns fresh node and triangle dictionaries for
237
+ the built-in preset.
238
+ - `get_perimeter(node_dict, triangle_dict)` computes each triangle perimeter
239
+ from the first three vertices.
240
+ - `save_xml(spec, filename)` writes `spec.to_xml()` to disk and returns the
241
+ resolved path.
242
+ - `view(spec)` compiles and opens the generated model in MuJoCo's passive
243
+ viewer.
244
+
245
+ Input expectations:
246
+
247
+ - Node names should be unique strings. Names beginning with `node_` are required
248
+ for the built-in metadata and environment helpers.
249
+ - Node positions must be 3D numeric sequences.
250
+ - Triangle entries must contain exactly the three vertex nodes plus one passive
251
+ node.
252
+ - The passive node must appear in that triangle's first three vertices.
253
+ - The builder helpers should be used when environment rigidity and slip helpers
254
+ are needed, because those helpers infer structure from generated body, site,
255
+ tendon, and actuator names.
256
+
257
+ Model modes:
258
+
259
+ - `realistic=False` creates one world-body per node with slide joints on `x`,
260
+ `y`, and `z`. This is the simpler abstract model and is useful for fast
261
+ algorithm development.
262
+ - `realistic=True` creates triangle bodies, clones shared triangle nodes inside
263
+ the generated model, and connects shared vertices through connector balls.
264
+ This is intended to better represent the triangle-module structure.
265
+
266
+ ## Environment Contract
267
+
268
+ The environment constructors accept any of these model sources:
269
+
270
+ - `mujoco.MjSpec`
271
+ - `mujoco.MjModel`
272
+ - XML string
273
+ - path to an XML file
274
+ - `TrussEnvConfig`
275
+
276
+ Available environments:
277
+
278
+ - `MujocoTrussEnv`: base environment with tendon lengths, tendon velocities,
279
+ center-of-mass position, and center-of-mass velocity in the observation.
280
+ - `MujocoRelativeObsEnv`: relative node-position observations and normalized
281
+ actuator delta actions.
282
+ - `MujocoVelocityCommandEnv`: relative observations with direct velocity command
283
+ actions.
284
+
285
+ Shared configuration is provided by `TrussEnvConfig`:
286
+
287
+ ```python
288
+ from mujoco_truss_gen import TrussEnvConfig
289
+
290
+ config = TrussEnvConfig(
291
+ model_source=spec,
292
+ max_steps=10_000,
293
+ nsubsteps=1,
294
+ speed=0.01,
295
+ forward_weight=5.0,
296
+ energy_weight=0.005,
297
+ alive_bonus=0.1,
298
+ rigidity_weight=0.5,
299
+ slip_weight=0.1,
300
+ critical_eig_threshold=0.03,
301
+ slip_height=0.2,
302
+ control_noise_std=0.0,
303
+ control_noise_relative=True,
304
+ runtime_apply_control_noise=False,
305
+ )
306
+ ```
307
+
308
+ Step/reset behavior:
309
+
310
+ - `reset(seed=...)` follows the Gymnasium API and returns `(obs, info)`.
311
+ - `step(action)` returns `(obs, reward, terminated, truncated, info)`.
312
+ - `truncated` becomes true when `max_steps` is reached.
313
+ - `terminated` becomes true when the normalized rigidity metric falls below
314
+ `critical_eig_threshold`.
315
+ - `info` includes reward components and `critical_eig`.
316
+
317
+ Action behavior:
318
+
319
+ - `MujocoTrussEnv` sends clipped actuator controls directly in the MuJoCo
320
+ actuator control range.
321
+ - `MujocoRelativeObsEnv` expects actions in `[-1, 1]`; each action component
322
+ changes the previous control by `action * config.speed`.
323
+ - `MujocoVelocityCommandEnv` expects actions in `[-config.speed, config.speed]`
324
+ and sends those values directly.
325
+
326
+ Reward behavior:
327
+
328
+ - The default reward combines forward velocity, alive bonus, energy penalty,
329
+ rigidity reward, and slip penalty.
330
+ - These defaults are provided for experimentation, not as a canonical objective
331
+ for every isoperimetric robot task.
332
+ - Custom tasks should subclass an environment and override `_get_obs()`,
333
+ `_compute_reward()`, `reset()`, or `step()` as needed.
334
+
335
+ Rendering:
336
+
337
+ - `render_mode="rgb_array"` returns a rendered NumPy RGB image.
338
+ - `render_mode="human"` opens a passive MuJoCo viewer when the local MuJoCo
339
+ viewer module is available.
340
+
341
+ ## Development
342
+
343
+ Set up a development environment:
344
+
345
+ ```bash
346
+ python -m pip install -e ".[dev]"
347
+ ```
348
+
349
+ Run tests:
350
+
351
+ ```bash
352
+ python -m pytest
353
+ ```
354
+
355
+ Run linting and formatting checks:
356
+
357
+ ```bash
358
+ python -m ruff check .
359
+ python -m ruff format --check .
360
+ ```
361
+
362
+ Build a local distribution:
363
+
364
+ ```bash
365
+ python -m build
366
+ ```
367
+
368
+ ## Publishing Releases
369
+
370
+ PyPI releases are immutable for a given version. Every code change that should
371
+ be published must use a new version number in `pyproject.toml`.
372
+
373
+ For small test releases, you can use a pre-release tag (e.g., `0.1.0a1`).
374
+
375
+ For bug fixes or backwards-compatible changes, you can use a patch release tag (e.g., `0.1.1`).
376
+
377
+ For new features or breaking changes, you can use a minor or major release tag (e.g., `0.2.0` or `1.0.0`).
378
+
379
+ Release checklist:
380
+
381
+ 1. Update `version` in `pyproject.toml`.
382
+ 2. Run `python -m pytest`.
383
+ 3. Run `python -m ruff check .`.
384
+ 4. Run `python -m ruff format --check .`.
385
+ 5. Build distributions with `python -m build`.
386
+ 6. Upload with `python -m twine upload dist/*`.
387
+ 7. Verify installation in a clean environment with
388
+ `python -m pip install mujoco-truss-gen`.
389
+
390
+ Users update to the newest published package with:
391
+
392
+ ```bash
393
+ python -m pip install --upgrade mujoco-truss-gen
394
+ ```
395
+
396
+ ## Repository Layout
397
+
398
+ ```text
399
+ mujoco-truss-gen/
400
+ ├── LICENSE
401
+ ├── README.md
402
+ ├── pyproject.toml
403
+ ├── tests/
404
+ │ └── test_envs.py
405
+ └── src/
406
+ ├── generate_mujoco_model.py
407
+ └── mujoco_truss_gen/
408
+ ├── __init__.py
409
+ ├── base_env.py
410
+ ├── generate_mujoco_model.py
411
+ ├── relative_observation_env.py
412
+ ├── velocity_command_env.py
413
+ └── mujoco_model/
414
+ ├── bodies.py
415
+ ├── builders.py
416
+ ├── constants.py
417
+ ├── constraints.py
418
+ ├── geometry.py
419
+ ├── io_viewer.py
420
+ ├── model.py
421
+ ├── model_types.py
422
+ ├── presets.py
423
+ └── tendons.py
424
+ ```
425
+
426
+ ## Citation
427
+
428
+ There is no formal citation for this package yet.
429
+
430
+ ## License
431
+
432
+ This project is distributed under the BSD-3-Clause license. See `LICENSE` for
433
+ the full license text.