mujoco-mojo 2.3.0__tar.gz → 2.3.2__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.
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/.gitignore +1 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/PKG-INFO +4 -1
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/pyproject.toml +5 -2
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/requirements.txt +60 -61
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/scripts/gen_ts_models.py +12 -1
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/__about__.py +3 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/__init__.py +1 -1
- mujoco_mojo-2.3.2/src/mujoco_mojo/meta.py +11 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mojo_model.py +18 -1
- mujoco_mojo-2.3.2/src/mujoco_mojo/runtime/video_recorder.py +221 -0
- mujoco_mojo-2.3.2/src/mujoco_mojo/settings.py +70 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/typing.py +1 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/dataframe.py +7 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/filters/filters.py +10 -1
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/cli.py +187 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/lab_executor.py +71 -5
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/main.py +44 -0
- mujoco_mojo-2.3.2/src/mujoco_mojo/utils/layers/dojo/plot_config.py +379 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/routers/monitor.py +28 -4
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/routers/mosaic.py +158 -8
- mujoco_mojo-2.3.2/src/mujoco_mojo/utils/layers/dojo/routers/sensai.py +343 -0
- mujoco_mojo-2.3.2/src/mujoco_mojo/utils/layers/dojo/sensai/__init__.py +17 -0
- mujoco_mojo-2.3.2/src/mujoco_mojo/utils/layers/dojo/sensai/agent.py +475 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/base.html +239 -124
- mujoco_mojo-2.3.2/src/mujoco_mojo/utils/layers/dojo/templates/partials/_sensai.html +256 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/partials/trial_viewer/_chart.html +47 -6
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/partials/trial_viewer/_json_editor.html +4 -2
- mujoco_mojo-2.3.2/src/mujoco_mojo/utils/layers/dojo/templates/partials/trial_viewer/_media_player.html +246 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/partials/trial_viewer/_signal_lab.html +985 -205
- mujoco_mojo-2.3.2/src/mujoco_mojo/utils/layers/dojo/templates/partials/trial_viewer/_trial_status.html +103 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/js/main.js +33 -1
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/js/monitor.js +1 -1
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/js/mosaic.js +1 -1
- mujoco_mojo-2.3.2/src/mujoco_mojo/utils/layers/dojo/templates/static/js/sensai.js +1566 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/js/trial-viewer.js +952 -110
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/build.mjs +1 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/package-lock.json +14 -1
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/package.json +2 -1
- mujoco_mojo-2.3.2/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/src/lib/plot-config.generated.ts +232 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/src/models.ts +40 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/src/monitor.ts +1 -1
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/src/mosaic.ts +1 -1
- mujoco_mojo-2.3.2/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/src/sensai.ts +393 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/src/store.ts +50 -1
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/src/trial-viewer.ts +1208 -136
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/src/types/global.d.ts +24 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/trial_viewer.html +6 -3
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/reloaded.py +195 -28
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/runner.py +16 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/statusing.py +4 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/runtime/monte_carlo_bumper.py +5 -4
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/uv.lock +86 -64
- mujoco_mojo-2.3.0/src/mujoco_mojo/meta.py +0 -4
- mujoco_mojo-2.3.0/src/mujoco_mojo/runtime/video_recorder.py +0 -109
- mujoco_mojo-2.3.0/src/mujoco_mojo/utils/layers/dojo/plot_config.py +0 -163
- mujoco_mojo-2.3.0/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/src/lib/plot-config.generated.ts +0 -90
- mujoco_mojo-2.3.0/typings/mujoco/__init__.pyi +0 -1273
- mujoco_mojo-2.3.0/typings/mujoco/_callbacks.pyi +0 -50
- mujoco_mojo-2.3.0/typings/mujoco/_constants.pyi +0 -183
- mujoco_mojo-2.3.0/typings/mujoco/_enums.pyi +0 -6973
- mujoco_mojo-2.3.0/typings/mujoco/_errors.pyi +0 -5
- mujoco_mojo-2.3.0/typings/mujoco/_functions.pyi +0 -2950
- mujoco_mojo-2.3.0/typings/mujoco/_render.pyi +0 -503
- mujoco_mojo-2.3.0/typings/mujoco/_specs.pyi +0 -2988
- mujoco_mojo-2.3.0/typings/mujoco/_structs.pyi +0 -6587
- mujoco_mojo-2.3.0/typings/mujoco/cgl/__init__.pyi +0 -23
- mujoco_mojo-2.3.0/typings/mujoco/cgl/cgl.pyi +0 -89
- mujoco_mojo-2.3.0/typings/mujoco/gl_context.pyi +0 -14
- mujoco_mojo-2.3.0/typings/mujoco/glfw/__init__.pyi +0 -17
- mujoco_mojo-2.3.0/typings/mujoco/renderer.pyi +0 -113
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/.gitattributes +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/.github/workflows/docs.yml +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/.github/workflows/release.yml +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/.pre-commit-config.yaml +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/.python-version +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/.vscode/settings.json +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/LICENSE +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/README.md +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/TODO.md +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/about.md +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/dark-hero-logo.png +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/dark-hero-logo.svg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/dark-logo.svg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/light-hero-logo.svg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/light-logo.svg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/logo.svg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/mesh/bunny_original.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/mesh/bunny_with_coacd.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/mesh/bunny_without_coacd.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/mesh/frustums.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/mesh/proximity/convex_hull_wireframe.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/mesh/proximity/real_wireframe.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/mesh/with_coacd.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/mesh/without_coacd.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/dark-export-options.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/dark-monitor-view.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/dark-mosaic-view.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/dark-notes-editor.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/dark-plot-editor.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/dark-selector-bar.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/dark-shapes-editor.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/generate-result.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/light-export-options.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/light-monitor-view.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/light-mosaic-view.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/light-notes-editor.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/light-plot-editor.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/light-selector-bar.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/light-shapes-editor.jpg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/assets/user-guides/runtime-anim.gif +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/index.md +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/javascripts/favicon-switcher.js +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/javascripts/mojo-highlighter.js +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/javascripts/tablesort.js +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/stylesheets/extra.css +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/user-guides/MOJO_RUNTIME_REPORT.md +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/user-guides/dojo.md +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/user-guides/generate-script.md +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/user-guides/getting-started.md +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/user-guides/init.md +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/user-guides/monitor.md +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/user-guides/monte_carlo_example.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/user-guides/mosaic.md +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/user-guides/optimization.md +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/user-guides/optimization_example.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/user-guides/reloaded.md +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/user-guides/running-jobs.md +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/docs/user-guides/runtime-script.md +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/examples/boxes_and_springs_monte_carlo.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/examples/boxes_and_springs_optimization.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/examples/tennis_racket_theorem.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/mkdocs.yml +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/scripts/copy_docs_examples_to_examples.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/scripts/fix_smart_quotes.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/scripts/gen_ref_pages.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/scripts/templating/filestomake.txt +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/scripts/templating/make_sensors.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/scripts/templating/sensor_template.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/base.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/defaults.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/dependency_path.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/extension.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/meta/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/meta/frame.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/meta/include.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/meta/replicate.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/actuator.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/actuator_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/actuator_attr/adhesion.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/actuator_attr/base.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/actuator_attr/cylinder.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/actuator_attr/damper.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/actuator_attr/dcmotor.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/actuator_attr/general.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/actuator_attr/intvelocity.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/actuator_attr/motor.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/actuator_attr/muscle.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/actuator_attr/plugin.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/actuator_attr/position.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/actuator_attr/velocity.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/asset.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/asset_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/asset_attr/hfield.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/asset_attr/material.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/asset_attr/material_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/asset_attr/material_attr/layer.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/asset_attr/mesh.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/asset_attr/model.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/asset_attr/texture.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/attach.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/camera.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/composite.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/composite_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/composite_attr/geom.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/composite_attr/joint.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/composite_attr/site.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/composite_attr/skin.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/flexcomp.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/flexcomp_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/flexcomp_attr/contact.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/flexcomp_attr/edge.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/flexcomp_attr/elasticity.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/flexcomp_attr/pin.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/free_joint.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/geom.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/inertial.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/joint.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/light.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/plugin.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/body_attr/site.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/compiler.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/compiler_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/compiler_attr/lengthrange.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/contact.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/contact_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/contact_attr/exclude.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/contact_attr/pair.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/deformable.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/deformable_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/deformable_attr/flex.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/deformable_attr/flex_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/deformable_attr/flex_attr/contact.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/deformable_attr/flex_attr/edge.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/deformable_attr/flex_attr/elasticity.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/deformable_attr/skin.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/deformable_attr/skin_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/deformable_attr/skin_attr/bone.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/equality.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/equality_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/equality_attr/connect.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/equality_attr/equality_base.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/equality_attr/flex.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/equality_attr/flexstrain.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/equality_attr/flexvert.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/equality_attr/joint.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/equality_attr/tendon.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/equality_attr/weld.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/keyframe.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/keyframe_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/keyframe_attr/key.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/option.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/option_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/option_attr/flag.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/accelerometer.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/actuatorfrc.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/actuatorpos.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/actuatorvel.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/ballangvel.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/ballquat.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/base.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/base_collision.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/camprojection.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/clock.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/contact.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/distance.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/e_kinetic.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/e_potential.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/force.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/frameangacc.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/frameangvel.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/framelinacc.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/framelinvel.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/framepos.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/framequat.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/framexaxis.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/frameyaxis.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/framezaxis.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/fromto.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/gyro.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/insidesite.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/jointactuatorfrc.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/jointlimitfrc.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/jointlimitpos.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/jointlimitvel.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/jointpos.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/jointvel.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/magnetometer.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/normal.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/plugin.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/rangefinder.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/subtreeangmom.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/subtreecom.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/subtreelinvel.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/tactile.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/tendonactuatorfrc.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/tendonlimitfrc.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/tendonlimitpos.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/tendonlimitvel.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/tendonpos.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/tendonvel.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/torque.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/touch.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/user.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/sensor_attr/velocimeter.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/size.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/statistic.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/tendon.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/tendon_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/tendon_attr/fixed.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/tendon_attr/fixed_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/tendon_attr/fixed_attr/joint.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/tendon_attr/spatial.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/tendon_attr/spatial_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/tendon_attr/spatial_attr/geom.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/tendon_attr/spatial_attr/pulley.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/tendon_attr/spatial_attr/site.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/tendon_attr/tendon_base.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/visual.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/visual_attr/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/visual_attr/global_.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/visual_attr/headlight.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/visual_attr/map.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/visual_attr/quality.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/visual_attr/rgba.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/mujoco_attr/visual_attr/scale.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/orientation.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/plugin.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/pose.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/position.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/mjcf/xml_model.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/runtime/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/runtime/load.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/runtime/runtime_manager.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/runtime/signal_manager.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/stochas/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/templates/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/templates/monte_carlo.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/templates/optimization.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/templates/reloaded.sh +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/templates/run_mc.sh +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/templates/run_opt.sh +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/color.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/defaults.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/filters/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/interp.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/routers/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/routers/morph.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/shared.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/error.html +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/monitor.html +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/morph.html +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/mosaic.html +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/partials/trial_viewer/_header.html +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/partials/trial_viewer/_lab_trigger.html +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/partials/trial_viewer/_macros.html +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/partials/trial_viewer/_overlays.html +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/partials/trial_viewer/_series_panel.html +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/chime.mp3 +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/dark-logo.svg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/js/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/js/toast.d.ts +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/js/toast.d.ts.map +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/js/toast.js +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/light-logo.svg +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/main.css +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/src/cm-bundle.ts +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/src/lib/format.ts +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/src/lib/options.ts +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/src/lib/toast.ts +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/ts/tsconfig.json +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/vendored/__init__.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/vendored/alpine.min.js +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/vendored/codemirror.bundle.js +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/vendored/confetti.browser.min.js +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/vendored/iro.min.js +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/vendored/litegraph.min.css +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/vendored/litegraph.min.js +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/vendored/lz-string.min.js +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/vendored/plotly-3.4.0.min.js +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/layers/dojo/templates/static/vendored/tailwind.min.js +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/log.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/proximity.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/proximity_mixin.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/utils/utils.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/src/mujoco_mojo/visualization.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/.gitignore +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/make_skybox.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/meshes/ball.stl +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/meshes/bunny2.stl +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/meshes/cup.stl +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/mjcf/inertial_test.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/mjcf/mesh.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/mjcf/orientation_test.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/mjcf/pos_test.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/mjcf/pose_test.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/mjcf/xml_model_test.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/model_with_skybox.xml +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/monte_carlo_test/asset_image.png +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/monte_carlo_test/monte_carlo.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/monte_carlo_test/overrides.json +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/monte_carlo_test/running_with_slurm.sh +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/runtime/conftest.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/runtime/loads_test.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/runtime/optimizer_bumper.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/runtime/runtime_manager_test.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/runtime/signal_manager_test.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/smoke_test.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/test_writer.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/utils/color_test.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/utils/dataframe_test.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/utils/filter_test.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/utils/interp_test.py +0 -0
- {mujoco_mojo-2.3.0 → mujoco_mojo-2.3.2}/tests/utils/proximity_test.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mujoco-mojo
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.2
|
|
4
4
|
Summary: A complete MJCF lifecycle and trial orchestration suite for MuJoCo, powered by Pydantic v2.
|
|
5
5
|
Project-URL: Homepage, https://github.com/Hydrowelder/mujoco-mojo
|
|
6
6
|
Project-URL: Documentation, https://hydrowelder.github.io/mujoco-mojo/
|
|
@@ -42,6 +42,7 @@ Requires-Dist: pip>=26.0.1
|
|
|
42
42
|
Requires-Dist: polars>=1.39.0
|
|
43
43
|
Requires-Dist: pyarrow>=23.0.1
|
|
44
44
|
Requires-Dist: pybind11-stubgen>=2.5.5
|
|
45
|
+
Requires-Dist: pydantic-settings>=2.14.1
|
|
45
46
|
Requires-Dist: pydantic>=2.12.5
|
|
46
47
|
Requires-Dist: python-fcl>=0.7.0.11
|
|
47
48
|
Requires-Dist: rich>=14.3.3
|
|
@@ -51,12 +52,14 @@ Requires-Dist: scipy>=1.17.0
|
|
|
51
52
|
Requires-Dist: sse-starlette>=3.3.4
|
|
52
53
|
Requires-Dist: stochas>=2.0.0
|
|
53
54
|
Requires-Dist: tabulate>=0.9.0
|
|
55
|
+
Requires-Dist: tomli-w>=1.2.0
|
|
54
56
|
Requires-Dist: trimesh>=4.11.2
|
|
55
57
|
Requires-Dist: typer>=0.24.1
|
|
56
58
|
Requires-Dist: uvicorn>=0.41.0
|
|
57
59
|
Provides-Extra: reloaded
|
|
58
60
|
Requires-Dist: mjviser>=0.0.11; extra == 'reloaded'
|
|
59
61
|
Requires-Dist: viser>=1.0.26; extra == 'reloaded'
|
|
62
|
+
Requires-Dist: watchfiles>=1.1.1; extra == 'reloaded'
|
|
60
63
|
Description-Content-Type: text/markdown
|
|
61
64
|
|
|
62
65
|
<p align="center">
|
|
@@ -42,6 +42,8 @@ dependencies = [
|
|
|
42
42
|
"python-fcl>=0.7.0.11",
|
|
43
43
|
"rtree>=1.4.1",
|
|
44
44
|
"filelock>=3.29.0",
|
|
45
|
+
"pydantic-settings>=2.14.1",
|
|
46
|
+
"tomli-w>=1.2.0",
|
|
45
47
|
]
|
|
46
48
|
classifiers = [
|
|
47
49
|
"Development Status :: 4 - Beta",
|
|
@@ -69,7 +71,8 @@ keywords = [
|
|
|
69
71
|
]
|
|
70
72
|
|
|
71
73
|
[project.optional-dependencies]
|
|
72
|
-
reloaded = ["mjviser>=0.0.11", "viser>=1.0.26"]
|
|
74
|
+
reloaded = ["mjviser>=0.0.11", "viser>=1.0.26", "watchfiles>=1.1.1"]
|
|
75
|
+
# sensai = ["pydantic-ai>=1.102.0", "requests>=2.32.5"]
|
|
73
76
|
|
|
74
77
|
[dependency-groups]
|
|
75
78
|
dev = [
|
|
@@ -143,7 +146,7 @@ ignore = [
|
|
|
143
146
|
]
|
|
144
147
|
|
|
145
148
|
[tool.pyright]
|
|
146
|
-
stubPath = "typings"
|
|
149
|
+
stubPath = "./typings"
|
|
147
150
|
venvPath = ".."
|
|
148
151
|
venv = ".venv"
|
|
149
152
|
ignore = ["typings", "scripts/templating/sensor_template.py"]
|
|
@@ -1033,9 +1033,9 @@ optype==0.15.0 \
|
|
|
1033
1033
|
--hash=sha256:457d6ca9e7da19967ec16d42bdf94e240b33b5d70a56fbbf5b427e5ea39cf41e \
|
|
1034
1034
|
--hash=sha256:caba40ece9ea39b499fa76c036a82e0d452a432dd4dd3e8e0d30892be2e8c76c
|
|
1035
1035
|
# via scipy-stubs
|
|
1036
|
-
packaging==
|
|
1037
|
-
--hash=sha256:
|
|
1038
|
-
--hash=sha256:
|
|
1036
|
+
packaging==25.0 \
|
|
1037
|
+
--hash=sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484 \
|
|
1038
|
+
--hash=sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f
|
|
1039
1039
|
# via
|
|
1040
1040
|
# fastparquet
|
|
1041
1041
|
# ipykernel
|
|
@@ -1293,6 +1293,7 @@ pydantic==2.12.5 \
|
|
|
1293
1293
|
# fastapi
|
|
1294
1294
|
# mujoco-mojo
|
|
1295
1295
|
# numpydantic
|
|
1296
|
+
# pydantic-settings
|
|
1296
1297
|
# stochas
|
|
1297
1298
|
pydantic-core==2.41.5 \
|
|
1298
1299
|
--hash=sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90 \
|
|
@@ -1357,6 +1358,10 @@ pydantic-core==2.41.5 \
|
|
|
1357
1358
|
--hash=sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75 \
|
|
1358
1359
|
--hash=sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7
|
|
1359
1360
|
# via pydantic
|
|
1361
|
+
pydantic-settings==2.14.1 \
|
|
1362
|
+
--hash=sha256:6e3c7edfd8277687cdc598f56e5cff0e9bfff0910a3749deaa8d4401c3a2b9de \
|
|
1363
|
+
--hash=sha256:e874d3bec7e787b0c9958277956ed9b4dd5de6a80e162188fdaff7c5e26fd5fa
|
|
1364
|
+
# via mujoco-mojo
|
|
1360
1365
|
pygments==2.19.2 \
|
|
1361
1366
|
--hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \
|
|
1362
1367
|
--hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b
|
|
@@ -1420,6 +1425,10 @@ python-dateutil==2.9.0.post0 \
|
|
|
1420
1425
|
# jupyter-client
|
|
1421
1426
|
# matplotlib
|
|
1422
1427
|
# pandas
|
|
1428
|
+
python-dotenv==1.2.2 \
|
|
1429
|
+
--hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \
|
|
1430
|
+
--hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3
|
|
1431
|
+
# via pydantic-settings
|
|
1423
1432
|
python-fcl==0.7.0.11 \
|
|
1424
1433
|
--hash=sha256:0a48312a0dcd8466e79be4b5025f52168d0e5b866b809f727923b313246989bc \
|
|
1425
1434
|
--hash=sha256:136585069f547c303d9b7d7a3e9a63e0b03937279532cd3144c0f12c5ce853d2 \
|
|
@@ -1735,6 +1744,10 @@ tabulate==0.9.0 \
|
|
|
1735
1744
|
--hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \
|
|
1736
1745
|
--hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f
|
|
1737
1746
|
# via mujoco-mojo
|
|
1747
|
+
tomli-w==1.2.0 \
|
|
1748
|
+
--hash=sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90 \
|
|
1749
|
+
--hash=sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021
|
|
1750
|
+
# via mujoco-mojo
|
|
1738
1751
|
tornado==6.5.5 \
|
|
1739
1752
|
--hash=sha256:192b8f3ea91bd7f1f50c06955416ed76c6b72f96779b962f07f911b91e8d30e9 \
|
|
1740
1753
|
--hash=sha256:2c9a876e094109333f888539ddb2de4361743e5d21eece20688e3e351e4990a6 \
|
|
@@ -1794,6 +1807,7 @@ typing-inspection==0.4.2 \
|
|
|
1794
1807
|
# via
|
|
1795
1808
|
# fastapi
|
|
1796
1809
|
# pydantic
|
|
1810
|
+
# pydantic-settings
|
|
1797
1811
|
tzdata==2025.3 ; sys_platform == 'emscripten' or sys_platform == 'win32' \
|
|
1798
1812
|
--hash=sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1 \
|
|
1799
1813
|
--hash=sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7
|
|
@@ -1890,64 +1904,49 @@ wcwidth==0.6.0 \
|
|
|
1890
1904
|
--hash=sha256:1a3a1e510b553315f8e146c54764f4fb6264ffad731b3d78088cdb1478ffbdad \
|
|
1891
1905
|
--hash=sha256:cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159
|
|
1892
1906
|
# via prompt-toolkit
|
|
1893
|
-
wrapt==
|
|
1894
|
-
--hash=sha256:
|
|
1895
|
-
--hash=sha256:
|
|
1896
|
-
--hash=sha256:
|
|
1897
|
-
--hash=sha256:
|
|
1898
|
-
--hash=sha256:
|
|
1899
|
-
--hash=sha256:
|
|
1900
|
-
--hash=sha256:
|
|
1901
|
-
--hash=sha256:
|
|
1902
|
-
--hash=sha256:
|
|
1903
|
-
--hash=sha256:
|
|
1904
|
-
--hash=sha256:
|
|
1905
|
-
--hash=sha256:
|
|
1906
|
-
--hash=sha256:
|
|
1907
|
-
--hash=sha256:
|
|
1908
|
-
--hash=sha256:
|
|
1909
|
-
--hash=sha256:
|
|
1910
|
-
--hash=sha256:
|
|
1911
|
-
--hash=sha256:
|
|
1912
|
-
--hash=sha256:
|
|
1913
|
-
--hash=sha256:
|
|
1914
|
-
--hash=sha256:
|
|
1915
|
-
--hash=sha256:
|
|
1916
|
-
--hash=sha256:
|
|
1917
|
-
--hash=sha256:
|
|
1918
|
-
--hash=sha256:
|
|
1919
|
-
--hash=sha256:
|
|
1920
|
-
--hash=sha256:
|
|
1921
|
-
--hash=sha256:
|
|
1922
|
-
--hash=sha256:
|
|
1923
|
-
--hash=sha256:
|
|
1924
|
-
--hash=sha256:
|
|
1925
|
-
--hash=sha256:
|
|
1926
|
-
--hash=sha256:
|
|
1927
|
-
--hash=sha256:
|
|
1928
|
-
--hash=sha256:
|
|
1929
|
-
--hash=sha256:
|
|
1930
|
-
--hash=sha256:
|
|
1931
|
-
--hash=sha256:
|
|
1932
|
-
--hash=sha256:
|
|
1933
|
-
--hash=sha256:
|
|
1934
|
-
--hash=sha256:
|
|
1935
|
-
--hash=sha256:
|
|
1936
|
-
--hash=sha256:c20b757c268d30d6215916a5fa8461048d023865d888e437fab451139cad6c8e \
|
|
1937
|
-
--hash=sha256:c7e6cd120ef837d5b6f860a6ea3745f8763805c418bb2f12eeb1fa6e25f22d22 \
|
|
1938
|
-
--hash=sha256:c8e46ae8e4032792eb2f677dbd0d557170a8e5524d22acc55199f43efedd39bf \
|
|
1939
|
-
--hash=sha256:da1f00a557c66225d53b095a97eace0fc5349e3bfda28fa34ffae238978ee575 \
|
|
1940
|
-
--hash=sha256:de9f1a2bbc5ac7f6012ec24525bdd444765a2ff64b5985ac6e0692144838542e \
|
|
1941
|
-
--hash=sha256:e3d3b35eedcf5f7d022291ecd7533321c4775f7b9cd0050a31a68499ba45757c \
|
|
1942
|
-
--hash=sha256:e6ed62c82ddf58d001096ae84ce7f833db97ae2263bff31c9b336ba8cfe3f508 \
|
|
1943
|
-
--hash=sha256:eba8155747eb2cae4a0b913d9ebd12a1db4d860fc4c829d7578c7b989bd3f2f0 \
|
|
1944
|
-
--hash=sha256:f01277d9a5fc1862f26f7626da9cf443bebc0abd2f303f41c5e995b15887dabd \
|
|
1945
|
-
--hash=sha256:f29c827a8d9936ac320746747a016c4bc66ef639f5cd0d32df24f5eacbf9c69f \
|
|
1946
|
-
--hash=sha256:f8bc1c264d8d1cf5b3560a87bbdd31131573eb25f9f9447bb6252b8d4c44a3a1 \
|
|
1947
|
-
--hash=sha256:f8fba1bae256186a83d1875b2b1f4e2d1242e8fac0f58ec0d7e41b26967b965c \
|
|
1948
|
-
--hash=sha256:fab036efe5464ec3291411fabb80a7a39e2dd80bae9bcbeeca5087fdfa891e19 \
|
|
1949
|
-
--hash=sha256:ff2aad9c4cda28a8f0653fc2d487596458c2a3f475e56ba02909e950a9efa6a9 \
|
|
1950
|
-
--hash=sha256:ff95d4264e55839be37bafe1536db2ab2de19da6b65f9244f01f332b5286cfbf
|
|
1907
|
+
wrapt==1.17.3 \
|
|
1908
|
+
--hash=sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828 \
|
|
1909
|
+
--hash=sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396 \
|
|
1910
|
+
--hash=sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d \
|
|
1911
|
+
--hash=sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7 \
|
|
1912
|
+
--hash=sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb \
|
|
1913
|
+
--hash=sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f \
|
|
1914
|
+
--hash=sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067 \
|
|
1915
|
+
--hash=sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b \
|
|
1916
|
+
--hash=sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7 \
|
|
1917
|
+
--hash=sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9 \
|
|
1918
|
+
--hash=sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977 \
|
|
1919
|
+
--hash=sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa \
|
|
1920
|
+
--hash=sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe \
|
|
1921
|
+
--hash=sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58 \
|
|
1922
|
+
--hash=sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8 \
|
|
1923
|
+
--hash=sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77 \
|
|
1924
|
+
--hash=sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454 \
|
|
1925
|
+
--hash=sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e \
|
|
1926
|
+
--hash=sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c \
|
|
1927
|
+
--hash=sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6 \
|
|
1928
|
+
--hash=sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd \
|
|
1929
|
+
--hash=sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277 \
|
|
1930
|
+
--hash=sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22 \
|
|
1931
|
+
--hash=sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116 \
|
|
1932
|
+
--hash=sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16 \
|
|
1933
|
+
--hash=sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc \
|
|
1934
|
+
--hash=sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804 \
|
|
1935
|
+
--hash=sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba \
|
|
1936
|
+
--hash=sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0 \
|
|
1937
|
+
--hash=sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0 \
|
|
1938
|
+
--hash=sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39 \
|
|
1939
|
+
--hash=sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4 \
|
|
1940
|
+
--hash=sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa \
|
|
1941
|
+
--hash=sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050 \
|
|
1942
|
+
--hash=sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6 \
|
|
1943
|
+
--hash=sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235 \
|
|
1944
|
+
--hash=sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056 \
|
|
1945
|
+
--hash=sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c \
|
|
1946
|
+
--hash=sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a \
|
|
1947
|
+
--hash=sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6 \
|
|
1948
|
+
--hash=sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0 \
|
|
1949
|
+
--hash=sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10
|
|
1951
1950
|
# via deprecated
|
|
1952
1951
|
zensical==0.0.31 \
|
|
1953
1952
|
--hash=sha256:03fa11e629a308507693489541f43e751697784e94365e7435b02104aefd1c2c \
|
|
@@ -60,7 +60,11 @@ def _schema_to_ts(node: dict, defs: dict) -> str:
|
|
|
60
60
|
items = [_schema_to_ts(s, defs) for s in node["prefixItems"]]
|
|
61
61
|
return f"[{', '.join(items)}]"
|
|
62
62
|
if "items" in node:
|
|
63
|
-
|
|
63
|
+
items_node = node["items"]
|
|
64
|
+
# discriminated union (oneOf + discriminator) → use the FilterEntry alias
|
|
65
|
+
if "oneOf" in items_node and "discriminator" in items_node:
|
|
66
|
+
return "FilterEntry[]"
|
|
67
|
+
return f"{_schema_to_ts(items_node, defs)}[]"
|
|
64
68
|
return "unknown[]"
|
|
65
69
|
|
|
66
70
|
if t == "object":
|
|
@@ -150,6 +154,13 @@ def main() -> None:
|
|
|
150
154
|
|
|
151
155
|
blocks: list[str] = []
|
|
152
156
|
|
|
157
|
+
# FilterEntry is the structural base for every discriminated filter object;
|
|
158
|
+
# emitted first so XAxisConfig/YAxisConfig can reference it.
|
|
159
|
+
blocks.append(
|
|
160
|
+
"/** a single filter in a filter stack — type-discriminated, open-ended properties. */\n"
|
|
161
|
+
"export type FilterEntry = { type: string; enabled?: boolean; [key: string]: unknown };\n"
|
|
162
|
+
)
|
|
163
|
+
|
|
153
164
|
# Emit each $def in definition order
|
|
154
165
|
for def_name, def_schema in defs.items():
|
|
155
166
|
blocks.append(_def_to_ts(def_name, def_schema, defs))
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from datetime import date
|
|
1
2
|
from importlib.metadata import PackageNotFoundError, version
|
|
2
3
|
|
|
3
4
|
try:
|
|
@@ -9,3 +10,5 @@ __author__ = "David Gable"
|
|
|
9
10
|
__email__ = "dave.a.gable@gmail.com"
|
|
10
11
|
__license__ = "Apache-2.0"
|
|
11
12
|
__summary__ = "A complete MJCF lifecycle and trial orchestration suite for MuJoCo, powered by Pydantic v2."
|
|
13
|
+
__copyright__ = f"© {date.today().year} David Gable"
|
|
14
|
+
__url__ = "https://github.com/Hydrowelder/mujoco-mojo"
|
|
@@ -12,7 +12,7 @@ MuJoCo does not ship Python type stubs. Generate them once with pybind11-stubgen
|
|
|
12
12
|
pip install pybind11-stubgen
|
|
13
13
|
pybind11-stubgen mujoco -o typings/ --numpy-array-wrap-with-annotated
|
|
14
14
|
|
|
15
|
-
Run this from the project root. The
|
|
15
|
+
Run this from the project root. The `typings/` directory is gitignored.
|
|
16
16
|
Then add to pyproject.toml:
|
|
17
17
|
|
|
18
18
|
.. code-block:: toml
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from pydantic import HttpUrl
|
|
4
|
+
|
|
5
|
+
from mujoco_mojo.__about__ import __url__
|
|
6
|
+
|
|
7
|
+
REPO_URL = HttpUrl(url=__url__)
|
|
8
|
+
"""Link to the remote repo for use with reporting elements."""
|
|
9
|
+
|
|
10
|
+
MUJOCO_MOJO_DIR: Path = Path.home() / ".mujoco-mojo"
|
|
11
|
+
"""Canonical user-level directory for all mujoco-mojo data (settings, profiles, lab graphs, etc.)."""
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from pathlib import Path
|
|
3
4
|
from typing import TypeVar
|
|
4
5
|
|
|
5
|
-
from pydantic import BaseModel, ConfigDict, Field, SerializeAsAny
|
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, SerializeAsAny
|
|
6
7
|
from stochas import StochasBase
|
|
7
8
|
|
|
8
9
|
from mujoco_mojo.base import MojoBaseModel
|
|
@@ -32,6 +33,22 @@ class MojoModel(MojoBaseModel, StochasBase):
|
|
|
32
33
|
user_data: SerializeAsAny[UserData] | None = None
|
|
33
34
|
"""User defined data for the model. This is used for transferring information from one function to another (generator to runtime or objective function)."""
|
|
34
35
|
|
|
36
|
+
_trial_dir: Path | None = PrivateAttr(default=None)
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def trial_dir(self) -> Path:
|
|
40
|
+
"""
|
|
41
|
+
Absolute path to this trial's workspace directory.
|
|
42
|
+
|
|
43
|
+
Set automatically after the generator runs. Available in runtime and objective functions. Raises `RuntimeError` if accessed inside the generator, where the directory has not yet been created.
|
|
44
|
+
"""
|
|
45
|
+
if self._trial_dir is None:
|
|
46
|
+
raise RuntimeError(
|
|
47
|
+
"trial_dir is not available inside the generator. "
|
|
48
|
+
"It is set after generation completes and the workspace is created."
|
|
49
|
+
)
|
|
50
|
+
return self._trial_dir
|
|
51
|
+
|
|
35
52
|
def get_user_data(self, cls: type[T]) -> T:
|
|
36
53
|
"""Returns the user_data re-validated into the requested class."""
|
|
37
54
|
if self.user_data is None:
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import TYPE_CHECKING, Self
|
|
4
|
+
|
|
5
|
+
import mujoco
|
|
6
|
+
|
|
7
|
+
from mujoco_mojo.typing import CameraName
|
|
8
|
+
from mujoco_mojo.utils.log import get_logger
|
|
9
|
+
from mujoco_mojo.visualization import ArrowConfig, LineConfig
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from mujoco_mojo.runtime.runtime_manager import RuntimeManager
|
|
13
|
+
|
|
14
|
+
logger = get_logger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class VideoRecorder:
|
|
19
|
+
"""
|
|
20
|
+
Records a MuJoCo simulation to a video file.
|
|
21
|
+
|
|
22
|
+
Frames are captured at a fixed rate (`fps`) relative to simulation time, not wall-clock time, so the output plays back at the exact rate specified regardless of how fast the simulation runs. The recorder skips `capture_frame` calls that fall between the interval boundaries, which prevents duplicate frames when the physics step is finer than 1/fps.
|
|
23
|
+
|
|
24
|
+
Typical usage inside a runtime function::
|
|
25
|
+
|
|
26
|
+
recorder = VideoRecorder(
|
|
27
|
+
path=model.trial_dir / "camera.mp4",
|
|
28
|
+
camera_name="top_view",
|
|
29
|
+
fps=30,
|
|
30
|
+
width=1280,
|
|
31
|
+
height=720,
|
|
32
|
+
).setup(mj_model).register_to_rm(runtime_manager)
|
|
33
|
+
|
|
34
|
+
`register_to_rm` wires the recorder into the `RuntimeManager` so that `capture_frame` is called automatically on every physics step and `save` is called when the simulation finishes.
|
|
35
|
+
|
|
36
|
+
Supported output formats (determined by the `path` extension):
|
|
37
|
+
|
|
38
|
+
- `.mp4`: H.264 via mediapy/ffmpeg; widest browser and player compatibility.
|
|
39
|
+
- `.webm`: VP9 via ffmpeg; smaller files, fully seekable in the Dojo viewer. Requires ffmpeg with libvpx-vp9 support.
|
|
40
|
+
- `.gif`: via PIL; no audio, loops automatically; large file size, not seekable.
|
|
41
|
+
|
|
42
|
+
Visual overlays (contact forces, net forces, custom arrows/lines) are controlled by the `show_*` flags and the `show_loads` flag passed to `capture_frame`.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
path: Path
|
|
46
|
+
"""Output file path. The extension determines the container and codec."""
|
|
47
|
+
|
|
48
|
+
camera_name: CameraName
|
|
49
|
+
"""Name of the MuJoCo camera to render from (must exist in the model)."""
|
|
50
|
+
|
|
51
|
+
show_loads: bool = False
|
|
52
|
+
"""Whether to render custom arrow overlays (passed via `custom_arrows` in `capture_frame`)."""
|
|
53
|
+
|
|
54
|
+
show_net_force: bool = False
|
|
55
|
+
"""Whether to render net force visualizations (`mjVIS_PERTFORCE`)."""
|
|
56
|
+
|
|
57
|
+
show_contacts: bool = False
|
|
58
|
+
"""Whether to render contact force visualizations (`mjVIS_CONTACTFORCE`)."""
|
|
59
|
+
|
|
60
|
+
show_proximities: bool = False
|
|
61
|
+
"""Whether to render custom line overlays (passed via `custom_lines` in `capture_frame`)."""
|
|
62
|
+
|
|
63
|
+
fps: int = 30
|
|
64
|
+
"""Target frame rate of the output video. Frames are sampled every `1/fps` seconds of simulation time."""
|
|
65
|
+
|
|
66
|
+
width: int = 640
|
|
67
|
+
"""Render width in pixels."""
|
|
68
|
+
|
|
69
|
+
height: int = 480
|
|
70
|
+
"""Render height in pixels."""
|
|
71
|
+
|
|
72
|
+
_frames: list = field(default_factory=list)
|
|
73
|
+
_renderer: mujoco.Renderer = field(init=False)
|
|
74
|
+
_vopt: mujoco.MjvOption = field(default_factory=mujoco.MjvOption, init=False)
|
|
75
|
+
_next_record_time: float = field(default=0.0, init=False)
|
|
76
|
+
|
|
77
|
+
def setup(self, mj_model: mujoco.MjModel) -> Self:
|
|
78
|
+
"""Initializes the MuJoCo renderer for this model. Must be called before the simulation loop."""
|
|
79
|
+
try:
|
|
80
|
+
self._renderer = mujoco.Renderer(
|
|
81
|
+
model=mj_model, height=self.height, width=self.width
|
|
82
|
+
)
|
|
83
|
+
except Exception as e:
|
|
84
|
+
msg = "Failed to initialize the MuJoCo Renderer. If on a server, try setting 'export MUJOCO_GL=egl' in your terminal."
|
|
85
|
+
logger.error(msg)
|
|
86
|
+
raise RuntimeError(msg) from e
|
|
87
|
+
|
|
88
|
+
# initialize the vopt with defaults
|
|
89
|
+
mujoco.mjv_defaultOption(self._vopt)
|
|
90
|
+
|
|
91
|
+
# whether or not to show debug graphics
|
|
92
|
+
self._vopt.flags[mujoco.mjtVisFlag.mjVIS_PERTFORCE] = int(self.show_net_force)
|
|
93
|
+
self._vopt.flags[mujoco.mjtVisFlag.mjVIS_CONTACTFORCE] = int(self.show_contacts)
|
|
94
|
+
return self
|
|
95
|
+
|
|
96
|
+
def capture_frame(
|
|
97
|
+
self,
|
|
98
|
+
mj_model: mujoco.MjModel,
|
|
99
|
+
mj_data: mujoco.MjData,
|
|
100
|
+
custom_arrows: list[ArrowConfig],
|
|
101
|
+
custom_lines: list[LineConfig],
|
|
102
|
+
):
|
|
103
|
+
"""Captures the current state as a video frame."""
|
|
104
|
+
if mj_data.time < self._next_record_time:
|
|
105
|
+
return
|
|
106
|
+
|
|
107
|
+
# update standard mujoco objects in scene
|
|
108
|
+
self._renderer.update_scene(
|
|
109
|
+
data=mj_data,
|
|
110
|
+
camera=self.camera_name,
|
|
111
|
+
scene_option=self._vopt,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
if custom_arrows and self.show_loads:
|
|
115
|
+
for arrow in custom_arrows:
|
|
116
|
+
arrow.draw_in_scene(mj_model, self._renderer.scene)
|
|
117
|
+
|
|
118
|
+
if custom_lines and self.show_proximities:
|
|
119
|
+
for line in custom_lines:
|
|
120
|
+
line.draw_in_scene(self._renderer.scene)
|
|
121
|
+
|
|
122
|
+
# capture and increment the clock for the next frame
|
|
123
|
+
self._frames.append(self._renderer.render())
|
|
124
|
+
self._next_record_time += 1 / self.fps
|
|
125
|
+
|
|
126
|
+
def save(self):
|
|
127
|
+
"""
|
|
128
|
+
Writes the captured frames to a video file.
|
|
129
|
+
|
|
130
|
+
Supported formats:
|
|
131
|
+
- `.mp4` — H.264 via mediapy/ffmpeg; universally compatible.
|
|
132
|
+
- `.webm` — VP9 via mediapy/ffmpeg; smaller files and fully seekable.
|
|
133
|
+
- `.gif` — via PIL; no audio, loops automatically, large file size, not seekable.
|
|
134
|
+
|
|
135
|
+
The output format is determined by the extension of `path`.
|
|
136
|
+
"""
|
|
137
|
+
if not self._frames:
|
|
138
|
+
return
|
|
139
|
+
import mediapy as media
|
|
140
|
+
|
|
141
|
+
if self.path.suffix.lower() == ".gif":
|
|
142
|
+
from PIL import Image
|
|
143
|
+
|
|
144
|
+
# convert arrays to PIL images
|
|
145
|
+
pil_images = [Image.fromarray(frame) for frame in self._frames]
|
|
146
|
+
|
|
147
|
+
# save gif
|
|
148
|
+
pil_images[0].save(
|
|
149
|
+
self.path,
|
|
150
|
+
save_all=True,
|
|
151
|
+
append_images=pil_images[1:],
|
|
152
|
+
duration=int(1000 / self.fps), # ms per frame
|
|
153
|
+
loop=0, # loop forever
|
|
154
|
+
)
|
|
155
|
+
elif self.path.suffix.lower() == ".webm":
|
|
156
|
+
self._save_webm()
|
|
157
|
+
else:
|
|
158
|
+
media.write_video(path=self.path, images=self._frames, fps=self.fps)
|
|
159
|
+
logger.info(f"Video saved to {self.path}")
|
|
160
|
+
|
|
161
|
+
def _save_webm(self) -> None:
|
|
162
|
+
"""Encodes frames to VP9 WebM by piping raw RGB directly to ffmpeg (no intermediate file)."""
|
|
163
|
+
import subprocess
|
|
164
|
+
|
|
165
|
+
h_raw, w_raw = self._frames[0].shape[:2]
|
|
166
|
+
# yuv420p requires even dimensions
|
|
167
|
+
w = w_raw - (w_raw % 2)
|
|
168
|
+
h = h_raw - (h_raw % 2)
|
|
169
|
+
|
|
170
|
+
proc = subprocess.Popen(
|
|
171
|
+
[
|
|
172
|
+
"ffmpeg",
|
|
173
|
+
"-y",
|
|
174
|
+
"-f",
|
|
175
|
+
"rawvideo",
|
|
176
|
+
"-vcodec",
|
|
177
|
+
"rawvideo",
|
|
178
|
+
"-s",
|
|
179
|
+
f"{w}x{h}",
|
|
180
|
+
"-pix_fmt",
|
|
181
|
+
"rgb24",
|
|
182
|
+
"-r",
|
|
183
|
+
str(self.fps),
|
|
184
|
+
"-i",
|
|
185
|
+
"pipe:0",
|
|
186
|
+
"-c:v",
|
|
187
|
+
"libvpx-vp9",
|
|
188
|
+
"-b:v",
|
|
189
|
+
"0",
|
|
190
|
+
"-crf",
|
|
191
|
+
"33",
|
|
192
|
+
"-cpu-used",
|
|
193
|
+
"2", # 0=slowest/best ... 8=fastest/worst; 4 is a good balance
|
|
194
|
+
"-row-mt",
|
|
195
|
+
"1", # row-based multithreading
|
|
196
|
+
"-threads",
|
|
197
|
+
"0", # use all available cores
|
|
198
|
+
"-an",
|
|
199
|
+
"-pix_fmt",
|
|
200
|
+
"yuv420p",
|
|
201
|
+
str(self.path),
|
|
202
|
+
],
|
|
203
|
+
stdin=subprocess.PIPE,
|
|
204
|
+
stderr=subprocess.DEVNULL,
|
|
205
|
+
)
|
|
206
|
+
try:
|
|
207
|
+
assert proc.stdin is not None
|
|
208
|
+
for frame in self._frames:
|
|
209
|
+
proc.stdin.write(frame[:h, :w].tobytes())
|
|
210
|
+
proc.stdin.close()
|
|
211
|
+
if proc.wait() != 0:
|
|
212
|
+
raise RuntimeError(
|
|
213
|
+
f"ffmpeg exited with a non-zero status while encoding {self.path}"
|
|
214
|
+
)
|
|
215
|
+
except Exception:
|
|
216
|
+
proc.kill()
|
|
217
|
+
raise
|
|
218
|
+
|
|
219
|
+
def register_to_rm(self, runtime_manager: "RuntimeManager") -> Self:
|
|
220
|
+
runtime_manager.add_video_recorder(self)
|
|
221
|
+
return self
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""Global user settings for mujoco_mojo, persisted to ~/.mujoco-mojo/settings.toml."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import tomli_w
|
|
6
|
+
from pydantic import BaseModel, Field, SecretStr, field_serializer
|
|
7
|
+
from pydantic_settings import (
|
|
8
|
+
BaseSettings,
|
|
9
|
+
PydanticBaseSettingsSource,
|
|
10
|
+
SettingsConfigDict,
|
|
11
|
+
TomlConfigSettingsSource,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
from mujoco_mojo.meta import MUJOCO_MOJO_DIR
|
|
15
|
+
|
|
16
|
+
SETTINGS_DIR = MUJOCO_MOJO_DIR
|
|
17
|
+
SETTINGS_FILE = SETTINGS_DIR / "settings.toml"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SensAISettings(BaseModel):
|
|
21
|
+
"""Settings for the SensAI assistant embedded in the Dojo dashboard."""
|
|
22
|
+
|
|
23
|
+
model_name: str = Field(default="qwen2.5:0.5b")
|
|
24
|
+
"""Ollama model identifier (e.g. `qwen2.5:0.5b`, `llama3.2:3b`)."""
|
|
25
|
+
|
|
26
|
+
base_url: str = Field(default="http://localhost:11434/v1")
|
|
27
|
+
"""Base URL for the OpenAI-compatible endpoint. Defaults to local Ollama."""
|
|
28
|
+
|
|
29
|
+
api_key: SecretStr = Field(default=SecretStr("ollama"))
|
|
30
|
+
"""API key sent with each request. For real keys prefer the `MUJOCO_MOJO_SENSAI__API_KEY` env var over storing here. Ollama ignores the value but the client requires a non-empty string."""
|
|
31
|
+
|
|
32
|
+
enabled: bool = Field(default=False)
|
|
33
|
+
"""Whether SensAI is active. Opt-in; toggled from the dashboard."""
|
|
34
|
+
|
|
35
|
+
@field_serializer("api_key")
|
|
36
|
+
def _serialize_api_key(self, v: SecretStr) -> str:
|
|
37
|
+
return v.get_secret_value()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class MujocoMojoSettings(BaseSettings):
|
|
41
|
+
"""
|
|
42
|
+
Global user-level settings persisted to ~/.mujoco-mojo/settings.toml.
|
|
43
|
+
|
|
44
|
+
Instantiate to load. Sources are checked in priority order: constructor kwargs > environment variables > TOML file > defaults. Environment variables use the prefix `MUJOCO_MOJO_` with `__` as the nested delimiter, e.g. `MUJOCO_MOJO_SENSAI__MODEL_NAME=llama3.2:3b`.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
model_config = SettingsConfigDict(
|
|
48
|
+
toml_file=SETTINGS_FILE,
|
|
49
|
+
env_prefix="MUJOCO_MOJO_",
|
|
50
|
+
env_nested_delimiter="__",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
sensai: SensAISettings = Field(default_factory=SensAISettings)
|
|
54
|
+
"""Settings for the SensAI assistant."""
|
|
55
|
+
|
|
56
|
+
@classmethod
|
|
57
|
+
def settings_customise_sources(
|
|
58
|
+
cls,
|
|
59
|
+
settings_cls: type[BaseSettings],
|
|
60
|
+
init_settings: PydanticBaseSettingsSource,
|
|
61
|
+
env_settings: PydanticBaseSettingsSource,
|
|
62
|
+
dotenv_settings: PydanticBaseSettingsSource,
|
|
63
|
+
file_secret_settings: PydanticBaseSettingsSource,
|
|
64
|
+
) -> tuple[PydanticBaseSettingsSource, ...]:
|
|
65
|
+
return (init_settings, env_settings, TomlConfigSettingsSource(settings_cls))
|
|
66
|
+
|
|
67
|
+
def save(self) -> None:
|
|
68
|
+
"""Persist current settings to ~/.mujoco-mojo/settings.toml."""
|
|
69
|
+
SETTINGS_DIR.mkdir(parents=True, exist_ok=True)
|
|
70
|
+
SETTINGS_FILE.write_bytes(tomli_w.dumps(self.model_dump()).encode())
|
|
@@ -104,9 +104,16 @@ else:
|
|
|
104
104
|
|
|
105
105
|
|
|
106
106
|
class ColumnManifest(TypedDict):
|
|
107
|
+
"""Manifest of all columns available for plotting."""
|
|
108
|
+
|
|
107
109
|
all: list[str]
|
|
110
|
+
"""Manifest of all columns available for plotting."""
|
|
111
|
+
|
|
108
112
|
rotatable_vectors: list[str]
|
|
113
|
+
"""All columns in self.all which are available be rotated using self.available_quats."""
|
|
114
|
+
|
|
109
115
|
available_quats: list[str]
|
|
116
|
+
"""All quaternion names which have enough information to rotate self.rotateable_vectors."""
|
|
110
117
|
|
|
111
118
|
|
|
112
119
|
class MojoNamespace:
|