openscvx 0.5.3.dev31__tar.gz → 0.5.3.dev33__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-0.5.3.dev31/openscvx.egg-info → openscvx-0.5.3.dev33}/PKG-INFO +1 -1
- openscvx-0.5.3.dev33/examples/aircraft/dynamic_soaring.py +333 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/_version.py +3 -3
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/autotuner/augmented_lagrangian.py +2 -2
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/penalty.py +4 -2
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/scvx/iteration.py +11 -2
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/lowered/jax_constraints.py +8 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/solvers/cvxpy_ptr_solver.py +6 -3
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/solvers/moreau_ptr_solver.py +6 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/solvers/qpax_ptr_solver.py +6 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/augmentation.py +0 -36
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lower.py +3 -1
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33/openscvx.egg-info}/PKG-INFO +1 -1
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx.egg-info/SOURCES.txt +1 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx.egg-info/scm_file_list.json +1 -0
- openscvx-0.5.3.dev33/openscvx.egg-info/scm_version.json +8 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/solvers/test_qpax_ptr_solver.py +40 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/test_augmentation.py +12 -26
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_autotuning.py +25 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_brachistochrone.py +71 -0
- openscvx-0.5.3.dev31/openscvx.egg-info/scm_version.json +0 -8
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/.github/assets/logo.svg +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/.github/release-drafter.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/.github/workflows/branch-name.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/.github/workflows/docs.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/.github/workflows/lint.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/.github/workflows/release.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/.github/workflows/tests-integration.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/.github/workflows/tests-unit.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/.gitignore +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/.gitmodules +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/CONTRIBUTING.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/LICENSE +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/README.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/Foundations/constraint_reformulation.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/Foundations/control_parameterization.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/Foundations/discretization.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/Foundations/ocp.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/Foundations/scvx.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/Foundations/time_dilation.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/UnderTheHood/batching_jit_grad.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/UnderTheHood/custom_algorithms_autotuners.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/UsersGuide/00_introduction.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/UsersGuide/05_visualization.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/UsersGuide/06_logic.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/UsersGuide/07_lie.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/UsersGuide/08_mpcc.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/UsersGuide/09_mjx_dynamics.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/assets/favicon.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/assets/logo.svg +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/assets/openscvx_logo_square.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/assets/viser-client/index.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/assets/viser-recordings/drone_racing.viser +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/citation.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/examples.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/index.md +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/docs/versions.json +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/_viser_embed_export.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/abstract/brachistochrone_batched.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/abstract/flappy_bird.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/abstract/hypersensitive.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/abstract/impulsive.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/abstract/stl_integer_variable.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/abstract/stl_or.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/aircraft/supersonic_time_to_climb.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/animations/7_dof_arm.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/animations/_camera.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/animations/_render.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/animations/_sensor_view.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/animations/dr_vp_polytope.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/animations/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/animations/logo.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/animations/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/arm/3_dof_arm.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/arm/7_dof_arm.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/arm/7_dof_arm_collision.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/arm/7_dof_arm_vp.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/arm/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/arm/franka_fr3v2_viewplanning.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/arm/franka_fr3v2_viewplanning_nodal.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/car/dubins_car.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/car/dubins_car_obstacle_conditional.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/car/dubins_car_obstacle_stl.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/car/dubins_car_stl_or.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/car/dubins_car_waypoint_stl.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/double_integrator/_plotting.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/double_integrator/moving_safe_zones.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/2d_obstacle_avoidance_batched_ic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/cinema_vp.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/cinema_vp_nodal.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/dr_vp.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/drone_racing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/drone_racing_batched_gates.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/logo.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/logo_utils/acl_logo.svg +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/logo_utils/openscvx_logo_single.svg +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/logo_utils/quadrotor_mesh.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/logo_utils/svg_path_utils.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/multi_agent_circle_swap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/obstacle_avoidance_vmap_2d.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/drone/openscvx_logo.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/frax/panda_frax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/frax/panda_frax_pick_place.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/frax/panda_frax_viewplanning.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/frax/panda_frax_waypoint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/mjx/cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/mjx/double_cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/mjx/skydio_x2_mjx.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/mjx/triple_cartpole_3d_mjx.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/mjx/triple_cartpole_game.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/mjx/triple_cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/mpc/double_integrator_discrete.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/mpc/double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/mpc/dubins_car_circle_analytical.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/mpc/dubins_car_circle_discrete.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/plotting.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/plotting_viser.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/realtime/3DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/realtime/6DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/rocket/6DoF_pdg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/rocket/6DoF_pdg_batched_ic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/rocket/ascent_launch_vehicle.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/spacecraft/halo_orbit.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/spacecraft/hohmann_transfer.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/spacecraft/let_transfer.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/examples/spacecraft/relative_loitering.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/figures/video_preview.png +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/material/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/material/overrides/assets/stylesheets/home-hero.css +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/material/overrides/assets/stylesheets/home-viser.css +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/material/overrides/home.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/material/overrides/main.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/material/overrides/partials/home-diagram.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/material/overrides/partials/home-dropin-banner.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/material/overrides/partials/home-hero.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/material/overrides/partials/home-pipeline.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/material/overrides/partials/home-viser-strip.html +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/mkdocs.yml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/__main__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/autotuner/acceptance_ratio.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/autotuner/base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/autotuner/constant_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/autotuner/ramp_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/history.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/hyperparams.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/loop.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/scvx/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/scvx/penalized_trust_region.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/state.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/weights.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/config.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/discretization/base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/discretization/discretize_linearize.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/discretization/linearize_discretize.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/discretization/sparse_utils/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/expert/byof.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/expert/validation.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/init/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/init/interpolation.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/init/inverse_kinematics.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/integrations/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/integrations/_utils.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/integrations/base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/integrations/frax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/integrations/menagerie.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/integrations/mjx.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/integrators/diffrax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/loader.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/plotting/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/plotting/plotting.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/plotting/publication.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/plotting/viser/coordinates.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/plotting/viser/orbits.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/problem.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/solvers/base.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/solvers/cones.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/solvers/ptr_solver.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/affine.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/builder.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/canonicalize.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/parameter.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/stljax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/time.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/array.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/control.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/math.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/state.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/parser/_registry.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/parser/array.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/parser/constraint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/parser/lie.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/parser/linalg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/parser/logic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/parser/math.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/parser/parser.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/parser/spatial.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/parser/stl.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/parser/stljax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/parser/tokenizer.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/sparsity.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/utils/cache.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/utils/caching.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/utils/printing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/utils/utils.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx.egg-info/entry_points.txt +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx.egg-info/requires.txt +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/pyproject.toml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/scripts/gen_example_pages.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/setup.cfg +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/_marks.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/algorithms/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/algorithms/_iteration_helpers.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/algorithms/autotuner/test_defaults_agreement.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/algorithms/autotuner/test_hyper_overrides.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/algorithms/autotuner/test_update_weights_jit.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/algorithms/test_algorithm_state_pytree.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/algorithms/test_iteration_fn_jit.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/algorithms/test_iteration_fn_parity.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/algorithms/test_make_solve_loop.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/conftest.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/expr/test_gmsr.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/fixtures/brachistochrone.json +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/fixtures/brachistochrone.yaml +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/hohmann_analytical.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/integrations/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/integrations/test_mjx.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/integrations/test_mjx_dynamics.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/solvers/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/solvers/_iteration_callback_helpers.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/solvers/test_cvxpy_callback_jit_spike.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/solvers/test_iteration_callback_cvxpy.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/solvers/test_iteration_callback_moreau.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/solvers/test_iteration_callback_qpax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/solvers/test_iteration_callback_vmap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/solvers/test_moreau_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/solvers/test_subproblem_pytree.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/test_stl.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/parser/test_array.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/parser/test_constraint.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/parser/test_lie.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/parser/test_linalg.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/parser/test_load.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/parser/test_logic.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/parser/test_math.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/parser/test_parser.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/parser/test_spatial.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/parser/test_stl.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/parser/test_tokenizer.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/parser/test_vmap.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/test_sparsity.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_discretization.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_examples.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_expert.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_impulsive.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_init.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_integrators.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_loader.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_multishot_propagation.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_optimization_results.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_plotting.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_propagation.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_solve_batched_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_solve_batched_cvxpy_export_errors.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_solve_batched_export_roundtrip.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_solve_batched_inference.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_solve_jax_bare_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_solve_jax_jit_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_solve_jax_vmap_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/tests/test_solve_jax_vmap_converged_no_drift.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.5.3.
|
|
3
|
+
Version: 0.5.3.dev33
|
|
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
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
"""Minimum wind-gradient dynamic soaring of a glider (Zhao 2004).
|
|
2
|
+
|
|
3
|
+
The dynamic soaring benchmark from Zhao, *"Optimal Pattern of Glider Dynamic
|
|
4
|
+
Soaring,"* Optimal Control Applications and Methods, Vol. 25, 2004, pp. 67-89,
|
|
5
|
+
reproduced in the GPOPS-II user's guide. A glider flies one closed loop through
|
|
6
|
+
a linear wind shear, extracting enough energy from the gradient to return to
|
|
7
|
+
its initial airspeed, flight-path angle, and (heading - 2 pi). The objective is
|
|
8
|
+
the *smallest* wind-gradient slope ``beta`` for which such an energy-neutral
|
|
9
|
+
loop exists.
|
|
10
|
+
|
|
11
|
+
Point-mass dynamics over a flat Earth with horizontal wind ``W_x = beta h``
|
|
12
|
+
(state ``[x, y, h, v, gamma, psi]`` = position, airspeed, flight-path angle,
|
|
13
|
+
heading; controls ``C_L`` = lift coefficient and ``phi`` = bank angle):
|
|
14
|
+
|
|
15
|
+
x_dot = v cos(gamma) sin(psi) + beta h
|
|
16
|
+
y_dot = v cos(gamma) cos(psi)
|
|
17
|
+
h_dot = v sin(gamma)
|
|
18
|
+
v_dot = -(rho S / 2 m)(CD0 + K C_L^2) v^2 - g sin(gamma) - W sin(psi) cos(gamma)
|
|
19
|
+
gamma_dot = (rho S / 2 m) C_L v cos(phi) - g cos(gamma) / v + W sin(psi) sin(gamma) / v
|
|
20
|
+
psi_dot = ((rho S / 2 m) C_L v sin(phi) - W cos(psi) / v) / cos(gamma)
|
|
21
|
+
|
|
22
|
+
with wind-shear rate ``W = dW_x/dt = beta v sin(gamma)``. The load factor
|
|
23
|
+
``n = (rho S / 2 m g) C_L v^2`` is limited to ``[-2, 5]`` along the whole loop.
|
|
24
|
+
|
|
25
|
+
Three GPOPS features map onto OpenSCvx as follows:
|
|
26
|
+
|
|
27
|
+
- The free static parameter ``beta`` becomes a state with zero dynamics, so a
|
|
28
|
+
single optimized value is shared by every node. Its final value carries a
|
|
29
|
+
``Minimize`` boundary condition — the Mayer objective.
|
|
30
|
+
- The periodicity events ``v_f = v_0``, ``gamma_f = gamma_0``, and
|
|
31
|
+
``psi_f = psi_0 - 2 pi`` become cross-node equality constraints tying node
|
|
32
|
+
``N-1`` to node 0. They are affine, so they are marked ``.convex()`` and
|
|
33
|
+
enforced exactly by the subproblem solver.
|
|
34
|
+
- The load-factor path constraint becomes a CTCS constraint, satisfied in
|
|
35
|
+
continuous time between nodes — which is why far fewer nodes are needed
|
|
36
|
+
here than GPOPS' collocation mesh.
|
|
37
|
+
|
|
38
|
+
The problem is nonconvex with several locally optimal loops; from the guide's
|
|
39
|
+
initial guess the SCP converges to ``beta ~ 0.069 1/s`` with a ~20 s period, a
|
|
40
|
+
slightly different basin than the IPOPT solution pictured in the guide. The
|
|
41
|
+
solution rides the ``n = 5`` load-factor ceiling through the high-speed bottom
|
|
42
|
+
turn, and forward propagation confirms the loop is periodic in continuous time.
|
|
43
|
+
|
|
44
|
+
Units are English (ft, s, slug), matching the reference.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
import os
|
|
48
|
+
import sys
|
|
49
|
+
|
|
50
|
+
import numpy as np
|
|
51
|
+
import plotly.graph_objects as go
|
|
52
|
+
from plotly.subplots import make_subplots
|
|
53
|
+
|
|
54
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
55
|
+
grandparent_dir = os.path.dirname(os.path.dirname(current_dir))
|
|
56
|
+
if grandparent_dir not in sys.path:
|
|
57
|
+
sys.path.append(grandparent_dir)
|
|
58
|
+
|
|
59
|
+
import openscvx as ox
|
|
60
|
+
from openscvx.plotting import plot_controls, plot_scp_iterations, plot_states
|
|
61
|
+
|
|
62
|
+
# ---------------------------------------------------------------------------
|
|
63
|
+
# Physical constants (English units, Zhao 2004)
|
|
64
|
+
# ---------------------------------------------------------------------------
|
|
65
|
+
rho = 0.002378 # air density (slug/ft^3)
|
|
66
|
+
CD0 = 0.00873 # zero-lift drag coefficient
|
|
67
|
+
K = 0.045 # induced drag factor
|
|
68
|
+
g = 32.2 # gravitational acceleration (ft/s^2)
|
|
69
|
+
m = 5.6 # glider mass (slug)
|
|
70
|
+
S = 45.09703 # wing reference area (ft^2)
|
|
71
|
+
|
|
72
|
+
load_min, load_max = -2.0, 5.0 # load factor limits
|
|
73
|
+
beta_min, beta_max = 0.005, 0.15 # wind-gradient slope bounds (1/s)
|
|
74
|
+
|
|
75
|
+
n = 20 # discretization nodes — CTCS keeps the path constraint tight between them
|
|
76
|
+
tf_guess = 24.0 # initial guess for the (free) loop period
|
|
77
|
+
|
|
78
|
+
# ---------------------------------------------------------------------------
|
|
79
|
+
# States — the guess is one circular loop through the shear layer: climbing
|
|
80
|
+
# into the wind, diving out of it.
|
|
81
|
+
# ---------------------------------------------------------------------------
|
|
82
|
+
_t = np.linspace(0.0, tf_guess, n)
|
|
83
|
+
_th = 2 * np.pi * _t / tf_guess
|
|
84
|
+
|
|
85
|
+
position = ox.State("position", shape=(3,)) # [x, y, h] (ft)
|
|
86
|
+
position.min = [-1000.0, -1000.0, 0.0]
|
|
87
|
+
position.max = [1000.0, 1000.0, 1000.0]
|
|
88
|
+
position.initial = [0.0, 0.0, 0.0]
|
|
89
|
+
position.final = [0.0, 0.0, 0.0]
|
|
90
|
+
position.guess = np.stack(
|
|
91
|
+
[500 * np.cos(_th) - 500, 300 * np.sin(_th), 400 - 400 * np.cos(_th)], axis=1
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
v = ox.State("speed", shape=(1,)) # airspeed (ft/s)
|
|
95
|
+
v.min, v.max = [10.0], [350.0]
|
|
96
|
+
v.initial, v.final = [ox.Free(200.0)], [ox.Free(200.0)]
|
|
97
|
+
v.guess = (80 * (1.5 + np.cos(_th))).reshape(-1, 1)
|
|
98
|
+
|
|
99
|
+
gamma = ox.State("flight_path_angle", shape=(1,))
|
|
100
|
+
gamma.min, gamma.max = [np.deg2rad(-75.0)], [np.deg2rad(75.0)]
|
|
101
|
+
gamma.initial, gamma.final = [ox.Free(0.0)], [ox.Free(0.0)]
|
|
102
|
+
gamma.guess = (np.pi / 6 * np.sin(_th)).reshape(-1, 1)
|
|
103
|
+
|
|
104
|
+
psi = ox.State("heading", shape=(1,))
|
|
105
|
+
psi.min, psi.max = [-3 * np.pi], [np.pi / 2]
|
|
106
|
+
psi.initial, psi.final = [ox.Free(-1.0)], [ox.Free(-1.0 - 2 * np.pi)]
|
|
107
|
+
psi.guess = (-1.0 - _t / 4).reshape(-1, 1)
|
|
108
|
+
|
|
109
|
+
# The wind-gradient slope is a single optimized constant: a state with zero
|
|
110
|
+
# dynamics whose final value is the Mayer objective.
|
|
111
|
+
beta = ox.State("wind_gradient", shape=(1,))
|
|
112
|
+
beta.min, beta.max = [beta_min], [beta_max]
|
|
113
|
+
beta.initial, beta.final = [ox.Free(0.08)], [ox.Minimize(0.08)]
|
|
114
|
+
beta.guess = np.full((n, 1), 0.08)
|
|
115
|
+
|
|
116
|
+
# ---------------------------------------------------------------------------
|
|
117
|
+
# Controls
|
|
118
|
+
# ---------------------------------------------------------------------------
|
|
119
|
+
CL = ox.Control("lift_coefficient", shape=(1,))
|
|
120
|
+
CL.min, CL.max = [-0.5], [1.5]
|
|
121
|
+
CL.guess = np.full((n, 1), 0.5)
|
|
122
|
+
|
|
123
|
+
phi = ox.Control("bank_angle", shape=(1,))
|
|
124
|
+
phi.min, phi.max = [np.deg2rad(-75.0)], [np.deg2rad(75.0)]
|
|
125
|
+
phi.guess = np.full((n, 1), -1.0)
|
|
126
|
+
|
|
127
|
+
states = [position, v, gamma, psi, beta]
|
|
128
|
+
controls = [CL, phi]
|
|
129
|
+
|
|
130
|
+
# ---------------------------------------------------------------------------
|
|
131
|
+
# Dynamics
|
|
132
|
+
# ---------------------------------------------------------------------------
|
|
133
|
+
hs = position[2]
|
|
134
|
+
vs, fpa, head, b = v[0], gamma[0], psi[0], beta[0]
|
|
135
|
+
cl, bank = CL[0], phi[0]
|
|
136
|
+
|
|
137
|
+
aero = rho * S / (2 * m) # (rho S / 2 m), the common aerodynamic factor
|
|
138
|
+
shear = b * vs * ox.Sin(fpa) # W = dW_x/dt, the wind-shear rate
|
|
139
|
+
|
|
140
|
+
dynamics = {
|
|
141
|
+
"position": ox.Concat(
|
|
142
|
+
vs * ox.Cos(fpa) * ox.Sin(head) + b * hs,
|
|
143
|
+
vs * ox.Cos(fpa) * ox.Cos(head),
|
|
144
|
+
vs * ox.Sin(fpa),
|
|
145
|
+
),
|
|
146
|
+
"speed": -aero * (CD0 + K * cl**2) * vs**2
|
|
147
|
+
- g * ox.Sin(fpa)
|
|
148
|
+
- shear * ox.Sin(head) * ox.Cos(fpa),
|
|
149
|
+
"flight_path_angle": aero * cl * vs * ox.Cos(bank)
|
|
150
|
+
- g * ox.Cos(fpa) / vs
|
|
151
|
+
+ shear * ox.Sin(head) * ox.Sin(fpa) / vs,
|
|
152
|
+
"heading": (aero * cl * vs * ox.Sin(bank) - shear * ox.Cos(head) / vs) / ox.Cos(fpa),
|
|
153
|
+
"wind_gradient": 0.0 * b,
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
# ---------------------------------------------------------------------------
|
|
157
|
+
# Constraints: state boxes and the load-factor limit hold in continuous time;
|
|
158
|
+
# the periodicity events tie the last node back to the first.
|
|
159
|
+
# ---------------------------------------------------------------------------
|
|
160
|
+
constraints = []
|
|
161
|
+
for state in states:
|
|
162
|
+
constraints.extend([ox.ctcs(state <= state.max), ox.ctcs(state.min <= state)])
|
|
163
|
+
|
|
164
|
+
load_factor = (aero / g) * cl * vs**2
|
|
165
|
+
constraints.extend([ox.ctcs(load_factor <= load_max), ox.ctcs(load_min <= load_factor)])
|
|
166
|
+
|
|
167
|
+
constraints.extend(
|
|
168
|
+
[
|
|
169
|
+
(v.at(n - 1) - v.at(0) == 0.0).convex(),
|
|
170
|
+
(gamma.at(n - 1) - gamma.at(0) == 0.0).convex(),
|
|
171
|
+
(psi.at(n - 1) - psi.at(0) == -2 * np.pi).convex(),
|
|
172
|
+
]
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
# ---------------------------------------------------------------------------
|
|
176
|
+
# Free final time — the loop period is optimized but carries no cost.
|
|
177
|
+
# ---------------------------------------------------------------------------
|
|
178
|
+
time = ox.Time(
|
|
179
|
+
initial=0.0,
|
|
180
|
+
final=ox.Free(tf_guess),
|
|
181
|
+
min=0.0,
|
|
182
|
+
max=30.0,
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
# A fixed proximal weight converges in ~25 iterations here, where the adaptive
|
|
186
|
+
# default stalls just short of the dynamics-feasibility tolerance.
|
|
187
|
+
problem = ox.Problem(
|
|
188
|
+
dynamics=dynamics,
|
|
189
|
+
states=states,
|
|
190
|
+
controls=controls,
|
|
191
|
+
time=time,
|
|
192
|
+
constraints=constraints,
|
|
193
|
+
N=n,
|
|
194
|
+
licq_max=1e-8,
|
|
195
|
+
algorithm={"lam_prox": 2e-2, "autotuner": ox.ConstantProximalWeight()},
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def plot_gpops_comparison(results):
|
|
200
|
+
"""Reproduce the six GPOPS-II diagnostic plots for this benchmark.
|
|
201
|
+
|
|
202
|
+
Lays out the 3-D soaring loop (x, y, h) followed by airspeed, flight-path
|
|
203
|
+
angle, heading, lift coefficient, and bank angle versus time. The
|
|
204
|
+
high-resolution propagated trajectory is drawn as a line with the
|
|
205
|
+
discretization nodes overlaid.
|
|
206
|
+
"""
|
|
207
|
+
nodes, traj = results.nodes, results.trajectory
|
|
208
|
+
|
|
209
|
+
def col(source, key, idx=0):
|
|
210
|
+
arr = np.asarray(source[key])
|
|
211
|
+
return arr[:, idx] if arr.ndim > 1 else arr
|
|
212
|
+
|
|
213
|
+
fig = make_subplots(
|
|
214
|
+
rows=2,
|
|
215
|
+
cols=3,
|
|
216
|
+
specs=[
|
|
217
|
+
[{"type": "scene"}, {"type": "xy"}, {"type": "xy"}],
|
|
218
|
+
[{"type": "xy"}, {"type": "xy"}, {"type": "xy"}],
|
|
219
|
+
],
|
|
220
|
+
subplot_titles=(
|
|
221
|
+
"Soaring Loop",
|
|
222
|
+
"Airspeed vs. Time",
|
|
223
|
+
"Flight-Path Angle vs. Time",
|
|
224
|
+
"Heading vs. Time",
|
|
225
|
+
"Lift Coefficient vs. Time",
|
|
226
|
+
"Bank Angle vs. Time",
|
|
227
|
+
),
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
line_style = {"color": "#19d3f3", "width": 3}
|
|
231
|
+
marker_style = {"color": "#ffa600", "size": 5}
|
|
232
|
+
|
|
233
|
+
fig.add_trace(
|
|
234
|
+
go.Scatter3d(
|
|
235
|
+
x=col(traj, "position", 0),
|
|
236
|
+
y=col(traj, "position", 1),
|
|
237
|
+
z=col(traj, "position", 2),
|
|
238
|
+
mode="lines",
|
|
239
|
+
name="Propagated",
|
|
240
|
+
line=line_style,
|
|
241
|
+
legendgroup="traj",
|
|
242
|
+
),
|
|
243
|
+
row=1,
|
|
244
|
+
col=1,
|
|
245
|
+
)
|
|
246
|
+
fig.add_trace(
|
|
247
|
+
go.Scatter3d(
|
|
248
|
+
x=col(nodes, "position", 0),
|
|
249
|
+
y=col(nodes, "position", 1),
|
|
250
|
+
z=col(nodes, "position", 2),
|
|
251
|
+
mode="markers",
|
|
252
|
+
name="Nodes",
|
|
253
|
+
marker=marker_style,
|
|
254
|
+
legendgroup="nodes",
|
|
255
|
+
),
|
|
256
|
+
row=1,
|
|
257
|
+
col=1,
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
# (row, col, y-trajectory, y-nodes) for the five time-series panels.
|
|
261
|
+
t_traj, t_nodes = col(traj, "time"), col(nodes, "time")
|
|
262
|
+
panels = [
|
|
263
|
+
(1, 2, col(traj, "speed"), col(nodes, "speed")),
|
|
264
|
+
(
|
|
265
|
+
1,
|
|
266
|
+
3,
|
|
267
|
+
np.rad2deg(col(traj, "flight_path_angle")),
|
|
268
|
+
np.rad2deg(col(nodes, "flight_path_angle")),
|
|
269
|
+
),
|
|
270
|
+
(2, 1, np.rad2deg(col(traj, "heading")), np.rad2deg(col(nodes, "heading"))),
|
|
271
|
+
(2, 2, col(traj, "lift_coefficient"), col(nodes, "lift_coefficient")),
|
|
272
|
+
(2, 3, np.rad2deg(col(traj, "bank_angle")), np.rad2deg(col(nodes, "bank_angle"))),
|
|
273
|
+
]
|
|
274
|
+
for r, c, yt, yn in panels:
|
|
275
|
+
fig.add_trace(
|
|
276
|
+
go.Scatter(
|
|
277
|
+
x=t_traj,
|
|
278
|
+
y=yt,
|
|
279
|
+
mode="lines",
|
|
280
|
+
name="Propagated",
|
|
281
|
+
line={"color": line_style["color"], "width": 2},
|
|
282
|
+
legendgroup="traj",
|
|
283
|
+
showlegend=False,
|
|
284
|
+
),
|
|
285
|
+
row=r,
|
|
286
|
+
col=c,
|
|
287
|
+
)
|
|
288
|
+
fig.add_trace(
|
|
289
|
+
go.Scatter(
|
|
290
|
+
x=t_nodes,
|
|
291
|
+
y=yn,
|
|
292
|
+
mode="markers",
|
|
293
|
+
name="Nodes",
|
|
294
|
+
marker=marker_style,
|
|
295
|
+
legendgroup="nodes",
|
|
296
|
+
showlegend=False,
|
|
297
|
+
),
|
|
298
|
+
row=r,
|
|
299
|
+
col=c,
|
|
300
|
+
)
|
|
301
|
+
fig.update_xaxes(title_text="Time [s]", row=r, col=c)
|
|
302
|
+
|
|
303
|
+
fig.update_yaxes(title_text="Airspeed [ft/s]", row=1, col=2)
|
|
304
|
+
fig.update_yaxes(title_text="Flight-path angle [deg]", row=1, col=3)
|
|
305
|
+
fig.update_yaxes(title_text="Heading [deg]", row=2, col=1)
|
|
306
|
+
fig.update_yaxes(title_text="Lift coefficient", row=2, col=2)
|
|
307
|
+
fig.update_yaxes(title_text="Bank angle [deg]", row=2, col=3)
|
|
308
|
+
fig.update_layout(
|
|
309
|
+
title="Dynamic Soaring",
|
|
310
|
+
template="plotly_dark",
|
|
311
|
+
scene={
|
|
312
|
+
"xaxis_title": "x [ft]",
|
|
313
|
+
"yaxis_title": "y [ft]",
|
|
314
|
+
"zaxis_title": "h [ft]",
|
|
315
|
+
"aspectmode": "data",
|
|
316
|
+
},
|
|
317
|
+
)
|
|
318
|
+
return fig
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
if __name__ == "__main__":
|
|
322
|
+
problem.initialize()
|
|
323
|
+
results = problem.solve()
|
|
324
|
+
results = problem.post_process()
|
|
325
|
+
|
|
326
|
+
beta_opt = float(np.asarray(results.nodes["wind_gradient"]).flatten()[-1])
|
|
327
|
+
final_time = float(np.asarray(results.nodes["time"]).flatten()[-1])
|
|
328
|
+
print(f"Minimum wind-gradient slope: {beta_opt:.4f} 1/s (loop period {final_time:.2f} s)")
|
|
329
|
+
|
|
330
|
+
plot_gpops_comparison(results).show()
|
|
331
|
+
plot_states(results).show()
|
|
332
|
+
plot_controls(results).show()
|
|
333
|
+
plot_scp_iterations(results).show()
|
|
@@ -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 = '0.5.3.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 5, 3, '
|
|
21
|
+
__version__ = version = '0.5.3.dev33'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 5, 3, 'dev33')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g3d6f6768a'
|
{openscvx-0.5.3.dev31 → openscvx-0.5.3.dev33}/openscvx/algorithms/autotuner/augmented_lagrangian.py
RENAMED
|
@@ -206,7 +206,7 @@ class AugmentedLagrangian(AcceptanceRatioAutotuner):
|
|
|
206
206
|
|
|
207
207
|
for idx, constraint in enumerate(nodal_constraints.nodal):
|
|
208
208
|
g = constraint.func(candidate.x, candidate.u, 0, params)
|
|
209
|
-
nu = jnp.maximum(0.0, g)
|
|
209
|
+
nu = jnp.abs(g) if constraint.is_equality else jnp.maximum(0.0, g)
|
|
210
210
|
|
|
211
211
|
if constraint.nodes is not None:
|
|
212
212
|
nodes_array = jnp.asarray(constraint.nodes)
|
|
@@ -245,7 +245,7 @@ class AugmentedLagrangian(AcceptanceRatioAutotuner):
|
|
|
245
245
|
|
|
246
246
|
for idx, constraint in enumerate(nodal_constraints.cross_node):
|
|
247
247
|
g = constraint.func(candidate.x, candidate.u, params)
|
|
248
|
-
nu = jnp.sum(jnp.maximum(0.0, g))
|
|
248
|
+
nu = jnp.sum(jnp.abs(g) if constraint.is_equality else jnp.maximum(0.0, g))
|
|
249
249
|
current = state.lam_vb_cross[idx]
|
|
250
250
|
case1 = current + nu * scale
|
|
251
251
|
case2 = current + (nu**2) / state.hyper.ep * scale
|
|
@@ -96,12 +96,14 @@ def calculate_nonlinear_penalty(
|
|
|
96
96
|
else:
|
|
97
97
|
g_filtered = g
|
|
98
98
|
w = lam_vb_nodal[:, idx]
|
|
99
|
-
|
|
99
|
+
viol = jnp.abs(g_filtered) if constraint.is_equality else jnp.maximum(0.0, g_filtered)
|
|
100
|
+
nodal_penalty = nodal_penalty + jnp.sum(w * viol)
|
|
100
101
|
|
|
101
102
|
for idx, constraint in enumerate(nodal_constraints.cross_node):
|
|
102
103
|
w = lam_vb_cross[idx]
|
|
103
104
|
g = constraint.func(x_bar, u_bar, params)
|
|
104
|
-
|
|
105
|
+
viol = jnp.abs(g) if constraint.is_equality else jnp.maximum(0.0, g)
|
|
106
|
+
nodal_penalty = nodal_penalty + w * jnp.sum(viol)
|
|
105
107
|
|
|
106
108
|
cost = calculate_cost_from_state(x_bar, settings, lam_cost)
|
|
107
109
|
x_diff = settings.sim.inv_S_x @ (x_bar[1:, :] - x_prop).T
|
|
@@ -145,6 +145,11 @@ def make_scp_iteration(
|
|
|
145
145
|
n_u = settings.sim.n_controls
|
|
146
146
|
n_nodal = len(jax_constraints.nodal)
|
|
147
147
|
|
|
148
|
+
# Equality columns measure violation two-sided (|nu_vb|); inequalities use
|
|
149
|
+
# the positive part. Built once at trace time as static boolean masks.
|
|
150
|
+
nodal_eq_mask = jnp.asarray([c.is_equality for c in jax_constraints.nodal], dtype=bool)
|
|
151
|
+
cross_eq_mask = jnp.asarray([c.is_equality for c in jax_constraints.cross_node], dtype=bool)
|
|
152
|
+
|
|
148
153
|
# Accept either a bare ``jax.jit`` callable or a ``jax.export`` wrapper.
|
|
149
154
|
dis_continuous = dis_continuous.call if hasattr(dis_continuous, "call") else dis_continuous
|
|
150
155
|
dis_impulsive = dis_impulsive.call if hasattr(dis_impulsive, "call") else dis_impulsive
|
|
@@ -311,9 +316,13 @@ def make_scp_iteration(
|
|
|
311
316
|
VC = jnp.abs(inv_S_x @ solution.nu.T).T
|
|
312
317
|
J_tr = jnp.sum(TR**2)
|
|
313
318
|
J_vc = jnp.sum(VC)
|
|
314
|
-
|
|
315
|
-
jnp.maximum(0.0, solution.
|
|
319
|
+
nodal_vb = jnp.where(
|
|
320
|
+
nodal_eq_mask, jnp.abs(solution.nu_vb), jnp.maximum(0.0, solution.nu_vb)
|
|
321
|
+
)
|
|
322
|
+
cross_vb = jnp.where(
|
|
323
|
+
cross_eq_mask, jnp.abs(solution.nu_vb_cross), jnp.maximum(0.0, solution.nu_vb_cross)
|
|
316
324
|
)
|
|
325
|
+
J_vb = jnp.sum(nodal_vb) + jnp.sum(cross_vb)
|
|
317
326
|
state = state.replace(
|
|
318
327
|
J_tr=jnp.asarray(J_tr, dtype=state.J_tr.dtype),
|
|
319
328
|
J_vb=jnp.asarray(J_vb, dtype=state.J_vb.dtype),
|
|
@@ -37,12 +37,19 @@ class LoweredNodalConstraint:
|
|
|
37
37
|
|
|
38
38
|
nodes (Optional[List[int]]): List of node indices where this constraint applies.
|
|
39
39
|
Set after lowering from NodalConstraint.
|
|
40
|
+
|
|
41
|
+
is_equality (bool): True if the source constraint was an ``Equality``
|
|
42
|
+
(``g == 0``), False for an ``Inequality`` (``g <= 0``). Controls the
|
|
43
|
+
virtual-buffer penalty shape downstream: equalities are penalized
|
|
44
|
+
two-sided (``|nu_vb|``), inequalities one-sided (``pos(nu_vb)``).
|
|
45
|
+
Defaults to False, preserving the inequality behavior.
|
|
40
46
|
"""
|
|
41
47
|
|
|
42
48
|
func: Callable[[jnp.ndarray, jnp.ndarray], jnp.ndarray]
|
|
43
49
|
grad_g_x: Optional[Callable[[jnp.ndarray, jnp.ndarray], jnp.ndarray]] = None
|
|
44
50
|
grad_g_u: Optional[Callable[[jnp.ndarray, jnp.ndarray], jnp.ndarray]] = None
|
|
45
51
|
nodes: Optional[List[int]] = None
|
|
52
|
+
is_equality: bool = False
|
|
46
53
|
|
|
47
54
|
|
|
48
55
|
@dataclass
|
|
@@ -110,6 +117,7 @@ class LoweredCrossNodeConstraint:
|
|
|
110
117
|
func: Callable[[jnp.ndarray, jnp.ndarray, dict], jnp.ndarray]
|
|
111
118
|
grad_g_X: Callable[[jnp.ndarray, jnp.ndarray, dict], jnp.ndarray]
|
|
112
119
|
grad_g_U: Callable[[jnp.ndarray, jnp.ndarray, dict], jnp.ndarray]
|
|
120
|
+
is_equality: bool = False
|
|
113
121
|
|
|
114
122
|
|
|
115
123
|
@dataclass
|
|
@@ -490,18 +490,21 @@ class CVXPyPTRSolver(PTRSolver):
|
|
|
490
490
|
# Virtual Control Slack
|
|
491
491
|
cost += sum(cp.sum(lam_vc[i - 1] * cp.abs(nu[i - 1])) for i in range(1, settings.sim.n))
|
|
492
492
|
|
|
493
|
-
# Virtual buffer penalty for nodal constraints (per-node weighting)
|
|
493
|
+
# Virtual buffer penalty for nodal constraints (per-node weighting).
|
|
494
|
+
# Equalities penalize |nu_vb|, inequalities penalize pos(nu_vb).
|
|
494
495
|
idx_ncvx = 0
|
|
495
496
|
if jax_constraints.nodal:
|
|
496
497
|
for constraint in jax_constraints.nodal:
|
|
497
|
-
|
|
498
|
+
pen = cp.abs if constraint.is_equality else cp.pos
|
|
499
|
+
cost += lam_vb_nodal[:, idx_ncvx] @ pen(nu_vb[idx_ncvx])
|
|
498
500
|
idx_ncvx += 1
|
|
499
501
|
|
|
500
502
|
# Virtual slack penalty for cross-node constraints
|
|
501
503
|
idx_cross = 0
|
|
502
504
|
if jax_constraints.cross_node:
|
|
503
505
|
for constraint in jax_constraints.cross_node:
|
|
504
|
-
|
|
506
|
+
pen = cp.abs if constraint.is_equality else cp.pos
|
|
507
|
+
cost += lam_vb_cross[idx_cross] * pen(nu_vb_cross[idx_cross])
|
|
505
508
|
idx_cross += 1
|
|
506
509
|
|
|
507
510
|
return cost
|
|
@@ -490,6 +490,12 @@ class MoreauPTRSolver(PTRSolver):
|
|
|
490
490
|
self._c_u_j = jnp.asarray(self._c_u, dtype=f)
|
|
491
491
|
self._jax_dtype = f
|
|
492
492
|
|
|
493
|
+
if any(c.is_equality for c in jax_constraints.nodal):
|
|
494
|
+
raise NotImplementedError(
|
|
495
|
+
"MoreauPTRSolver does not support L1-penalized equality "
|
|
496
|
+
"constraints. Use CVXPyPTRSolver."
|
|
497
|
+
)
|
|
498
|
+
|
|
493
499
|
self.layout = _ConicLayout(N=N, n_x=n_x, n_u=n_u, n_nodal=len(jax_constraints.nodal))
|
|
494
500
|
self._jax_constraints = jax_constraints
|
|
495
501
|
self._x_unified = x_unified
|
|
@@ -329,6 +329,12 @@ class QPAXPTRSolver(PTRSolver):
|
|
|
329
329
|
self._c_u_j = jnp.asarray(self._c_u, dtype=f)
|
|
330
330
|
self._jax_dtype = f
|
|
331
331
|
|
|
332
|
+
if any(c.is_equality for c in jax_constraints.nodal):
|
|
333
|
+
raise NotImplementedError(
|
|
334
|
+
"QPAXPTRSolver does not support L1-penalized equality "
|
|
335
|
+
"constraints. Use CVXPyPTRSolver."
|
|
336
|
+
)
|
|
337
|
+
|
|
332
338
|
self.layout = _QPLayout(N=N, n_x=n_x, n_u=n_u, n_nodal=len(jax_constraints.nodal))
|
|
333
339
|
self._jax_constraints = jax_constraints
|
|
334
340
|
self._x_unified = x_unified
|
|
@@ -75,30 +75,6 @@ from openscvx.symbolic.expr.state import State
|
|
|
75
75
|
from openscvx.symbolic.expr.time import Time
|
|
76
76
|
|
|
77
77
|
|
|
78
|
-
def _check_nonconvex_equality(constraint: Constraint, context: str) -> None:
|
|
79
|
-
"""Raise a helpful error if constraint is a non-convex equality.
|
|
80
|
-
|
|
81
|
-
Non-convex equality constraints are not supported.
|
|
82
|
-
|
|
83
|
-
Args:
|
|
84
|
-
constraint: The constraint to check
|
|
85
|
-
context: Description of where this constraint appears (for error message)
|
|
86
|
-
|
|
87
|
-
Raises:
|
|
88
|
-
ValueError: If constraint is an Equality and not marked as convex
|
|
89
|
-
"""
|
|
90
|
-
if isinstance(constraint, Equality) and not constraint.is_convex:
|
|
91
|
-
raise ValueError(
|
|
92
|
-
f"Non-convex equality constraint in {context}. "
|
|
93
|
-
f"Equality constraints must be affine (linear) and marked as convex "
|
|
94
|
-
f"using .convex(). For example:\n"
|
|
95
|
-
f" (velocity.at(0) == velocity.at(n-1)).convex()\n"
|
|
96
|
-
f"If your equality constraint is nonlinear, consider reformulating it "
|
|
97
|
-
f"as two inequality constraints or using a different approach.\n"
|
|
98
|
-
f"Constraint: {constraint}"
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
|
|
102
78
|
def sort_ctcs_constraints(
|
|
103
79
|
constraints_ctcs: List[CTCS],
|
|
104
80
|
) -> Tuple[List[CTCS], List[Tuple[int, int]], int]:
|
|
@@ -265,9 +241,6 @@ def separate_constraints(constraint_set: ConstraintSet, n_nodes: int) -> Constra
|
|
|
265
241
|
f"Constraint: {c.constraint}"
|
|
266
242
|
)
|
|
267
243
|
|
|
268
|
-
# Check for non-convex equality constraints
|
|
269
|
-
_check_nonconvex_equality(c.constraint, "nodal constraint")
|
|
270
|
-
|
|
271
244
|
# Regular nodal constraint - categorize by convexity
|
|
272
245
|
if c.constraint.is_convex:
|
|
273
246
|
constraint_set.nodal_convex.append(c)
|
|
@@ -277,9 +250,6 @@ def separate_constraints(constraint_set: ConstraintSet, n_nodes: int) -> Constra
|
|
|
277
250
|
elif isinstance(c, Constraint):
|
|
278
251
|
# Bare constraint - check if it's a cross-node constraint
|
|
279
252
|
if _contains_node_reference(c):
|
|
280
|
-
# Check for non-convex equality constraints
|
|
281
|
-
_check_nonconvex_equality(c, "cross-node constraint")
|
|
282
|
-
|
|
283
253
|
# Cross-node constraint: wrap in CrossNodeConstraint
|
|
284
254
|
cross_node = CrossNodeConstraint(c)
|
|
285
255
|
if c.is_convex:
|
|
@@ -287,9 +257,6 @@ def separate_constraints(constraint_set: ConstraintSet, n_nodes: int) -> Constra
|
|
|
287
257
|
else:
|
|
288
258
|
constraint_set.cross_node.append(cross_node)
|
|
289
259
|
else:
|
|
290
|
-
# Check for non-convex equality constraints
|
|
291
|
-
_check_nonconvex_equality(c, "nodal constraint")
|
|
292
|
-
|
|
293
260
|
# Regular constraint: apply at all nodes
|
|
294
261
|
all_nodes = list(range(n_nodes))
|
|
295
262
|
nodal_constraint = NodalConstraint(c, all_nodes)
|
|
@@ -310,9 +277,6 @@ def separate_constraints(constraint_set: ConstraintSet, n_nodes: int) -> Constra
|
|
|
310
277
|
# Add nodal constraints from CTCS constraints that have check_nodally=True
|
|
311
278
|
ctcs_nodal_constraints = get_nodal_constraints_from_ctcs(constraint_set.ctcs)
|
|
312
279
|
for constraint, interval in ctcs_nodal_constraints:
|
|
313
|
-
# Check for non-convex equality constraints
|
|
314
|
-
_check_nonconvex_equality(constraint, "CTCS check_nodally constraint")
|
|
315
|
-
|
|
316
280
|
# CTCS check_nodally constraints cannot have NodeReferences (validated above)
|
|
317
281
|
# Convert CTCS interval (start, end) to list of nodes [start, start+1, ..., end-1]
|
|
318
282
|
interval_nodes = list(range(interval[0], interval[1]))
|
|
@@ -73,7 +73,7 @@ from openscvx.lowered import (
|
|
|
73
73
|
LoweredProblem,
|
|
74
74
|
)
|
|
75
75
|
from openscvx.symbolic.constraint_set import ConstraintSet
|
|
76
|
-
from openscvx.symbolic.expr import Expr, NodeReference, traverse
|
|
76
|
+
from openscvx.symbolic.expr import Equality, Expr, NodeReference, traverse
|
|
77
77
|
from openscvx.symbolic.expr.control import Control
|
|
78
78
|
from openscvx.symbolic.unified import unify_controls, unify_states
|
|
79
79
|
|
|
@@ -628,6 +628,7 @@ def _lower_jax_constraints(
|
|
|
628
628
|
grad_g_x=jax.vmap(jacfwd(fn, argnums=0), in_axes=(0, 0, None, None)),
|
|
629
629
|
grad_g_u=jax.vmap(jacfwd(fn, argnums=1), in_axes=(0, 0, None, None)),
|
|
630
630
|
nodes=constraints.nodal[i].nodes,
|
|
631
|
+
is_equality=isinstance(constraints.nodal[i].constraint, Equality),
|
|
631
632
|
)
|
|
632
633
|
lowered_nodal.append(constraint)
|
|
633
634
|
|
|
@@ -644,6 +645,7 @@ def _lower_jax_constraints(
|
|
|
644
645
|
func=constraint_fn,
|
|
645
646
|
grad_g_X=grad_g_X,
|
|
646
647
|
grad_g_U=grad_g_U,
|
|
648
|
+
is_equality=isinstance(cross_node_constraint.constraint, Equality),
|
|
647
649
|
)
|
|
648
650
|
lowered_cross_node.append(cross_node_lowered)
|
|
649
651
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.5.3.
|
|
3
|
+
Version: 0.5.3.dev33
|
|
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
|
|
@@ -63,6 +63,7 @@ examples/abstract/hypersensitive.py
|
|
|
63
63
|
examples/abstract/impulsive.py
|
|
64
64
|
examples/abstract/stl_integer_variable.py
|
|
65
65
|
examples/abstract/stl_or.py
|
|
66
|
+
examples/aircraft/dynamic_soaring.py
|
|
66
67
|
examples/aircraft/supersonic_time_to_climb.py
|
|
67
68
|
examples/animations/7_dof_arm.py
|
|
68
69
|
examples/animations/_camera.py
|
|
@@ -333,6 +333,7 @@
|
|
|
333
333
|
"examples/abstract/stl_or.py",
|
|
334
334
|
"examples/abstract/stl_integer_variable.py",
|
|
335
335
|
"examples/abstract/brachistochrone.py",
|
|
336
|
+
"examples/aircraft/dynamic_soaring.py",
|
|
336
337
|
"examples/aircraft/supersonic_time_to_climb.py",
|
|
337
338
|
"examples/drone/dr_vp.py",
|
|
338
339
|
"examples/drone/openscvx_logo.py",
|