openscvx 0.5.3.dev13__tar.gz → 0.5.3.dev15__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.
Files changed (376) hide show
  1. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/.gitignore +3 -3
  2. {openscvx-0.5.3.dev13/openscvx.egg-info → openscvx-0.5.3.dev15}/PKG-INFO +1 -1
  3. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/spacecraft/halo_orbit.py +79 -59
  4. openscvx-0.5.3.dev15/examples/spacecraft/relative_loitering.py +458 -0
  5. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/_version.py +3 -3
  6. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/algorithms/scvx/penalized_trust_region.py +1 -0
  7. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/integrators/diffrax.py +4 -1
  8. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/lowered/cvxpy_variables.py +9 -15
  9. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/solvers/base.py +11 -0
  10. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/solvers/cvxpy_ptr_solver.py +145 -56
  11. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lower.py +8 -16
  12. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15/openscvx.egg-info}/PKG-INFO +1 -1
  13. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx.egg-info/SOURCES.txt +1 -0
  14. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/solvers/test_iteration_callback_cvxpy.py +15 -3
  15. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/test_brachistochrone.py +2 -2
  16. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/.github/assets/logo.svg +0 -0
  17. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/.github/release-drafter.yml +0 -0
  18. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/.github/workflows/_docs.yml +0 -0
  19. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/.github/workflows/branch-name.yml +0 -0
  20. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/.github/workflows/docs.yml +0 -0
  21. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/.github/workflows/lint.yml +0 -0
  22. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/.github/workflows/nightly.yml +0 -0
  23. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/.github/workflows/release-drafter.yml +0 -0
  24. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/.github/workflows/release.yml +0 -0
  25. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/.github/workflows/tests-integration.yml +0 -0
  26. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/.github/workflows/tests-unit.yml +0 -0
  27. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/.gitmodules +0 -0
  28. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/CONTRIBUTING.md +0 -0
  29. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/LICENSE +0 -0
  30. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/README.md +0 -0
  31. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/Foundations/constraint_reformulation.md +0 -0
  32. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/Foundations/control_parameterization.md +0 -0
  33. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/Foundations/discretization.md +0 -0
  34. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/Foundations/ocp.md +0 -0
  35. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/Foundations/scvx.md +0 -0
  36. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/Foundations/time_dilation.md +0 -0
  37. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/UnderTheHood/lowering_architecture.md +0 -0
  38. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
  39. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/UsersGuide/00_introduction.md +0 -0
  40. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
  41. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
  42. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
  43. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
  44. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/UsersGuide/05_visualization.md +0 -0
  45. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/UsersGuide/06_logic.md +0 -0
  46. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/UsersGuide/07_lie.md +0 -0
  47. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/UsersGuide/08_mpcc.md +0 -0
  48. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/UsersGuide/09_mjx_dynamics.md +0 -0
  49. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/assets/favicon.png +0 -0
  50. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/assets/images/ct-scvx_dark.png +0 -0
  51. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/assets/images/ct-scvx_light.png +0 -0
  52. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/assets/images/ctcs_dark.png +0 -0
  53. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/assets/images/ctcs_light.png +0 -0
  54. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/assets/images/problem_class_dark.png +0 -0
  55. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/assets/images/problem_class_light.png +0 -0
  56. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/assets/logo.svg +0 -0
  57. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/assets/openscvx_logo_square.png +0 -0
  58. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/assets/viser-client/index.html +0 -0
  59. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/assets/viser-recordings/drone_racing.viser +0 -0
  60. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
  61. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/citation.md +0 -0
  62. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/examples.md +0 -0
  63. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/index.md +0 -0
  64. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/javascripts/mathjax.js +0 -0
  65. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/docs/versions.json +0 -0
  66. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/_viser_embed_export.py +0 -0
  67. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/abstract/brachistochrone.py +0 -0
  68. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/abstract/hypersensitive.py +0 -0
  69. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/abstract/impulsive.py +0 -0
  70. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/abstract/stl_integer_variable.py +0 -0
  71. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/abstract/stl_or.py +0 -0
  72. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/animations/7_dof_arm.py +0 -0
  73. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/animations/_camera.py +0 -0
  74. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/animations/_render.py +0 -0
  75. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/animations/_sensor_view.py +0 -0
  76. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/animations/dr_vp_polytope.py +0 -0
  77. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/animations/franka_fr3v2_pick_place.py +0 -0
  78. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/animations/logo.py +0 -0
  79. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/animations/obstacle_avoidance_vmap.py +0 -0
  80. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/arm/3_dof_arm.py +0 -0
  81. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/arm/7_dof_arm.py +0 -0
  82. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/arm/7_dof_arm_collision.py +0 -0
  83. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/arm/7_dof_arm_vp.py +0 -0
  84. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/arm/franka_fr3v2_pick_place.py +0 -0
  85. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/arm/franka_fr3v2_viewplanning.py +0 -0
  86. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/car/dubins_car.py +0 -0
  87. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/car/dubins_car_disjoint.py +0 -0
  88. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/car/dubins_car_obstacle_conditional.py +0 -0
  89. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/car/dubins_car_obstacle_stl.py +0 -0
  90. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/car/dubins_car_stl_or.py +0 -0
  91. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/car/dubins_car_waypoint_stl.py +0 -0
  92. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/drone/cinema_vp.py +0 -0
  93. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/drone/dr_double_integrator.py +0 -0
  94. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/drone/dr_vp.py +0 -0
  95. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/drone/dr_vp_nodal.py +0 -0
  96. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/drone/dr_vp_polytope.py +0 -0
  97. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/drone/drone_racing.py +0 -0
  98. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/drone/logo.py +0 -0
  99. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/drone/logo_utils/acl_logo.svg +0 -0
  100. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/drone/logo_utils/svg_path_utils.py +0 -0
  101. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/drone/obstacle_avoidance.py +0 -0
  102. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/drone/obstacle_avoidance_nodal.py +0 -0
  103. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/drone/obstacle_avoidance_vmap.py +0 -0
  104. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/mjx/cartpole_mjx.py +0 -0
  105. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/mjx/double_cartpole_mjx.py +0 -0
  106. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/mjx/skydio_x2_mjx.py +0 -0
  107. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/mjx/triple_cartpole_3d_mjx.py +0 -0
  108. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/mjx/triple_cartpole_game.py +0 -0
  109. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/mjx/triple_cartpole_mjx.py +0 -0
  110. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/mpc/double_integrator_discrete.py +0 -0
  111. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/mpc/double_integrator_drone_racing.py +0 -0
  112. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/mpc/dubins_car_circle_analytical.py +0 -0
  113. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/mpc/dubins_car_circle_discrete.py +0 -0
  114. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
  115. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/plotting.py +0 -0
  116. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/plotting_viser.py +0 -0
  117. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/realtime/3DoF_pdg_realtime.py +0 -0
  118. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/realtime/6DoF_pdg_realtime.py +0 -0
  119. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
  120. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
  121. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
  122. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
  123. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
  124. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
  125. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/realtime/cinema_vp_realtime.py +0 -0
  126. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/realtime/drone_racing_realtime.py +0 -0
  127. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/realtime/dubins_car_realtime.py +0 -0
  128. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
  129. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/rocket/3DoF_pdg.py +0 -0
  130. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/rocket/6DoF_pdg.py +0 -0
  131. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/spacecraft/hohmann_transfer.py +0 -0
  132. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/spacecraft/let_transfer.py +0 -0
  133. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/examples/spacecraft/proxops_cw.py +0 -0
  134. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/figures/ctlos_cine.gif +0 -0
  135. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/figures/ctlos_dr.gif +0 -0
  136. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/figures/dtlos_cine.gif +0 -0
  137. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/figures/dtlos_dr.gif +0 -0
  138. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/figures/openscvx_logo.svg +0 -0
  139. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/figures/openscvx_logo_square.png +0 -0
  140. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/figures/oscvx_structure_full_dark.svg +0 -0
  141. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/figures/video_preview.png +0 -0
  142. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/material/__init__.py +0 -0
  143. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/material/overrides/assets/stylesheets/custom.css +0 -0
  144. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
  145. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/material/overrides/assets/stylesheets/home-hero.css +0 -0
  146. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/material/overrides/assets/stylesheets/home-viser.css +0 -0
  147. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/material/overrides/home.html +0 -0
  148. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/material/overrides/main.html +0 -0
  149. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/material/overrides/partials/home-diagram.html +0 -0
  150. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/material/overrides/partials/home-dropin-banner.html +0 -0
  151. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/material/overrides/partials/home-hero.html +0 -0
  152. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/material/overrides/partials/home-pipeline.html +0 -0
  153. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/material/overrides/partials/home-viser-strip.html +0 -0
  154. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/mkdocs.yml +0 -0
  155. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/__init__.py +0 -0
  156. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/__main__.py +0 -0
  157. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/algorithms/__init__.py +0 -0
  158. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/algorithms/autotuner/__init__.py +0 -0
  159. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +0 -0
  160. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/algorithms/autotuner/augmented_lagrangian.py +0 -0
  161. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/algorithms/autotuner/constant_proximal_weight.py +0 -0
  162. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/algorithms/autotuner/ramp_proximal_weight.py +0 -0
  163. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/algorithms/base.py +0 -0
  164. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/algorithms/optimization_results.py +0 -0
  165. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/algorithms/scvx/__init__.py +0 -0
  166. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/algorithms/weights.py +0 -0
  167. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/config.py +0 -0
  168. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/discretization/__init__.py +0 -0
  169. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/discretization/base.py +0 -0
  170. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/discretization/discretize_linearize.py +0 -0
  171. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/discretization/linearize_discretize.py +0 -0
  172. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
  173. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/discretization/sparse_utils/__init__.py +0 -0
  174. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
  175. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
  176. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/expert/__init__.py +0 -0
  177. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/expert/byof.py +0 -0
  178. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/expert/lowering.py +0 -0
  179. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/expert/validation.py +0 -0
  180. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/init/__init__.py +0 -0
  181. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/init/interpolation.py +0 -0
  182. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/init/inverse_kinematics.py +0 -0
  183. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/integrations/__init__.py +0 -0
  184. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/integrations/base.py +0 -0
  185. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/integrations/menagerie.py +0 -0
  186. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/integrations/mjx.py +0 -0
  187. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/integrators/__init__.py +0 -0
  188. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/integrators/runge_kutta.py +0 -0
  189. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/loader.py +0 -0
  190. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/lowered/__init__.py +0 -0
  191. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/lowered/cvxpy_constraints.py +0 -0
  192. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/lowered/dynamics.py +0 -0
  193. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/lowered/jax_constraints.py +0 -0
  194. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/lowered/parameters.py +0 -0
  195. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/lowered/problem.py +0 -0
  196. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/lowered/unified.py +0 -0
  197. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/plotting/__init__.py +0 -0
  198. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/plotting/plotting.py +0 -0
  199. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/plotting/scp_iteration.py +0 -0
  200. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/plotting/viser/__init__.py +0 -0
  201. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/plotting/viser/animated.py +0 -0
  202. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/plotting/viser/orbits.py +0 -0
  203. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/plotting/viser/plotly_integration.py +0 -0
  204. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/plotting/viser/primitives.py +0 -0
  205. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/plotting/viser/scp.py +0 -0
  206. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/plotting/viser/server.py +0 -0
  207. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/problem.py +0 -0
  208. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/propagation/__init__.py +0 -0
  209. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/propagation/post_processing.py +0 -0
  210. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/propagation/propagation.py +0 -0
  211. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/solvers/__init__.py +0 -0
  212. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/solvers/moreau_ptr_solver.py +0 -0
  213. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/solvers/ptr_solver.py +0 -0
  214. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/solvers/qpax_ptr_solver.py +0 -0
  215. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/__init__.py +0 -0
  216. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/augmentation.py +0 -0
  217. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/builder.py +0 -0
  218. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/constraint_set.py +0 -0
  219. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/__init__.py +0 -0
  220. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/arithmetic.py +0 -0
  221. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/array.py +0 -0
  222. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/constraint.py +0 -0
  223. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/control.py +0 -0
  224. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/expr.py +0 -0
  225. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/lie/__init__.py +0 -0
  226. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
  227. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/lie/se3.py +0 -0
  228. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/lie/so3.py +0 -0
  229. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/linalg.py +0 -0
  230. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/logic.py +0 -0
  231. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/math.py +0 -0
  232. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/parameter.py +0 -0
  233. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/spatial.py +0 -0
  234. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/state.py +0 -0
  235. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/stl.py +0 -0
  236. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/stljax.py +0 -0
  237. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/time.py +0 -0
  238. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/variable.py +0 -0
  239. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/expr/vmap.py +0 -0
  240. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/hashing.py +0 -0
  241. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/__init__.py +0 -0
  242. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
  243. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
  244. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
  245. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
  246. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
  247. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
  248. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
  249. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
  250. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
  251. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
  252. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
  253. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
  254. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
  255. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
  256. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
  257. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
  258. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/array.py +0 -0
  259. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
  260. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/control.py +0 -0
  261. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
  262. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
  263. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
  264. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
  265. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/math.py +0 -0
  266. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
  267. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/state.py +0 -0
  268. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
  269. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
  270. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
  271. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/parser/__init__.py +0 -0
  272. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/parser/_registry.py +0 -0
  273. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/parser/array.py +0 -0
  274. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/parser/constraint.py +0 -0
  275. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/parser/lie.py +0 -0
  276. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/parser/linalg.py +0 -0
  277. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/parser/logic.py +0 -0
  278. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/parser/math.py +0 -0
  279. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/parser/parser.py +0 -0
  280. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/parser/spatial.py +0 -0
  281. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/parser/stl.py +0 -0
  282. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/parser/stljax.py +0 -0
  283. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/parser/tokenizer.py +0 -0
  284. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/preprocessing.py +0 -0
  285. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/problem.py +0 -0
  286. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/sparsity.py +0 -0
  287. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/symbolic/unified.py +0 -0
  288. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/utils/__init__.py +0 -0
  289. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/utils/cache.py +0 -0
  290. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/utils/caching.py +0 -0
  291. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/utils/printing.py +0 -0
  292. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/utils/profiling.py +0 -0
  293. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx/utils/utils.py +0 -0
  294. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx.egg-info/dependency_links.txt +0 -0
  295. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx.egg-info/entry_points.txt +0 -0
  296. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx.egg-info/requires.txt +0 -0
  297. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/openscvx.egg-info/top_level.txt +0 -0
  298. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/pyproject.toml +0 -0
  299. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/scripts/gen_example_pages.py +0 -0
  300. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/scripts/gen_ref_pages.py +0 -0
  301. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
  302. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/setup.cfg +0 -0
  303. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/__init__.py +0 -0
  304. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/_marks.py +0 -0
  305. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/algorithms/__init__.py +0 -0
  306. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/algorithms/autotuner/__init__.py +0 -0
  307. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/algorithms/autotuner/test_update_weights_jit.py +0 -0
  308. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/algorithms/test_algorithm_state_pytree.py +0 -0
  309. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/brachistochrone_analytical.py +0 -0
  310. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/conftest.py +0 -0
  311. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/expr/__init__.py +0 -0
  312. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/expr/test_gmsr.py +0 -0
  313. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/fixtures/brachistochrone.json +0 -0
  314. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/fixtures/brachistochrone.yaml +0 -0
  315. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/hohmann_analytical.py +0 -0
  316. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/integrations/__init__.py +0 -0
  317. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/integrations/test_mjx.py +0 -0
  318. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/integrations/test_mjx_dynamics.py +0 -0
  319. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/solvers/__init__.py +0 -0
  320. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/solvers/_iteration_callback_helpers.py +0 -0
  321. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/solvers/test_cvxpy_callback_jit_spike.py +0 -0
  322. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/solvers/test_iteration_callback_moreau.py +0 -0
  323. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/solvers/test_iteration_callback_qpax.py +0 -0
  324. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/solvers/test_iteration_callback_vmap.py +0 -0
  325. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/solvers/test_moreau_ptr_solver.py +0 -0
  326. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/solvers/test_qpax_ptr_solver.py +0 -0
  327. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/solvers/test_subproblem_pytree.py +0 -0
  328. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/__init__.py +0 -0
  329. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/__init__.py +0 -0
  330. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/test_arithmetic.py +0 -0
  331. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/test_array.py +0 -0
  332. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/test_constraint.py +0 -0
  333. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/test_expr.py +0 -0
  334. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/test_lie.py +0 -0
  335. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/test_linalg.py +0 -0
  336. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/test_logic.py +0 -0
  337. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/test_math.py +0 -0
  338. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/test_node_reference.py +0 -0
  339. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/test_parameters.py +0 -0
  340. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/test_scaling.py +0 -0
  341. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/test_spatial.py +0 -0
  342. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/test_stl.py +0 -0
  343. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/test_variable.py +0 -0
  344. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/expr/test_vmap.py +0 -0
  345. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/parser/__init__.py +0 -0
  346. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/parser/test_array.py +0 -0
  347. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/parser/test_constraint.py +0 -0
  348. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/parser/test_lie.py +0 -0
  349. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/parser/test_linalg.py +0 -0
  350. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/parser/test_load.py +0 -0
  351. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/parser/test_logic.py +0 -0
  352. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/parser/test_math.py +0 -0
  353. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/parser/test_parser.py +0 -0
  354. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/parser/test_spatial.py +0 -0
  355. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/parser/test_stl.py +0 -0
  356. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/parser/test_tokenizer.py +0 -0
  357. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/parser/test_vmap.py +0 -0
  358. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/test_augmentation.py +0 -0
  359. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/test_hashing.py +0 -0
  360. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/test_lower_cvxpy.py +0 -0
  361. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/test_lower_jax.py +0 -0
  362. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/test_preprocessing.py +0 -0
  363. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/test_sparsity.py +0 -0
  364. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/symbolic/test_unified.py +0 -0
  365. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/test_autotuning.py +0 -0
  366. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/test_cvxpygen_optional.py +0 -0
  367. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/test_discretization.py +0 -0
  368. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/test_examples.py +0 -0
  369. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/test_expert.py +0 -0
  370. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/test_impulsive.py +0 -0
  371. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/test_init.py +0 -0
  372. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/test_integrators.py +0 -0
  373. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/test_loader.py +0 -0
  374. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/test_optimization_results.py +0 -0
  375. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/test_plotting.py +0 -0
  376. {openscvx-0.5.3.dev13 → openscvx-0.5.3.dev15}/tests/test_propagation.py +0 -0
@@ -216,8 +216,8 @@ material/*
216
216
  !material/overrides/**
217
217
  src/
218
218
 
219
- # SPICE kernels for spacecrafts examples
220
- examples/spacecraft/ker/
219
+ # Database for astrodynamics application
220
+ **/ker/**
221
221
 
222
222
  # Solver_data folder
223
- solver_data/
223
+ solver_data/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscvx
3
- Version: 0.5.3.dev13
3
+ Version: 0.5.3.dev15
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 = 398600.4354360959
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 and for plotting.
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
- if __name__ == "__main__":
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
- xf_opt = np.concatenate([pos[-1], vel[-1]])
163
-
164
- # Match the post-optimization check style in main_orbs_2.py:
165
- # integrate only to t_f from optimized initial state and export xyz.
166
- traj_plot = np.asarray(
167
- solve_ivp_diffrax(
168
- lambda t, x: cr3bp_rhs(x, jnp.zeros((0,), dtype=x.dtype), 0, {}),
169
- tau_final=t_opt,
170
- y_0=jnp.asarray(x0_opt, dtype=jnp.float64),
171
- args=(),
172
- tau_0=0.0,
173
- num_substeps=2000,
174
- solver_name="Dopri8",
175
- rtol=integration_tol,
176
- atol=integration_tol,
177
- ),
178
- dtype=float,
179
- )
180
-
181
- # Plot guess and solution using the exact plot_projections_2d style.
182
- guess_results = OptimizationResults(converged=True, t_final=float(t_opt))
183
- guess_results.trajectory = {
184
- "time": np.linspace(0.0, t_opt, guess_dense.shape[0]).reshape(-1, 1),
185
- "position": guess_dense[:, :3],
186
- "velocity": guess_dense[:, 3:6],
187
- }
188
- guess_results.nodes = {
189
- "time": np.array([0.0, t_opt]).reshape(-1, 1),
190
- "position": nominal_guess[:, :3],
191
- "velocity": nominal_guess[:, 3:6],
192
- }
193
- fig_guess = plot_projections_2d(guess_results, velocity_var_name="velocity")
194
- fig_guess.update_layout(title="Initial Guess - XY, XZ, YZ Projections")
195
- fig_guess.show()
196
-
197
- solution_results = OptimizationResults(converged=bool(results.converged), t_final=float(t_opt))
198
- solution_results.trajectory = {
199
- "time": np.linspace(0.0, t_opt, traj_plot.shape[0]).reshape(-1, 1),
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.dev13'
22
- __version_tuple__ = version_tuple = (0, 5, 3, 'dev13')
21
+ __version__ = version = '0.5.3.dev15'
22
+ __version_tuple__ = version_tuple = (0, 5, 3, 'dev15')
23
23
 
24
- __commit_id__ = commit_id = 'gf4df0a724'
24
+ __commit_id__ = commit_id = 'ge47b6d19c'
@@ -701,6 +701,7 @@ class PenalizedTrustRegion(Algorithm):
701
701
  lam_vb_nodal=np.asarray(state.lam_vb_nodal),
702
702
  lam_vb_cross=np.asarray(state.lam_vb_cross),
703
703
  )
704
+ self._solver.update_proximal_terms()
704
705
 
705
706
  t0 = time.time()
706
707
  result = self._solver.solve()