virtualmodelcontrol 0.3.0__tar.gz → 0.5.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-0.5.0/CHANGELOG.md +630 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/PKG-INFO +1 -7
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/README.md +0 -2
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/api/index.md +4 -1
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/concepts/conventions.md +7 -6
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/concepts/efficiency.md +10 -10
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/concepts/finger.md +11 -9
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/concepts/library.md +8 -7
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/concepts/passivity.md +8 -7
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/concepts/pcc.md +8 -7
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/concepts/vmc.md +11 -10
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/development/contributing.md +9 -7
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/examples/finger.md +130 -7
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/examples/hand.md +20 -19
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/examples/hanging-arm.md +110 -58
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/examples/soft-arm.md +29 -28
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/examples/turtle.md +12 -8
- virtualmodelcontrol-0.5.0/docs/examples/two-arms.md +307 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/index.md +35 -8
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/installation.md +15 -15
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/schematics/library_map.py +13 -3
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/troubleshooting.md +4 -4
- virtualmodelcontrol-0.5.0/docs/tutorials/build-a-robot.md +464 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/tutorials/configurations.md +26 -24
- virtualmodelcontrol-0.5.0/docs/tutorials/contact.md +432 -0
- virtualmodelcontrol-0.5.0/docs/tutorials/coordinates-and-components.md +291 -0
- virtualmodelcontrol-0.5.0/docs/tutorials/crawl.md +362 -0
- virtualmodelcontrol-0.5.0/docs/tutorials/energy.md +305 -0
- virtualmodelcontrol-0.5.0/docs/tutorials/estimation.md +357 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/tutorials/extend.md +40 -17
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/tutorials/first-controller.md +7 -7
- virtualmodelcontrol-0.5.0/docs/tutorials/fit.md +93 -0
- virtualmodelcontrol-0.5.0/docs/tutorials/force.md +541 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/tutorials/introduction.md +8 -9
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/tutorials/kinematics.md +96 -7
- virtualmodelcontrol-0.5.0/docs/tutorials/optimize.md +739 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/tutorials/parameters.md +6 -6
- virtualmodelcontrol-0.5.0/docs/tutorials/real-time.md +352 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/tutorials/run-logs.md +24 -20
- virtualmodelcontrol-0.5.0/docs/tutorials/stiffness.md +294 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/tutorials/swaps.md +19 -21
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/tutorials/tuning.md +75 -16
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/pyproject.toml +10 -24
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/__init__.py +40 -9
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/_version.py +2 -2
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/adaptation/__init__.py +17 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/adaptation/force.py +107 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/adaptation/limits.py +39 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/adaptation/position.py +94 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/adaptation/scalar.py +94 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/adaptation/seeking.py +90 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/adaptation/stiffness.py +71 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/config/coordinates.py +110 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/control/__init__.py +4 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/control/controller.py +30 -9
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/control/projection.py +14 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/control/tank.py +70 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/core/__init__.py +2 -1
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/core/space.py +83 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/core/symbolic.py +1 -25
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/dynamics.py +25 -5
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/estimation/__init__.py +28 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/estimation/balance.py +34 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/estimation/compliance.py +29 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/estimation/contact.py +35 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/estimation/imu.py +131 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/estimation/inversion.py +99 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/estimation/kalman.py +218 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/estimation/measurement.py +80 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/estimation/momentum.py +74 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/estimation/sensors.py +122 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/estimation/stiffness.py +45 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/estimation/velocity.py +37 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/hardware/__init__.py +5 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/hardware/profile.py +114 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/identification/__init__.py +19 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/identification/params.py +120 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/identification/steps.py +55 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/identification/stiffness.py +126 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/identification/transmission.py +18 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/math.py +188 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/mechanisms/__init__.py +28 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/mechanisms/components/__init__.py +9 -2
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/mechanisms/components/base.py +6 -2
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/mechanisms/components/dissipation.py +152 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/mechanisms/components/gated.py +40 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/mechanisms/components/inertance.py +29 -1
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/mechanisms/components/locomotion.py +59 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/mechanisms/components/sources.py +27 -4
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/mechanisms/coordinates/__init__.py +21 -4
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/mechanisms/coordinates/base.py +10 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/mechanisms/coordinates/frames.py +189 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/mechanisms/coordinates/geometry.py +187 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/mechanisms/coordinates/ops.py +18 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/mechanisms/coordinates/references.py +13 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/mechanisms/mechanism.py +20 -3
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/models/__init__.py +4 -1
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/models/actuation.py +51 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/models/assembly.py +2 -2
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/models/function.py +70 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/models/kinematics.py +14 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/models/rigid/poe.py +238 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/models/rigid/spline.py +41 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/optimization/__init__.py +41 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/optimization/asktell.py +258 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/optimization/builder.py +185 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/optimization/collocation.py +235 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/optimization/equilibrium.py +64 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/optimization/horizon.py +224 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/optimization/nlp.py +66 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/optimization/problem.py +270 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/optimization/result.py +63 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/optimization/search.py +125 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/optimization/solver.py +80 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/optimization/terms.py +217 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/optimization/trajectory.py +54 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/optimization/variables.py +67 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/robots/adapt.py +9 -16
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/robots/bimanual.py +4 -13
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/robots/helyx.py +4 -10
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/robots/turtle.py +213 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/sim/__init__.py +5 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/sim/balance.py +50 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/sim/model_plant.py +12 -0
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/sim/rollout.py +158 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/sim/run.py +35 -51
- virtualmodelcontrol-0.5.0/src/virtualmodelcontrol/testing.py +183 -0
- virtualmodelcontrol-0.5.0/tests/adaptation/test_fingertip.py +139 -0
- virtualmodelcontrol-0.5.0/tests/adaptation/test_force.py +219 -0
- virtualmodelcontrol-0.5.0/tests/adaptation/test_grasp.py +99 -0
- virtualmodelcontrol-0.5.0/tests/adaptation/test_holding.py +154 -0
- virtualmodelcontrol-0.5.0/tests/adaptation/test_loop.py +58 -0
- virtualmodelcontrol-0.5.0/tests/adaptation/test_position.py +71 -0
- virtualmodelcontrol-0.5.0/tests/adaptation/test_scalar.py +155 -0
- virtualmodelcontrol-0.5.0/tests/adaptation/test_seeking.py +139 -0
- virtualmodelcontrol-0.5.0/tests/adaptation/test_stiffness_tracking.py +136 -0
- virtualmodelcontrol-0.5.0/tests/adaptation/test_virtual_state.py +67 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/config/test_config.py +76 -0
- virtualmodelcontrol-0.5.0/tests/control/test_inputs.py +32 -0
- virtualmodelcontrol-0.5.0/tests/control/test_projection.py +45 -0
- virtualmodelcontrol-0.5.0/tests/control/test_tank.py +152 -0
- virtualmodelcontrol-0.5.0/tests/core/test_space.py +113 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/core/test_symbolic.py +1 -10
- virtualmodelcontrol-0.5.0/tests/data/adaptation.npz +0 -0
- virtualmodelcontrol-0.5.0/tests/data/compliance.npz +0 -0
- virtualmodelcontrol-0.5.0/tests/data/estimation.npz +0 -0
- virtualmodelcontrol-0.5.0/tests/data/fingertip.npz +0 -0
- virtualmodelcontrol-0.5.0/tests/data/heuristics.npz +0 -0
- virtualmodelcontrol-0.5.0/tests/data/imu.npz +0 -0
- virtualmodelcontrol-0.5.0/tests/data/kalman.npz +0 -0
- virtualmodelcontrol-0.5.0/tests/data/mocap.npz +0 -0
- virtualmodelcontrol-0.5.0/tests/data/optimization.json +326 -0
- virtualmodelcontrol-0.5.0/tests/data/optimization.npz +0 -0
- virtualmodelcontrol-0.5.0/tests/data/transmission.npz +0 -0
- virtualmodelcontrol-0.5.0/tests/estimation/test_compliance_golden.py +63 -0
- virtualmodelcontrol-0.5.0/tests/estimation/test_contact.py +201 -0
- virtualmodelcontrol-0.5.0/tests/estimation/test_imu.py +236 -0
- virtualmodelcontrol-0.5.0/tests/estimation/test_inversion.py +264 -0
- virtualmodelcontrol-0.5.0/tests/estimation/test_kalman.py +261 -0
- virtualmodelcontrol-0.5.0/tests/estimation/test_kalman_golden.py +149 -0
- virtualmodelcontrol-0.5.0/tests/estimation/test_kalman_unscented.py +184 -0
- virtualmodelcontrol-0.5.0/tests/estimation/test_mocap_golden.py +109 -0
- virtualmodelcontrol-0.5.0/tests/estimation/test_momentum.py +176 -0
- virtualmodelcontrol-0.5.0/tests/estimation/test_sensors.py +115 -0
- virtualmodelcontrol-0.5.0/tests/estimation/test_velocity.py +67 -0
- virtualmodelcontrol-0.5.0/tests/hardware/test_profile.py +37 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/helpers.py +23 -3
- virtualmodelcontrol-0.5.0/tests/identification/test_fit_params.py +168 -0
- virtualmodelcontrol-0.5.0/tests/identification/test_friction.py +98 -0
- virtualmodelcontrol-0.5.0/tests/identification/test_steps.py +174 -0
- virtualmodelcontrol-0.5.0/tests/identification/test_transmission.py +59 -0
- virtualmodelcontrol-0.5.0/tests/lab_optimization.py +137 -0
- virtualmodelcontrol-0.5.0/tests/mechanisms/test_distances.py +140 -0
- virtualmodelcontrol-0.5.0/tests/mechanisms/test_frames.py +182 -0
- virtualmodelcontrol-0.5.0/tests/mechanisms/test_friction.py +163 -0
- virtualmodelcontrol-0.5.0/tests/mechanisms/test_gated.py +68 -0
- virtualmodelcontrol-0.5.0/tests/mechanisms/test_more_components.py +208 -0
- virtualmodelcontrol-0.5.0/tests/mechanisms/test_pair_contact.py +124 -0
- virtualmodelcontrol-0.5.0/tests/mechanisms/test_phase_spring.py +346 -0
- virtualmodelcontrol-0.5.0/tests/mechanisms/test_virtual_model.py +175 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/models/test_actuation.py +67 -4
- virtualmodelcontrol-0.5.0/tests/models/test_contact_map.py +38 -0
- virtualmodelcontrol-0.5.0/tests/models/test_floating.py +165 -0
- virtualmodelcontrol-0.5.0/tests/models/test_floating_base.py +46 -0
- virtualmodelcontrol-0.5.0/tests/models/test_function.py +86 -0
- virtualmodelcontrol-0.5.0/tests/models/test_poe.py +165 -0
- virtualmodelcontrol-0.5.0/tests/models/test_rail.py +196 -0
- virtualmodelcontrol-0.5.0/tests/optimization/test_asktell.py +259 -0
- virtualmodelcontrol-0.5.0/tests/optimization/test_collocation.py +223 -0
- virtualmodelcontrol-0.5.0/tests/optimization/test_equilibrium.py +151 -0
- virtualmodelcontrol-0.5.0/tests/optimization/test_horizon.py +263 -0
- virtualmodelcontrol-0.5.0/tests/optimization/test_lab.py +128 -0
- virtualmodelcontrol-0.5.0/tests/optimization/test_periodic.py +583 -0
- virtualmodelcontrol-0.5.0/tests/optimization/test_problem.py +424 -0
- virtualmodelcontrol-0.5.0/tests/optimization/test_search.py +146 -0
- virtualmodelcontrol-0.5.0/tests/optimization/test_structure.py +120 -0
- virtualmodelcontrol-0.5.0/tests/optimization/test_swap.py +51 -0
- virtualmodelcontrol-0.5.0/tests/optimization/test_terms.py +226 -0
- virtualmodelcontrol-0.5.0/tests/optimization/test_variables.py +43 -0
- virtualmodelcontrol-0.5.0/tests/robots/test_crawler.py +333 -0
- virtualmodelcontrol-0.5.0/tests/robots/test_turtle.py +113 -0
- virtualmodelcontrol-0.5.0/tests/sim/test_balance.py +110 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/sim/test_record.py +22 -0
- virtualmodelcontrol-0.5.0/tests/sim/test_rollout.py +193 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/sim/test_wallclock.py +13 -9
- virtualmodelcontrol-0.5.0/tests/small_plan.py +62 -0
- virtualmodelcontrol-0.5.0/tests/soft_arm_plan.py +30 -0
- virtualmodelcontrol-0.5.0/tests/test_benchmark.py +54 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/test_dynamics.py +18 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/test_import.py +1 -10
- virtualmodelcontrol-0.5.0/tests/test_math.py +152 -0
- virtualmodelcontrol-0.5.0/tests/test_testing.py +191 -0
- virtualmodelcontrol-0.3.0/CHANGELOG.md +0 -291
- virtualmodelcontrol-0.3.0/docs/examples/two-arms.md +0 -180
- virtualmodelcontrol-0.3.0/docs/tutorials/build-a-robot.md +0 -181
- virtualmodelcontrol-0.3.0/docs/tutorials/contact.md +0 -199
- virtualmodelcontrol-0.3.0/docs/tutorials/coordinates-and-components.md +0 -161
- virtualmodelcontrol-0.3.0/docs/tutorials/energy.md +0 -193
- virtualmodelcontrol-0.3.0/docs/tutorials/interactive.md +0 -221
- virtualmodelcontrol-0.3.0/docs/tutorials/real-time.md +0 -232
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/hardware/__init__.py +0 -38
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/hardware/bus.py +0 -203
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/hardware/check.py +0 -41
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/hardware/dynamixel.py +0 -162
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/hardware/homing.py +0 -70
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/hardware/profile.py +0 -194
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/identification/__init__.py +0 -7
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/identification/stiffness.py +0 -70
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/interactive/__init__.py +0 -25
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/interactive/controls.py +0 -82
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/interactive/interactive.py +0 -111
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/interactive/joystick.py +0 -101
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/interactive/keyboard.py +0 -64
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/interactive/recorder.py +0 -87
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/interactive/session.py +0 -96
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/interactive/window.py +0 -205
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/mechanisms/components/dissipation.py +0 -72
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/mechanisms/coordinates/frames.py +0 -62
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/mechanisms/coordinates/geometry.py +0 -74
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/models/rigid/poe.py +0 -158
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/robots/turtle.py +0 -99
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/ros/__init__.py +0 -41
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/ros/joint_io.py +0 -52
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/ros/node.py +0 -53
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/ros/params.py +0 -43
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/ros/plant.py +0 -121
- virtualmodelcontrol-0.3.0/src/virtualmodelcontrol/ros/twin.py +0 -82
- virtualmodelcontrol-0.3.0/tests/core/test_space.py +0 -52
- virtualmodelcontrol-0.3.0/tests/hardware/test_dynamixel.py +0 -164
- virtualmodelcontrol-0.3.0/tests/hardware/test_profile.py +0 -85
- virtualmodelcontrol-0.3.0/tests/interactive/conftest.py +0 -58
- virtualmodelcontrol-0.3.0/tests/interactive/test_controls.py +0 -83
- virtualmodelcontrol-0.3.0/tests/interactive/test_interactive.py +0 -261
- virtualmodelcontrol-0.3.0/tests/interactive/test_joystick.py +0 -74
- virtualmodelcontrol-0.3.0/tests/interactive/test_keyboard.py +0 -62
- virtualmodelcontrol-0.3.0/tests/interactive/test_session.py +0 -127
- virtualmodelcontrol-0.3.0/tests/interactive/test_window.py +0 -191
- virtualmodelcontrol-0.3.0/tests/models/test_poe.py +0 -75
- virtualmodelcontrol-0.3.0/tests/robots/test_turtle.py +0 -50
- virtualmodelcontrol-0.3.0/tests/ros/conftest.py +0 -9
- virtualmodelcontrol-0.3.0/tests/ros/test_joint_io.py +0 -29
- virtualmodelcontrol-0.3.0/tests/ros/test_ros.py +0 -136
- virtualmodelcontrol-0.3.0/tests/sim/test_paced.py +0 -108
- virtualmodelcontrol-0.3.0/tests/test_benchmark.py +0 -27
- virtualmodelcontrol-0.3.0/tests/test_deprecations.py +0 -106
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/.gitignore +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/CITATION.cff +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/LICENSE +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/benchmarks/tick.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/_ext/video.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/_static/create-lab.png +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/_static/custom.css +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/_static/favicon.svg +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/_static/logo-light.svg +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/_static/logo.svg +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/_static/readme-hero.svg +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/_templates/autosummary/module.rst +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/_templates/partials/toc.html +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/conf.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/development/changelog.md +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/development/roadmap.md +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/docs_setup.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/schematics/__init__.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/schematics/_draw.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/schematics/bimanual.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/schematics/control_loop.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/schematics/energy_flow.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/schematics/finger.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/schematics/four_steps.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/schematics/hand.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/schematics/helyx.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/schematics/mechanism.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/schematics/params.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/schematics/pcc.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/schematics/turtle.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/schematics/ur5.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/scripts/readme_figure.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/tutorials/reach.yaml +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/docs/tutorials/run-settings.yaml +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/compiler.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/config/__init__.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/config/controllers.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/config/experiment.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/config/files.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/config/spec.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/control/blending.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/control/output.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/control/schedule.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/core/params.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/core/registry.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/core/signals.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/core/units.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/identification/efficiency.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/identification/plateaus.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/mechanisms/components/constrained.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/mechanisms/components/storage.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/mechanisms/coordinates/joints.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/models/continuum/__init__.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/models/continuum/pcc.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/models/efficiency.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/models/joint_space.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/models/kinematic.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/models/rigid/__init__.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/models/rigid/couplings.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/py.typed +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/robots/__init__.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/robots/ur5.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/sim/plant.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/sim/replay.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/sim/runlog.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/system.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/viz/__init__.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/viz/animation.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/viz/draw.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/src/virtualmodelcontrol/viz/style.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/conftest.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/control/test_blending.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/control/test_honesty.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/control/test_output.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/control/test_schedule.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/control/test_vmc_golden.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/core/test_params.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/core/test_registry.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/core/test_signals.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/data/components.npz +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/data/configs/finger.yaml +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/data/configs/hand.yaml +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/data/configs/soft-arm.yaml +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/data/configs/turtle.yaml +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/data/configs/two-arms.yaml +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/data/configs/ur5-hand.yaml +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/data/derivatives.npz +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/data/dynamics.npz +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/data/efficiency.npz +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/data/finger.npz +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/data/hand.npz +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/data/pcc.npz +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/data/turtle.npz +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/data/vmc.npz +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/hardware/test_templates.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/identification/test_efficiency_fit.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/identification/test_stiffness_fit.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/mechanisms/test_components.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/mechanisms/test_components_golden.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/mechanisms/test_contact.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/mechanisms/test_coordinates.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/mechanisms/test_mechanism.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/models/test_assembly.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/models/test_efficiency.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/models/test_kinematics.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/models/test_pcc.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/robots/test_adapt.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/robots/test_bimanual.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/robots/test_hand.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/robots/test_helyx.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/robots/test_parametric.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/robots/test_ur5.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/sim/test_replay.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/sim/test_run.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/sim/test_runlog.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/test_compiler.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/test_docs.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/test_readme.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/viz/test_animate.py +0 -0
- {virtualmodelcontrol-0.3.0 → virtualmodelcontrol-0.5.0}/tests/viz/test_viz.py +0 -0
|
@@ -0,0 +1,630 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow
|
|
5
|
+
[Semantic Versioning](https://semver.org/) (0.x: the API may change between minor versions).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.5.0] - 2026-10-06
|
|
10
|
+
|
|
11
|
+
This release also carries the work meant for 0.4.0 (optimization of virtual mechanisms, the energy
|
|
12
|
+
tank, tuning and the calibrations), which was never released on its own.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- `vmc.optimization`: plan the motion of a controller on a robot and optimize its Params.
|
|
17
|
+
`Problem(system)` is built once and solved many times. `free` chooses the Params to optimize
|
|
18
|
+
and `parameter` the ones set at every solve (references, say), by name or glob; bounds and
|
|
19
|
+
scale come from the Param. `Collocation(q0, horizon, nodes, initial=, transition=, scales=)` is
|
|
20
|
+
trapezoidal collocation of the closed loop on the robot's full dynamics, without inverting the
|
|
21
|
+
mass matrix. With an `initial` controller, its torques fade out as the new ones fade in with the
|
|
22
|
+
blend of `SwapController`, so the plan is what the swap executes, and the model starts at rest
|
|
23
|
+
where the robot is whatever it gets wrong there. `Effort`, `Cost` (a library coordinate brought
|
|
24
|
+
to zero from a time on) and `Bound` (a coordinate kept within limits) are the terms, `Term`
|
|
25
|
+
the base to write your own. `Result` holds the motion, the Params found, the cost by term and
|
|
26
|
+
the solver's status, and `apply` puts the values into a running controller (returning the exact
|
|
27
|
+
energy jump) or into a system. `search_references` searches a reference on a grid, one at a
|
|
28
|
+
time, keeping the best converged plan. `Problem.build` returns the `NLP` for any other solver.
|
|
29
|
+
`Collocation(scheme="hermite-simpson")` integrates to fourth order instead of second: it adds the
|
|
30
|
+
acceleration at the middle of every interval to the unknowns, and needs far fewer nodes for the
|
|
31
|
+
same agreement with a simulation.
|
|
32
|
+
The program agrees with the lab's own optimization code to rounding error, and its solved plans
|
|
33
|
+
to solver tolerance. Controllers with virtual states and non-flat configuration spaces are not
|
|
34
|
+
supported yet.
|
|
35
|
+
- `optimization.Equilibrium(q0)`: the closed loop at rest, as a static problem. It takes the place of
|
|
36
|
+
`Collocation`: the unknown is a configuration where the controller's torques balance the
|
|
37
|
+
robot's own forces, found with the free Params, and the terms see it as their one node.
|
|
38
|
+
`Cost` and `Effort` count it once, and a `Bound` holds there. The tutorial finds where the
|
|
39
|
+
soft arm rests, in milliseconds.
|
|
40
|
+
- `Collocation(periodic=True)` plans an orbit that repeats: the last node equals the first (q and
|
|
41
|
+
v), the first node is free (`q0` and `v0` are only the solver's starting guess), and `Bound`
|
|
42
|
+
reaches it. `Collocation(free_time=(lower, upper))` makes the horizon an unknown within these
|
|
43
|
+
bounds, starting at `horizon`: the node spacing, the controller's time and the coordinates of
|
|
44
|
+
`vmc.Time()` are expressions of it, and `Effort` and `Cost` integrate with the horizon found.
|
|
45
|
+
The windows of the terms still read the nodes' times at the starting horizon. `Result.horizon`
|
|
46
|
+
is the horizon found (the given one for a fixed horizon, 0 for an `Equilibrium`) and
|
|
47
|
+
`Result.t` uses it; `warm_start` takes a `horizon`. `Trajectory.dt` is a number or an
|
|
48
|
+
expression of the free horizon, and `Trajectory.times` and `Trajectory.horizon` are the same,
|
|
49
|
+
for terms of your own. `optimization.Period(param)` holds the horizon equal to a Param, so that
|
|
50
|
+
a controller whose reference is a function of `vmc.Time()` and that Param (a period, free or a
|
|
51
|
+
parameter) repeats with the orbit. Neither option goes with an `initial` controller. Both
|
|
52
|
+
schemes work.
|
|
53
|
+
- Docs: tutorial "Optimizing a virtual mechanism".
|
|
54
|
+
- Docs: the optimization tutorial finds the period of a mass on a spring, and the least-effort
|
|
55
|
+
period of a pulled one with a controller that keeps time, against their closed forms.
|
|
56
|
+
- Docs: the optimization tutorial plans the soft arm around a sphere (`Bound` on `SphereDistance`),
|
|
57
|
+
checks the clearance in simulation, and shows that two sets of scales give the same plan.
|
|
58
|
+
- `vmc.sim.rollout(system, q0, T, dt)`: the closed loop simulated in one compiled call
|
|
59
|
+
(`mapaccum`), differentiable with respect to the controller's live Params, with the robot
|
|
60
|
+
integrated by `"implicit"` (the default, as `ModelPlant`), `"rk4"` or `"cvodes"`;
|
|
61
|
+
it reproduces `vmc.sim.run` to rounding error. `vmc.sim.ode(system)` is the closed loop in
|
|
62
|
+
continuous time, f(t, x) for SciPy's `solve_ivp`.
|
|
63
|
+
- `vmc.control.Tank(controller, level, capacity)`: an energy budget for changing a running
|
|
64
|
+
controller. `tank.set(values)` applies a change of live Params as far as the tank can pay for
|
|
65
|
+
the exact jump it gives the controller's energy (the largest fraction of the step that fits);
|
|
66
|
+
a step that releases energy is applied whole, even with an empty tank, and refills it.
|
|
67
|
+
`result.apply(tank)` passes an optimizer's result through it. `VMCController.jump(values)`
|
|
68
|
+
gives the jump `set` would give, without applying it.
|
|
69
|
+
Run in place of the controller (`vmc.sim.run(plant, tank, ...)`), the tank also refills itself
|
|
70
|
+
with what the controller's own dampers take at every step.
|
|
71
|
+
- `identification.fit_stiffness_damping` takes a run log (`RunLog`) as it is, or a mapping whose motor
|
|
72
|
+
torques are `motor_torque` or `u`.
|
|
73
|
+
- `identification.Steps(baseline, pulls, held_out, hold, rest)`: the step experiment as a controller
|
|
74
|
+
that runs on any plant. Every motor gets the baseline torque, and each pull adds a torque to some
|
|
75
|
+
motors for `hold` seconds, with `rest` seconds at the baseline between them. Its log marks the
|
|
76
|
+
training steps (`train`), which the fit uses as they are; the held-out ones are for validation.
|
|
77
|
+
- `fit_stiffness_damping(..., friction=True)` adds a static friction torque per motor, F sign(θ̇),
|
|
78
|
+
to the fit and returns it after K and D (`K, D, F`). Friction that is not in the fit passes for
|
|
79
|
+
damping. A motor that stands still has none in the model, so a run that stops at the end of every
|
|
80
|
+
step hardly shows it: use one that keeps the motors moving.
|
|
81
|
+
- `identification.validate(model, run)`: simulates a robot with its stiffness and damping under the
|
|
82
|
+
logged torques of the held-out steps of a run, from the state the run is in at the first of them,
|
|
83
|
+
and returns the root-mean-square error and the variance accounted for of each coordinate.
|
|
84
|
+
`vmc.sim.rollout` takes `u`, motor torques with a row per step, to simulate open loop.
|
|
85
|
+
- Docs: the hanging arm's page identifies its stiffness and damping with `Steps`, checks them on
|
|
86
|
+
held-out steps and shows the friction option.
|
|
87
|
+
- `identification.fit_transmission(motor, joint)`: the joint angle per motor angle of a cable drive,
|
|
88
|
+
from a sweep of the joint, by least squares through the origin. It reproduces the finger's and
|
|
89
|
+
the hand's transmission constants from their recorded sweeps. The finger's page shows it.
|
|
90
|
+
- `vmc.adaptation`: laws that change a running controller's live Params, a step at a time. Every
|
|
91
|
+
`step` returns the jump of the controller's energy [J] that was applied, and a `Tank` passed in
|
|
92
|
+
place of the controller applies only the part it pays for. A new value stays within the Param's
|
|
93
|
+
bounds (a stiffness stops at zero), and a square matrix stays symmetric and positive
|
|
94
|
+
semidefinite (`control.project_psd`).
|
|
95
|
+
- `ForceTracking(controller, site, params, normal=None, max_force_step=0.01, max_step=None,
|
|
96
|
+
rate=None)` descends the error of a contact force: `params` are glob patterns of live Params
|
|
97
|
+
(a spring's goal or its stiffness), `normal` keeps the force along it. The gradient is exact,
|
|
98
|
+
by automatic differentiation of the delivered torque, and agrees with the lab's hand-derived
|
|
99
|
+
one to 1e-8 for the goal and the stiffness, at the tip and mid-arm, along a normal and in 3D,
|
|
100
|
+
also where the point's Jacobian has rank below 3 (the two-motor finger). A step is the largest
|
|
101
|
+
that changes the force by `max_force_step` [N] (the lab finds it by a finite-difference probe
|
|
102
|
+
and agrees to 1e-5), or `rate`, a fixed learning rate as in the finger's experiments, where
|
|
103
|
+
it agrees with the lab's joint-space stiffness and reference descent at the lab's rates.
|
|
104
|
+
`direction` gives the descent direction without applying it.
|
|
105
|
+
- `ForceRatio(controller, params, max_change=0.05)` and `Stiffening(controller, params, low,
|
|
106
|
+
high, alpha)`: the laws of the lab's hand and finger that need no model. The first scales
|
|
107
|
+
stiffnesses by 1 plus or minus `max_change` times the relative error of the force (the hand's
|
|
108
|
+
multiplicative law); the second sets k(F) = low + (high - low)(1 - exp(-alpha F)) from the
|
|
109
|
+
measured force (the finger's law). Both equal the lab's. K(d) is the `SigmoidSpring` and the
|
|
110
|
+
`PolynomialSpring`.
|
|
111
|
+
- `StiffnessTracking(controller, site, params, normal=None, robot=None, fraction=1.0)`: direct
|
|
112
|
+
stiffness tracking. The stiffness at the site is affine in the springs' stiffness, so `target`
|
|
113
|
+
solves a linear system for the Params that give a wanted matrix, the solution of smallest
|
|
114
|
+
norm as in the lab's inversion, and `step` goes `fraction` of the way. Where no spring pulls
|
|
115
|
+
it agrees with the lab's inversion to 1e-6; where they do, it counts the geometric terms
|
|
116
|
+
that the lab's leaves out.
|
|
117
|
+
- `PositionRegulation(controller, sites, gain=0.05)`: integral pose regulation. A step adds
|
|
118
|
+
`gain` times the error of a point of the robot to the goal of the spring that pulls it.
|
|
119
|
+
- `HoldingGoals(controller, sites, robot=None)`: the open-loop counterpart, the lab's position
|
|
120
|
+
feedforward. It puts the goals at wanted positions (default: where the points are) plus the
|
|
121
|
+
smallest offset that lets the springs carry the robot's own stiffness and weight at the pose
|
|
122
|
+
now, one Newton step on the static balance. It agrees with the lab's to 1e-9; with as many
|
|
123
|
+
springs as motors the arm then stays where it is.
|
|
124
|
+
- `vmc.estimation`: quantities of a running robot that no sensor measures. Both take the
|
|
125
|
+
controller, a site (a name, an arc parameter or `(part, s)`) and a `normal`, and a `robot`:
|
|
126
|
+
the model that holds the arm at rest, without the surroundings the plant may have. They use the
|
|
127
|
+
controller's law before the output stages, the system's transmission and efficiency, and leave
|
|
128
|
+
velocities out.
|
|
129
|
+
- `ContactForce(controller, site, normal=None, robot=None)`: the force a robot exerts at a site
|
|
130
|
+
at rest. What the delivered motor torques and the robot's own stiffness and weight do not
|
|
131
|
+
balance goes through the site's Jacobian by the pseudo-inverse. It agrees with the lab's
|
|
132
|
+
contact force from the virtual springs and the structural stiffness (the efficiency on the
|
|
133
|
+
springs' term only) to 1e-9, with its torque-based variant, and with the finger's. A fingertip
|
|
134
|
+
at rest on a simulated table reads the table's force to 2 %.
|
|
135
|
+
- `TaskStiffness(controller, site, normal=None, robot=None)`: the stiffness [N/m] at the site, a
|
|
136
|
+
3 by 3 matrix. It is the stiffness of the static balance, by automatic differentiation, with
|
|
137
|
+
the geometric terms (the Hessians of the site and of the springs) counted, and agrees with
|
|
138
|
+
the lab's exact apparent stiffness to 1e-8. The lab's first-order version leaves the
|
|
139
|
+
geometric terms out and is not provided.
|
|
140
|
+
- `KalmanFilter(system, dt, Q=None, P0=None, gate=40.0, robot=None)` and `Measurement(q, v, Rq,
|
|
141
|
+
Rv, observed, name)`: a Kalman filter of the robot's state (q, v). Its process model is the
|
|
142
|
+
robot's own dynamics, linearised at the estimate at rest and held over the step (the lab's
|
|
143
|
+
frozen mass matrix, in general form), with the command going through the system's
|
|
144
|
+
transmission. It fuses encoders (`kf.encoder`) and any sensor that sees part of the state,
|
|
145
|
+
gates each measurement on its innovation, and reports the sensors it rejected (`rejected`,
|
|
146
|
+
`rejected_total`) and the expected ones that offered nothing (`missing`). Over a run with
|
|
147
|
+
dropouts and an outlier of each sensor it agrees with the lab's filter in its state to 1e-9,
|
|
148
|
+
its covariance, its innovation distances and the sensors it rejects.
|
|
149
|
+
- `Inversion(robot, at, damping, tol, max_iter)`: the configuration that puts the robot's points
|
|
150
|
+
`at` where a position sensor saw them (motion-capture markers), by damped Gauss-Newton from the
|
|
151
|
+
last result, for any robot. It agrees with the lab's closed form for the three-section arm
|
|
152
|
+
to 1e-8, and finds the soft arm from its neutral configuration up to 0.6 rad of bend in each
|
|
153
|
+
section (give `q0` beyond). `VelocityFilter(dt, alpha=0.3)`: the low-passed difference of
|
|
154
|
+
consecutive samples, the lab's velocity of the markers, with `dt` the sensor's own period.
|
|
155
|
+
- `ImuFilter(arm, mounts, kp, acc_tol, gravity)`: the curvature (Dx, Dy) of each section of a
|
|
156
|
+
soft arm and its rate from an IMU on its base and on each section end, by a complementary
|
|
157
|
+
filter of each section's relative rotation (the gyros turn it, the gravity both accelerometers
|
|
158
|
+
see corrects it, and it is kept on the rotations the arm can make). `calibrate` takes the
|
|
159
|
+
gyro bias and the starting pose from the arm held still. Its `observed` coordinates go to
|
|
160
|
+
`Measurement`. It agrees with the lab's filter to 1e-10 over a run with accelerometers that
|
|
161
|
+
cannot be trusted.
|
|
162
|
+
- `VMCController.inputs()`: the vector the law reads, with the live Params as they are now.
|
|
163
|
+
A Param that acts only through a virtual state does not change the force at once, and the
|
|
164
|
+
laws leave it.
|
|
165
|
+
- Docs: the tutorials "Track a contact force" (the laws, the estimate without a sensor, the tank)
|
|
166
|
+
and "Shape the stiffness of the tip"; the finger's page presses between two force levels; the
|
|
167
|
+
two arms' page holds an object with a chosen force, with estimates alone, with a sensor on the
|
|
168
|
+
object, and through a tank (the object feels the wanted force to 0.2 % from the estimates).
|
|
169
|
+
- `vmc.Gated(component, gate)`: an element whose force and energy are multiplied by a live Param
|
|
170
|
+
`gate` between 0 and 1. `optimization.Sparsity(weight, *patterns)` adds the sum of the free Params
|
|
171
|
+
that match (each at least 0) to the cost. With the gates free, the optimizer keeps the elements
|
|
172
|
+
that earn their place: structure optimization, tested on a mass with three springs and on the
|
|
173
|
+
soft arm with five repulsive fields, and shown in the optimization tutorial ("Which fields to
|
|
174
|
+
keep").
|
|
175
|
+
- `vmc.models.FunctionModel(frame, space, params, sites, q_unit)`: a kinematic model from a function
|
|
176
|
+
`frame(q, at, p)` that returns the rotation and the position of a site, as CasADi values or as
|
|
177
|
+
lists and arrays. It works in `Kinematics`, mechanisms and `check_model`; a function cannot be
|
|
178
|
+
written to a file, so it has no `to_dict`.
|
|
179
|
+
- `vmc.testing.check_model(model)`: the model contract in one call, for a kinematic model or a
|
|
180
|
+
robot's mechanism: everything finite (also with each Param a tenth of its default and ten times
|
|
181
|
+
it), orthonormal rotations, Jacobians, angular Jacobians and Hessians against finite
|
|
182
|
+
differences, no jump along the arc parameter `s`, `to_dict` and `from_dict` giving the model
|
|
183
|
+
back, and, for a robot with masses and no dampers, an energy drift that falls with the step. It
|
|
184
|
+
raises an `AssertionError` that lists the failed checks and returns the worst error of each. The
|
|
185
|
+
tutorials "Build your own robot" and "Extend the library" use it.
|
|
186
|
+
- `vmc.BoxDistance`, `CapsuleDistance` and `CylinderDistance`: signed distances from a point to a
|
|
187
|
+
box with its sides along the axes, a capsule and a cylinder, for contacts and obstacles, with the
|
|
188
|
+
same Params as `SphereDistance` (and the kinds `box_distance`, `capsule_distance` and
|
|
189
|
+
`cylinder_distance` in configuration files). The contact tutorial uses the cylinder.
|
|
190
|
+
- `vmc.ContactFriction(distance, stiffness, friction)`: Coulomb friction at a contact, smoothed. It
|
|
191
|
+
pushes a point against its sliding speed along the surface, with the size of the friction
|
|
192
|
+
coefficient times the contact spring's force (give it the spring's stiffness `Param`), and falls
|
|
193
|
+
linearly below the small speed `speed`, so a point at rest creeps. It works on every signed
|
|
194
|
+
distance, which now share the base class `SurfaceDistance` with a `unit_normal`; the type is
|
|
195
|
+
`contact_friction` in configuration files. The contact tutorial drags a fingertip along a table.
|
|
196
|
+
- `vmc.sim.run(..., record="robot")` logs what a simulated robot feels, component by component:
|
|
197
|
+
`robot/<name>/y`, `ydot`, `force` and `torque` of each spring, damper and contact, from
|
|
198
|
+
`ModelPlant.elements()` (and `Dynamics.elements`). A real robot reports no forces, so recording
|
|
199
|
+
it raises an error.
|
|
200
|
+
- `vmc.estimation.Encoders`, `Markers`, `Imus` and `LoadCell`: simulated sensors, the true state in
|
|
201
|
+
and a noisy reading out, as the estimators take it. The encoders read the motors through the
|
|
202
|
+
transmission, with noise and a constant slack per motor; the markers, the positions of points of
|
|
203
|
+
the arm; the IMUs, the angular velocity and gravity in each frame's own axes, with a constant gyro
|
|
204
|
+
bias; the load cell, a force with a bias and noise. Every one has a seed. The estimation tutorial
|
|
205
|
+
uses them in place of the lines it wrote by hand.
|
|
206
|
+
- `vmc.adaptation.DitherSeeking(controller, params, amplitude, frequency, gain, window)`: extremum
|
|
207
|
+
seeking from the cost alone, the two-tone law of the turtle paper. Each scalar live Param is held
|
|
208
|
+
at an estimate plus a sinusoidal dither at its own frequency (2π n / `window`, a whole n each, so
|
|
209
|
+
that the tones are orthogonal); the cost's correlation with a tone over the window is the slope
|
|
210
|
+
with respect to that Param, and the estimate moves downhill at `gain` times it, at most
|
|
211
|
+
`max_rate`, within the Param's bounds. On a `Tank`, the changes are paid from its energy, which is
|
|
212
|
+
the paper's passivity cap. The crawl tutorial lets the crawler find its best `peak` this way.
|
|
213
|
+
- `turtle.controller(robot, depth=, peak=, steer=, limit=)`: with any of them the cranks' springs
|
|
214
|
+
are `PhaseSpring`s (the paper's phase-modulated, saturating potential); without, they are the
|
|
215
|
+
plain ones of the lab's controller, as before.
|
|
216
|
+
- `vmc.optimization.MovingHorizon(system, dt, window=10, Q=, P=)`: moving-horizon estimation of a
|
|
217
|
+
robot's state (q, v). Every step finds the states of the last `window` steps that best agree
|
|
218
|
+
with the sensors' readings (the same `Measurement`s as the Kalman filter's), with the robot's own
|
|
219
|
+
dynamics up to the process noise `Q`, and with the state before the window, which goes one step of
|
|
220
|
+
an extended Kalman filter whenever the window slides. It is solved by Gauss-Newton with a trust
|
|
221
|
+
region. With a linear robot it is the Kalman filter, to rounding error, however short the window;
|
|
222
|
+
it also gives `cost` and the covariance `P`. The estimation tutorial runs it on the soft arm.
|
|
223
|
+
- `vmc.identification.fit_params(robot, names, runs)`: any Params of a robot, by name or glob,
|
|
224
|
+
fitted to logged runs by least squares on the residual of its own dynamics, within the Params'
|
|
225
|
+
bounds. A residual linear in the Params (masses, stiffnesses, dampings, efficiencies) is solved
|
|
226
|
+
in a step, and any other, such as the saturating damper's, by Gauss-Newton. It returns the values
|
|
227
|
+
in each Param's shape, their standard errors and the residual's root mean square. A run with
|
|
228
|
+
an `a` uses it, and otherwise the acceleration is the smoothed velocity's difference against the
|
|
229
|
+
torques averaged over the step they were held. It agrees with ordinary least squares, values and
|
|
230
|
+
covariance, on a mass, spring and damper. The tutorial "Fit Params to a run" uses it.
|
|
231
|
+
- `KalmanFilter(..., unscented=True, substeps=10)`: the prediction sends sigma points of the
|
|
232
|
+
estimate (the scaled unscented transform, a root of three standard deviations out) through the
|
|
233
|
+
robot's own integrator, in `substeps` steps, instead of linearising at the estimate; the sensors
|
|
234
|
+
stay linear, so the update is the same. On a double pendulum it follows the mean of a Monte
|
|
235
|
+
Carlo to 0.003 where the linearised prediction is off by 2; on a linear robot the two agree.
|
|
236
|
+
- `vmc.estimation.MomentumObserver(system, dt, gain, robot=None)`: the external force on a robot
|
|
237
|
+
from its motion, without accelerations. From the momentum and what the model says would change
|
|
238
|
+
it, it gives the generalized force the model does not explain, as a low-pass filter of bandwidth
|
|
239
|
+
`gain` of the true one, and `force(site, normal)` carries it to a site, as `ContactForce` does.
|
|
240
|
+
It works while the robot moves, where `ContactForce` assumes rest. The force tutorial shows a
|
|
241
|
+
finger landing on a table. Its velocity must be the rate of its configuration (no floating
|
|
242
|
+
bodies yet).
|
|
243
|
+
- `vmc.estimation.object_compliance(position, force, baseline_position, baseline_force)`: the
|
|
244
|
+
compliance in m/N of an object a tip presses, the distance over the force that stiffer settings
|
|
245
|
+
of the controller add to a gentle one, from the median of each setting's samples. It is the
|
|
246
|
+
lab's probe of the hand, and it agrees with the lab's code to rounding error. The force tutorial
|
|
247
|
+
shows it on three objects, with the force from `ContactForce`.
|
|
248
|
+
- Docs: the contact tutorial also shows two points of a robot touching (a self-contact, the two
|
|
249
|
+
arms), friction between two points and a soft object between two tips, from the pieces above.
|
|
250
|
+
- `vmc.control.project_psd(K)`: the symmetric positive semidefinite matrix nearest to a stiffness,
|
|
251
|
+
for an update that an adaptation law proposes, before it goes through `set` or a tank.
|
|
252
|
+
- `vmc.sim.energy_balance(log)`: the controller's energy over a run recorded with
|
|
253
|
+
`record=["energy"]`: its energy, the work given through its port, what its dampers took and its
|
|
254
|
+
sources gave, `injected` (what changes of live Params put in, plus the error of the steps) and
|
|
255
|
+
the `margin` it can still give, which stays above 0 while the controller is passive.
|
|
256
|
+
- `vmc.optimization.Grid`, `Random`, `CMAES`, `ExtremumSeeking` and `Bayes`: gradient-free tuning by ask and tell
|
|
257
|
+
(`ask()` gives candidates, `tell(candidates, costs)` takes their costs), `tune` to run it, and
|
|
258
|
+
`bounds_of` for the bounds and values of named Params. `Bayes` fits a Gaussian process to the
|
|
259
|
+
costs seen so far and asks for the candidate with the highest expected improvement: it suits
|
|
260
|
+
slow episodes, tens of them. The episodes are yours, in simulation or on a robot in your own loop.
|
|
261
|
+
- `compile_dynamics(robot, runtime, actuation)` takes the actuation of a robot that has none, so a
|
|
262
|
+
system's efficiency Params (`robot.efficiency.c1`) are the ones the dynamics read.
|
|
263
|
+
- `vmc.math`: rotations and rigid transforms that run on numpy arrays and CasADi symbols alike
|
|
264
|
+
(`rot_x`, `rot_y`, `rot_z`, `rot`, `skew`, `vee`, `exp_so3`, `log_so3`, `transform`, `invert`,
|
|
265
|
+
`exp_se3`, `log_se3`, `adjoint`), for writing the `frame` of a `FunctionModel`. Every function
|
|
266
|
+
is smooth at the identity, also in its second derivatives (the exact forms lose them there).
|
|
267
|
+
They replace the three rotation helpers of `core.symbolic`.
|
|
268
|
+
- `SerialChain` joints: `"helical"` (a turn that slides by a pitch, given as `("helical", pitch)`),
|
|
269
|
+
`"spherical"` (three coordinates, a rotation vector about the joint's point) and `"free"` (six:
|
|
270
|
+
a translation and a rotation vector, a floating base). A chain on a free base, a brick of point
|
|
271
|
+
masses thrown with a spin and its momenta and energy are tested; a branch of a tree is a part
|
|
272
|
+
mounted on a site of another part by `Assembly`.
|
|
273
|
+
- `SerialChain` joint `("rail", waypoints)`: a slide along the natural cubic spline through the
|
|
274
|
+
waypoints, which are a `design` Param (an array of rows of three) in the frame of the joint
|
|
275
|
+
before it. Its coordinate is the spline parameter, 0 at the first waypoint and 1 at the last. It
|
|
276
|
+
agrees with SciPy's natural spline, and a bead on a circular wire swings as a pendulum.
|
|
277
|
+
- `SerialChain` joint `"floating"`: a floating base whose rotation is a unit quaternion, with
|
|
278
|
+
seven coordinates and six velocities (the translation's and the body's angular velocity in its
|
|
279
|
+
own axes). `vmc.Quaternion` is its space, and `Space.coadjoint` gives the term that
|
|
280
|
+
velocities that do not commute add to the dynamics (the Euler-Poincare term), which
|
|
281
|
+
`compile_dynamics` now includes. A body tumbles about its intermediate axis through several
|
|
282
|
+
full turns by Euler's equations, and a base with an arm keeps its momenta and energy.
|
|
283
|
+
- `vmc.FramePoint(model, site, q=coordinate)`: a point of a virtual model, at the configuration
|
|
284
|
+
that `coordinate` gives: a virtual state (a cart on a rail with a mass of its own), a
|
|
285
|
+
reference, or a function of time. `vmc.Time()` is the time of the run, to build functions of
|
|
286
|
+
time with `Custom`; a damper on the difference to such a goal feels its velocity.
|
|
287
|
+
- More coordinates: `vmc.Sum` (and the plus sign: `tip + [0, 0, 0.05]`), `vmc.FrameRotation` (a
|
|
288
|
+
frame's rotation matrix, row by row), `vmc.OrientationError(model, site, goal=)` (the rotation
|
|
289
|
+
vector from a goal orientation to a frame's, in the goal's axes, with `goal` a live Param; a
|
|
290
|
+
spring on it is a rotational spring whose torque is exact at any error, where the one from the
|
|
291
|
+
angular Jacobian is 8 % off at 0.4 rad), `vmc.InFrame` and `vmc.FromFrame` (a vector along the
|
|
292
|
+
axes of a frame, and back: a stiffness along the tool's axes turns with the tool). They take a
|
|
293
|
+
site or an arc parameter, and a virtual model through `q=`. Configuration files build them as
|
|
294
|
+
`sum`, `rotation`, `orientation_error`, `in_frame` and `from_frame`.
|
|
295
|
+
- More components: `vmc.RotationalInertia(rotation, inertia)`, the inertia of a rigid body about
|
|
296
|
+
its frame (a matrix, or three principal moments) on the frame's rotation matrix, next to a
|
|
297
|
+
`PointMass` for its mass: it follows Euler's equations, moves like the same body made of point
|
|
298
|
+
masses to rounding error, and a rotational spring on it oscillates at the square root of K over
|
|
299
|
+
I. `vmc.DiodeDamper(y, D, sign, smoothing)` damps one direction of motion only.
|
|
300
|
+
`ForceSource(y, f, max_force=, max_power=)` bounds the force smoothly, and the power it
|
|
301
|
+
delivers. `Mechanism.add_mass_along(name, mass, s0, s1, n)` spreads a mass along a model as
|
|
302
|
+
point masses at the nodes of Gauss-Legendre quadrature. An `Inertance` on a difference is an
|
|
303
|
+
inerter, tested.
|
|
304
|
+
- Docs: "A spring on the tool's orientation" and "A spring along the tool's axes" in "Kinematics on
|
|
305
|
+
the UR5"; "A damper that works one way" in "Coordinates and components"; a rigid body and the
|
|
306
|
+
mass along an arm in "Build your own robot".
|
|
307
|
+
- Docs: the tutorial "Estimate the state of a soft arm" (encoders with slack, markers and IMUs
|
|
308
|
+
fused by the filter, an outlier and lost frames); "A rail along a path" and the floating joint
|
|
309
|
+
in "Build your own robot"; "A cart on a rail" in "Coordinates and components".
|
|
310
|
+
- `vmc.PhaseSpring(coord, stiffness, depth, peak, steer, side, limit)`: a spring on a deflection e
|
|
311
|
+
whose stiffness follows a phase, on the coordinate `Stack(e, phase)`: K (1 + side steer) (1 +
|
|
312
|
+
depth cos(phase - peak)). Its force is minus the gradient of its energy, so the phase feels the
|
|
313
|
+
reaction that keeps a flywheel loop passive. With `limit` the potential saturates, and the torque
|
|
314
|
+
never goes above K (1 + |steer|) times the limit. With no depth, no steer and no limit it is a
|
|
315
|
+
`LinearSpring`. The type is `phase_spring` in configuration files.
|
|
316
|
+
- `vmc.models.Passive(nv)`: an actuation with no motors, for a part that nothing drives, such as a
|
|
317
|
+
floating body. Stacked with the other parts' motors (`Assembly.stacked_actuation`), the motor
|
|
318
|
+
vector holds only theirs, so a simulated robot can have more coordinates than motors. The motors
|
|
319
|
+
do not give a passive part's configuration, so a controller is compiled against a robot without
|
|
320
|
+
it, and the simulator runs the one with it.
|
|
321
|
+
- `robots.turtle.crawler(**CRAWLER)`: a simple crawler for the simulator, with placeholder
|
|
322
|
+
constants, not the lab's turtle: a floating body on the ground with gravity, two cranks about its
|
|
323
|
+
lateral axis with a foot each, and a contact spring, damper and friction at each foot and at the
|
|
324
|
+
four corners of the underside. Its motors are the two cranks, in the gait convention of
|
|
325
|
+
`turtle.robot()`, which is what the controller is compiled against. Under the flywheel controller
|
|
326
|
+
it crawls forward, further the faster the flywheel is driven, and does not advance without
|
|
327
|
+
friction; a positive steer of `PhaseSpring` turns it left. Docs: the tutorial "Crawl with a
|
|
328
|
+
flywheel".
|
|
329
|
+
|
|
330
|
+
### Removed
|
|
331
|
+
|
|
332
|
+
- `vmc.ros` (`RosPlant`, `control`, `serve`, `LiveParams`, `JointIO`, `TOPICS`) and the direct
|
|
333
|
+
Dynamixel path (`hardware.DynamixelPlant`, `home`, `present_ticks`, `scan`, `latency_timer`,
|
|
334
|
+
`Bus`, `SdkBus`, `FakeBus`), deprecated in 0.3.0. The library is communication-agnostic: it
|
|
335
|
+
turns measurements into torques, and how they reach the robot stays outside it. The Dynamixel
|
|
336
|
+
SDK and pyserial are no longer dependencies, and CI no longer runs the ROS tests. Hardware
|
|
337
|
+
profiles (`HardwareProfile`, `Motor`, `KT`, `MODES` and each robot's `hardware` template) stay.
|
|
338
|
+
A project that still uses a removed name keeps `virtualmodelcontrol==0.3.0`.
|
|
339
|
+
- `vmc.interactive` (the window, the keyboard, the joystick, the session, the mailbox, the wrapper
|
|
340
|
+
and the recorder), the `joystick` extra and `SimClock`'s `speed`, `now` and `sleep`: the library
|
|
341
|
+
is for control, not for interfaces. A running controller still changes through
|
|
342
|
+
`controller.set`, schedules and swaps. A project that uses them keeps `virtualmodelcontrol==0.3.0`.
|
|
343
|
+
- From the hardware profiles, the raw Dynamixel units (encoder ticks, velocity units, goal
|
|
344
|
+
currents, motor constants `kt` and the `KT` table, baud rate, serial port, velocity filter, home
|
|
345
|
+
ticks, per-motor torque limits and operating modes). A `Motor` is now `Motor(id, sign, hold)`
|
|
346
|
+
and a `HardwareProfile` `(motors, rate, bus_order)`, with the conversions between a driver's
|
|
347
|
+
degrees, bus order and signs and the library's SI units.
|
|
348
|
+
|
|
349
|
+
## [0.3.0] - 2026-10-05
|
|
350
|
+
|
|
351
|
+
### Added
|
|
352
|
+
|
|
353
|
+
- `vmc.config`: experiments in YAML files. `vmc.config.load` reads the robot (a template and its
|
|
354
|
+
arguments), named coordinates, the controller's elements (a registered component `type`, the
|
|
355
|
+
`coordinate` it acts on, its gains), controllers to swap to, and how to run them: a simulation
|
|
356
|
+
(with the robot's dynamics and simulated elements such as contacts), the rate, the duration,
|
|
357
|
+
output stages, schedules and the initial virtual state.
|
|
358
|
+
`Experiment.run` runs it, `save` writes it back with the Params' current values. Robot
|
|
359
|
+
templates, output stages and coordinate kinds are registry entries, so a project adds its own.
|
|
360
|
+
An experiment from a file gives the same run as the same experiment written in Python.
|
|
361
|
+
- `vmc.control.Schedule` and `ScheduledController`: live Params that follow values over time
|
|
362
|
+
(in straight lines or steps) and swaps at given times; a new run starts afresh. The lab's
|
|
363
|
+
linear ramps are two-point schedules.
|
|
364
|
+
- `vmc.sim.run(..., z0=...)` also takes a function of the first reading, such as
|
|
365
|
+
`turtle.initial_state`.
|
|
366
|
+
- Docs: tutorial "Experiments in files".
|
|
367
|
+
- Run logs. `vmc.sim.RunLog` saves a run whole or not at all (`save`: a compressed `.npz` with a
|
|
368
|
+
schema version and what the run was, in `meta`: the library's version, the start time, the
|
|
369
|
+
Params at the start, the plant's hardware profile and, from a configuration, the
|
|
370
|
+
configuration; written through a temporary file, and a name already taken is refused unless
|
|
371
|
+
`overwrite=True`), loads it back (`load`) and exports CSV (`to_csv`, one column per entry).
|
|
372
|
+
`step` adds one step and keeps every signal at one row per step, with NaN for what a step
|
|
373
|
+
did not compute.
|
|
374
|
+
- `vmc.sim.replay` sends a log's motor torques again to a simulated robot, each held for as long
|
|
375
|
+
as it was in the run, from the log's `q` and `v` or, for a real robot's log, from its first
|
|
376
|
+
motor reading (`ModelPlant.state_from_motors`); `vmc.sim.compare` gives the largest and the
|
|
377
|
+
root-mean-square difference of each signal of two runs. A replay on the true model gives the
|
|
378
|
+
run back.
|
|
379
|
+
- A run's log holds `law_torque`, the controller's torque before the output stages.
|
|
380
|
+
`vmc.sim.run(..., record=...)` adds the live Params (`"params"`), each element's coordinate,
|
|
381
|
+
rate, force and share of the motor torques (`"elements"`), and the controller's energies and
|
|
382
|
+
powers (`"energy"`), from `VMCController.elements()` and `balance()`.
|
|
383
|
+
- Configurations: `experiment.run` settings (`name`, `folder`, `overwrite`, `record`) save each
|
|
384
|
+
run beside the file and refuse a name already taken before the run starts.
|
|
385
|
+
- Docs: tutorial "Run logs".
|
|
386
|
+
- `vmc.interactive`: change a running controller by hand. `Controls` is a thread-safe mailbox
|
|
387
|
+
for new values of live Params and for swaps. `Interactive` wraps any controller and applies
|
|
388
|
+
what the mailbox holds just before each step, in a simulation or inside a robot's own node;
|
|
389
|
+
the changes act exactly as `controller.set` before the step, and it counts the energy they give
|
|
390
|
+
the running controller (`injected`). `Recorder` turns what was applied into `schedule` entries
|
|
391
|
+
with `step` interpolation and saves them into a configuration, which repeats the session
|
|
392
|
+
exactly. `Window` (matplotlib, no new dependency) draws the robot live, with goals to drag,
|
|
393
|
+
sliders, buttons to swap controllers, record and pause; `Keyboard` and `Joystick` (pygame, the
|
|
394
|
+
extra `virtualmodelcontrol[joystick]`) move a goal; `Session` runs a simulation in real time
|
|
395
|
+
in a worker thread with its window.
|
|
396
|
+
- `vmc.sim.SimClock(dt, speed=...)` paces a simulation to the computer's clock: with `speed`,
|
|
397
|
+
`run(T=None)` runs until stopped and Ctrl-C ends it with the log so far. Other simulations are
|
|
398
|
+
unchanged. `VMCController.live_params()` and `Experiment.z0()`.
|
|
399
|
+
- Docs: tutorial "Interactive control".
|
|
400
|
+
- Docs: tutorials "Real-time runs" (the loop on the computer's clock: measured steps, late steps
|
|
401
|
+
never caught up in a burst, old and missing readings, Ctrl-C, and a checklist for the first run
|
|
402
|
+
on a robot) and "Swaps and schedules" (the quintic blend and its continuity, a swap on the soft
|
|
403
|
+
arm, the schedules' interpolation).
|
|
404
|
+
- `vmc.ros.control`: the controller node. It runs a controller at the profile's rate on the
|
|
405
|
+
robot behind the driver's topics, with its live Params as ROS parameters, for a duration or
|
|
406
|
+
until Ctrl-C, and ends with zero torque.
|
|
407
|
+
- On real time (`WallClock`), `vmc.sim.run(..., T=None)` runs until Ctrl-C, and Ctrl-C ends
|
|
408
|
+
a real-time run with the log so far.
|
|
409
|
+
- CI runs the ROS tests in ROS 2 Humble and Jazzy containers, on a private domain.
|
|
410
|
+
- `vmc.control.SwapController` and `blend_weight`: one set of virtual elements replaces another
|
|
411
|
+
with a quintic blend of the two controllers' torques (continuous torque and first two
|
|
412
|
+
derivatives), the blend the lab's controller uses; a swap asked for during a blend waits for
|
|
413
|
+
it. `vmc.ros.control(..., swaps={name: controller})` swaps on a `String` message.
|
|
414
|
+
- `vmc.Efficiency`: the motor torque a transmission delivers, as a polynomial of the commanded
|
|
415
|
+
one, τ = c₁u + c₂u² + … + cₙuⁿ, each coefficient one value for every motor or one per motor.
|
|
416
|
+
The coefficients are `design` Params, to change, tune, keep live in a simulator or identify.
|
|
417
|
+
`Direct` and `TendonTransmission` take one, or a number for its linear coefficient.
|
|
418
|
+
- `vmc.identification`: `plateaus`, the settled end of every hold of a command in a log, and
|
|
419
|
+
`fit_efficiency`, a least-squares fit through the origin, motor by motor or shared, from
|
|
420
|
+
delivered torques or from one measured quantity with a weight per motor (a fingertip force,
|
|
421
|
+
say). Both agree with the lab's calibration code, and the fit gives the finger's
|
|
422
|
+
`adapt.MOTOR_EFFICIENCY` back from its recorded data.
|
|
423
|
+
- Docs: concepts pages "Transmission efficiency", "Virtual Model Control" (coordinates, forces,
|
|
424
|
+
the torques that realize them, virtual states), "Passivity" (the energy balances, stability,
|
|
425
|
+
what weakens it) and "Finger and hand kinematics" (motors to joints, joints to the
|
|
426
|
+
fingertip, the hand's couplings).
|
|
427
|
+
- The constrained elements as components of their own: `ConstrainedLinearSpring`,
|
|
428
|
+
`ConstrainedTanhSpring`, `ConstrainedGaussianSpring`, `ConstrainedLinearDamper` and
|
|
429
|
+
`ConstrainedTanhDamper` act along one direction (`normal`) only, leaving the plane normal to
|
|
430
|
+
it free. They give the forces of the lab's constrained elements, checked against them; the
|
|
431
|
+
tanh ones saturate along the normal rather than axis by axis.
|
|
432
|
+
- `vmc.identification.fit_stiffness_damping`: a robot's diagonal stiffness and damping from
|
|
433
|
+
logged runs under known motor torques, by least squares with K, D ≥ 0 in motor torques,
|
|
434
|
+
relative to a resting baseline, with the robot's masses and gravity known; each run can carry
|
|
435
|
+
its own gravity. It recovers the stiffness and damping of a simulated arm within a few percent.
|
|
436
|
+
- Docs: two single-arm examples, each about its own arm and its own experiments. The soft arm on
|
|
437
|
+
its side (`145-145-145`) reaches past an obstacle with two repulsive fields, over a sweep of
|
|
438
|
+
their strength, and a tanh spring limits the force on a string tied to the tip. The hanging
|
|
439
|
+
arm (`145-290-290`) is identified from simulated step responses with
|
|
440
|
+
`fit_stiffness_damping` and reaches around an obstacle with a tanh spring and two fields.
|
|
441
|
+
Both use the same stiffness and damping. The tutorials, the home page and the README use the
|
|
442
|
+
arm on its side; the Helyx geometries and the parametric template are on the soft-arm
|
|
443
|
+
kinematics page.
|
|
444
|
+
|
|
445
|
+
### Changed
|
|
446
|
+
|
|
447
|
+
- Every robot's efficiency is 1 by default: models identified from the commanded torques
|
|
448
|
+
already include their transmission. The soft arm and the two arms take each torque as the
|
|
449
|
+
controller sends it again, with `helyx.SIM_STIFFNESS`, `helyx.SIM_DAMPING`,
|
|
450
|
+
`bimanual.STIFFNESS` and `bimanual.DAMPING` referred to the commanded torque (the identified
|
|
451
|
+
values divided by the 0.12 they were fitted with), as in 0.1.0. 0.2.0 applied 0.12 to every
|
|
452
|
+
torque with physical stiffness and damping: the same equilibria without gravity, but natural
|
|
453
|
+
frequencies about 2.9 times lower and a gravity compensation that cancelled only 12 % of the
|
|
454
|
+
weight. `helyx.EFFICIENCY`, `bimanual.EFFICIENCY`, `adapt.MOTOR_EFFICIENCY` and
|
|
455
|
+
`adapt.HAND_MOTOR_EFFICIENCY` stay as calibrations, never as defaults.
|
|
456
|
+
- A transmission's efficiency Param is now `efficiency.c1` (and `c2`, … for a polynomial);
|
|
457
|
+
transmissions saved by 0.2.0 still load.
|
|
458
|
+
- `import virtualmodelcontrol` no longer loads SciPy, which took about three quarters of its
|
|
459
|
+
import time; `identification.fit_stiffness_damping` loads it when called.
|
|
460
|
+
- Docs: the opening page has no left index (the pages of the five sections keep theirs) and
|
|
461
|
+
leads to the concepts and the reference. Installation: the conda recipe takes Python from
|
|
462
|
+
conda-forge, because conda's default channels stop a new installation until Anaconda's terms of
|
|
463
|
+
service are accepted, and shows how to keep ROS's `PYTHONPATH` out of a conda environment, where
|
|
464
|
+
pip otherwise ends with an error about ROS's packages and skips the ones ROS also ships.
|
|
465
|
+
|
|
466
|
+
### Deprecated
|
|
467
|
+
|
|
468
|
+
- `vmc.ros` (`RosPlant`, `control`, `serve`, `LiveParams`, `JointIO`, `TOPICS`) and the direct
|
|
469
|
+
Dynamixel path (`hardware.DynamixelPlant`, `home`, `present_ticks`, `scan`, `latency_timer`,
|
|
470
|
+
`Bus`, `SdkBus`, `FakeBus`) warn when used, and leave in 0.4.0 together with the Dynamixel SDK
|
|
471
|
+
and pyserial dependencies and the ROS CI job. The library is communication-agnostic: it turns
|
|
472
|
+
measurements into torques, and how they reach the robot stays outside it. Hardware profiles
|
|
473
|
+
(`HardwareProfile`, `Motor`, `KT`, `MODES` and each robot's `hardware` template) stay. Python
|
|
474
|
+
shows a `DeprecationWarning` only for code run as a script or in a notebook; run a node with
|
|
475
|
+
`python -W default` to see them there.
|
|
476
|
+
|
|
477
|
+
### Fixed
|
|
478
|
+
|
|
479
|
+
- `vmc.sim.run` needs only the plant's documented methods: when its guard trips, it sends zero
|
|
480
|
+
torque without reading the plant's last command `u`, which a plant of one's own may not have.
|
|
481
|
+
The zero command has one torque per motor rate, also on real time.
|
|
482
|
+
- `vmc.ros` is available after `import virtualmodelcontrol as vmc`, like `vmc.viz` and
|
|
483
|
+
`vmc.hardware`; it imports ROS only when a ROS class is first used.
|
|
484
|
+
- The hand example grasps the ball with the pads of the thumb, index and middle fingers: the
|
|
485
|
+
ball sits where the thumb opposes the fingers, and the grasp takes the thumb's tip at the end
|
|
486
|
+
of its last phalanx. Before, the thumb pressed on the ball with its side. The template's
|
|
487
|
+
kinematics are unchanged.
|
|
488
|
+
- Figure labels written as math where the figure font has no glyph (N·m on the efficiency
|
|
489
|
+
page); a test keeps figure text to characters the font draws.
|
|
490
|
+
|
|
491
|
+
## [0.2.0] - 2026-10-04
|
|
492
|
+
|
|
493
|
+
### Added
|
|
494
|
+
|
|
495
|
+
- Every dependency installs with the package: numpy, SciPy, CasADi, matplotlib, PyYAML, the
|
|
496
|
+
Dynamixel SDK and pyserial. CI runs on Ubuntu 22.04 and 24.04, with a clean-install job.
|
|
497
|
+
- Robot templates: `robots.bimanual` (two Helyx arms on one frame, with their identified
|
|
498
|
+
stiffness and damping and the transmission efficiency 0.12), `robots.adapt.hand` (five digits,
|
|
499
|
+
13 motors, spread coupling, masses and joint limits), `robots.turtle` (two cranks and the
|
|
500
|
+
virtual-flywheel controller), `robots.ur5` (from DH parameters) and `ur5.with_hand()`.
|
|
501
|
+
- Every template is parametric in its geometry, with today's values as defaults:
|
|
502
|
+
`helyx.arm(lengths=..., section_radius=..., spool_radius=..., tendon_angles=..., masses=...)`
|
|
503
|
+
for any number of segments; `bimanual.arms(lengths=..., tendon_angles=...,
|
|
504
|
+
base_positions=..., efficiency=...)`, each one for both arms or by arm;
|
|
505
|
+
`adapt.finger(link_lengths=..., link_masses=..., link_cogs=..., joint_axes=...,
|
|
506
|
+
motor_radius=..., pulley_radius=..., pip_transmission=...)` and `adapt.finger_coupling`;
|
|
507
|
+
`adapt.hand(...)` and `ur5.with_hand(...)`, which replace any entry of the hand's geometry
|
|
508
|
+
tables by key (`tip_offsets={"thumb": ...}`), with the hand's mounting position on the
|
|
509
|
+
flange; `ur5.arm(d=..., a=..., alpha=...)`; joint-limit springs with custom ranges; output
|
|
510
|
+
stages and `add_dynamics` sized to the arm.
|
|
511
|
+
- `vmc.Kinematics`: positions, rotations, Jacobians, angular Jacobians and Hessians of any site,
|
|
512
|
+
from configuration or from motor angles.
|
|
513
|
+
- `models.JointSpace` for robots described by their joints only; `SerialChain.from_dh` and site
|
|
514
|
+
rotations; `Assembly` parts mounted on another part's frame.
|
|
515
|
+
- `TendonTransmission(efficiency=...)` and `Direct(efficiency=...)` (one value or one per
|
|
516
|
+
motor): the robot receives the commanded torque times the efficiency. `adapt.finger`,
|
|
517
|
+
`adapt.hand` and `ur5.with_hand` take `efficiency=...` and stay lossless by default: the
|
|
518
|
+
measured `adapt.MOTOR_EFFICIENCY` and `adapt.HAND_MOTOR_EFFICIENCY` are static calibrations for
|
|
519
|
+
force estimates, and unequal efficiencies on coupled motors make virtual elements
|
|
520
|
+
non-conservative in simulation.
|
|
521
|
+
- `SpeedRegulator`: drives a virtual state at a commanded speed, with a ramp.
|
|
522
|
+
- `control.output`, opt-in output stages for real hardware: `FrictionCompensation`,
|
|
523
|
+
`Pretension`, `TorqueOffset`, `TorqueLimit`; each template's own stage
|
|
524
|
+
(`helyx.output_stage()`, `bimanual.output_stage()`, `adapt.output_stage()`,
|
|
525
|
+
`adapt.hand_output_stage()`).
|
|
526
|
+
- `vmc.viz`: the lab figure style (`use_style`, `save` as PDF and SVG) and drawing helpers
|
|
527
|
+
(`draw_robot`, `draw_spring`, `draw_damper`, `draw_frame`, `draw_force`, `draw_goal`,
|
|
528
|
+
`label_axes`). `vmc.viz` is available after `import virtualmodelcontrol as vmc` and loads
|
|
529
|
+
matplotlib only when first used.
|
|
530
|
+
- `vmc.viz.animate`: an animation of a run (the robot, springs to fixed points, the path of a
|
|
531
|
+
site, anything else through a callback), saved as MP4, GIF or animated WebP. `imageio-ffmpeg`
|
|
532
|
+
is now a dependency, so MP4 works on every system.
|
|
533
|
+
- `vmc.sim.run(..., z0=...)` starts the controller from a given virtual state, and the run log
|
|
534
|
+
records the virtual state `z` when the controller has one.
|
|
535
|
+
- Contact as stiff one-sided springs: signed distances `PlaneDistance` and `SphereDistance`,
|
|
536
|
+
`ContactSpring` (optional smoothing for optimization) and `ContactDamper` (damps only in
|
|
537
|
+
contact); `adapt.add_dynamics` gives the finger and the hand their gravity for simulation.
|
|
538
|
+
- Documentation rebuilt for students: the Material layout (sections as tabs, the pages of each
|
|
539
|
+
section in the left sidebar), large type, the library's logo and navy colours;
|
|
540
|
+
installation and troubleshooting; tutorials (how it works, a first controller, coordinates
|
|
541
|
+
and components, parameters, energy, kinematics, tuning, contact, building a robot, extending
|
|
542
|
+
the library); an example per robot (soft arm, two arms, finger, hand and the UR5, turtle), each
|
|
543
|
+
opening with its robot's schematic and parameters; concepts (the library's structure, soft-arm
|
|
544
|
+
kinematics, conventions and glossary). Every figure, schematic, table value and animation is
|
|
545
|
+
computed when the documentation builds.
|
|
546
|
+
- `vmc.hardware.HardwareProfile`: the motors of a robot (bus ID, Dynamixel model, sign, mode,
|
|
547
|
+
motor constant, optional torque limit) in the library's motor order, with the bus settings;
|
|
548
|
+
conversions both ways between encoder ticks, raw velocities, goal currents and the published
|
|
549
|
+
degrees of a ROS driver and SI units, with commands clamped before the integer conversion so
|
|
550
|
+
they saturate instead of overflowing; saved and loaded as YAML. Each template has its
|
|
551
|
+
profile: `helyx.hardware()`, `bimanual.hardware()`, `adapt.finger_hardware()`,
|
|
552
|
+
`adapt.hand_hardware()`, `turtle.hardware()`.
|
|
553
|
+
- `vmc.hardware.DynamixelPlant`: a robot's Dynamixel motors as a plant through the Dynamixel
|
|
554
|
+
SDK, without ROS. It sets a safe goal before each motor's torque goes on, takes the start
|
|
555
|
+
positions as zero, reads angles and smoothed rates, writes torques as clamped goal currents,
|
|
556
|
+
sends zero torque when commands stop (a watchdog), and on leaving (exceptions and Ctrl-C
|
|
557
|
+
included) sends zero torque and switches the torque motors off; held motors keep their
|
|
558
|
+
position. `hardware.home` drives the motors slowly to recorded home positions and refuses a
|
|
559
|
+
motor that lost a turn; `hardware.scan` finds the motors and their baud rate;
|
|
560
|
+
`hardware.FakeBus` stands in for the bus in tests and dry runs.
|
|
561
|
+
- `vmc.sim.WallClock`: `vmc.sim.run` on real time, the loop of simulation unchanged. Each step
|
|
562
|
+
runs on the computer's clock with its measured time; a reading older than `stale` sends
|
|
563
|
+
zero torque; a late step starts the next one from now instead of catching up; the log
|
|
564
|
+
records each step's `dt`, and `log.info` the rate, the slowest step, the overruns and the
|
|
565
|
+
stale readings, with a warning when steps overran.
|
|
566
|
+
- `virtualmodelcontrol.ros` (ROS 2, any distribution; rclpy and std_msgs, loaded only when
|
|
567
|
+
used): `RosPlant`, the robot behind the lab driver's topics (degrees, the bus order, raw
|
|
568
|
+
signs, torques kept within the range of the driver's goal current); `serve`, a digital twin
|
|
569
|
+
that publishes a simulated robot on the same topics, with a lockstep mode in which a run over
|
|
570
|
+
ROS repeats the simulator's; `LiveParams`, a controller's live Params as ROS parameters,
|
|
571
|
+
applied between steps.
|
|
572
|
+
|
|
573
|
+
### Changed
|
|
574
|
+
|
|
575
|
+
- The soft arm models the efficiency of its tendons: it receives η = 0.12 times the commanded
|
|
576
|
+
torque (`helyx.EFFICIENCY`), and `helyx.SIM_STIFFNESS` and `helyx.SIM_DAMPING` are the
|
|
577
|
+
identified, physical values. 0.1.0 divided them by 0.12 and delivered the full torque: the
|
|
578
|
+
same equilibria without gravity, but natural frequencies about 2.9 times too high and a sag
|
|
579
|
+
under gravity about 8 times too small. Controllers are unchanged and never divide their
|
|
580
|
+
torques by η, so the simulated arm receives η of every command, gravity compensation
|
|
581
|
+
included.
|
|
582
|
+
- The figure style without LaTeX uses matplotlib's own Computer Modern font (`cmr10`) instead
|
|
583
|
+
of DejaVu Serif, with tick labels set as math. Figures made with LaTeX are unchanged.
|
|
584
|
+
|
|
585
|
+
### Fixed
|
|
586
|
+
|
|
587
|
+
- `RunLog` copies each row, so a signal updated in place (a controller's virtual state) is
|
|
588
|
+
recorded correctly at every step.
|
|
589
|
+
- `bimanual.add_dynamics` takes the stiffness and damping of one arm (a dict by arm, arrays
|
|
590
|
+
included) and keeps the other arm's identified values.
|
|
591
|
+
- `viz.draw_robot`: no joint markers along continuum arms mounted in an assembly; robots without
|
|
592
|
+
geometry (joint-space models) draw nothing instead of failing; serial chains end at their
|
|
593
|
+
`tool` site (the UR5 flange) as well as at a `tip`.
|
|
594
|
+
|
|
595
|
+
## [0.1.0] - 2026-10-04
|
|
596
|
+
|
|
597
|
+
First public release.
|
|
598
|
+
|
|
599
|
+
### Added
|
|
600
|
+
|
|
601
|
+
- Package scaffold: `pyproject.toml` (hatchling + hatch-vcs), tests, docs, CI workflows.
|
|
602
|
+
- `core`: `Param` and `ParamSet` with scopes (fixed, design, episode, stage) and a `Binding` that
|
|
603
|
+
keeps live Params symbolic and folds the rest in; spaces `Euclidean`, `SO2`, `Product`;
|
|
604
|
+
symbolic helpers; `Signals`; a registry with plugin entry points; unit strings.
|
|
605
|
+
- `mechanisms`: coordinates (`FramePoint`, `Joint`, `State`, `Ref`, `Difference`, `Slice`,
|
|
606
|
+
`Stack`, `Projection`, `Norm`, `Custom`), components (linear, tanh, Gaussian, sigmoid,
|
|
607
|
+
polynomial and limit springs; linear and tanh dampers; `PointMass`, `Inertance`; `ForceSource`,
|
|
608
|
+
`GravityCompensation`) and `Mechanism`. A tanh spring on a projection saturates at its maximum
|
|
609
|
+
force in every direction.
|
|
610
|
+
- `models`: parametric `PCC` with n segments, `TendonTransmission` (θ > 0 pulls), `Direct`
|
|
611
|
+
drive, and `SerialChain` (product of exponentials).
|
|
612
|
+
- `robots.helyx`: the three Helyx arm geometries with their default parameters.
|
|
613
|
+
- `VirtualMechanismSystem`, `compile()` and `VMCController`: about 20 µs per control step for
|
|
614
|
+
three springs and three dampers on a three-segment arm (`benchmarks/tick.py`).
|
|
615
|
+
- `compile_dynamics()`: robot dynamics assembled from the robot's components (canonical
|
|
616
|
+
residual, mass matrix, energy, power, linearly implicit Euler step); `Gravity` component.
|
|
617
|
+
- `sim`: `Plant` and `SimPlant` protocols, `ModelPlant`, `run()` with a `Guard` (zero torque on
|
|
618
|
+
missing or non-finite readings) and a `RunLog`.
|
|
619
|
+
- `models.Actuation` protocol; `helyx.add_dynamics` with the simulated arm's stiffness and
|
|
620
|
+
damping.
|
|
621
|
+
- Docs: closed-loop simulation tutorial and an "Extend the library" how-to.
|
|
622
|
+
- `models.LinearCoupling` (one motor driving several joints), `models.Assembly` (several models
|
|
623
|
+
mounted on one base) with `StackedActuation`; `FramePoint` accepts a part and an arc parameter.
|
|
624
|
+
- `robots.adapt`: the ADAPT finger (two motors, coupled distal joints), joint-angle coordinate
|
|
625
|
+
and joint-limit spring.
|
|
626
|
+
|
|
627
|
+
[Unreleased]: https://github.com/vigno0405/VirtualModelControl/compare/v0.3.0...HEAD
|
|
628
|
+
[0.3.0]: https://github.com/vigno0405/VirtualModelControl/compare/v0.2.0...v0.3.0
|
|
629
|
+
[0.2.0]: https://github.com/vigno0405/VirtualModelControl/compare/v0.1.0...v0.2.0
|
|
630
|
+
[0.1.0]: https://github.com/vigno0405/VirtualModelControl/releases/tag/v0.1.0
|