openscvx 0.5.3.dev31__tar.gz → 0.5.3.dev33__tar.gz

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