virtualmodelcontrol 1.2.2__tar.gz → 1.3.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.
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/CHANGELOG.md +79 -4
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/CITATION.cff +2 -2
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/PKG-INFO +1 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/concepts/conventions.md +1 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/concepts/library.md +1 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/examples/hanging-arm.md +2 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/examples/soft-arm.md +9 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/installation.md +2 -2
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/extend.md +6 -2
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/fit.md +1 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/mpc.md +13 -6
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/optimize.md +7 -4
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/soft-and-assemblies.md +9 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/tuning.md +2 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/underactuated.md +163 -16
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/__init__.py +2 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/_version.py +2 -2
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/adaptation/seeking.py +2 -2
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/control/__init__.py +2 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/control/blending.py +2 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/control/controller.py +13 -5
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/control/output.py +62 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/control/schedule.py +2 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/control/state.py +1 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/control/tank.py +2 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/control/underactuated.py +23 -10
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/core/params.py +44 -14
- virtualmodelcontrol-1.3.0/src/virtualmodelcontrol/core/registry.py +89 -0
- virtualmodelcontrol-1.3.0/src/virtualmodelcontrol/identification/identifiability.py +29 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/identification/params.py +10 -20
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/identification/stiffness.py +19 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/__init__.py +2 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/components/gated.py +5 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/coordinates/__init__.py +2 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/coordinates/geometry.py +3 -3
- virtualmodelcontrol-1.3.0/src/virtualmodelcontrol/mechanisms/coordinates/joints.py +99 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/mechanism.py +16 -3
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/assembly.py +5 -3
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/asktell.py +33 -10
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/builder.py +26 -9
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/horizon.py +33 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/mpc.py +53 -22
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/problem.py +37 -5
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/solver.py +1 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/terms.py +3 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/robots/adapt.py +2 -2
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/robots/helyx.py +32 -2
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/robots/planar.py +20 -3
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/sim/rollout.py +7 -7
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/viz/style.py +2 -2
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/control/test_blending.py +10 -0
- virtualmodelcontrol-1.3.0/tests/control/test_inputs.py +76 -0
- virtualmodelcontrol-1.3.0/tests/control/test_output.py +131 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/control/test_schedule.py +14 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/control/test_state_layout.py +1 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/control/test_tank.py +10 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/control/test_underactuated.py +53 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/core/test_params.py +29 -0
- virtualmodelcontrol-1.3.0/tests/core/test_registry.py +82 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/identification/test_fit_params.py +27 -7
- virtualmodelcontrol-1.3.0/tests/identification/test_stiffness_fit.py +68 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/mechanisms/test_coordinates.py +7 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/mechanisms/test_gated.py +10 -0
- virtualmodelcontrol-1.3.0/tests/mechanisms/test_mechanism.py +79 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/models/test_actuation.py +11 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/models/test_assembly.py +57 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/models/test_pcc.py +17 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/models/test_poe.py +16 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_asktell.py +37 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_equilibrium.py +3 -3
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_horizon.py +36 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_mpc.py +81 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_plant.py +70 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_problem.py +20 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_solvers.py +2 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_structure.py +2 -1
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/robots/test_planar.py +13 -0
- virtualmodelcontrol-1.2.2/src/virtualmodelcontrol/core/registry.py +0 -54
- virtualmodelcontrol-1.2.2/src/virtualmodelcontrol/mechanisms/coordinates/joints.py +0 -51
- virtualmodelcontrol-1.2.2/tests/control/test_inputs.py +0 -32
- virtualmodelcontrol-1.2.2/tests/control/test_output.py +0 -63
- virtualmodelcontrol-1.2.2/tests/core/test_registry.py +0 -43
- virtualmodelcontrol-1.2.2/tests/identification/test_stiffness_fit.py +0 -27
- virtualmodelcontrol-1.2.2/tests/mechanisms/test_mechanism.py +0 -39
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/.gitignore +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/LICENSE +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/README.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/benchmarks/tick.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/_ext/video.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/_static/create-lab.png +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/_static/custom.css +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/_static/favicon.svg +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/_static/logo-light.svg +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/_static/logo.svg +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/_static/readme-hero.svg +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/_templates/autosummary/module.rst +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/_templates/partials/toc.html +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/api/index.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/concepts/efficiency.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/concepts/finger.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/concepts/passivity.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/concepts/pcc.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/concepts/vmc.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/conf.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/development/changelog.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/development/contributing.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/development/roadmap.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/development/support.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/docs_setup.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/examples/finger.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/examples/hand.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/examples/turtle.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/examples/two-arms.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/index.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/schematics/__init__.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/schematics/_draw.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/schematics/bimanual.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/schematics/control_loop.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/schematics/energy_flow.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/schematics/finger.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/schematics/four_steps.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/schematics/hand.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/schematics/helyx.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/schematics/library_map.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/schematics/mechanism.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/schematics/params.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/schematics/pcc.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/schematics/turtle.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/schematics/ur5.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/scripts/readme_figure.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/troubleshooting.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/build-a-robot.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/components.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/configurations.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/contact.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/coordinates-and-components.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/coordinates.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/crawl.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/energy.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/estimation.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/first-controller.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/force-estimates.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/force.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/friction.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/introduction.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/joints.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/kinematics.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/optimize-obstacles.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/optimize-periodic.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/outside.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/parameters.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/reach.yaml +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/real-time.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/run-logs.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/run-settings.yaml +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/stiffness.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/swaps.md +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/pyproject.toml +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/adaptation/__init__.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/adaptation/force.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/adaptation/limits.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/adaptation/position.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/adaptation/scalar.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/adaptation/stiffness.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/compiler.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/config/__init__.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/config/controllers.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/config/coordinates.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/config/experiment.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/config/files.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/config/spec.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/control/projection.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/core/__init__.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/core/backends.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/core/signals.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/core/space.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/core/symbolic.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/core/units.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/dynamics.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/estimation/__init__.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/estimation/balance.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/estimation/compliance.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/estimation/contact.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/estimation/imu.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/estimation/inversion.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/estimation/kalman.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/estimation/measurement.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/estimation/momentum.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/estimation/sensors.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/estimation/stiffness.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/estimation/velocity.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/hardware/__init__.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/hardware/profile.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/identification/__init__.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/identification/efficiency.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/identification/plateaus.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/identification/steps.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/identification/transmission.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/math.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/components/__init__.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/components/base.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/components/constrained.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/components/dissipation.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/components/inertance.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/components/locomotion.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/components/sources.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/components/storage.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/coordinates/base.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/coordinates/frames.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/coordinates/ops.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/mechanisms/coordinates/references.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/__init__.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/actuation.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/continuum/__init__.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/continuum/pcc.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/efficiency.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/equations.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/friction.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/function.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/joint_space.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/kinematic.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/kinematics.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/rigid/__init__.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/rigid/couplings.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/rigid/poe.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/models/rigid/spline.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/__init__.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/collocation.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/equilibrium.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/nlp.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/result.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/search.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/shooting.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/tank.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/trajectory.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/variables.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/optimization/virtual.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/py.typed +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/robots/__init__.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/robots/bimanual.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/robots/turtle.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/robots/ur5.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/sim/__init__.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/sim/balance.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/sim/model_plant.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/sim/plant.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/sim/replay.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/sim/run.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/sim/runlog.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/system.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/testing.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/viz/__init__.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/viz/animation.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/viz/draw.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/adaptation/test_fingertip.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/adaptation/test_force.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/adaptation/test_grasp.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/adaptation/test_holding.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/adaptation/test_loop.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/adaptation/test_position.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/adaptation/test_scalar.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/adaptation/test_seeking.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/adaptation/test_stiffness_tracking.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/adaptation/test_virtual_state.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/backend_helpers.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/config/test_config.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/conftest.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/control/test_honesty.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/control/test_projection.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/control/test_underactuated_golden.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/control/test_vmc_golden.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/core/test_backends.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/core/test_backends_torch.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/core/test_signals.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/core/test_space.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/core/test_symbolic.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/adaptation.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/compliance.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/components.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/configs/finger.yaml +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/configs/hand.yaml +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/configs/soft-arm.yaml +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/configs/turtle.yaml +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/configs/two-arms.yaml +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/configs/ur5-hand.yaml +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/derivatives.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/dynamics.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/efficiency.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/estimation.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/finger.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/fingertip.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/hand.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/heuristics.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/imu.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/kalman.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/mocap.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/optimization.json +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/optimization.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/pcc.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/transmission.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/turtle.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/underactuated.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/data/vmc.npz +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/estimation/test_compliance_golden.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/estimation/test_contact.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/estimation/test_imu.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/estimation/test_inversion.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/estimation/test_kalman.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/estimation/test_kalman_golden.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/estimation/test_kalman_unscented.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/estimation/test_mocap_golden.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/estimation/test_momentum.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/estimation/test_sensors.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/estimation/test_unmeasured.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/estimation/test_velocity.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/hardware/test_profile.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/hardware/test_templates.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/helpers.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/identification/test_efficiency_fit.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/identification/test_fit_friction.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/identification/test_friction.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/identification/test_steps.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/identification/test_transmission.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/lab_optimization.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/mechanisms/test_components.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/mechanisms/test_components_golden.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/mechanisms/test_contact.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/mechanisms/test_distances.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/mechanisms/test_frames.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/mechanisms/test_friction.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/mechanisms/test_more_components.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/mechanisms/test_pair_contact.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/mechanisms/test_phase_spring.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/mechanisms/test_virtual_model.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/models/test_contact_map.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/models/test_efficiency.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/models/test_equations.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/models/test_floating.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/models/test_floating_base.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/models/test_function.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/models/test_kinematics.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/models/test_rail.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/models/test_static_friction.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/models/test_underactuated.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_collocation.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_lab.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_periodic.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_search.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_shooting.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_swap.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_tank.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_terms.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_variables.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/optimization/test_virtual.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/robots/test_adapt.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/robots/test_bimanual.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/robots/test_crawler.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/robots/test_hand.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/robots/test_helyx.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/robots/test_parametric.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/robots/test_turtle.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/robots/test_ur5.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/sim/test_balance.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/sim/test_record.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/sim/test_replay.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/sim/test_rollout.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/sim/test_run.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/sim/test_runlog.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/sim/test_wallclock.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/small_plan.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/soft_arm_plan.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/test_benchmark.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/test_compiler.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/test_docs.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/test_dynamics.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/test_import.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/test_math.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/test_python_versions.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/test_readme.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/test_testing.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/underactuated_lab.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/viz/test_animate.py +0 -0
- {virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/tests/viz/test_viz.py +0 -0
|
@@ -4,6 +4,80 @@ All notable changes to this project are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow
|
|
5
5
|
[Semantic Versioning](https://semver.org/) (0.x: the API may change between minor versions).
|
|
6
6
|
|
|
7
|
+
## [1.3.0] - 2026-10-30
|
|
8
|
+
|
|
9
|
+
A minor release. A plan of a robot with fewer motors than coordinates now reads the motors, as the controller that
|
|
10
|
+
runs does (see Changed), and the result of a review of the whole library: the fixes below, most of them for
|
|
11
|
+
cases that gave a wrong or a silent answer, and the tension floor for tendons that only pull. Nothing else changes
|
|
12
|
+
for a robot with a motor on every coordinate.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- `control.TensionFloor`: an output stage for tendons that only pull. It lifts the torques of each
|
|
17
|
+
group of tendons (a segment's three) together until the lowest is at a floor, so no tendon is
|
|
18
|
+
told to push. Equal torques on evenly spaced tendons only squeeze the segment, so the bend
|
|
19
|
+
that the command makes is the same. Its corner is rounded, and `symbolic` is the same map for
|
|
20
|
+
a plan (`Problem(output=)`).
|
|
21
|
+
- `Mechanism.motor` and the `MotorAngle` coordinate: entries of the robot's motor angles, as its
|
|
22
|
+
actuation gives them. A `LimitSpring` on it is a limit on how far a motor may turn.
|
|
23
|
+
- `helyx.tension_stage`, `helyx.unwind_limit` and their numbers `TENSION_FLOOR`,
|
|
24
|
+
`UNWIND_LIMIT` and `UNWIND_STIFFNESS`: the tension floor, and a limit on how far a motor may
|
|
25
|
+
unwind (pulling is free). Both are optional, and `helyx.output_stage` is unchanged.
|
|
26
|
+
- `control.underactuated.Frozen(at=)` and `controller(gravity=<motor angles>)`: the rest of the
|
|
27
|
+
passive joints balanced once at a pose. The frozen torque stays the gradient of a potential,
|
|
28
|
+
which `gravity=True` (the balance found again at every reading, as before) does not: its torque
|
|
29
|
+
has a curl of a few percent in the test. `Frozen.rest` can be set as the `q_rest` of the
|
|
30
|
+
actuation.
|
|
31
|
+
- A `Param` can be shared by several sections or joints (`PCC([0.2, 0.2], radius)`, one axis for two
|
|
32
|
+
joints): it keeps one value, `ParamSet.by_name()` lists every name it has, and `select` finds
|
|
33
|
+
it by any of them (under its own name).
|
|
34
|
+
- `MovingHorizon.encoder` of a robot with fewer motors than coordinates measures the motors, as the
|
|
35
|
+
Kalman filter's does (it pinned the passive joint at its rest angle: an error of 0.37 rad in the
|
|
36
|
+
test, 0.001 now). `MovingHorizon.P` is defined from `reset` on.
|
|
37
|
+
- A term of a plan can use a site of a `plant` that is another robot.
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- A plan of a robot with fewer motors than coordinates now reads the motors, as `VMCController`
|
|
42
|
+
does (the frozen controller of `control.underactuated`). It used to read the whole state, so
|
|
43
|
+
that `Problem(system)` and the simulation of `VMCController(compile(system))` were different
|
|
44
|
+
controllers (a gap of 0.36 rad in the test). `Problem(reads="state")` plans the whole-state
|
|
45
|
+
controller (`StateController`, `"naive"`), and `reads="motors"` asks for the default outright.
|
|
46
|
+
For a robot with a motor on every coordinate nothing changes.
|
|
47
|
+
- `MPC` applies a plan only if its solve converged (a real-time iteration is applied as it is):
|
|
48
|
+
a failed solve used to jump the controller's Params. `MPC.applied` says whether the last plan
|
|
49
|
+
was, and the next solve after a failed one starts from the measured state. `rti=True` is undone
|
|
50
|
+
by a later `MPC` of the same problem without it, `reset` drops a plan that is being made, and
|
|
51
|
+
`start` waits until the last plan was polled.
|
|
52
|
+
- `Result.params` and `Result.steps` are held inside the Params' bounds (the solver relaxes a
|
|
53
|
+
bound by about 1e-8).
|
|
54
|
+
- `fit_params` and `fit_stiffness_damping` refuse an even `smoothing` (it shifted the derivative by
|
|
55
|
+
half a sample: a damping of 1.5 came out as 1.88), and a run whose `train` mask is off everywhere.
|
|
56
|
+
`fit_stiffness_damping` returns NaN, with a warning that names it, for a stiffness or damping
|
|
57
|
+
that the runs do not determine (it returned 0). `fit_params` takes one name as a string, and
|
|
58
|
+
a run with nothing to train is skipped when another has samples (an error when none has).
|
|
59
|
+
- `VMCController.set` refuses a value whose size is not the Param's (a scalar was broadcast into a
|
|
60
|
+
matrix), and `live_params()` returns copies. `balance()` and `elements()` use the Params as
|
|
61
|
+
`set` left them.
|
|
62
|
+
- `register` replaces a class defined again (a script or a notebook cell run twice) and still
|
|
63
|
+
refuses another object under a taken name. A plugin that fails to import no longer keeps the
|
|
64
|
+
others from loading: its error is raised by `get` of a name that is missing (and said in the
|
|
65
|
+
`KeyError`), and is a warning in `names`.
|
|
66
|
+
- `robot.joint` counts from the end (`slice(0, -1)`) and takes numpy integers; an index out of
|
|
67
|
+
range is a `ValueError` that says how many coordinates there are.
|
|
68
|
+
- `TensionFloor` needs a positive `width` (zero gave NaN).
|
|
69
|
+
- In `ask` and `tell`, a cost that is not finite (an episode that failed) counts as the worst cost
|
|
70
|
+
so far (`inf` until one is known) and is never the best; `Bayes` used to fail for good after one.
|
|
71
|
+
- `planar.arm(rest=)` takes one angle per passive joint as well as one per joint.
|
|
72
|
+
- The messages that named `Collocation` and `Equilibrium` name `Shooting` too.
|
|
73
|
+
|
|
74
|
+
### Fixed
|
|
75
|
+
|
|
76
|
+
- `Tank`, `SwapController` and `ScheduledController` can be copied and pickled.
|
|
77
|
+
- `Gated` forwards what the wrapped component reads.
|
|
78
|
+
- The docstring of `rollout` says that its `z` rows are the state the law used, one step behind
|
|
79
|
+
`run`'s.
|
|
80
|
+
|
|
7
81
|
## [1.2.2] - 2026-10-11
|
|
8
82
|
|
|
9
83
|
A patch: a fit says when its data do not determine a Param, and gives the same values on every machine; two
|
|
@@ -369,7 +443,7 @@ tank, tuning and the calibrations), which was never released on its own.
|
|
|
369
443
|
geometric terms out and is not provided.
|
|
370
444
|
- `KalmanFilter(system, dt, Q=None, P0=None, gate=40.0, robot=None)` and `Measurement(q, v, Rq,
|
|
371
445
|
Rv, observed, name)`: a Kalman filter of the robot's state (q, v). Its process model is the
|
|
372
|
-
robot's own dynamics,
|
|
446
|
+
robot's own dynamics, linearized at the estimate at rest and held over the step (the lab's
|
|
373
447
|
frozen mass matrix, in general form), with the command going through the system's
|
|
374
448
|
transmission. It fuses encoders (`kf.encoder`) and any sensor that sees part of the state,
|
|
375
449
|
gates each measurement on its innovation, and reports the sensors it rejected (`rejected`,
|
|
@@ -460,9 +534,9 @@ tank, tuning and the calibrations), which was never released on its own.
|
|
|
460
534
|
covariance, on a mass, spring and damper. The tutorial "Fit Params to a run" uses it.
|
|
461
535
|
- `KalmanFilter(..., unscented=True, substeps=10)`: the prediction sends sigma points of the
|
|
462
536
|
estimate (the scaled unscented transform, a root of three standard deviations out) through the
|
|
463
|
-
robot's own integrator, in `substeps` steps, instead of
|
|
537
|
+
robot's own integrator, in `substeps` steps, instead of linearizing at the estimate; the sensors
|
|
464
538
|
stay linear, so the update is the same. On a double pendulum it follows the mean of a Monte
|
|
465
|
-
Carlo to 0.003 where the
|
|
539
|
+
Carlo to 0.003 where the linearized prediction is off by 2; on a linear robot the two agree.
|
|
466
540
|
- `vmc.estimation.MomentumObserver(system, dt, gain, robot=None)`: the external force on a robot
|
|
467
541
|
from its motion, without accelerations. From the momentum and what the model says would change
|
|
468
542
|
it, it gives the generalized force the model does not explain, as a low-pass filter of bandwidth
|
|
@@ -854,7 +928,8 @@ First public release.
|
|
|
854
928
|
- `robots.adapt`: the ADAPT finger (two motors, coupled distal joints), joint-angle coordinate
|
|
855
929
|
and joint-limit spring.
|
|
856
930
|
|
|
857
|
-
[Unreleased]: https://github.com/vigno0405/VirtualModelControl/compare/v1.
|
|
931
|
+
[Unreleased]: https://github.com/vigno0405/VirtualModelControl/compare/v1.3.0...HEAD
|
|
932
|
+
[1.3.0]: https://github.com/vigno0405/VirtualModelControl/compare/v1.2.2...v1.3.0
|
|
858
933
|
[1.2.2]: https://github.com/vigno0405/VirtualModelControl/compare/v1.2.1...v1.2.2
|
|
859
934
|
[1.2.1]: https://github.com/vigno0405/VirtualModelControl/compare/v1.2.0...v1.2.1
|
|
860
935
|
[1.2.0]: https://github.com/vigno0405/VirtualModelControl/compare/v1.1.0...v1.2.0
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
cff-version: 1.2.0
|
|
2
2
|
message: "If you use this software, please cite it as below."
|
|
3
3
|
type: software
|
|
4
|
-
version: 1.
|
|
5
|
-
date-released: "2026-10-
|
|
4
|
+
version: 1.3.0
|
|
5
|
+
date-released: "2026-10-30"
|
|
6
6
|
title: "virtualmodelcontrol: Virtual Model Control for robots"
|
|
7
7
|
authors:
|
|
8
8
|
- family-names: Vignoli
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: virtualmodelcontrol
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Virtual Model Control: robots and controllers as mechanisms of springs, dampers and inertances, compiled with CasADi.
|
|
5
5
|
Project-URL: Repository, https://github.com/vigno0405/VirtualModelControl
|
|
6
6
|
Project-URL: Documentation, https://vigno0405.github.io/VirtualModelControl/
|
|
@@ -94,7 +94,7 @@ tank
|
|
|
94
94
|
|
|
95
95
|
output stage
|
|
96
96
|
An optional correction of the motor commands for real hardware: friction compensation,
|
|
97
|
-
pretension, an offset or a torque limit.
|
|
97
|
+
pretension, a tension floor, an offset or a torque limit.
|
|
98
98
|
|
|
99
99
|
template
|
|
100
100
|
A function that builds a ready-made robot, such as `helyx.arm`, with every geometric number
|
|
@@ -39,7 +39,7 @@ a robot middleware such as ROS: signals come in and go out as arrays.
|
|
|
39
39
|
| describe a new robot | `vmc.models`: `PCC`, `SerialChain`, `JointSpace`, `LinearCoupling`, `Assembly`, `TendonTransmission` |
|
|
40
40
|
| place virtual elements | `vmc.Mechanism`, coordinates and components such as `vmc.LinearSpring` |
|
|
41
41
|
| compile and run a controller | `vmc.VirtualMechanismSystem`, `vmc.compile`, `vmc.VMCController` |
|
|
42
|
-
| correct commands for real hardware | `vmc.control.output`: friction compensation, pretension, limits |
|
|
42
|
+
| correct commands for real hardware | `vmc.control.output`: friction compensation, pretension, a tension floor, limits |
|
|
43
43
|
| get positions, Jacobians, Hessians | `vmc.Kinematics` |
|
|
44
44
|
| get the robot's equations of motion | `vmc.compile_dynamics` (from the components, or from a function with `vmc.models.Equations`) |
|
|
45
45
|
| simulate a closed loop | `vmc.sim`: `ModelPlant`, `run`, `SimClock` |
|
|
@@ -76,7 +76,8 @@ size, are held out: the fit never sees them.
|
|
|
76
76
|
`Steps` is this experiment as a controller. It runs on any plant, here the simulated arm, and
|
|
77
77
|
its log goes straight to `identification.fit_stiffness_damping`. The fit knows the arm's
|
|
78
78
|
masses and gravity, and fits its diagonal stiffness and damping by least squares, relative to
|
|
79
|
-
the resting baseline.
|
|
79
|
+
the resting baseline. A stiffness or damping that the run does not determine, say of a motor that
|
|
80
|
+
never pulls, comes back as NaN with a warning, not as a zero. The masses are never fitted. Here the simulator plays the arm, so the
|
|
80
81
|
result can be checked against the values it was given.
|
|
81
82
|
|
|
82
83
|
```{code-cell} python
|
|
@@ -78,6 +78,15 @@ The nine motors and their bus are in `helyx.hardware("145-145-145")`. On the rea
|
|
|
78
78
|
`helyx.output_stage()` adds a small pretension to every motor command
|
|
79
79
|
({glue:text}`pretension:.3f` N·m per radian of motor angle). The simulations below leave it out.
|
|
80
80
|
|
|
81
|
+
A tendon only pulls, and a motor that is told to push unwinds without end. A virtual spring on
|
|
82
|
+
the tip asks the tendons on the far side of a bend to do just that. `helyx.tension_stage()` is an
|
|
83
|
+
output stage that lifts the three tendons of each segment together until the lowest is at
|
|
84
|
+
`helyx.TENSION_FLOOR`: equal torques on three evenly spaced tendons only squeeze the segment, so
|
|
85
|
+
the bend is the same, and every tendon stays taut. `helyx.unwind_limit(arm)` is a spring on the
|
|
86
|
+
motor angles that pushes back a motor that has unwound more than `helyx.UNWIND_LIMIT` from its
|
|
87
|
+
start angle. Both are optional and tunable, and both have a smooth form, so a plan can include
|
|
88
|
+
them with `Problem(output=helyx.tension_stage())`.
|
|
89
|
+
|
|
81
90
|
## Reach past an obstacle
|
|
82
91
|
|
|
83
92
|
A spring pulls the tip towards a target beyond an obstacle, while two repulsive Gaussian
|
|
@@ -128,10 +128,10 @@ pip install -e .
|
|
|
128
128
|
An experiment should always run the same code. Pin the version, and move the pin on purpose:
|
|
129
129
|
|
|
130
130
|
```bash
|
|
131
|
-
pip install "virtualmodelcontrol==1.
|
|
131
|
+
pip install "virtualmodelcontrol==1.3.0"
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
-
In a `requirements.txt` file, write `virtualmodelcontrol==1.
|
|
134
|
+
In a `requirements.txt` file, write `virtualmodelcontrol==1.3.0`. In a conda `environment.yml`,
|
|
135
135
|
list it under `pip:`. `pip show virtualmodelcontrol` tells you which version you have, and the
|
|
136
136
|
[changelog](development/changelog.md) what changed between versions.
|
|
137
137
|
|
|
@@ -57,7 +57,9 @@ class QuarticSpring(Component):
|
|
|
57
57
|
return 0.25 * ctx.param(self.stiffness) * ca.sumsqr(y) ** 2
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
Run the cell again, in a notebook or after an edit, and the new class replaces the old one
|
|
61
|
+
under the name. Another class under a taken name is refused. It acts on any coordinate, and
|
|
62
|
+
`compile` treats it like the built-in springs:
|
|
61
63
|
|
|
62
64
|
```{code-cell} python
|
|
63
65
|
from virtualmodelcontrol.robots import helyx
|
|
@@ -370,7 +372,9 @@ my_project = "my_project.vmc_plugins"
|
|
|
370
372
|
```
|
|
371
373
|
|
|
372
374
|
Importing `my_project.vmc_plugins` must run its `register(...)` decorators. The library loads
|
|
373
|
-
the plugins the first time a name is looked up and not found.
|
|
375
|
+
the plugins the first time a name is looked up and not found. A plugin that fails to import does
|
|
376
|
+
not keep the others from loading: its error is raised, and a name that is not there says that a
|
|
377
|
+
plugin is broken. So configuration files can use
|
|
374
378
|
the plugins' names ([Experiments in files](configurations.md)). Register a robot template as
|
|
375
379
|
`"robot"`, a simulation's dynamics as `"dynamics"`, an output stage as `"output"`, a controller
|
|
376
380
|
template as `"controller"` and a component as `"component"`. Register a coordinate kind as
|
|
@@ -118,7 +118,7 @@ assert abs(float(tanh_fit.values["damper.damping"]) - 1.5) < 0.1
|
|
|
118
118
|
|
|
119
119
|
The true values are 2 kg, 40 N/m and 1.5 N·s/m. The log holds no accelerations, so the fit
|
|
120
120
|
gets them by smoothing the velocity and differentiating it, which is where its error comes from
|
|
121
|
-
(`smoothing` is the number of samples of the smoothing). A run that has an `a` of its own, as a
|
|
121
|
+
(`smoothing` is the number of samples of the smoothing: an odd number, at least 5). A run that has an `a` of its own, as a
|
|
122
122
|
simulation can give, is used as it is. After the fit, {glue:text}`fit_rms:.4f` N is left over
|
|
123
123
|
per sample. The numbers after ± are the standard errors: how far the values may be off if what is
|
|
124
124
|
left over is noise. Here it is not noise, it is the smoothing, so the errors are much larger than
|
|
@@ -122,8 +122,10 @@ bottom.set_ylabel("stiffness [N/m]");
|
|
|
122
122
|
|
|
123
123
|
`MPC` wraps the problem. It builds the program once, and every `step` solves it from the
|
|
124
124
|
measured state, starting from the previous plan moved one interval on. It sets the Params of the
|
|
125
|
-
plan on the controller through `controller.set`,
|
|
126
|
-
|
|
125
|
+
plan on the controller through `controller.set`, if the solve converged (a failed one leaves the
|
|
126
|
+
Params as they are, `mpc.applied` and `mpc.result.converged` say, and the next solve starts from
|
|
127
|
+
the measured state), and returns the jump this gave the
|
|
128
|
+
controller's energy, as the [adaptation laws](stiffness.md) do:
|
|
127
129
|
|
|
128
130
|
```{code-cell} python
|
|
129
131
|
mpc = opt.MPC(problem) # the start and the Params that step become inputs
|
|
@@ -211,8 +213,9 @@ while running:
|
|
|
211
213
|
```
|
|
212
214
|
|
|
213
215
|
A solve lets the other threads run, so the loop keeps its rate. `start` does nothing while a
|
|
214
|
-
plan is being made
|
|
215
|
-
|
|
216
|
+
plan is being made or has not been polled yet, `reset` drops a plan that is being made, and an
|
|
217
|
+
error in the thread is raised by the next `poll`. Create the `MPC` after setting the problem's
|
|
218
|
+
solver and options, since it creates the solver then.
|
|
216
219
|
|
|
217
220
|
## A tank pays for the changes
|
|
218
221
|
|
|
@@ -282,7 +285,9 @@ glue("rti", 1e3 * float(abs(fast[-1, 1] - 1.0)), display=False)
|
|
|
282
285
|
```
|
|
283
286
|
|
|
284
287
|
Every plan is one iteration, and the mass ends {glue:text}`rti:.1f` mm from the goal. A plan
|
|
285
|
-
then is not an optimum, only a step towards it; `plan.converged` is false for it by design
|
|
288
|
+
then is not an optimum, only a step towards it; `plan.converged` is false for it by design, and
|
|
289
|
+
it is applied all the same. `rti=True` sets the problem's solver to `"rti"`, and an `MPC` of the
|
|
290
|
+
same problem without it puts the previous solver back.
|
|
286
291
|
|
|
287
292
|
## Solvers
|
|
288
293
|
|
|
@@ -326,7 +331,9 @@ glue("it_exact", int(rows["ipopt-exact"][0]), display=False)
|
|
|
326
331
|
|
|
327
332
|
The default `"ipopt"` takes {glue:text}`it_ipopt` iterations against {glue:text}`it_exact` for
|
|
328
333
|
`"ipopt-exact"`, as its Hessian is approximate, and ends at an acceptable level; `"rti"` is one
|
|
329
|
-
step from a cold start, so its plan is not the optimum.
|
|
334
|
+
step from a cold start, so its plan is not the optimum. On a harder shooting the quasi-Newton
|
|
335
|
+
Hessian can use all of its 500 iterations without converging (it does on another problem with
|
|
336
|
+
CasADi 3.8.2): take `"ipopt-exact"` for a shooting, and read `plan.converged`.
|
|
330
337
|
|
|
331
338
|
Which QP solver the SQP presets use is the `qpsol` option, and not every one of CasADi's
|
|
332
339
|
suits a shooting. Tried on this problem with CasADi 3.7 and 3.8: `qrqp` (the default), `qpoases`
|
|
@@ -256,8 +256,9 @@ glue("gain", float(100 * (1 - found.result.cost / anchor)), display=False)
|
|
|
256
256
|
sideways = [c["cost"] for c in found.candidates
|
|
257
257
|
if c["cost"] is not None
|
|
258
258
|
and np.abs(np.array(c["references"][key]) - target)[:2].max() > 1e-6]
|
|
259
|
-
assert len(sideways) >= 2 and min(sideways) >
|
|
260
|
-
glue("
|
|
259
|
+
assert len(sideways) >= 2 and min(sideways) > anchor # the target is the better reference
|
|
260
|
+
glue("sideways_min", float(min(sideways) / anchor), display=False)
|
|
261
|
+
glue("sideways_max", float(max(sideways) / anchor), display=False)
|
|
261
262
|
glue("k_search", found.result.params["new.pull.stiffness"].item(), display=False)
|
|
262
263
|
```
|
|
263
264
|
|
|
@@ -266,8 +267,10 @@ neighbors. The status says how each solve ended: an acceptable level counts as c
|
|
|
266
267
|
point that did not converge has no cost. The best reference lies {glue:text}`offset:.0f` mm from
|
|
267
268
|
the target along z, and it lowers the cost by {glue:text}`gain:.1f` %, with a stiffness of
|
|
268
269
|
{glue:text}`k_search:.0f` N/m: for this task the target is already a good reference. Moving it
|
|
269
|
-
sideways costs
|
|
270
|
-
|
|
270
|
+
sideways costs {glue:text}`sideways_min:.1f` to {glue:text}`sideways_max:.0f` times more (a solve of
|
|
271
|
+
this non-convex plan can end at a different optimum from another point's, and the CasADi version
|
|
272
|
+
changes where: read the statuses). `found.result` is the plan, `found.references` the point that gave it, and
|
|
273
|
+
`found.candidates` every point tried.
|
|
271
274
|
|
|
272
275
|
## Where the arm rests
|
|
273
276
|
|
{virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/docs/tutorials/soft-and-assemblies.md
RENAMED
|
@@ -37,6 +37,15 @@ soft = vmc.Mechanism(
|
|
|
37
37
|
soft.actuation.motor_sizes(soft.space) # motor angles, motor rates
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
A number is a `Param`, and one `Param` can stand for several: give the same one to both sections
|
|
41
|
+
and they share its value, so that `Problem.free` and `set` change it once.
|
|
42
|
+
|
|
43
|
+
```{code-cell} python
|
|
44
|
+
radius = vmc.Param("radius", 0.03, unit="m", scope="design")
|
|
45
|
+
shared = PCC([0.2, 0.2], radius) # one radius for both sections
|
|
46
|
+
shared.params["seg1.d"] is shared.params["seg2.d"]
|
|
47
|
+
```
|
|
48
|
+
|
|
40
49
|
The arm's mass is not lumped by itself. `soft.add_mass_along(name, mass, s0, s1, n)` spreads a mass
|
|
41
50
|
evenly between two arc parameters as $n$ point masses at the nodes of Gauss-Legendre quadrature,
|
|
42
51
|
which is exact for any polynomial of degree $2n - 1$ in the arc length. Here the height of the
|
|
@@ -125,7 +125,8 @@ A searcher is made from the bounds of the Params: `Grid(lower, upper, points)`,
|
|
|
125
125
|
`Bayes(lower, upper, initial=...)` and `Random(lower, upper, size=...)`. `CMAES(start, step, lower,
|
|
126
126
|
upper, size=...)` also takes a starting point and the size of its first steps, and
|
|
127
127
|
`ExtremumSeeking(start, amplitude, gain, ...)` the size of its test moves and a gain. The CMA-ES
|
|
128
|
-
loop below is the same as `tune`, written out
|
|
128
|
+
loop below is the same as `tune`, written out. An episode that failed, with a cost that is `inf`
|
|
129
|
+
or NaN, counts as the worst cost so far and is never the best:
|
|
129
130
|
|
|
130
131
|
```{code-cell} python
|
|
131
132
|
from virtualmodelcontrol import optimization as opt
|
|
@@ -108,7 +108,9 @@ builds it, and `base` chooses how its torques are rendered:
|
|
|
108
108
|
- `"frozen"` evaluates the same law with the passive joint held at its rest angle, whatever it
|
|
109
109
|
does. It needs the motors only, and its torque is the exact gradient of a potential. With
|
|
110
110
|
`gravity=True` it holds the passive joint where its spring balances the arm's own weight
|
|
111
|
-
instead of at the rest angle
|
|
111
|
+
instead of at the rest angle, found again at every reading ([a passive joint under
|
|
112
|
+
weight](#a-passive-joint-under-weight) says what that costs); with `gravity=` the motor
|
|
113
|
+
angles of a pose it finds the balance once, there.
|
|
112
114
|
|
|
113
115
|
```{code-cell} python
|
|
114
116
|
def reach(robot, compensate=True, stiffness=150.0):
|
|
@@ -120,8 +122,9 @@ def reach(robot, compensate=True, stiffness=150.0):
|
|
|
120
122
|
ctrl.add("gravity", vmc.GravityCompensation(robot))
|
|
121
123
|
return vmc.compile(vmc.VirtualMechanismSystem(robot, ctrl))
|
|
122
124
|
|
|
123
|
-
def run(compiled, base, correction=None, gravity=False, T=4.0):
|
|
124
|
-
controller = ua.controller(compiled, base, correction, gravity=gravity
|
|
125
|
+
def run(compiled, base, correction=None, gravity=False, T=4.0, **stage):
|
|
126
|
+
controller = ua.controller(compiled, base, correction, gravity=gravity,
|
|
127
|
+
**stage)
|
|
125
128
|
plant = vmc.sim.ModelPlant(arm, q0=[0.3, 0.3, 0.3], max_step=1e-4)
|
|
126
129
|
log = vmc.sim.run(plant, controller, vmc.sim.SimClock(5e-4), T=T)
|
|
127
130
|
return log.arrays()
|
|
@@ -174,6 +177,58 @@ goal (naive, and frozen with `gravity=True`) and {glue:text}`bare_frozen:.0f` mm
|
|
|
174
177
|
frozen). Where the passive joint is at rest and carries nothing, naive and frozen send the
|
|
175
178
|
same torques.
|
|
176
179
|
|
|
180
|
+
## A passive joint under weight
|
|
181
|
+
|
|
182
|
+
The frozen controller keeps the arm passive because its torque is the gradient of a potential:
|
|
183
|
+
the field of motor angles $\theta \mapsto u(\theta)$ has no curl, so the motors cannot gain
|
|
184
|
+
energy by going around a loop. That holds while the rest of the passive joint is a constant. With
|
|
185
|
+
`gravity=True` the rest is the joint's balance at the current motor angles, and it moves as they
|
|
186
|
+
do, which puts a small curl into the field. We measure the curl as the asymmetry of the Jacobian
|
|
187
|
+
of $u$ with respect to $\theta$, relative to its size, for the plain frozen controller, for
|
|
188
|
+
`gravity=True`, and for `gravity=` the motor angles of a pose, where the balance is solved once:
|
|
189
|
+
|
|
190
|
+
```{code-cell} python
|
|
191
|
+
def curl(gravity, theta, h=1e-6):
|
|
192
|
+
controller = ua.controller(compiled, "frozen", gravity=gravity)
|
|
193
|
+
|
|
194
|
+
def torque(theta):
|
|
195
|
+
reading = vmc.Signals(0.0, motor_position=theta, q=[0.0] * 3,
|
|
196
|
+
motor_velocity=[0.0, 0.0], v=[0.0] * 3)
|
|
197
|
+
controller.reset(0.0, reading)
|
|
198
|
+
return np.asarray(controller.step(0.0, reading)["law_torque"])
|
|
199
|
+
|
|
200
|
+
jac = np.column_stack([(torque(theta + h * e) - torque(theta - h * e))
|
|
201
|
+
/ (2 * h) for e in np.eye(2)])
|
|
202
|
+
return abs(jac - jac.T).max() / abs(jac).max()
|
|
203
|
+
|
|
204
|
+
pose = B.T @ runs["naive"]["q"][-1] # the motor angles where the reach ends
|
|
205
|
+
curls = {"plain": curl(False, pose), "moving": curl(True, pose),
|
|
206
|
+
"fixed": curl(pose, pose)}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
```{code-cell} python
|
|
210
|
+
:tags: [remove-cell]
|
|
211
|
+
assert curls["plain"] < 1e-8 and curls["fixed"] < 1e-8
|
|
212
|
+
assert 1e-3 < curls["moving"] < 0.2
|
|
213
|
+
settled = run(compiled, "frozen", gravity=pose)
|
|
214
|
+
final_fixed = 1000 * float(tip_error(settled)[-1])
|
|
215
|
+
assert final_fixed < 1.0, final_fixed
|
|
216
|
+
glue("curl_plain", float(curls["plain"]), display=False)
|
|
217
|
+
glue("curl_fixed", float(curls["fixed"]), display=False)
|
|
218
|
+
glue("curl_moving", float(curls["moving"]), display=False)
|
|
219
|
+
glue("final_fixed", final_fixed, display=False)
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
The plain frozen torque has no curl ({glue:text}`curl_plain:.0e`), and neither has the one whose
|
|
223
|
+
balance is solved once ({glue:text}`curl_fixed:.0e`). The torque that follows the balance has a
|
|
224
|
+
curl of {glue:text}`curl_moving:.1%` here: a few percent of the field, but not a gradient, so the
|
|
225
|
+
guarantee does not cover it. Give `gravity=` the motor angles of the pose the arm works around, such as where the
|
|
226
|
+
reach ends. With the balance solved there, the frozen controller ends
|
|
227
|
+
{glue:text}`final_fixed:.1e` mm from the goal, as it does with `gravity=True`, and its torque is
|
|
228
|
+
a gradient again. The rest it found is `ua.Frozen(arm.actuation, dynamics, at=pose).rest`, which
|
|
229
|
+
can be set as the `q_rest` of the actuation, the way [a plan](#planning-with-these-controllers)
|
|
230
|
+
reads it.
|
|
231
|
+
|
|
177
232
|
## Keeping the arm passive
|
|
178
233
|
|
|
179
234
|
The naive torque is not the gradient of anything, so a controller built on it can put energy
|
|
@@ -227,8 +282,57 @@ Without a correction the arm gains up to {glue:text}`peak_none:.2f` J from the c
|
|
|
227
282
|
the passive correction it gains {glue:text}`peak_passive:.3f` J at most, the rounding of the
|
|
228
283
|
control period (the guarantee holds in continuous time and the gain falls with the period). With
|
|
229
284
|
the tank it gains {glue:text}`peak_tank:.2f` J, the budget it started with (the default
|
|
230
|
-
`tank=1.0` J of `ua.controller`).
|
|
231
|
-
|
|
285
|
+
`tank=1.0` J of `ua.controller`).
|
|
286
|
+
|
|
287
|
+
The `width` of a correction, in W, smooths the point where it starts. Its default, 1 W, is as
|
|
288
|
+
large as the power of this arm, so the correction also slows the reach when little needs
|
|
289
|
+
correcting: after 4 s the passive correction is still {glue:text}`slow_default:.0f` mm from the
|
|
290
|
+
goal, and with `width=1e-2` it is {glue:text}`slow_narrow:.1f` mm. Take the smallest power that
|
|
291
|
+
matters in your loop.
|
|
292
|
+
|
|
293
|
+
```{code-cell} python
|
|
294
|
+
:tags: [remove-cell]
|
|
295
|
+
narrow = run(compiled, "naive", "passive", width=1e-2)
|
|
296
|
+
slow_default = 1000 * float(tip_error(corrected["passive"])[-1])
|
|
297
|
+
slow_narrow = 1000 * float(tip_error(narrow)[-1])
|
|
298
|
+
assert slow_default > 10.0 and slow_narrow < 1.0, (slow_default, slow_narrow)
|
|
299
|
+
glue("slow_default", slow_default, display=False)
|
|
300
|
+
glue("slow_narrow", slow_narrow, display=False)
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
The frozen controller needs no correction to keep the energy of its own virtual spring from
|
|
304
|
+
growing, since its torque is a gradient (with `gravity=True`, only up to the small curl above).
|
|
305
|
+
Do not stack them. A correction compares the power the motors inject with what the arm's own
|
|
306
|
+
dampers dissipate, and a virtual spring that is releasing its energy injects power, so it also
|
|
307
|
+
cuts the torque of the frozen controller:
|
|
308
|
+
|
|
309
|
+
```{code-cell} python
|
|
310
|
+
def removed(base, T=4.0, dt=5e-4):
|
|
311
|
+
"""The torque [N·m s] that the passive correction takes off the law."""
|
|
312
|
+
controller = ua.controller(compiled, base, "passive", width=1e-4)
|
|
313
|
+
plant = vmc.sim.ModelPlant(arm, q0=[0.3, 0.3, 0.3], max_step=1e-4)
|
|
314
|
+
controller.reset(0.0, plant.read())
|
|
315
|
+
total = 0.0
|
|
316
|
+
for _ in range(round(T / dt)):
|
|
317
|
+
command = controller.step(plant.t, plant.read())
|
|
318
|
+
total += dt * float(np.abs(command["law_torque"]
|
|
319
|
+
- command["motor_torque"]).sum())
|
|
320
|
+
plant.write(command)
|
|
321
|
+
plant.advance(dt)
|
|
322
|
+
return total
|
|
323
|
+
|
|
324
|
+
cut = {base: removed(base) for base in ("naive", "frozen")}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
```{code-cell} python
|
|
328
|
+
:tags: [remove-cell]
|
|
329
|
+
assert cut["frozen"] > 0.1 and cut["naive"] > 0.1, cut
|
|
330
|
+
glue("cut_frozen", float(cut["frozen"]), display=False)
|
|
331
|
+
glue("cut_naive", float(cut["naive"]), display=False)
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
Over this reach the correction takes {glue:text}`cut_frozen:.1f` N·m·s off the frozen torque and
|
|
335
|
+
{glue:text}`cut_naive:.1f` N·m·s off the naive one. Use the corrections on the naive controller.
|
|
232
336
|
|
|
233
337
|
## A force along a direction
|
|
234
338
|
|
|
@@ -308,6 +412,44 @@ for ax, (name, robot) in zip(axes, robots.items()):
|
|
|
308
412
|
axes[0].set_ylabel("height [m]");
|
|
309
413
|
```
|
|
310
414
|
|
|
415
|
+
## Planning with these controllers
|
|
416
|
+
|
|
417
|
+
A plan of the [optimization layer](optimize.md) is the closed loop, so it has to read what the
|
|
418
|
+
controller on the robot reads. For a robot with fewer motors than joints, `Problem(system)`
|
|
419
|
+
plans the controller that reads the motors, as `VMCController` does: the frozen one, with the
|
|
420
|
+
passive joints at their rest angles. `Problem(system, reads="state")` plans the whole-state
|
|
421
|
+
controller of `"naive"` instead, and `reads="motors"` asks for the first one outright. Here is
|
|
422
|
+
where each plan puts the arm at rest, started near where the matching simulation of the reach
|
|
423
|
+
ended:
|
|
424
|
+
|
|
425
|
+
```{code-cell} python
|
|
426
|
+
from virtualmodelcontrol import optimization as opt
|
|
427
|
+
|
|
428
|
+
def planned_end(reads, base):
|
|
429
|
+
start = runs[base]["q"][-1] + 0.05 # a guess near where it ends
|
|
430
|
+
problem = opt.Problem(compiled.system, reads=reads)
|
|
431
|
+
problem.add(opt.Equilibrium(start))
|
|
432
|
+
q = problem.solve().q[0]
|
|
433
|
+
return 1000 * np.linalg.norm(kin.position(q, "tip")[:2] - [0.45, 0.15])
|
|
434
|
+
|
|
435
|
+
planned = {"naive": planned_end("state", "naive"),
|
|
436
|
+
"frozen": planned_end("motors", "frozen")}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
```{code-cell} python
|
|
440
|
+
:tags: [remove-cell]
|
|
441
|
+
assert abs(planned["naive"] - 1000 * final["naive"]) < 0.1
|
|
442
|
+
assert abs(planned["frozen"] - 1000 * final["frozen"]) < 0.1
|
|
443
|
+
glue("planned_naive", float(planned["naive"]), display=False)
|
|
444
|
+
glue("planned_frozen", float(planned["frozen"]), display=False)
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
The plans end {glue:text}`planned_naive:.1f` mm and {glue:text}`planned_frozen:.1f` mm from the
|
|
448
|
+
goal, where the simulations above end. The frozen controller's rest is the `q_rest` Param of the
|
|
449
|
+
actuation, so a plan can optimize it (`problem.free("arm.q_rest")`), and set it to a balanced
|
|
450
|
+
rest as in the section above. The corrections have no symbolic form yet: `Problem(output=...)`
|
|
451
|
+
refuses them. Plan the controller and add the correction when you run it.
|
|
452
|
+
|
|
311
453
|
## When the passive joint is not measured
|
|
312
454
|
|
|
313
455
|
The naive controller needs the angle and the rate of every joint, and the encoders give the
|
|
@@ -317,7 +459,7 @@ joint moves the other two through the coupling, and the filter reads it from the
|
|
|
317
459
|
see, $\theta = B^\top q$, as combinations of $q$ (the measurement's `matrix`), not as a reading
|
|
318
460
|
of $q$, so the passive joint is left to the model. Each period the loop updates the filter with
|
|
319
461
|
the encoders, hands the estimate to the controller as the signals `q` and `v`, and predicts
|
|
320
|
-
the next period from the torques it sent.
|
|
462
|
+
the next period from the torques it sent. A `MovingHorizon` estimator takes the same `encoder`.
|
|
321
463
|
|
|
322
464
|
```{code-cell} python
|
|
323
465
|
from virtualmodelcontrol.estimation import Encoders, KalmanFilter
|
|
@@ -440,21 +582,26 @@ assert torque.shape == (2,) and np.isfinite(torque).all()
|
|
|
440
582
|
|
|
441
583
|
## Choosing
|
|
442
584
|
|
|
443
|
-
- Start with `"frozen"`, with `gravity
|
|
444
|
-
motors, its torque is a gradient, and it agrees with
|
|
445
|
-
rest.
|
|
585
|
+
- Start with `"frozen"`, with `gravity=` the motor angles of the pose it works around if the
|
|
586
|
+
arm carries weight: it needs only the motors, its torque is a gradient, and it agrees with
|
|
587
|
+
the naive one where the passive joints rest. `gravity=True` follows the balance at every
|
|
588
|
+
reading instead, which is closer to the naive controller far from one pose, but its torque
|
|
589
|
+
is not a gradient.
|
|
446
590
|
- Take `"naive"` when the whole state is measured or estimated well and you want the force the
|
|
447
591
|
spring asks for even away from the passive joints' rest.
|
|
448
|
-
- Add `"passive"` when the arm must never gain energy, and `"tank"` to
|
|
449
|
-
to a budget. A correction removes torque, so it can slow the reach
|
|
450
|
-
task needs.
|
|
592
|
+
- Add `"passive"` to the naive controller when the arm must never gain energy, and `"tank"` to
|
|
593
|
+
allow short bursts up to a budget. A correction removes torque, so it can slow the reach: set
|
|
594
|
+
`tank` to what the task needs and `width` to the smallest power that matters. They also cut
|
|
595
|
+
the frozen torque, which needs no correction.
|
|
451
596
|
- The laws and estimators that read a controller's motors (`ForceTracking`, `StiffnessTracking`,
|
|
452
597
|
`PositionRegulation`, `HoldingGoals`, `ContactForce`, `TaskStiffness`) refuse a
|
|
453
|
-
`StateController`, which is what `"naive"` and `"frozen"` with `gravity
|
|
598
|
+
`StateController`, which is what `"naive"` and `"frozen"` with `gravity` set give, with a
|
|
454
599
|
`ValueError`. Plain `"frozen"` is a `VMCController` and works with them; for a force on
|
|
455
600
|
an underactuated arm use `DirectionalForce`.
|
|
456
|
-
- `gravity
|
|
601
|
+
- `gravity=` holds the passive joints where their springs balance the arm's weight, not at
|
|
457
602
|
the rest angle: the right reference for an arm that hangs or reaches out. The weight itself
|
|
458
603
|
is compensated by a `GravityCompensation` in the controller, as for any robot.
|
|
459
|
-
- `planar.arm(rest=...)` sets the passive joints' rest angles
|
|
460
|
-
|
|
604
|
+
- `planar.arm(rest=...)` sets the passive joints' rest angles, one for all, one per passive
|
|
605
|
+
joint or one per joint. The frozen controller reads them as the `q_rest` of the actuation,
|
|
606
|
+
and `add_dynamics` copies them into the passive springs' rest: the two do not follow each
|
|
607
|
+
other after that.
|
|
@@ -37,6 +37,7 @@ from .mechanisms import (
|
|
|
37
37
|
LinearDamper,
|
|
38
38
|
LinearSpring,
|
|
39
39
|
Mechanism,
|
|
40
|
+
MotorAngle,
|
|
40
41
|
Norm,
|
|
41
42
|
OrientationError,
|
|
42
43
|
PhaseSpring,
|
|
@@ -110,6 +111,7 @@ __all__ = [
|
|
|
110
111
|
"LinearDamper",
|
|
111
112
|
"LinearSpring",
|
|
112
113
|
"Mechanism",
|
|
114
|
+
"MotorAngle",
|
|
113
115
|
"Norm",
|
|
114
116
|
"OrientationError",
|
|
115
117
|
"Param",
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '1.
|
|
22
|
-
__version_tuple__ = version_tuple = (1,
|
|
21
|
+
__version__ = version = '1.3.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 3, 0)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -74,9 +74,9 @@ class DitherSeeking:
|
|
|
74
74
|
if len(self._t) > 2 and self._t[-1] - self._t[0] > 0.9 * self.window:
|
|
75
75
|
times, costs = np.array(self._t), np.array(self._cost)
|
|
76
76
|
weights = np.gradient(times)
|
|
77
|
-
|
|
77
|
+
centered = costs - np.sum(costs * weights) / np.sum(weights)
|
|
78
78
|
probes = np.sin(np.outer(self.frequency, times))
|
|
79
|
-
self.slope = 2.0 / self.amplitude * (probes @ (
|
|
79
|
+
self.slope = 2.0 / self.amplitude * (probes @ (centered * weights)) / np.sum(weights)
|
|
80
80
|
dt = times[-1] - times[-2]
|
|
81
81
|
rate = np.clip(self.gain * self.slope, -self.max_rate, self.max_rate)
|
|
82
82
|
for i, name in enumerate(self.names):
|
{virtualmodelcontrol-1.2.2 → virtualmodelcontrol-1.3.0}/src/virtualmodelcontrol/control/__init__.py
RENAMED
|
@@ -6,6 +6,7 @@ from .output import (
|
|
|
6
6
|
FrictionCompensation,
|
|
7
7
|
Pretension,
|
|
8
8
|
StaticFrictionCompensation,
|
|
9
|
+
TensionFloor,
|
|
9
10
|
TorqueLimit,
|
|
10
11
|
TorqueOffset,
|
|
11
12
|
)
|
|
@@ -23,6 +24,7 @@ __all__ = [
|
|
|
23
24
|
"StaticFrictionCompensation",
|
|
24
25
|
"SwapController",
|
|
25
26
|
"Tank",
|
|
27
|
+
"TensionFloor",
|
|
26
28
|
"TorqueLimit",
|
|
27
29
|
"TorqueOffset",
|
|
28
30
|
"VMCController",
|