openscvx 2.dev4__tar.gz → 2.dev5__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.
- {openscvx-2.dev4/openscvx.egg-info → openscvx-2.dev5}/PKG-INFO +1 -1
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/mjx/cartpole_mjx.py +13 -19
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/mjx/double_cartpole_mjx.py +9 -18
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/mjx/skydio_x2_mjx.py +14 -21
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/mjx/triple_cartpole_3d_mjx.py +9 -18
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/mjx/triple_cartpole_mjx.py +10 -19
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/__init__.py +4 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/_version.py +3 -3
- openscvx-2.dev5/openscvx/integrations/__init__.py +66 -0
- openscvx-2.dev5/openscvx/integrations/base.py +89 -0
- openscvx-2.dev5/openscvx/integrations/mjx.py +496 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/problem.py +13 -4
- {openscvx-2.dev4 → openscvx-2.dev5/openscvx.egg-info}/PKG-INFO +1 -1
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx.egg-info/SOURCES.txt +2 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/integrations/test_mjx.py +2 -69
- openscvx-2.dev5/tests/integrations/test_mjx_dynamics.py +542 -0
- openscvx-2.dev4/openscvx/integrations/__init__.py +0 -62
- openscvx-2.dev4/openscvx/integrations/mjx.py +0 -323
- {openscvx-2.dev4 → openscvx-2.dev5}/.github/assets/logo.svg +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/.github/release-drafter.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/.github/workflows/_docs.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/.github/workflows/branch-name.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/.github/workflows/docs.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/.github/workflows/lint.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/.github/workflows/nightly.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/.github/workflows/release.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/.github/workflows/tests-integration.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/.github/workflows/tests-unit.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/.gitignore +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/.gitmodules +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/CONTRIBUTING.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/LICENSE +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/README.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/Foundations/constraint_reformulation.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/Foundations/control_parameterization.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/Foundations/discretization.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/Foundations/ocp.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/Foundations/scvx.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/Foundations/time_dilation.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/UsersGuide/00_introduction.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/UsersGuide/05_visualization.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/UsersGuide/06_logic.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/UsersGuide/07_lie.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/UsersGuide/08_mpcc.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/assets/favicon.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/assets/logo.svg +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/assets/openscvx_logo_square.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/assets/viser-client/index.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/assets/viser-recordings/drone_racing.viser +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/citation.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/examples.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/index.md +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/javascripts/mathjax.js +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/docs/versions.json +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/_viser_embed_export.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/abstract/hypersensitive.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/abstract/impulsive.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/abstract/stl_integer_variable.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/abstract/stl_or.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/animations/7_dof_arm.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/animations/_camera.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/animations/_render.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/animations/_sensor_view.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/animations/dr_vp_polytope.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/animations/franka_fr3v2_pick_place.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/animations/logo.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/animations/obstacle_avoidance_vmap.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/arm/3_dof_arm.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/arm/7_dof_arm.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/arm/7_dof_arm_collision.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/arm/7_dof_arm_vp.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/arm/franka_fr3v2_pick_place.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/arm/franka_fr3v2_viewplanning.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/car/dubins_car.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/car/dubins_car_obstacle_conditional.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/car/dubins_car_obstacle_stl.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/car/dubins_car_stl_or.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/car/dubins_car_waypoint_stl.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/drone/cinema_vp.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/drone/dr_vp.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/drone/drone_racing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/drone/logo.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/drone/logo_utils/acl_logo.svg +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/drone/logo_utils/svg_path_utils.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/mjx/triple_cartpole_game.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/mpc/double_integrator_discrete.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/mpc/double_integrator_drone_racing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/mpc/dubins_car_circle_analytical.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/mpc/dubins_car_circle_discrete.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/plotting.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/plotting_viser.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/realtime/3DoF_pdg_realtime.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/realtime/6DoF_pdg_realtime.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/rocket/6DoF_pdg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/spacecraft/halo_orbit.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/spacecraft/hohmann_transfer.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/spacecraft/let_transfer.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/figures/ctlos_cine.gif +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/figures/ctlos_dr.gif +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/figures/dtlos_cine.gif +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/figures/dtlos_dr.gif +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/figures/openscvx_logo.svg +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/figures/openscvx_logo_square.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/figures/video_preview.png +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/material/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/material/overrides/assets/stylesheets/home-hero.css +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/material/overrides/assets/stylesheets/home-viser.css +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/material/overrides/home.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/material/overrides/main.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/material/overrides/partials/home-diagram.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/material/overrides/partials/home-dropin-banner.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/material/overrides/partials/home-hero.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/material/overrides/partials/home-pipeline.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/material/overrides/partials/home-viser-strip.html +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/mkdocs.yml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/__main__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/algorithms/augmented_lagrangian.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/algorithms/base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/algorithms/constant_proximal_weight.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/algorithms/penalized_trust_region.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/algorithms/ramp_proximal_weight.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/algorithms/weights.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/config.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/discretization/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/discretization/base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/discretization/discretize_linearize.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/discretization/linearize_discretize.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/discretization/sparse_utils/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/expert/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/expert/byof.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/expert/lowering.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/expert/validation.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/init/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/init/interpolation.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/init/inverse_kinematics.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/integrations/menagerie.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/integrators/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/integrators/diffrax.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/loader.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/lowered/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/lowered/parameters.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/lowered/problem.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/lowered/unified.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/plotting/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/plotting/plotting.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/plotting/viser/orbits.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/propagation/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/propagation/propagation.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/solvers/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/solvers/base.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/solvers/ptr_solver.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/augmentation.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/builder.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/parameter.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/stljax.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/time.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lower.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/array.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/control.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/math.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/state.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/parser/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/parser/_registry.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/parser/array.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/parser/constraint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/parser/lie.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/parser/linalg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/parser/logic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/parser/math.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/parser/parser.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/parser/spatial.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/parser/stl.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/parser/stljax.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/parser/tokenizer.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/problem.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/sparsity.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/symbolic/unified.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/utils/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/utils/cache.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/utils/caching.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/utils/printing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/utils/profiling.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx/utils/utils.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx.egg-info/entry_points.txt +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx.egg-info/requires.txt +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/pyproject.toml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/scripts/gen_example_pages.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/scripts/gen_ref_pages.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/setup.cfg +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/expr/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/expr/test_gmsr.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/fixtures/brachistochrone.json +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/fixtures/brachistochrone.yaml +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/hohmann_analytical.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/integrations/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/test_stl.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/parser/__init__.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/parser/test_array.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/parser/test_constraint.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/parser/test_lie.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/parser/test_linalg.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/parser/test_load.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/parser/test_logic.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/parser/test_math.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/parser/test_parser.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/parser/test_spatial.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/parser/test_stl.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/parser/test_tokenizer.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/parser/test_vmap.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/test_augmentation.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/test_sparsity.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/symbolic/test_unified.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/test_autotuning.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/test_brachistochrone.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/test_discretization.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/test_examples.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/test_expert.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/test_impulsive.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/test_init.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/test_integrators.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/test_loader.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/test_optimization_results.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/test_plotting.py +0 -0
- {openscvx-2.dev4 → openscvx-2.dev5}/tests/test_propagation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.dev5
|
|
4
4
|
Summary: A general Python-based successive convexification implementation which uses a JAX backend.
|
|
5
5
|
Author-email: Chris Hayner and Griffin Norris <haynec@uw.edu>
|
|
6
6
|
License: Apache Software License
|
|
@@ -34,7 +34,6 @@ except ImportError:
|
|
|
34
34
|
sys.exit(1)
|
|
35
35
|
|
|
36
36
|
import openscvx as ox
|
|
37
|
-
from openscvx.integrations import mjx_byof
|
|
38
37
|
|
|
39
38
|
CARTPOLE_XML = """
|
|
40
39
|
<mujoco model="cartpole">
|
|
@@ -69,36 +68,32 @@ n_u = int(mjx_model.nu)
|
|
|
69
68
|
n = 60
|
|
70
69
|
total_time = 3.0
|
|
71
70
|
|
|
72
|
-
|
|
71
|
+
# ── MJX dynamics as a first-class adapter ─────────────────────────────────────
|
|
72
|
+
# `MjxDynamics` builds default qpos / qvel / ctrl State and Control objects
|
|
73
|
+
# matching the model's nq / nv / nu and routes the MJX forward dynamics into
|
|
74
|
+
# the BYOF channel internally — no separate `byof=` plumbing required.
|
|
75
|
+
dyn = ox.MjxDynamics(mjx_model)
|
|
76
|
+
qpos, qvel = dyn.states
|
|
77
|
+
(ctrl,) = dyn.controls
|
|
78
|
+
|
|
73
79
|
qpos.min = np.array([-3.0, -2.0 * np.pi])
|
|
74
80
|
qpos.max = np.array([3.0, 2.0 * np.pi])
|
|
75
81
|
qpos.initial = np.array([0.0, np.pi])
|
|
76
82
|
qpos.final = np.array([0.0, 0.0])
|
|
77
83
|
|
|
78
|
-
qvel = ox.State("qvel", shape=(n_v,))
|
|
79
84
|
qvel.min = np.array([-10.0, -15.0])
|
|
80
85
|
qvel.max = np.array([10.0, 15.0])
|
|
81
86
|
qvel.initial = np.array([0.0, 0.0])
|
|
82
87
|
qvel.final = np.array([0.0, 0.0])
|
|
83
88
|
|
|
84
|
-
ctrl = ox.Control("ctrl", shape=(n_u,))
|
|
85
89
|
ctrl.min = np.array([-1.0])
|
|
86
90
|
ctrl.max = np.array([1.0])
|
|
87
91
|
ctrl.guess = np.zeros((n, n_u))
|
|
88
92
|
|
|
89
|
-
states = [qpos, qvel]
|
|
90
|
-
controls = [ctrl]
|
|
91
|
-
|
|
92
|
-
dynamics = {
|
|
93
|
-
"qpos": qvel,
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
byof: ox.ByofSpec = {"dynamics": mjx_byof(mjx_model, qpos=qpos, qvel=qvel, ctrl=ctrl)}
|
|
97
|
-
|
|
98
93
|
constraints = []
|
|
99
|
-
for state in states:
|
|
94
|
+
for state in dyn.states:
|
|
100
95
|
constraints.extend([ox.ctcs(state <= state.max), ox.ctcs(state.min <= state)])
|
|
101
|
-
for control in controls:
|
|
96
|
+
for control in dyn.controls:
|
|
102
97
|
constraints.extend([ox.ctcs(control <= control.max), ox.ctcs(control.min <= control)])
|
|
103
98
|
|
|
104
99
|
theta_guess = np.linspace(np.pi, 0.0, n)
|
|
@@ -115,13 +110,12 @@ time = ox.Time(
|
|
|
115
110
|
)
|
|
116
111
|
|
|
117
112
|
problem = ox.Problem(
|
|
118
|
-
dynamics=
|
|
119
|
-
states=states,
|
|
120
|
-
controls=controls,
|
|
113
|
+
dynamics=dyn,
|
|
114
|
+
states=dyn.states,
|
|
115
|
+
controls=dyn.controls,
|
|
121
116
|
time=time,
|
|
122
117
|
constraints=constraints,
|
|
123
118
|
N=n,
|
|
124
|
-
byof=byof,
|
|
125
119
|
algorithm={
|
|
126
120
|
"lam_prox": 1e-1,
|
|
127
121
|
"lam_cost": 1e-2,
|
|
@@ -34,8 +34,6 @@ except ImportError:
|
|
|
34
34
|
sys.exit(1)
|
|
35
35
|
|
|
36
36
|
import openscvx as ox
|
|
37
|
-
from openscvx import ByofSpec
|
|
38
|
-
from openscvx.integrations import mjx_byof
|
|
39
37
|
|
|
40
38
|
L1, L2 = 0.5, 0.4 # link lengths (m)
|
|
41
39
|
|
|
@@ -81,32 +79,26 @@ n_u = int(mjx_model.nu) # 1: cart force
|
|
|
81
79
|
n = 400
|
|
82
80
|
total_time = 2.5
|
|
83
81
|
|
|
84
|
-
# ──
|
|
85
|
-
|
|
82
|
+
# ── MJX dynamics adapter ──────────────────────────────────────────────────────
|
|
83
|
+
dyn = ox.MjxDynamics(mjx_model)
|
|
84
|
+
qpos, qvel = dyn.states
|
|
85
|
+
(ctrl,) = dyn.controls
|
|
86
|
+
ctrl.parameterization = "ZOH"
|
|
87
|
+
|
|
86
88
|
qpos.min = np.array([-8.0, -2 * np.pi, -2 * np.pi])
|
|
87
89
|
qpos.max = np.array([8.0, 2 * np.pi, 2 * np.pi])
|
|
88
90
|
qpos.initial = np.array([0.0, np.pi, 0.0]) # cart at origin, link1 hanging down
|
|
89
91
|
qpos.final = [ox.Free(0.0), 0.0, 0.0] # cart free, both links upright
|
|
90
92
|
|
|
91
|
-
qvel = ox.State("qvel", shape=(n_v,))
|
|
92
93
|
qvel.min = np.array([-12.0, -12.0, -12.0])
|
|
93
94
|
qvel.max = np.array([12.0, 12.0, 12.0])
|
|
94
95
|
qvel.initial = np.zeros(n_v)
|
|
95
96
|
qvel.final = [0.0, 0.0, 0.0]
|
|
96
97
|
|
|
97
|
-
ctrl = ox.Control("ctrl", shape=(n_u,), parameterization="ZOH")
|
|
98
98
|
ctrl.min = np.array([-2.0])
|
|
99
99
|
ctrl.max = np.array([2.0])
|
|
100
100
|
ctrl.guess = np.zeros((n, n_u))
|
|
101
101
|
|
|
102
|
-
states = [qpos, qvel]
|
|
103
|
-
controls = [ctrl]
|
|
104
|
-
|
|
105
|
-
# ── Dynamics: position kinematics symbolically, velocity via MJX ──────────────
|
|
106
|
-
dynamics: dict = {"qpos": qvel} # nq == nv, valid for all-revolute/prismatic joints
|
|
107
|
-
|
|
108
|
-
byof: ByofSpec = {"dynamics": mjx_byof(mjx_model, qpos=qpos, qvel=qvel, ctrl=ctrl)}
|
|
109
|
-
|
|
110
102
|
# ── Constraints (CTCS on state / control bounds) ───────────────────────────────
|
|
111
103
|
constraints = []
|
|
112
104
|
|
|
@@ -123,13 +115,12 @@ time = ox.Time(
|
|
|
123
115
|
)
|
|
124
116
|
|
|
125
117
|
problem = ox.Problem(
|
|
126
|
-
dynamics=
|
|
127
|
-
states=states,
|
|
128
|
-
controls=controls,
|
|
118
|
+
dynamics=dyn,
|
|
119
|
+
states=dyn.states,
|
|
120
|
+
controls=dyn.controls,
|
|
129
121
|
time=time,
|
|
130
122
|
constraints=constraints,
|
|
131
123
|
N=n,
|
|
132
|
-
byof=byof,
|
|
133
124
|
algorithm={
|
|
134
125
|
"lam_prox": 1e-1,
|
|
135
126
|
"lam_cost": 0e0,
|
|
@@ -51,8 +51,7 @@ from examples.plotting_viser import (
|
|
|
51
51
|
create_animated_plotting_server,
|
|
52
52
|
create_scp_animated_plotting_server,
|
|
53
53
|
)
|
|
54
|
-
from openscvx import
|
|
55
|
-
from openscvx.integrations import mjx_byof
|
|
54
|
+
from openscvx import Problem
|
|
56
55
|
from openscvx.utils import gen_vertices, rot
|
|
57
56
|
|
|
58
57
|
HOVER_CTRL = 3.2495625 # N per motor for level hover (from menagerie keyframe)
|
|
@@ -78,33 +77,28 @@ n_u = int(mjx_model.nu) # 4 — rotor thrusts
|
|
|
78
77
|
n = 22
|
|
79
78
|
total_time = 24.0
|
|
80
79
|
|
|
81
|
-
# ──
|
|
82
|
-
|
|
80
|
+
# ── MJX dynamics adapter ──────────────────────────────────────────────────────
|
|
81
|
+
# The free joint has nq=7 but nv=6 (quaternion adds one extra position DOF).
|
|
82
|
+
# MjxDynamics detects nq > nv and automatically routes quaternion kinematics
|
|
83
|
+
# for "qpos" alongside the MJX "qvel" dynamics through the BYOF channel.
|
|
84
|
+
dyn = ox.MjxDynamics(mjx_model)
|
|
85
|
+
qpos, qvel = dyn.states
|
|
86
|
+
(ctrl,) = dyn.controls
|
|
87
|
+
|
|
83
88
|
qpos.min = np.array([-200.0, -100.0, 15.0, -1.0, -1.0, -1.0, -1.0])
|
|
84
89
|
qpos.max = np.array([200.0, 100.0, 200.0, 1.0, 1.0, 1.0, 1.0])
|
|
85
90
|
qpos.initial = np.concatenate([START_POS, HOVER_QUAT])
|
|
86
91
|
qpos.final = [10.0, 0.0, 20.0, ("free", 1.0), ("free", 0.0), ("free", 0.0), ("free", 0.0)]
|
|
87
92
|
|
|
88
|
-
qvel = ox.State("qvel", shape=(n_v,))
|
|
89
93
|
qvel.min = np.array([-100.0, -100.0, -100.0, -10.0, -10.0, -10.0])
|
|
90
94
|
qvel.max = np.array([100.0, 100.0, 100.0, 10.0, 10.0, 10.0])
|
|
91
95
|
qvel.initial = np.zeros(n_v)
|
|
92
96
|
qvel.final = [("free", 0.0)] * n_v
|
|
93
97
|
|
|
94
|
-
ctrl = ox.Control("ctrl", shape=(n_u,))
|
|
95
98
|
ctrl.min = np.zeros(n_u)
|
|
96
99
|
ctrl.max = 13.0 * np.ones(n_u)
|
|
97
100
|
ctrl.guess = HOVER_CTRL * np.ones((n, n_u))
|
|
98
101
|
|
|
99
|
-
states = [qpos, qvel]
|
|
100
|
-
controls = [ctrl]
|
|
101
|
-
|
|
102
|
-
# ── Dynamics via BYOF ─────────────────────────────────────────────────────────
|
|
103
|
-
# The free joint has nq=7 but nv=6 (quaternion adds one extra position DOF).
|
|
104
|
-
# nq=7, nv=6 (free joint): mjx_byof detects nq > nv and automatically
|
|
105
|
-
# includes quaternion kinematics for "qpos" alongside the MJX "qvel" dynamics.
|
|
106
|
-
byof: ByofSpec = {"dynamics": mjx_byof(mjx_model, qpos=qpos, qvel=qvel, ctrl=ctrl)}
|
|
107
|
-
|
|
108
102
|
# ── Gate parameters (matching examples/drone/drone_racing.py) ───────────────
|
|
109
103
|
n_gates = 10
|
|
110
104
|
initial_gate_centers = [
|
|
@@ -135,9 +129,9 @@ gate_centers = np.array(modified_centers)
|
|
|
135
129
|
|
|
136
130
|
# ── Constraints ───────────────────────────────────────────────────────────────
|
|
137
131
|
constraints = []
|
|
138
|
-
for state in states:
|
|
132
|
+
for state in dyn.states:
|
|
139
133
|
constraints.extend([ox.ctcs(state <= state.max), ox.ctcs(state.min <= state)])
|
|
140
|
-
for control in controls:
|
|
134
|
+
for control in dyn.controls:
|
|
141
135
|
constraints.extend([ox.ctcs(control <= control.max), ox.ctcs(control.min <= control)])
|
|
142
136
|
|
|
143
137
|
# Enforce sequential gate traversal using nodal constraints on qpos position.
|
|
@@ -172,13 +166,12 @@ time = ox.Time(
|
|
|
172
166
|
)
|
|
173
167
|
|
|
174
168
|
problem = Problem(
|
|
175
|
-
dynamics=
|
|
176
|
-
states=states,
|
|
177
|
-
controls=controls,
|
|
169
|
+
dynamics=dyn,
|
|
170
|
+
states=dyn.states,
|
|
171
|
+
controls=dyn.controls,
|
|
178
172
|
time=time,
|
|
179
173
|
constraints=constraints,
|
|
180
174
|
N=n,
|
|
181
|
-
byof=byof,
|
|
182
175
|
algorithm={
|
|
183
176
|
"lam_prox": 1e-1,
|
|
184
177
|
"lam_cost": 1e-2,
|
|
@@ -57,8 +57,7 @@ except ImportError:
|
|
|
57
57
|
sys.exit(1)
|
|
58
58
|
|
|
59
59
|
import openscvx as ox
|
|
60
|
-
from openscvx import
|
|
61
|
-
from openscvx.integrations import mjx_byof
|
|
60
|
+
from openscvx import Problem
|
|
62
61
|
|
|
63
62
|
L1, L2, L3 = 0.5, 0.4, 0.3 # link lengths (m)
|
|
64
63
|
|
|
@@ -122,8 +121,11 @@ IDX_A1, IDX_B1 = 2, 3
|
|
|
122
121
|
IDX_A2, IDX_B2 = 4, 5
|
|
123
122
|
IDX_A3, IDX_B3 = 6, 7
|
|
124
123
|
|
|
125
|
-
# ──
|
|
126
|
-
|
|
124
|
+
# ── MJX dynamics adapter ──────────────────────────────────────────────────────
|
|
125
|
+
dyn = ox.MjxDynamics(mjx_model)
|
|
126
|
+
qpos, qvel = dyn.states
|
|
127
|
+
(ctrl,) = dyn.controls
|
|
128
|
+
|
|
127
129
|
qpos.min = np.array(
|
|
128
130
|
[-8.0, -8.0, -2 * np.pi, -2 * np.pi, -2 * np.pi, -2 * np.pi, -2 * np.pi, -2 * np.pi]
|
|
129
131
|
)
|
|
@@ -142,25 +144,15 @@ qpos.final = [
|
|
|
142
144
|
0.0, # link 3 upright
|
|
143
145
|
]
|
|
144
146
|
|
|
145
|
-
qvel = ox.State("qvel", shape=(n_v,))
|
|
146
147
|
qvel.min = np.full(n_v, -12.0)
|
|
147
148
|
qvel.max = np.full(n_v, 12.0)
|
|
148
149
|
qvel.initial = np.zeros(n_v)
|
|
149
150
|
qvel.final = [0.0] * n_v
|
|
150
151
|
|
|
151
|
-
ctrl = ox.Control("ctrl", shape=(n_u,))
|
|
152
152
|
ctrl.min = np.array([-2.0, -2.0])
|
|
153
153
|
ctrl.max = np.array([2.0, 2.0])
|
|
154
154
|
ctrl.guess = np.zeros((n, n_u))
|
|
155
155
|
|
|
156
|
-
states = [qpos, qvel]
|
|
157
|
-
controls = [ctrl]
|
|
158
|
-
|
|
159
|
-
# ── Dynamics: position kinematics symbolically, velocity via MJX ──────────────
|
|
160
|
-
dynamics: dict = {"qpos": qvel} # nq == nv
|
|
161
|
-
|
|
162
|
-
byof: ByofSpec = {"dynamics": mjx_byof(mjx_model, qpos=qpos, qvel=qvel, ctrl=ctrl)}
|
|
163
|
-
|
|
164
156
|
# ── Constraints (CTCS on state / control bounds) ─────────────────────────────
|
|
165
157
|
constraints = []
|
|
166
158
|
|
|
@@ -179,13 +171,12 @@ time = ox.Time(
|
|
|
179
171
|
)
|
|
180
172
|
|
|
181
173
|
problem = Problem(
|
|
182
|
-
dynamics=
|
|
183
|
-
states=states,
|
|
184
|
-
controls=controls,
|
|
174
|
+
dynamics=dyn,
|
|
175
|
+
states=dyn.states,
|
|
176
|
+
controls=dyn.controls,
|
|
185
177
|
time=time,
|
|
186
178
|
constraints=constraints,
|
|
187
179
|
N=n,
|
|
188
|
-
byof=byof,
|
|
189
180
|
algorithm={
|
|
190
181
|
"lam_prox": 1e-1,
|
|
191
182
|
"lam_cost": 0e0,
|
|
@@ -35,8 +35,7 @@ except ImportError:
|
|
|
35
35
|
sys.exit(1)
|
|
36
36
|
|
|
37
37
|
import openscvx as ox
|
|
38
|
-
from openscvx import
|
|
39
|
-
from openscvx.integrations import mjx_byof
|
|
38
|
+
from openscvx import Problem
|
|
40
39
|
|
|
41
40
|
L1, L2, L3 = 0.5, 0.4, 0.3 # link lengths (m)
|
|
42
41
|
|
|
@@ -88,35 +87,28 @@ n_u = int(mjx_model.nu) # 1: cart force
|
|
|
88
87
|
n = 60 # more nodes → finer resolution near the unstable upright equilibrium
|
|
89
88
|
total_time = 2.5
|
|
90
89
|
|
|
91
|
-
# ──
|
|
92
|
-
|
|
90
|
+
# ── MJX dynamics adapter ──────────────────────────────────────────────────────
|
|
91
|
+
dyn = ox.MjxDynamics(mjx_model)
|
|
92
|
+
qpos, qvel = dyn.states
|
|
93
|
+
(ctrl,) = dyn.controls
|
|
94
|
+
|
|
93
95
|
qpos.min = np.array([-100.0, -2 * np.pi, -2 * np.pi, -2 * np.pi])
|
|
94
96
|
qpos.max = np.array([100.0, 2 * np.pi, 2 * np.pi, 2 * np.pi])
|
|
95
97
|
qpos.initial = np.array([0.0, np.pi, 0.0, 0.0]) # all links hanging down
|
|
96
98
|
qpos.final = [ox.Free(0.0), 0.0, 0.0, 0.0] # all links upright
|
|
97
99
|
|
|
98
|
-
qvel = ox.State("qvel", shape=(n_v,))
|
|
99
100
|
qvel.min = np.array([-12.0, -12.0, -12.0, -12.0])
|
|
100
101
|
qvel.max = np.array([12.0, 12.0, 12.0, 12.0])
|
|
101
102
|
qvel.initial = np.zeros(n_v)
|
|
102
103
|
qvel.final = [0.0, 0.0, 0.0, 0.0]
|
|
103
104
|
|
|
104
|
-
ctrl = ox.Control("ctrl", shape=(n_u,))
|
|
105
105
|
ctrl.min = np.array([-3.0])
|
|
106
106
|
ctrl.max = np.array([3.0])
|
|
107
107
|
ctrl.guess = np.zeros((n, n_u))
|
|
108
108
|
|
|
109
|
-
states = [qpos, qvel]
|
|
110
|
-
controls = [ctrl]
|
|
111
|
-
|
|
112
|
-
# ── Dynamics: position kinematics symbolically, velocity via MJX ──────────────
|
|
113
|
-
dynamics: dict = {"qpos": qvel} # nq==nv so this is always valid
|
|
114
|
-
|
|
115
|
-
byof: ByofSpec = {"dynamics": mjx_byof(mjx_model, qpos=qpos, qvel=qvel, ctrl=ctrl)}
|
|
116
|
-
|
|
117
109
|
# ── Constraints (CTCS on state / control bounds) ───────────────────────────────
|
|
118
110
|
constraints = []
|
|
119
|
-
for state in states:
|
|
111
|
+
for state in dyn.states:
|
|
120
112
|
constraints.extend([ox.ctcs(state <= state.max), ox.ctcs(state.min <= state)])
|
|
121
113
|
|
|
122
114
|
# ── Initial guess: linearly swing θ₁ from π → 0, others stay 0 ───────────────
|
|
@@ -132,13 +124,12 @@ time = ox.Time(
|
|
|
132
124
|
)
|
|
133
125
|
|
|
134
126
|
problem = Problem(
|
|
135
|
-
dynamics=
|
|
136
|
-
states=states,
|
|
137
|
-
controls=controls,
|
|
127
|
+
dynamics=dyn,
|
|
128
|
+
states=dyn.states,
|
|
129
|
+
controls=dyn.controls,
|
|
138
130
|
time=time,
|
|
139
131
|
constraints=constraints,
|
|
140
132
|
N=n,
|
|
141
|
-
byof=byof,
|
|
142
133
|
algorithm={
|
|
143
134
|
"lam_prox": 1e0,
|
|
144
135
|
"lam_cost": 0e0,
|
|
@@ -25,6 +25,7 @@ from openscvx.discretization import (
|
|
|
25
25
|
VectorizeDiscretizeLinearize,
|
|
26
26
|
)
|
|
27
27
|
from openscvx.expert import ByofSpec
|
|
28
|
+
from openscvx.integrations import DynamicsAdapter, MjxDynamics
|
|
28
29
|
from openscvx.loader import load_dict, load_json, load_yaml
|
|
29
30
|
from openscvx.problem import Problem
|
|
30
31
|
from openscvx.solvers import PTRSolver
|
|
@@ -176,6 +177,9 @@ __all__ = [
|
|
|
176
177
|
"lie",
|
|
177
178
|
# Expert mode types
|
|
178
179
|
"ByofSpec",
|
|
180
|
+
# External-backend dynamics adapters
|
|
181
|
+
"DynamicsAdapter",
|
|
182
|
+
"MjxDynamics",
|
|
179
183
|
# Discretization
|
|
180
184
|
"DiscretizeLinearizeVectorize",
|
|
181
185
|
"LinearizeDiscretize",
|
|
@@ -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 = '2.
|
|
22
|
-
__version_tuple__ = version_tuple = (2, '
|
|
21
|
+
__version__ = version = '2.dev5'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 'dev5')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g4161a5a13'
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""External-backend dynamics adapters for OpenSCvx.
|
|
2
|
+
|
|
3
|
+
The recommended entry-point is `MjxDynamics`, which goes directly into the
|
|
4
|
+
``dynamics=`` slot of `Problem` and constructs the matching State/Control
|
|
5
|
+
objects for the user. Free-joint quaternion kinematics for floating-base
|
|
6
|
+
models (drones, humanoids) are detected and handled automatically::
|
|
7
|
+
|
|
8
|
+
from openscvx.integrations import MjxDynamics
|
|
9
|
+
|
|
10
|
+
dyn = MjxDynamics(mjx_model)
|
|
11
|
+
problem = ox.Problem(
|
|
12
|
+
dynamics=dyn,
|
|
13
|
+
states=dyn.states,
|
|
14
|
+
controls=dyn.controls,
|
|
15
|
+
...
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
For advanced users who need custom State/Control names (or to interleave
|
|
19
|
+
them with extra custom states), `mjx_dynamics` is exposed as the underlying
|
|
20
|
+
BYOF callable factory — assemble your own ``byof["dynamics"]`` dict from it.
|
|
21
|
+
|
|
22
|
+
All MJX symbols delegate lazily so ``mujoco.mjx`` is only imported when
|
|
23
|
+
actually used. The ``menagerie`` submodule is also loaded lazily.
|
|
24
|
+
|
|
25
|
+
Example — cartpole (``nq == nv``)::
|
|
26
|
+
|
|
27
|
+
from openscvx.integrations import MjxDynamics
|
|
28
|
+
|
|
29
|
+
dyn = MjxDynamics(mjx_model)
|
|
30
|
+
problem = ox.Problem(dynamics=dyn, states=dyn.states, controls=dyn.controls, ...)
|
|
31
|
+
|
|
32
|
+
Example — quadrotor with free joint (``nq=7``, ``nv=6``)::
|
|
33
|
+
|
|
34
|
+
from openscvx.integrations import MjxDynamics
|
|
35
|
+
|
|
36
|
+
dyn = MjxDynamics(mjx_model)
|
|
37
|
+
problem = ox.Problem(dynamics=dyn, states=dyn.states, controls=dyn.controls, ...)
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
from typing import Any
|
|
41
|
+
|
|
42
|
+
from .base import DynamicsAdapter
|
|
43
|
+
from .mjx import MjxDynamics
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def mjx_dynamics(*args: Any, **kwargs: Any) -> Any:
|
|
47
|
+
"""Lazy delegate; imports ``mujoco.mjx`` on first call."""
|
|
48
|
+
from .mjx import mjx_dynamics as _mjx_dynamics
|
|
49
|
+
|
|
50
|
+
return _mjx_dynamics(*args, **kwargs)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def __getattr__(name: str) -> Any:
|
|
54
|
+
if name == "menagerie":
|
|
55
|
+
from . import menagerie
|
|
56
|
+
|
|
57
|
+
return menagerie
|
|
58
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
__all__ = [
|
|
62
|
+
"DynamicsAdapter",
|
|
63
|
+
"MjxDynamics",
|
|
64
|
+
"mjx_dynamics",
|
|
65
|
+
"menagerie",
|
|
66
|
+
]
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Base class for external-backend dynamics adapters.
|
|
2
|
+
|
|
3
|
+
A `DynamicsAdapter` is the easy on-ramp for users who want to plug an
|
|
4
|
+
external physics backend (MuJoCo MJX, Brax, Drake, ...) into OpenSCvx without
|
|
5
|
+
manually constructing State/Control objects with matching shapes or routing
|
|
6
|
+
raw JAX callables through the expert ``byof`` channel.
|
|
7
|
+
|
|
8
|
+
The intended call site is::
|
|
9
|
+
|
|
10
|
+
dyn = ox.MjxDynamics(mjx_model)
|
|
11
|
+
problem = ox.Problem(
|
|
12
|
+
dynamics=dyn,
|
|
13
|
+
states=dyn.states,
|
|
14
|
+
controls=dyn.controls,
|
|
15
|
+
...
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
Internally, `Problem` detects the adapter, calls `DynamicsAdapter.expand`,
|
|
19
|
+
and merges the resulting BYOF callables into the user's ``byof`` dict (if
|
|
20
|
+
any). Everything downstream sees ordinary ``dynamics`` and ``byof`` dicts.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import copy
|
|
26
|
+
from abc import ABC, abstractmethod
|
|
27
|
+
from typing import TYPE_CHECKING, Tuple
|
|
28
|
+
|
|
29
|
+
if TYPE_CHECKING:
|
|
30
|
+
from openscvx.symbolic.expr.control import Control
|
|
31
|
+
from openscvx.symbolic.expr.state import State
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class DynamicsAdapter(ABC):
|
|
35
|
+
"""Abstract base class for external-backend dynamics adapters.
|
|
36
|
+
|
|
37
|
+
Subclasses describe the State/Control objects they synthesize on
|
|
38
|
+
``.states`` / ``.controls`` and implement `expand` to return the
|
|
39
|
+
two-channel ``(dynamics_dict, byof_dict)`` representation consumed by
|
|
40
|
+
`Problem`.
|
|
41
|
+
|
|
42
|
+
The split mirrors the existing two-channel API: ``dynamics_dict`` carries
|
|
43
|
+
symbolic Expr entries (e.g. ``{"qpos": qvel}``) while ``byof_dict`` carries
|
|
44
|
+
raw JAX callables under the ``"dynamics"`` key. Either or both may be
|
|
45
|
+
empty, but ``expand()`` should never silently produce overlapping keys.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
states: list["State"]
|
|
49
|
+
controls: list["Control"]
|
|
50
|
+
|
|
51
|
+
@abstractmethod
|
|
52
|
+
def expand(self) -> Tuple[dict, dict]:
|
|
53
|
+
"""Return ``(dynamics_dict, byof_dict)`` in OpenSCvx's internal form.
|
|
54
|
+
|
|
55
|
+
``dynamics_dict`` maps state names to symbolic ``Expr`` derivatives
|
|
56
|
+
(the same shape as the ``dynamics=`` argument to ``Problem``).
|
|
57
|
+
``byof_dict`` has the same shape as the ``byof=`` argument: its
|
|
58
|
+
``"dynamics"`` key (if present) maps state names to raw JAX callables.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _merge_byof(user_byof: dict | None, extra_byof: dict) -> dict:
|
|
63
|
+
"""Merge an adapter-synthesized BYOF dict into a user-provided one.
|
|
64
|
+
|
|
65
|
+
Only the ``"dynamics"`` sub-dict is deep-merged; other keys are taken
|
|
66
|
+
verbatim from whichever side provides them. Raises ``ValueError`` on any
|
|
67
|
+
key collision under ``"dynamics"`` — a user passing both
|
|
68
|
+
``dynamics=ox.MjxDynamics(...)`` and ``byof={"dynamics": {"qvel": ...}}``
|
|
69
|
+
almost certainly has a bug, and silent override would mask it.
|
|
70
|
+
"""
|
|
71
|
+
if not user_byof:
|
|
72
|
+
return copy.copy(extra_byof)
|
|
73
|
+
|
|
74
|
+
merged = dict(user_byof)
|
|
75
|
+
extra_dyn = extra_byof.get("dynamics", {})
|
|
76
|
+
user_dyn = user_byof.get("dynamics", {})
|
|
77
|
+
|
|
78
|
+
if extra_dyn:
|
|
79
|
+
collisions = set(user_dyn) & set(extra_dyn)
|
|
80
|
+
if collisions:
|
|
81
|
+
raise ValueError(
|
|
82
|
+
"DynamicsAdapter produced byof['dynamics'] entries that "
|
|
83
|
+
f"collide with user-provided byof['dynamics']: {sorted(collisions)}. "
|
|
84
|
+
"Drop the duplicate keys from your byof dict, or drop the adapter "
|
|
85
|
+
"and assemble byof['dynamics'] manually for full control."
|
|
86
|
+
)
|
|
87
|
+
merged["dynamics"] = {**user_dyn, **extra_dyn}
|
|
88
|
+
|
|
89
|
+
return merged
|