openscvx 0.5.3.dev13__tar.gz → 0.5.3.dev14__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.dev13 → openscvx-0.5.3.dev14}/.gitignore +3 -3
- {openscvx-0.5.3.dev13/openscvx.egg-info → openscvx-0.5.3.dev14}/PKG-INFO +1 -1
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/spacecraft/halo_orbit.py +79 -59
- openscvx-0.5.3.dev14/examples/spacecraft/relative_loitering.py +458 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/_version.py +3 -3
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14/openscvx.egg-info}/PKG-INFO +1 -1
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx.egg-info/SOURCES.txt +1 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/test_brachistochrone.py +2 -2
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/.github/assets/logo.svg +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/.github/release-drafter.yml +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/.github/workflows/branch-name.yml +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/.github/workflows/docs.yml +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/.github/workflows/lint.yml +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/.github/workflows/release.yml +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/.github/workflows/tests-integration.yml +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/.github/workflows/tests-unit.yml +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/.gitmodules +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/CONTRIBUTING.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/LICENSE +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/README.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/Foundations/constraint_reformulation.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/Foundations/control_parameterization.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/Foundations/discretization.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/Foundations/ocp.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/Foundations/scvx.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/Foundations/time_dilation.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/UsersGuide/00_introduction.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/UsersGuide/05_visualization.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/UsersGuide/06_logic.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/UsersGuide/07_lie.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/UsersGuide/08_mpcc.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/UsersGuide/09_mjx_dynamics.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/assets/favicon.png +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/assets/logo.svg +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/assets/openscvx_logo_square.png +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/assets/viser-client/index.html +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/assets/viser-recordings/drone_racing.viser +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/citation.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/examples.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/index.md +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/docs/versions.json +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/_viser_embed_export.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/abstract/hypersensitive.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/abstract/impulsive.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/abstract/stl_integer_variable.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/abstract/stl_or.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/animations/7_dof_arm.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/animations/_camera.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/animations/_render.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/animations/_sensor_view.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/animations/dr_vp_polytope.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/animations/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/animations/logo.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/animations/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/arm/3_dof_arm.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/arm/7_dof_arm.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/arm/7_dof_arm_collision.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/arm/7_dof_arm_vp.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/arm/franka_fr3v2_pick_place.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/arm/franka_fr3v2_viewplanning.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/car/dubins_car.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/car/dubins_car_obstacle_conditional.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/car/dubins_car_obstacle_stl.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/car/dubins_car_stl_or.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/car/dubins_car_waypoint_stl.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/drone/cinema_vp.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/drone/dr_vp.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/drone/drone_racing.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/drone/logo.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/drone/logo_utils/acl_logo.svg +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/drone/logo_utils/svg_path_utils.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/mjx/cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/mjx/double_cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/mjx/skydio_x2_mjx.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/mjx/triple_cartpole_3d_mjx.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/mjx/triple_cartpole_game.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/mjx/triple_cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/mpc/double_integrator_discrete.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/mpc/double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/mpc/dubins_car_circle_analytical.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/mpc/dubins_car_circle_discrete.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/plotting.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/plotting_viser.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/realtime/3DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/realtime/6DoF_pdg_realtime.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/rocket/6DoF_pdg.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/spacecraft/hohmann_transfer.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/spacecraft/let_transfer.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/figures/video_preview.png +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/material/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/material/overrides/assets/stylesheets/home-hero.css +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/material/overrides/assets/stylesheets/home-viser.css +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/material/overrides/home.html +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/material/overrides/main.html +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/material/overrides/partials/home-diagram.html +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/material/overrides/partials/home-dropin-banner.html +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/material/overrides/partials/home-hero.html +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/material/overrides/partials/home-pipeline.html +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/material/overrides/partials/home-viser-strip.html +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/mkdocs.yml +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/__main__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/algorithms/autotuner/augmented_lagrangian.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/algorithms/autotuner/constant_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/algorithms/autotuner/ramp_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/algorithms/base.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/algorithms/scvx/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/algorithms/scvx/penalized_trust_region.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/algorithms/weights.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/config.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/discretization/base.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/discretization/discretize_linearize.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/discretization/linearize_discretize.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/discretization/sparse_utils/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/expert/byof.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/expert/validation.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/init/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/init/interpolation.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/init/inverse_kinematics.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/integrations/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/integrations/base.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/integrations/menagerie.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/integrations/mjx.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/integrators/diffrax.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/loader.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/plotting/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/plotting/plotting.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/plotting/viser/orbits.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/problem.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/solvers/base.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/solvers/cvxpy_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/solvers/moreau_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/solvers/ptr_solver.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/solvers/qpax_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/augmentation.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/builder.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/parameter.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/stljax.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/time.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lower.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/array.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/control.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/math.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/state.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/parser/_registry.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/parser/array.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/parser/constraint.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/parser/lie.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/parser/linalg.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/parser/logic.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/parser/math.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/parser/parser.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/parser/spatial.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/parser/stl.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/parser/stljax.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/parser/tokenizer.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/sparsity.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/utils/cache.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/utils/caching.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/utils/printing.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx/utils/utils.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx.egg-info/entry_points.txt +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx.egg-info/requires.txt +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/pyproject.toml +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/scripts/gen_example_pages.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/setup.cfg +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/_marks.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/algorithms/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/algorithms/autotuner/test_update_weights_jit.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/algorithms/test_algorithm_state_pytree.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/conftest.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/expr/test_gmsr.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/fixtures/brachistochrone.json +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/fixtures/brachistochrone.yaml +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/hohmann_analytical.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/integrations/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/integrations/test_mjx.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/integrations/test_mjx_dynamics.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/solvers/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/solvers/_iteration_callback_helpers.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/solvers/test_cvxpy_callback_jit_spike.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/solvers/test_iteration_callback_cvxpy.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/solvers/test_iteration_callback_moreau.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/solvers/test_iteration_callback_qpax.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/solvers/test_iteration_callback_vmap.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/solvers/test_moreau_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/solvers/test_qpax_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/solvers/test_subproblem_pytree.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/test_stl.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/parser/test_array.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/parser/test_constraint.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/parser/test_lie.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/parser/test_linalg.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/parser/test_load.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/parser/test_logic.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/parser/test_math.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/parser/test_parser.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/parser/test_spatial.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/parser/test_stl.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/parser/test_tokenizer.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/parser/test_vmap.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/test_augmentation.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/test_sparsity.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/test_autotuning.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/test_discretization.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/test_examples.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/test_expert.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/test_impulsive.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/test_init.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/test_integrators.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/test_loader.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/test_optimization_results.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/test_plotting.py +0 -0
- {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev14}/tests/test_propagation.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.dev14
|
|
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
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import os
|
|
11
11
|
import sys
|
|
12
|
+
from pathlib import Path
|
|
12
13
|
|
|
13
14
|
import jax
|
|
14
15
|
import jax.numpy as jnp
|
|
@@ -21,21 +22,51 @@ sys.path.append(grandparent_dir)
|
|
|
21
22
|
|
|
22
23
|
import openscvx as ox
|
|
23
24
|
from openscvx import Problem
|
|
24
|
-
from openscvx.algorithms import OptimizationResults
|
|
25
25
|
from openscvx.integrators import solve_ivp_diffrax
|
|
26
|
-
from openscvx.plotting import plot_projections_2d
|
|
27
26
|
from openscvx.symbolic.lower import lower_to_jax
|
|
28
27
|
|
|
29
28
|
# Use float64 in JAX for high-accuracy propagation.
|
|
30
29
|
jax.config.update("jax_enable_x64", True)
|
|
31
30
|
|
|
31
|
+
kernel_dir = Path(current_dir) / "ker"
|
|
32
|
+
kernel_filenames = ("gm_de440.tpc",)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _load_spice_mu_from_local_kernels(kernel_dir: Path) -> tuple[float, float]:
|
|
36
|
+
"""Load Earth/Moon GM constants from local SPICE kernels."""
|
|
37
|
+
try:
|
|
38
|
+
import spiceypy as spice
|
|
39
|
+
except ImportError as exc:
|
|
40
|
+
raise ImportError(
|
|
41
|
+
"spiceypy is required for examples/spacecraft/halo_orbit.py. "
|
|
42
|
+
"Install it with: pip install spiceypy"
|
|
43
|
+
) from exc
|
|
44
|
+
|
|
45
|
+
missing = [name for name in kernel_filenames if not (kernel_dir / name).is_file()]
|
|
46
|
+
if missing:
|
|
47
|
+
missing_str = ", ".join(missing)
|
|
48
|
+
raise FileNotFoundError(
|
|
49
|
+
f"Missing required SPICE kernel files in '{kernel_dir}': {missing_str}"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
spice.kclear()
|
|
53
|
+
try:
|
|
54
|
+
for kernel_name in kernel_filenames:
|
|
55
|
+
spice.furnsh(str(kernel_dir / kernel_name))
|
|
56
|
+
|
|
57
|
+
mu_earth_val = float(spice.bodvrd("EARTH", "GM", 1)[1][0])
|
|
58
|
+
mu_moon_val = float(spice.bodvrd("MOON", "GM", 1)[1][0])
|
|
59
|
+
return mu_earth_val, mu_moon_val
|
|
60
|
+
finally:
|
|
61
|
+
spice.kclear()
|
|
62
|
+
|
|
63
|
+
|
|
32
64
|
r0 = np.array([0.98736, 0.0, 0.00877])
|
|
33
65
|
v0 = np.array([0.0, 1.63446, 0.0])
|
|
34
66
|
x0_seed = np.concatenate([r0, v0])
|
|
35
67
|
|
|
36
68
|
# Earth-Moon mass ratio used in normalized CR3BP
|
|
37
|
-
mu_earth =
|
|
38
|
-
mu_moon = 4902.800066163796
|
|
69
|
+
mu_earth, mu_moon = _load_spice_mu_from_local_kernels(kernel_dir)
|
|
39
70
|
mu = mu_moon / (mu_earth + mu_moon)
|
|
40
71
|
t_f = 1.522
|
|
41
72
|
t_opt = 6.0 * t_f # 6 revolutions
|
|
@@ -71,7 +102,7 @@ dynamics = {
|
|
|
71
102
|
}
|
|
72
103
|
cr3bp_rhs = lower_to_jax(ox.Concat(velocity, velocity_dot))
|
|
73
104
|
|
|
74
|
-
# Dense high-accuracy propagation used only to build a reliable guess
|
|
105
|
+
# Dense high-accuracy propagation used only to build a reliable guess.
|
|
75
106
|
guess_dense = np.asarray(
|
|
76
107
|
solve_ivp_diffrax(
|
|
77
108
|
lambda t, x: cr3bp_rhs(x, jnp.zeros((0,), dtype=x.dtype), 0, {}),
|
|
@@ -90,14 +121,12 @@ guess_dense = np.asarray(
|
|
|
90
121
|
# Keep optimization decision vector at two nodes only: initial and final.
|
|
91
122
|
nominal_guess = np.vstack([guess_dense[0], guess_dense[-1]])
|
|
92
123
|
|
|
93
|
-
# Broad bounds (required by OpenSCvx for all variables)
|
|
94
124
|
position.min = np.array([-2.0, -2.0, -2.0])
|
|
95
125
|
position.max = np.array([2.0, 2.0, 2.0])
|
|
96
126
|
velocity.min = np.array([-3.0, -3.0, -3.0])
|
|
97
127
|
velocity.max = np.array([3.0, 3.0, 3.0])
|
|
98
128
|
|
|
99
129
|
# Initial/final conditions:
|
|
100
|
-
# y0 = vx0 = vz0 = 0 (fixed), x0/z0/vy0 free around the seed values.
|
|
101
130
|
position.initial = [ox.Free(float(x0_seed[0])), 0.0, ox.Free(float(x0_seed[2]))]
|
|
102
131
|
velocity.initial = [0.0, ox.Free(float(x0_seed[4])), 0.0]
|
|
103
132
|
|
|
@@ -151,60 +180,51 @@ problem.settings.prp.solver = "Dopri8"
|
|
|
151
180
|
problem.settings.prp.atol = integration_tol
|
|
152
181
|
problem.settings.prp.rtol = integration_tol
|
|
153
182
|
|
|
154
|
-
|
|
183
|
+
|
|
184
|
+
def _solve_halo_orbit() -> np.ndarray:
|
|
185
|
+
"""Solve halo initialization problem and return x0_t."""
|
|
155
186
|
problem.initialize()
|
|
156
187
|
results = problem.solve()
|
|
157
188
|
results = problem.post_process()
|
|
158
189
|
|
|
159
|
-
pos = results.trajectory["position"]
|
|
160
|
-
vel = results.trajectory["velocity"]
|
|
190
|
+
pos = np.asarray(results.trajectory["position"], dtype=float)
|
|
191
|
+
vel = np.asarray(results.trajectory["velocity"], dtype=float)
|
|
161
192
|
x0_opt = np.concatenate([pos[0], vel[0]])
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
"position": traj_plot[:, :3],
|
|
201
|
-
"velocity": traj_plot[:, 3:6],
|
|
202
|
-
}
|
|
203
|
-
solution_results.nodes = {
|
|
204
|
-
"time": results.nodes["time"],
|
|
205
|
-
"position": results.nodes["position"],
|
|
206
|
-
"velocity": results.nodes["velocity"],
|
|
207
|
-
}
|
|
208
|
-
fig_solution = plot_projections_2d(solution_results, velocity_var_name="velocity")
|
|
209
|
-
fig_solution.update_layout(title="Solution - XY, XZ, YZ Projections")
|
|
210
|
-
fig_solution.show()
|
|
193
|
+
return x0_opt
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def get_halo_initial_condition(
|
|
197
|
+
*,
|
|
198
|
+
force_recompute: bool = False,
|
|
199
|
+
verbose: bool = False,
|
|
200
|
+
) -> np.ndarray:
|
|
201
|
+
"""Return halo initial condition x0_t as a simple API."""
|
|
202
|
+
# `force_recompute` is kept for API stability with older callers.
|
|
203
|
+
_ = force_recompute
|
|
204
|
+
x0_t = _solve_halo_orbit()
|
|
205
|
+
if verbose:
|
|
206
|
+
print("Computed halo target initial state.")
|
|
207
|
+
return x0_t
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def get_halo_target_initial_state(
|
|
211
|
+
*,
|
|
212
|
+
force_recompute: bool = False,
|
|
213
|
+
use_cache: bool = True,
|
|
214
|
+
cache_file: Path | None = None,
|
|
215
|
+
verbose: bool = False,
|
|
216
|
+
return_metadata: bool = False,
|
|
217
|
+
) -> np.ndarray | tuple[np.ndarray, dict[str, str]]:
|
|
218
|
+
"""Backward-compatible wrapper; cache options are ignored."""
|
|
219
|
+
_ = use_cache
|
|
220
|
+
_ = cache_file
|
|
221
|
+
x0_t = get_halo_initial_condition(force_recompute=force_recompute, verbose=verbose)
|
|
222
|
+
if return_metadata:
|
|
223
|
+
return x0_t, {"source": "solve", "cache_file": "none"}
|
|
224
|
+
return x0_t
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
if __name__ == "__main__":
|
|
228
|
+
x0_t = get_halo_initial_condition(verbose=True)
|
|
229
|
+
np.set_printoptions(precision=8, suppress=True)
|
|
230
|
+
print(x0_t)
|
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
"""Relative loitering in Earth-Moon CR3BP with CTCS box-violation regularization.
|
|
2
|
+
|
|
3
|
+
- Relative dynamics around a target halo-like trajectory in CR3BP rotating frame
|
|
4
|
+
- Three impulsive burns at nodes [0, 1, 2]
|
|
5
|
+
- Free final time with maximization objective
|
|
6
|
+
- Nodal keep-in-zone (KIZ) box constraints plus CTCS smooth-ReLU penalties
|
|
7
|
+
- Strict local SPICE loading from `examples/spacecraft/ker`
|
|
8
|
+
- Target initial condition x0_t loaded from `ker/halo_orbit_x0_t.npz`;
|
|
9
|
+
if missing/invalid, computed once via `halo_orbit.py` and saved there
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
import shutil
|
|
14
|
+
import sys
|
|
15
|
+
import urllib.request
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
import jax
|
|
19
|
+
import jax.numpy as jnp
|
|
20
|
+
import numpy as np
|
|
21
|
+
|
|
22
|
+
# Add grandparent directory to path to import openscvx without installation.
|
|
23
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
24
|
+
grandparent_dir = os.path.dirname(os.path.dirname(current_dir))
|
|
25
|
+
sys.path.append(grandparent_dir)
|
|
26
|
+
|
|
27
|
+
import openscvx as ox
|
|
28
|
+
from openscvx import Problem
|
|
29
|
+
from openscvx.integrators import solve_ivp_diffrax
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
from openscvx.plotting import plot_projections_2d, plot_states
|
|
33
|
+
except Exception:
|
|
34
|
+
plot_projections_2d = None
|
|
35
|
+
plot_states = None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _enable_jax_x64() -> None:
|
|
39
|
+
"""Enable float64 in JAX for high-accuracy propagation."""
|
|
40
|
+
jax.config.update("jax_enable_x64", True)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
reference_date = "2024-08-28T00:00:00"
|
|
44
|
+
kernel_dir = Path(current_dir) / "ker"
|
|
45
|
+
kernel_urls = {
|
|
46
|
+
"naif0012.tls": "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/lsk/naif0012.tls",
|
|
47
|
+
"de440.bsp": "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/de440.bsp",
|
|
48
|
+
"pck00011.tpc": "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/pck/pck00011.tpc",
|
|
49
|
+
"gm_de440.tpc": "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/pck/gm_de440.tpc",
|
|
50
|
+
}
|
|
51
|
+
kernel_filenames = tuple(kernel_urls.keys())
|
|
52
|
+
halo_x0_file = kernel_dir / "halo_orbit_x0_t.npz"
|
|
53
|
+
|
|
54
|
+
# Problem constants (normalized CR3BP units)
|
|
55
|
+
n_nodes = 4
|
|
56
|
+
impulse_nodes = [0, 1, 2]
|
|
57
|
+
tf_guess = 1.522
|
|
58
|
+
time_max_factor = 6.0
|
|
59
|
+
time_max = time_max_factor * tf_guess
|
|
60
|
+
max_deltav = 2.5e-4
|
|
61
|
+
r_ref_km = 384400.0
|
|
62
|
+
kiz_box_width_km = 15.0
|
|
63
|
+
kiz_box_width_dyn = kiz_box_width_km / r_ref_km
|
|
64
|
+
|
|
65
|
+
integration_tol = 1e-14
|
|
66
|
+
target_num_substeps = 4000
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _download_kernel(url: str, destination: Path) -> None:
|
|
70
|
+
"""Download a single SPICE kernel to destination atomically."""
|
|
71
|
+
temp_destination = destination.with_suffix(destination.suffix + ".part")
|
|
72
|
+
with (
|
|
73
|
+
urllib.request.urlopen(url, timeout=120) as response,
|
|
74
|
+
temp_destination.open("wb") as out_file,
|
|
75
|
+
):
|
|
76
|
+
shutil.copyfileobj(response, out_file)
|
|
77
|
+
temp_destination.replace(destination)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _ensure_spice_kernels(kernel_dir: Path) -> None:
|
|
81
|
+
"""Ensure all required kernels exist in kernel_dir, downloading missing files."""
|
|
82
|
+
kernel_dir.mkdir(parents=True, exist_ok=True)
|
|
83
|
+
missing = [name for name in kernel_filenames if not (kernel_dir / name).is_file()]
|
|
84
|
+
if not missing:
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
download_errors = []
|
|
88
|
+
for kernel_name in missing:
|
|
89
|
+
destination = kernel_dir / kernel_name
|
|
90
|
+
try:
|
|
91
|
+
_download_kernel(kernel_urls[kernel_name], destination)
|
|
92
|
+
except Exception as exc:
|
|
93
|
+
part_file = destination.with_suffix(destination.suffix + ".part")
|
|
94
|
+
if part_file.exists():
|
|
95
|
+
part_file.unlink()
|
|
96
|
+
download_errors.append(f"{kernel_name}: {exc}")
|
|
97
|
+
|
|
98
|
+
if download_errors:
|
|
99
|
+
raise RuntimeError("Failed to download SPICE kernels: " + "; ".join(download_errors))
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _load_spice_mu_from_local_kernels(kernel_dir: Path) -> tuple[float, float]:
|
|
103
|
+
"""Load Earth/Moon GM constants from local SPICE kernels only."""
|
|
104
|
+
try:
|
|
105
|
+
import spiceypy as spice
|
|
106
|
+
except ImportError as exc:
|
|
107
|
+
raise ImportError(
|
|
108
|
+
"spiceypy is required for examples/spacecraft/relative_loitering.py. "
|
|
109
|
+
"Install it with: pip install spiceypy"
|
|
110
|
+
) from exc
|
|
111
|
+
|
|
112
|
+
_ensure_spice_kernels(kernel_dir)
|
|
113
|
+
|
|
114
|
+
spice.kclear()
|
|
115
|
+
try:
|
|
116
|
+
for kernel_name in kernel_filenames:
|
|
117
|
+
spice.furnsh(str(kernel_dir / kernel_name))
|
|
118
|
+
|
|
119
|
+
mu_earth_val = float(spice.bodvrd("EARTH", "GM", 1)[1][0])
|
|
120
|
+
mu_moon_val = float(spice.bodvrd("MOON", "GM", 1)[1][0])
|
|
121
|
+
return mu_earth_val, mu_moon_val
|
|
122
|
+
finally:
|
|
123
|
+
spice.kclear()
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _cr3bp_rhs_numeric(x: jnp.ndarray, mu: float) -> jnp.ndarray:
|
|
127
|
+
"""Absolute CR3BP dynamics in rotating frame for numeric integration."""
|
|
128
|
+
x_e, y_e, z_e, vx_e, vy_e, vz_e = x
|
|
129
|
+
|
|
130
|
+
r1x = x_e + mu
|
|
131
|
+
r2x = x_e - (1.0 - mu)
|
|
132
|
+
d1 = jnp.sqrt(r1x**2 + y_e**2 + z_e**2)
|
|
133
|
+
d2 = jnp.sqrt(r2x**2 + y_e**2 + z_e**2)
|
|
134
|
+
|
|
135
|
+
ax = 2.0 * vy_e + x_e - (1.0 - mu) * r1x / d1**3 - mu * r2x / d2**3
|
|
136
|
+
ay = -2.0 * vx_e + y_e - (1.0 - mu) * y_e / d1**3 - mu * y_e / d2**3
|
|
137
|
+
az = -(1.0 - mu) * z_e / d1**3 - mu * z_e / d2**3
|
|
138
|
+
|
|
139
|
+
return jnp.array([vx_e, vy_e, vz_e, ax, ay, az], dtype=x.dtype)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _cr3bp_accel_expr(x_e, y_e, z_e, vx_e, vy_e, vz_e, mu: float):
|
|
143
|
+
"""Absolute CR3BP acceleration as symbolic expressions."""
|
|
144
|
+
r1x = x_e + mu
|
|
145
|
+
r2x = x_e - (1.0 - mu)
|
|
146
|
+
d1 = ox.Sqrt(r1x**2 + y_e**2 + z_e**2)
|
|
147
|
+
d2 = ox.Sqrt(r2x**2 + y_e**2 + z_e**2)
|
|
148
|
+
|
|
149
|
+
ax = 2.0 * vy_e + x_e - (1.0 - mu) * r1x / d1**3 - mu * r2x / d2**3
|
|
150
|
+
ay = -2.0 * vx_e + y_e - (1.0 - mu) * y_e / d1**3 - mu * y_e / d2**3
|
|
151
|
+
az = -(1.0 - mu) * z_e / d1**3 - mu * z_e / d2**3
|
|
152
|
+
return ax, ay, az
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _build_target_reference(
|
|
156
|
+
mu: float, x0_t: np.ndarray, t_horizon: float
|
|
157
|
+
) -> tuple[np.ndarray, np.ndarray]:
|
|
158
|
+
"""Integrate target absolute trajectory over [0, t_horizon]."""
|
|
159
|
+
traj = np.asarray(
|
|
160
|
+
solve_ivp_diffrax(
|
|
161
|
+
lambda t, x: _cr3bp_rhs_numeric(x, mu),
|
|
162
|
+
tau_final=t_horizon,
|
|
163
|
+
y_0=jnp.asarray(x0_t, dtype=jnp.float64),
|
|
164
|
+
args=(),
|
|
165
|
+
tau_0=0.0,
|
|
166
|
+
num_substeps=target_num_substeps,
|
|
167
|
+
solver_name="Dopri8",
|
|
168
|
+
rtol=integration_tol,
|
|
169
|
+
atol=integration_tol,
|
|
170
|
+
),
|
|
171
|
+
dtype=float,
|
|
172
|
+
)
|
|
173
|
+
t_grid = np.linspace(0.0, t_horizon, traj.shape[0], dtype=float)
|
|
174
|
+
return t_grid, traj
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def _load_halo_x0_from_file(file_path: Path) -> np.ndarray:
|
|
178
|
+
"""Load halo initial condition from local NPZ file and validate shape."""
|
|
179
|
+
with np.load(file_path, allow_pickle=False) as data:
|
|
180
|
+
if "x0_t" not in data.files:
|
|
181
|
+
raise KeyError(f"Missing 'x0_t' in {file_path}. Found keys: {data.files}")
|
|
182
|
+
x0_t = np.asarray(data["x0_t"], dtype=np.float64).reshape(-1)
|
|
183
|
+
if x0_t.shape != (6,):
|
|
184
|
+
raise ValueError(f"Invalid x0_t shape in {file_path}: expected (6,), got {x0_t.shape}")
|
|
185
|
+
return x0_t
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def _get_target_x0_t(
|
|
189
|
+
*,
|
|
190
|
+
force_recompute_halo: bool,
|
|
191
|
+
verbose: bool,
|
|
192
|
+
) -> tuple[np.ndarray, str]:
|
|
193
|
+
"""Load target x0_t from ker file when available, otherwise compute and cache it."""
|
|
194
|
+
if not force_recompute_halo and halo_x0_file.is_file():
|
|
195
|
+
try:
|
|
196
|
+
x0_t = _load_halo_x0_from_file(halo_x0_file)
|
|
197
|
+
if verbose:
|
|
198
|
+
print(f"Loaded target x0_t from file: {halo_x0_file}")
|
|
199
|
+
return x0_t, f"file:{halo_x0_file}"
|
|
200
|
+
except Exception as exc:
|
|
201
|
+
if verbose:
|
|
202
|
+
print(f"Failed to read {halo_x0_file} ({exc}). Recomputing x0_t.")
|
|
203
|
+
|
|
204
|
+
from examples.spacecraft.halo_orbit import get_halo_initial_condition
|
|
205
|
+
|
|
206
|
+
x0_t = get_halo_initial_condition(force_recompute=force_recompute_halo, verbose=verbose)
|
|
207
|
+
halo_x0_file.parent.mkdir(parents=True, exist_ok=True)
|
|
208
|
+
np.savez(halo_x0_file, x0_t=np.asarray(x0_t, dtype=np.float64))
|
|
209
|
+
if verbose:
|
|
210
|
+
print(f"Saved target x0_t to file: {halo_x0_file}")
|
|
211
|
+
return np.asarray(x0_t, dtype=np.float64), f"solve+save:{halo_x0_file}"
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def build_relative_loitering_problem(
|
|
215
|
+
*,
|
|
216
|
+
force_recompute_halo: bool = False,
|
|
217
|
+
verbose: bool = True,
|
|
218
|
+
) -> tuple[Problem, dict]:
|
|
219
|
+
"""Create the relative-loitering OpenSCvx problem and context dictionary."""
|
|
220
|
+
mu_earth, mu_moon = _load_spice_mu_from_local_kernels(kernel_dir)
|
|
221
|
+
mu = mu_moon / (mu_earth + mu_moon)
|
|
222
|
+
|
|
223
|
+
x0_t, x0_t_source = _get_target_x0_t(
|
|
224
|
+
force_recompute_halo=force_recompute_halo,
|
|
225
|
+
verbose=verbose,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
target_time_grid, target_traj = _build_target_reference(mu=mu, x0_t=x0_t, t_horizon=time_max)
|
|
229
|
+
|
|
230
|
+
position = ox.State("position", shape=(3,))
|
|
231
|
+
velocity = ox.State("velocity", shape=(3,))
|
|
232
|
+
|
|
233
|
+
position._slice = slice(0, 3)
|
|
234
|
+
velocity._slice = slice(3, 6)
|
|
235
|
+
|
|
236
|
+
position.min = np.array([-2.0, -2.0, -2.0])
|
|
237
|
+
position.max = np.array([2.0, 2.0, 2.0])
|
|
238
|
+
velocity.min = np.array([-4.0, -4.0, -4.0])
|
|
239
|
+
velocity.max = np.array([4.0, 4.0, 4.0])
|
|
240
|
+
|
|
241
|
+
position.initial = np.array([1e-6, 0.0, 0.0])
|
|
242
|
+
velocity.initial = np.array([0.0, 0.0, 0.0])
|
|
243
|
+
|
|
244
|
+
position.final = [ox.Free(0.0), ox.Free(0.0), ox.Free(0.0)]
|
|
245
|
+
velocity.final = [ox.Free(0.0), ox.Free(0.0), ox.Free(0.0)]
|
|
246
|
+
|
|
247
|
+
position.guess = np.linspace(position.initial, np.zeros(3), n_nodes)
|
|
248
|
+
velocity.guess = np.zeros((n_nodes, 3))
|
|
249
|
+
|
|
250
|
+
delta_v = ox.Control(
|
|
251
|
+
"delta_v",
|
|
252
|
+
shape=(3,),
|
|
253
|
+
parameterization="impulsive",
|
|
254
|
+
nodes=impulse_nodes,
|
|
255
|
+
)
|
|
256
|
+
delta_v.min = -max_deltav * np.ones(3)
|
|
257
|
+
delta_v.max = max_deltav * np.ones(3)
|
|
258
|
+
delta_v.guess = np.zeros((n_nodes, 3))
|
|
259
|
+
|
|
260
|
+
time_guess = np.linspace(0.0, tf_guess, n_nodes).reshape(-1, 1)
|
|
261
|
+
time = ox.Time(
|
|
262
|
+
initial=0.0,
|
|
263
|
+
final=ox.Maximize(float(tf_guess)),
|
|
264
|
+
min=0.0,
|
|
265
|
+
max=time_max,
|
|
266
|
+
guess=time_guess,
|
|
267
|
+
time_dilation_min=0.1,
|
|
268
|
+
time_dilation_max=time_max,
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
t_expr = time[0]
|
|
272
|
+
x_t = ox.Cinterp(t_expr, target_time_grid, target_traj[:, 0])
|
|
273
|
+
y_t = ox.Cinterp(t_expr, target_time_grid, target_traj[:, 1])
|
|
274
|
+
z_t = ox.Cinterp(t_expr, target_time_grid, target_traj[:, 2])
|
|
275
|
+
vx_t = ox.Cinterp(t_expr, target_time_grid, target_traj[:, 3])
|
|
276
|
+
vy_t = ox.Cinterp(t_expr, target_time_grid, target_traj[:, 4])
|
|
277
|
+
vz_t = ox.Cinterp(t_expr, target_time_grid, target_traj[:, 5])
|
|
278
|
+
|
|
279
|
+
x_c = position[0] + x_t
|
|
280
|
+
y_c = position[1] + y_t
|
|
281
|
+
z_c = position[2] + z_t
|
|
282
|
+
vx_c = velocity[0] + vx_t
|
|
283
|
+
vy_c = velocity[1] + vy_t
|
|
284
|
+
vz_c = velocity[2] + vz_t
|
|
285
|
+
|
|
286
|
+
ax_c, ay_c, az_c = _cr3bp_accel_expr(x_c, y_c, z_c, vx_c, vy_c, vz_c, mu)
|
|
287
|
+
ax_t, ay_t, az_t = _cr3bp_accel_expr(x_t, y_t, z_t, vx_t, vy_t, vz_t, mu)
|
|
288
|
+
|
|
289
|
+
dynamics = {
|
|
290
|
+
"position": velocity,
|
|
291
|
+
"velocity": ox.Concat(ax_c - ax_t, ay_c - ay_t, az_c - az_t),
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
dynamics_discrete = {
|
|
295
|
+
"position": position,
|
|
296
|
+
"velocity": velocity + delta_v,
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
constraints = []
|
|
300
|
+
all_nodes = list(range(n_nodes))
|
|
301
|
+
|
|
302
|
+
constraints.append((position <= kiz_box_width_dyn).convex().at(all_nodes))
|
|
303
|
+
constraints.append((position >= -kiz_box_width_dyn).convex().at(all_nodes))
|
|
304
|
+
|
|
305
|
+
for node in impulse_nodes:
|
|
306
|
+
constraints.append((ox.linalg.Norm(delta_v) <= max_deltav).convex().at([node]))
|
|
307
|
+
|
|
308
|
+
ctcs_intervals = [(0, 1), (1, 2), (2, 3)]
|
|
309
|
+
for idx, interval in enumerate(ctcs_intervals):
|
|
310
|
+
for axis in range(3):
|
|
311
|
+
constraints.append(
|
|
312
|
+
(position[axis] - kiz_box_width_dyn <= 0.0).over(
|
|
313
|
+
interval,
|
|
314
|
+
penalty="smooth_relu",
|
|
315
|
+
idx=idx,
|
|
316
|
+
)
|
|
317
|
+
)
|
|
318
|
+
constraints.append(
|
|
319
|
+
(-position[axis] - kiz_box_width_dyn <= 0.0).over(
|
|
320
|
+
interval,
|
|
321
|
+
penalty="smooth_relu",
|
|
322
|
+
idx=idx,
|
|
323
|
+
)
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
problem = Problem(
|
|
327
|
+
dynamics=dynamics,
|
|
328
|
+
dynamics_discrete=dynamics_discrete,
|
|
329
|
+
states=[position, velocity],
|
|
330
|
+
controls=[delta_v],
|
|
331
|
+
time=time,
|
|
332
|
+
constraints=constraints,
|
|
333
|
+
N=n_nodes,
|
|
334
|
+
licq_min=0.0,
|
|
335
|
+
licq_max=1e-8,
|
|
336
|
+
discretizer={
|
|
337
|
+
"ode_solver": "Dopri8",
|
|
338
|
+
"diffrax_kwargs": {"atol": integration_tol, "rtol": integration_tol},
|
|
339
|
+
},
|
|
340
|
+
algorithm={
|
|
341
|
+
"k_max": 150,
|
|
342
|
+
"lam_prox": 4e-1,
|
|
343
|
+
"lam_vc": 1e2,
|
|
344
|
+
"lam_cost": 1e0,
|
|
345
|
+
"ep_vc": 1e-8,
|
|
346
|
+
"ep_tr": 1e-8,
|
|
347
|
+
"autotuner": ox.AugmentedLagrangian(),
|
|
348
|
+
},
|
|
349
|
+
solver={"cvx_solver": "CLARABEL", "solver_args": {}},
|
|
350
|
+
float_dtype="float64",
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
problem.settings.prp.solver = "Dopri8"
|
|
354
|
+
problem.settings.prp.atol = integration_tol
|
|
355
|
+
problem.settings.prp.rtol = integration_tol
|
|
356
|
+
|
|
357
|
+
context = {
|
|
358
|
+
"mu_earth": float(mu_earth),
|
|
359
|
+
"mu_moon": float(mu_moon),
|
|
360
|
+
"mu": float(mu),
|
|
361
|
+
"x0_t": np.asarray(x0_t, dtype=float),
|
|
362
|
+
"x0_t_source": x0_t_source,
|
|
363
|
+
"target_time_grid": target_time_grid,
|
|
364
|
+
"target_traj": target_traj,
|
|
365
|
+
}
|
|
366
|
+
return problem, context
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def _print_solution_summary(results, context: dict) -> None:
|
|
370
|
+
"""Print compact mission and constraint diagnostics."""
|
|
371
|
+
t_final = float(np.asarray(results.nodes["time"][-1]).squeeze())
|
|
372
|
+
delta_v_nodes = np.asarray(results.nodes["delta_v"], dtype=float)
|
|
373
|
+
|
|
374
|
+
impulse_norms = np.linalg.norm(delta_v_nodes[impulse_nodes], axis=1)
|
|
375
|
+
total_impulse = float(np.sum(impulse_norms))
|
|
376
|
+
|
|
377
|
+
pos_nodes = np.asarray(results.nodes["position"], dtype=float)
|
|
378
|
+
max_abs_pos = np.max(np.abs(pos_nodes), axis=0)
|
|
379
|
+
|
|
380
|
+
print(f"Reference date: {reference_date}")
|
|
381
|
+
print(f"SPICE kernels: {kernel_dir}")
|
|
382
|
+
print(f"Target x0_t source: {context['x0_t_source']}")
|
|
383
|
+
print(f"Converged: {bool(results.converged)}")
|
|
384
|
+
print(f"Final time: {t_final:.9f}")
|
|
385
|
+
|
|
386
|
+
for local_idx, node in enumerate(impulse_nodes):
|
|
387
|
+
print(f"||delta_v|| at node {node}: {impulse_norms[local_idx]:.9e}")
|
|
388
|
+
print(f"Total ||delta_v|| over impulse nodes: {total_impulse:.9e}")
|
|
389
|
+
|
|
390
|
+
print(
|
|
391
|
+
"Max |position| at nodes: "
|
|
392
|
+
f"x={max_abs_pos[0]:.9e}, y={max_abs_pos[1]:.9e}, z={max_abs_pos[2]:.9e} "
|
|
393
|
+
f"(KIZ bound={kiz_box_width_dyn:.9e})"
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
for idx in range(3):
|
|
397
|
+
ctcs_name = f"_ctcs_aug_{idx}"
|
|
398
|
+
if ctcs_name in results.nodes:
|
|
399
|
+
ctcs_vals = np.asarray(results.nodes[ctcs_name], dtype=float).flatten()
|
|
400
|
+
print(f"{ctcs_name} max: {np.max(ctcs_vals):.9e}")
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
def _apply_kiz_limits_to_state_plot(fig, kiz_half_width: float) -> None:
|
|
404
|
+
"""Clamp position subplots to KIZ scale and draw explicit KIZ bounds."""
|
|
405
|
+
y_lim = 1.1 * kiz_half_width
|
|
406
|
+
for col in (1, 2, 3):
|
|
407
|
+
fig.update_yaxes(range=[-y_lim, y_lim], row=1, col=col)
|
|
408
|
+
fig.add_hrect(
|
|
409
|
+
y0=-kiz_half_width,
|
|
410
|
+
y1=kiz_half_width,
|
|
411
|
+
fillcolor="rgba(76, 175, 80, 0.12)",
|
|
412
|
+
line_width=0,
|
|
413
|
+
layer="below",
|
|
414
|
+
row=1,
|
|
415
|
+
col=col,
|
|
416
|
+
)
|
|
417
|
+
fig.add_hline(
|
|
418
|
+
y=kiz_half_width,
|
|
419
|
+
line_dash="dash",
|
|
420
|
+
line_color="rgba(200, 0, 0, 0.9)",
|
|
421
|
+
line_width=2,
|
|
422
|
+
row=1,
|
|
423
|
+
col=col,
|
|
424
|
+
)
|
|
425
|
+
fig.add_hline(
|
|
426
|
+
y=-kiz_half_width,
|
|
427
|
+
line_dash="dash",
|
|
428
|
+
line_color="rgba(200, 0, 0, 0.9)",
|
|
429
|
+
line_width=2,
|
|
430
|
+
row=1,
|
|
431
|
+
col=col,
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
if __name__ == "__main__":
|
|
436
|
+
_enable_jax_x64()
|
|
437
|
+
problem, context = build_relative_loitering_problem(force_recompute_halo=False, verbose=True)
|
|
438
|
+
|
|
439
|
+
problem.initialize()
|
|
440
|
+
results = problem.solve()
|
|
441
|
+
results = problem.post_process()
|
|
442
|
+
|
|
443
|
+
_print_solution_summary(results, context)
|
|
444
|
+
|
|
445
|
+
if (plot_projections_2d is None) or (plot_states is None):
|
|
446
|
+
print(
|
|
447
|
+
"Skipping plotting because plotting dependencies failed to import. "
|
|
448
|
+
"Check NumPy/Matplotlib compatibility in your environment."
|
|
449
|
+
)
|
|
450
|
+
else:
|
|
451
|
+
fig_proj = plot_projections_2d(results, velocity_var_name="velocity")
|
|
452
|
+
fig_proj.update_layout(title="Relative Loitering Solution - XY, XZ, YZ Projections")
|
|
453
|
+
fig_proj.show()
|
|
454
|
+
|
|
455
|
+
fig_states = plot_states(results, ["position", "velocity", "time"], cols=3)
|
|
456
|
+
_apply_kiz_limits_to_state_plot(fig_states, kiz_box_width_dyn)
|
|
457
|
+
fig_states.update_layout(title_text="Relative Loitering - State Evolution")
|
|
458
|
+
fig_states.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.dev14'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 5, 3, 'dev14')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g3d695e763'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.5.3.
|
|
3
|
+
Version: 0.5.3.dev14
|
|
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
|