openscvx 0.5.3.dev51__tar.gz → 0.5.3.dev53__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 (533) hide show
  1. {openscvx-0.5.3.dev51/openscvx.egg-info → openscvx-0.5.3.dev53}/PKG-INFO +1 -1
  2. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/UsersGuide/02_drone_racing_constraints.md +1 -1
  3. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +1 -1
  4. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/UsersGuide/05_visualization.md +28 -1
  5. openscvx-0.5.3.dev53/examples/_maze.py +492 -0
  6. openscvx-0.5.3.dev53/examples/_maze_viz.py +464 -0
  7. openscvx-0.5.3.dev53/examples/abstract/chen_allgoewer.py +266 -0
  8. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/abstract/flappy_bird.py +139 -96
  9. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/animations/7_dof_arm.py +1 -1
  10. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/animations/_render.py +128 -6
  11. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/animations/franka_fr3v2_pick_place.py +1 -1
  12. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/animations/obstacle_avoidance_vmap.py +2 -2
  13. openscvx-0.5.3.dev53/examples/animations/senss_hop_lidar_camera.py +226 -0
  14. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/arm/7_dof_arm.py +1 -1
  15. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/arm/7_dof_arm_collision.py +1 -1
  16. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/arm/7_dof_arm_vp.py +1 -1
  17. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/arm/franka_fr3v2_pick_place.py +0 -1
  18. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/arm/franka_fr3v2_viewplanning.py +1 -2
  19. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/arm/franka_fr3v2_viewplanning_nodal.py +1 -2
  20. openscvx-0.5.3.dev53/examples/car/racing/_plotting.py +311 -0
  21. openscvx-0.5.3.dev53/examples/car/racing/_time2spatial.py +140 -0
  22. openscvx-0.5.3.dev53/examples/car/racing/_tracks/LMS_Track.txt +256 -0
  23. openscvx-0.5.3.dev53/examples/car/racing/_tracks/LMS_Track_x4.txt +260 -0
  24. openscvx-0.5.3.dev53/examples/car/racing/_tracks/readDataFcn.py +47 -0
  25. openscvx-0.5.3.dev53/examples/car/racing/_viser.py +908 -0
  26. openscvx-0.5.3.dev53/examples/car/racing/race_car_hybrid.py +571 -0
  27. openscvx-0.5.3.dev53/examples/car/racing/race_car_ice.py +369 -0
  28. openscvx-0.5.3.dev53/examples/car/racing/race_car_mpc.py +537 -0
  29. openscvx-0.5.3.dev53/examples/car/racing/race_car_multi_agent.py +860 -0
  30. openscvx-0.5.3.dev53/examples/car/racing/race_car_multi_agent_mpcc.py +1154 -0
  31. openscvx-0.5.3.dev53/examples/car/racing/race_car_multi_agent_mpcc_ice.py +985 -0
  32. openscvx-0.5.3.dev53/examples/car/racing/race_car_openscvx.py +380 -0
  33. openscvx-0.5.3.dev53/examples/double_integrator/double_integrator_static.py +138 -0
  34. openscvx-0.5.3.dev53/examples/double_integrator/maze_rrt_scp.py +346 -0
  35. openscvx-0.5.3.dev53/examples/double_integrator/multiphase_velocity.py +155 -0
  36. {openscvx-0.5.3.dev51/examples/drone → openscvx-0.5.3.dev53/examples/double_integrator}/obstacle_avoidance_vmap_2d.py +58 -96
  37. openscvx-0.5.3.dev53/examples/drone/_plotting.py +330 -0
  38. openscvx-0.5.3.dev53/examples/drone/_terrain.py +143 -0
  39. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/logo.py +0 -53
  40. openscvx-0.5.3.dev53/examples/drone/lunar_terrain_agl.py +255 -0
  41. openscvx-0.5.3.dev53/examples/drone/maze_scp.py +592 -0
  42. openscvx-0.5.3.dev53/examples/drone/moving_safe_columns.py +254 -0
  43. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/openscvx_logo.py +4 -57
  44. openscvx-0.5.3.dev53/examples/drone/quadrotor_hector.py +348 -0
  45. openscvx-0.5.3.dev53/examples/drone/quadrotor_zigzag.py +230 -0
  46. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/frax/panda_frax.py +1 -1
  47. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/frax/panda_frax_viewplanning.py +1 -1
  48. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/frax/panda_frax_waypoint.py +1 -1
  49. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/mjx/triple_cartpole_3d_mjx.py +1 -1
  50. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/mjx/triple_cartpole_mjx.py +1 -1
  51. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/mpc/double_integrator_discrete.py +4 -3
  52. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/mpc/double_integrator_drone_racing.py +4 -3
  53. openscvx-0.5.3.dev53/examples/multi_agent/ilqgames_three_agent.py +520 -0
  54. openscvx-0.5.3.dev53/examples/multi_agent/ilqgames_three_agent_lqr.py +467 -0
  55. {openscvx-0.5.3.dev51/examples/drone → openscvx-0.5.3.dev53/examples/multi_agent}/multi_agent_circle_swap.py +18 -31
  56. openscvx-0.5.3.dev53/examples/pendulum/pendulum_swingup_ocp.py +247 -0
  57. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/plotting.py +16 -807
  58. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/plotting_viser.py +43 -45
  59. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/realtime/3DoF_pdg_realtime.py +3 -2
  60. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/realtime/6DoF_pdg_realtime.py +3 -2
  61. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +1 -1
  62. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/realtime/cinema_vp_realtime.py +3 -3
  63. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/realtime/drone_racing_realtime.py +3 -3
  64. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/realtime/obstacle_avoidance_realtime.py +3 -3
  65. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/rocket/6DoF_pdg.py +1 -1
  66. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/rocket/6DoF_pdg_batched_ic.py +5 -17
  67. openscvx-0.5.3.dev53/examples/rocket/6DoF_pdg_stc.py +726 -0
  68. openscvx-0.5.3.dev53/examples/rocket/6DoF_pdg_stc_ifthen.py +707 -0
  69. openscvx-0.5.3.dev53/examples/rocket/_cstc_plotting.py +1003 -0
  70. openscvx-0.5.3.dev53/examples/rocket/reusable_launch_vehicle.py +229 -0
  71. openscvx-0.5.3.dev53/examples/rocket/rocket_ilqr.py +392 -0
  72. openscvx-0.5.3.dev53/examples/rocket/senss/6DoF_pdg_dem.py +872 -0
  73. openscvx-0.5.3.dev53/examples/rocket/senss/6DoF_pdg_dem_static.py +381 -0
  74. openscvx-0.5.3.dev53/examples/rocket/senss/6DoF_pdg_stc_senss.py +817 -0
  75. openscvx-0.5.3.dev53/examples/rocket/senss/6DoF_pdg_stc_senss_gimbal.py +809 -0
  76. openscvx-0.5.3.dev53/examples/rocket/senss/6DoF_pdg_stc_senss_gimbal_hop.py +871 -0
  77. openscvx-0.5.3.dev53/examples/rocket/senss/6DoF_pdg_stc_senss_hop.py +870 -0
  78. openscvx-0.5.3.dev53/examples/rocket/senss/6DoF_pdg_stc_senss_planar.py +802 -0
  79. openscvx-0.5.3.dev53/examples/rocket/senss/_dem.py +363 -0
  80. openscvx-0.5.3.dev53/examples/rocket/senss/_halo/__init__.py +16 -0
  81. openscvx-0.5.3.dev53/examples/rocket/senss/_halo/dem.py +307 -0
  82. openscvx-0.5.3.dev53/examples/rocket/senss/_halo/lidar.py +277 -0
  83. openscvx-0.5.3.dev53/examples/rocket/senss/_hop_lidar_overlay.py +481 -0
  84. openscvx-0.5.3.dev53/examples/rocket/senss/senss_dem.png +0 -0
  85. openscvx-0.5.3.dev53/examples/scaling/scaling_study.py +1267 -0
  86. openscvx-0.5.3.dev53/examples/spacecraft/capstone/capstone.bin +0 -0
  87. openscvx-0.5.3.dev53/examples/spacecraft/capstone/capstone.gltf +616 -0
  88. openscvx-0.5.3.dev53/examples/spacecraft/capstone/capstone_albedo.jpg +0 -0
  89. openscvx-0.5.3.dev53/examples/spacecraft/capstone/capstone_ao.jpg +0 -0
  90. openscvx-0.5.3.dev53/examples/spacecraft/capstone/capstone_normals.png +0 -0
  91. openscvx-0.5.3.dev53/examples/spacecraft/capstone/capstone_pbr_jpg.jpg +0 -0
  92. openscvx-0.5.3.dev53/examples/spacecraft/capstone/capstone_plot_mesh.npz +0 -0
  93. openscvx-0.5.3.dev53/examples/spacecraft/capstone/foil_normal.jpg +0 -0
  94. openscvx-0.5.3.dev53/examples/spacecraft/dual_deputy_inspection_cw.py +672 -0
  95. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/spacecraft/let_transfer.py +8 -36
  96. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/__init__.py +2 -0
  97. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/_version.py +3 -3
  98. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/discretization/discretize_linearize.py +2 -2
  99. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/discretization/linearize_discretize.py +2 -2
  100. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/discretization/linearize_discretize_sparse.py +1 -1
  101. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/plotting/__init__.py +15 -0
  102. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/plotting/plotting.py +16 -10
  103. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/plotting/publication.py +78 -26
  104. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/plotting/scp_iteration.py +6 -4
  105. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/plotting/viser/__init__.py +17 -0
  106. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/plotting/viser/animated.py +69 -20
  107. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/plotting/viser/primitives.py +28 -10
  108. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/plotting/viser/server.py +73 -11
  109. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/propagation/propagation.py +1 -1
  110. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/__init__.py +3 -1
  111. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/math.py +47 -1
  112. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/cvxpy/math.py +12 -1
  113. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/math.py +9 -1
  114. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/math.py +9 -2
  115. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/parser/math.py +9 -1
  116. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53/openscvx.egg-info}/PKG-INFO +1 -1
  117. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx.egg-info/SOURCES.txt +61 -5
  118. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx.egg-info/scm_file_list.json +61 -5
  119. openscvx-0.5.3.dev53/openscvx.egg-info/scm_version.json +8 -0
  120. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/scripts/gen_example_pages.py +10 -3
  121. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/e2e/test_brachistochrone.py +31 -22
  122. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_math.py +40 -0
  123. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/parser/test_math.py +7 -1
  124. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/test_lower_latex.py +6 -0
  125. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/test_examples.py +12 -3
  126. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/test_loader.py +11 -4
  127. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/test_plotting.py +316 -1
  128. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/test_propagation.py +4 -4
  129. openscvx-0.5.3.dev51/examples/drone/2d_obstacle_avoidance_batched_ic.py +0 -326
  130. openscvx-0.5.3.dev51/examples/drone/dr_double_integrator.py +0 -163
  131. openscvx-0.5.3.dev51/openscvx.egg-info/scm_version.json +0 -8
  132. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/assets/logo.svg +0 -0
  133. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/release-drafter.yml +0 -0
  134. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/workflows/_docs.yml +0 -0
  135. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/workflows/_extra.yml +0 -0
  136. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/workflows/branch-name.yml +0 -0
  137. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/workflows/docs.yml +0 -0
  138. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/workflows/lint.yml +0 -0
  139. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/workflows/nightly.yml +0 -0
  140. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/workflows/release-drafter.yml +0 -0
  141. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/workflows/release.yml +0 -0
  142. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/workflows/tests-cvxpygen.yml +0 -0
  143. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/workflows/tests-examples.yml +0 -0
  144. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/workflows/tests-lie.yml +0 -0
  145. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/workflows/tests-mjx.yml +0 -0
  146. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/workflows/tests-qpax.yml +0 -0
  147. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.github/workflows/tests.yml +0 -0
  148. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.gitignore +0 -0
  149. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/.gitmodules +0 -0
  150. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/CITATION.cff +0 -0
  151. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/CONTRIBUTING.md +0 -0
  152. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/LICENSE +0 -0
  153. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/README.md +0 -0
  154. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/Foundations/constraint_reformulation.md +0 -0
  155. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/Foundations/control_parameterization.md +0 -0
  156. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/Foundations/discretization.md +0 -0
  157. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/Foundations/ocp.md +0 -0
  158. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/Foundations/scvx.md +0 -0
  159. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/Foundations/time_dilation.md +0 -0
  160. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/UnderTheHood/batching_jit_grad.md +0 -0
  161. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/UnderTheHood/custom_algorithms_autotuners.md +0 -0
  162. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/UnderTheHood/lowering_architecture.md +0 -0
  163. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
  164. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/UsersGuide/00_introduction.md +0 -0
  165. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
  166. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
  167. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/UsersGuide/06_logic.md +0 -0
  168. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/UsersGuide/07_lie.md +0 -0
  169. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/UsersGuide/08_mpcc.md +0 -0
  170. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/UsersGuide/09_mjx_dynamics.md +0 -0
  171. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/assets/favicon.png +0 -0
  172. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/assets/images/ct-scvx_dark.png +0 -0
  173. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/assets/images/ct-scvx_light.png +0 -0
  174. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/assets/images/ctcs_dark.png +0 -0
  175. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/assets/images/ctcs_light.png +0 -0
  176. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/assets/images/problem_class_dark.png +0 -0
  177. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/assets/images/problem_class_light.png +0 -0
  178. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/assets/logo.svg +0 -0
  179. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/assets/openscvx_logo_square.png +0 -0
  180. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/assets/viser-client/index.html +0 -0
  181. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/assets/viser-recordings/drone_racing.viser +0 -0
  182. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
  183. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/changelog.md +0 -0
  184. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/citation.md +0 -0
  185. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/examples.md +0 -0
  186. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/index.md +0 -0
  187. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/installation.md +0 -0
  188. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/javascripts/mathjax.js +0 -0
  189. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/llms.txt +0 -0
  190. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/docs/versions.json +0 -0
  191. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/_viser_embed_export.py +0 -0
  192. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/abstract/brachistochrone.py +0 -0
  193. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/abstract/brachistochrone_batched.py +0 -0
  194. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/abstract/hypersensitive.py +0 -0
  195. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/abstract/impulsive.py +0 -0
  196. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/abstract/stl_integer_variable.py +0 -0
  197. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/abstract/stl_or.py +0 -0
  198. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/aircraft/dynamic_soaring.py +0 -0
  199. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/aircraft/supersonic_time_to_climb.py +0 -0
  200. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/animations/_camera.py +0 -0
  201. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/animations/_sensor_view.py +0 -0
  202. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/animations/dr_vp_polytope.py +0 -0
  203. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/animations/logo.py +0 -0
  204. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/arm/3_dof_arm.py +0 -0
  205. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/car/dubins_car.py +0 -0
  206. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/car/dubins_car_disjoint.py +0 -0
  207. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/car/dubins_car_obstacle_conditional.py +0 -0
  208. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/car/dubins_car_obstacle_stl.py +0 -0
  209. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/car/dubins_car_stl_or.py +0 -0
  210. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/car/dubins_car_waypoint_stl.py +0 -0
  211. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/double_integrator/_plotting.py +0 -0
  212. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/double_integrator/moving_safe_zones.py +0 -0
  213. {openscvx-0.5.3.dev51/examples/drone → openscvx-0.5.3.dev53/examples/double_integrator}/obstacle_avoidance_vmap.py +0 -0
  214. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/boresight_trace_mpcc.py +0 -0
  215. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/cinema_vp.py +0 -0
  216. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/cinema_vp_nodal.py +0 -0
  217. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/dr_vp.py +0 -0
  218. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/dr_vp_nodal.py +0 -0
  219. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/dr_vp_polytope.py +0 -0
  220. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/drone_racing.py +0 -0
  221. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/drone_racing_batched_gates.py +0 -0
  222. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/logo_utils/acl_logo.svg +0 -0
  223. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/logo_utils/circle.svg +0 -0
  224. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/logo_utils/openscvx_logo_single.svg +0 -0
  225. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/logo_utils/quadrotor_mesh.py +0 -0
  226. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/logo_utils/svg_path_utils.py +0 -0
  227. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/obstacle_avoidance.py +0 -0
  228. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/drone/obstacle_avoidance_nodal.py +0 -0
  229. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/frax/panda_frax_pick_place.py +0 -0
  230. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/frax/ur5e_assets/ur5e.urdf +0 -0
  231. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/frax/ur5e_pen_trace.py +0 -0
  232. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/frax/ur5e_pen_trace_mpcc.py +0 -0
  233. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/mjx/cartpole_mjx.py +0 -0
  234. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/mjx/double_cartpole_mjx.py +0 -0
  235. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/mjx/skydio_x2_mjx.py +0 -0
  236. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/mjx/triple_cartpole_game.py +0 -0
  237. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/mpc/dubins_car_circle_analytical.py +0 -0
  238. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/mpc/dubins_car_circle_discrete.py +0 -0
  239. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
  240. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
  241. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
  242. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
  243. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
  244. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
  245. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/realtime/dubins_car_realtime.py +0 -0
  246. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/rocket/3DoF_pdg.py +0 -0
  247. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/rocket/ascent_launch_vehicle.py +0 -0
  248. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/spacecraft/halo_orbit.py +0 -0
  249. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/spacecraft/hohmann_transfer.py +0 -0
  250. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/spacecraft/proxops_cw.py +0 -0
  251. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/examples/spacecraft/relative_loitering.py +0 -0
  252. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/figures/ctlos_cine.gif +0 -0
  253. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/figures/ctlos_dr.gif +0 -0
  254. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/figures/dtlos_cine.gif +0 -0
  255. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/figures/dtlos_dr.gif +0 -0
  256. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/figures/openscvx_logo.svg +0 -0
  257. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/figures/openscvx_logo_square.png +0 -0
  258. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/figures/oscvx_structure_full_dark.svg +0 -0
  259. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/figures/video_preview.png +0 -0
  260. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/material/__init__.py +0 -0
  261. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/material/overrides/assets/stylesheets/custom.css +0 -0
  262. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
  263. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/material/overrides/assets/stylesheets/home-hero.css +0 -0
  264. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/material/overrides/assets/stylesheets/home-viser.css +0 -0
  265. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/material/overrides/home.html +0 -0
  266. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/material/overrides/main.html +0 -0
  267. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/material/overrides/partials/home-diagram.html +0 -0
  268. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/material/overrides/partials/home-dropin-banner.html +0 -0
  269. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/material/overrides/partials/home-hero.html +0 -0
  270. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/material/overrides/partials/home-pipeline.html +0 -0
  271. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/material/overrides/partials/home-viser-strip.html +0 -0
  272. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/material/overrides/sitemap.xml +0 -0
  273. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/mkdocs.yml +0 -0
  274. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/__main__.py +0 -0
  275. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/__init__.py +0 -0
  276. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/autotuner/__init__.py +0 -0
  277. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/autotuner/acceptance_ratio.py +0 -0
  278. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +0 -0
  279. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/autotuner/augmented_lagrangian.py +0 -0
  280. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/autotuner/base.py +0 -0
  281. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/autotuner/constant_proximal_weight.py +0 -0
  282. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/autotuner/ramp_proximal_weight.py +0 -0
  283. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/base.py +0 -0
  284. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/history.py +0 -0
  285. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/hyperparams.py +0 -0
  286. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/loop.py +0 -0
  287. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/optimization_results.py +0 -0
  288. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/penalty.py +0 -0
  289. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/scvx/__init__.py +0 -0
  290. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/scvx/iteration.py +0 -0
  291. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/scvx/penalized_trust_region.py +0 -0
  292. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/state.py +0 -0
  293. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/algorithms/weights.py +0 -0
  294. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/config.py +0 -0
  295. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/discretization/__init__.py +0 -0
  296. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/discretization/base.py +0 -0
  297. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/discretization/sparse_utils/__init__.py +0 -0
  298. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
  299. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
  300. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/expert/__init__.py +0 -0
  301. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/expert/byof.py +0 -0
  302. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/expert/lowering.py +0 -0
  303. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/expert/validation.py +0 -0
  304. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/init/__init__.py +0 -0
  305. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/init/interpolation.py +0 -0
  306. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/init/inverse_kinematics.py +0 -0
  307. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/integrations/__init__.py +0 -0
  308. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/integrations/_utils.py +0 -0
  309. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/integrations/base.py +0 -0
  310. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/integrations/frax.py +0 -0
  311. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/integrations/menagerie.py +0 -0
  312. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/integrations/mjx.py +0 -0
  313. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/integrators/__init__.py +0 -0
  314. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/integrators/diffrax.py +0 -0
  315. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/integrators/runge_kutta.py +0 -0
  316. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/loader.py +0 -0
  317. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/lowered/__init__.py +0 -0
  318. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/lowered/cvxpy_constraints.py +0 -0
  319. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/lowered/cvxpy_variables.py +0 -0
  320. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/lowered/dynamics.py +0 -0
  321. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/lowered/jax_constraints.py +0 -0
  322. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/lowered/parameters.py +0 -0
  323. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/lowered/problem.py +0 -0
  324. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/lowered/unified.py +0 -0
  325. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/plotting/viser/coordinates.py +0 -0
  326. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/plotting/viser/orbits.py +0 -0
  327. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/plotting/viser/plotly_integration.py +0 -0
  328. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/plotting/viser/scp.py +0 -0
  329. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/problem.py +0 -0
  330. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/propagation/__init__.py +0 -0
  331. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/propagation/post_processing.py +0 -0
  332. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/solvers/__init__.py +0 -0
  333. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/solvers/base.py +0 -0
  334. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/solvers/cones.py +0 -0
  335. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/solvers/cvxpy_ptr_solver.py +0 -0
  336. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/solvers/moreau_ptr_solver.py +0 -0
  337. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/solvers/ptr_solver.py +0 -0
  338. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/solvers/qpax_ptr_solver.py +0 -0
  339. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/__init__.py +0 -0
  340. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/affine.py +0 -0
  341. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/augmentation.py +0 -0
  342. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/builder.py +0 -0
  343. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/canonicalize.py +0 -0
  344. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/constraint_set.py +0 -0
  345. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/arithmetic.py +0 -0
  346. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/array.py +0 -0
  347. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/autodiff.py +0 -0
  348. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/constraint.py +0 -0
  349. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/control.py +0 -0
  350. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/expr.py +0 -0
  351. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/lie/__init__.py +0 -0
  352. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
  353. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/lie/se3.py +0 -0
  354. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/lie/so3.py +0 -0
  355. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/linalg.py +0 -0
  356. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/logic.py +0 -0
  357. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/parameter.py +0 -0
  358. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/spatial.py +0 -0
  359. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/state.py +0 -0
  360. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/stl.py +0 -0
  361. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/stljax.py +0 -0
  362. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/time.py +0 -0
  363. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/variable.py +0 -0
  364. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/expr/vmap.py +0 -0
  365. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/hashing.py +0 -0
  366. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lower.py +0 -0
  367. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/__init__.py +0 -0
  368. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
  369. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
  370. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
  371. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
  372. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
  373. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/cvxpy/autodiff.py +0 -0
  374. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
  375. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
  376. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
  377. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
  378. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
  379. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
  380. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
  381. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
  382. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
  383. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
  384. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/array.py +0 -0
  385. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/autodiff.py +0 -0
  386. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
  387. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/control.py +0 -0
  388. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
  389. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
  390. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
  391. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
  392. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
  393. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/state.py +0 -0
  394. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
  395. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
  396. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
  397. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/__init__.py +0 -0
  398. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/_lowerer.py +0 -0
  399. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/_registry.py +0 -0
  400. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/arithmetic.py +0 -0
  401. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/array.py +0 -0
  402. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/autodiff.py +0 -0
  403. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/constraint.py +0 -0
  404. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/control.py +0 -0
  405. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/expr.py +0 -0
  406. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/formulation.py +0 -0
  407. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/lie.py +0 -0
  408. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/linalg.py +0 -0
  409. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/logic.py +0 -0
  410. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/spatial.py +0 -0
  411. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/state.py +0 -0
  412. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/stl.py +0 -0
  413. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/lowerers/latex/vmap.py +0 -0
  414. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/parser/__init__.py +0 -0
  415. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/parser/_registry.py +0 -0
  416. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/parser/array.py +0 -0
  417. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/parser/constraint.py +0 -0
  418. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/parser/lie.py +0 -0
  419. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/parser/linalg.py +0 -0
  420. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/parser/logic.py +0 -0
  421. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/parser/parser.py +0 -0
  422. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/parser/spatial.py +0 -0
  423. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/parser/stl.py +0 -0
  424. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/parser/stljax.py +0 -0
  425. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/parser/tokenizer.py +0 -0
  426. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/preprocessing.py +0 -0
  427. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/problem.py +0 -0
  428. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/sparsity.py +0 -0
  429. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/symbolic/unified.py +0 -0
  430. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/utils/__init__.py +0 -0
  431. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/utils/cache.py +0 -0
  432. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/utils/caching.py +0 -0
  433. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/utils/printing.py +0 -0
  434. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/utils/profiling.py +0 -0
  435. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx/utils/utils.py +0 -0
  436. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx.egg-info/dependency_links.txt +0 -0
  437. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx.egg-info/entry_points.txt +0 -0
  438. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx.egg-info/requires.txt +0 -0
  439. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/openscvx.egg-info/top_level.txt +0 -0
  440. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/pyproject.toml +0 -0
  441. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/scripts/gen_ref_pages.py +0 -0
  442. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
  443. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/scripts/mkdocs_seo_hook.py +0 -0
  444. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/setup.cfg +0 -0
  445. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/__init__.py +0 -0
  446. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/algorithms/__init__.py +0 -0
  447. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/algorithms/_iteration_helpers.py +0 -0
  448. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/algorithms/autotuner/__init__.py +0 -0
  449. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/algorithms/autotuner/test_defaults_agreement.py +0 -0
  450. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/algorithms/autotuner/test_hyper_overrides.py +0 -0
  451. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/algorithms/autotuner/test_update_weights_jit.py +0 -0
  452. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/algorithms/test_algorithm_state_pytree.py +0 -0
  453. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/algorithms/test_iteration_fn_jit.py +0 -0
  454. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/algorithms/test_iteration_fn_parity.py +0 -0
  455. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/algorithms/test_make_solve_loop.py +0 -0
  456. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/brachistochrone_analytical.py +0 -0
  457. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/conftest.py +0 -0
  458. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/e2e/__init__.py +0 -0
  459. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/e2e/test_impulsive.py +0 -0
  460. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/e2e/test_multishot_propagation.py +0 -0
  461. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/e2e/test_solve_batched_brachistochrone.py +0 -0
  462. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/e2e/test_solve_batched_cvxpy_export_errors.py +0 -0
  463. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/e2e/test_solve_batched_export_roundtrip.py +0 -0
  464. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/e2e/test_solve_jax_bare_brachistochrone.py +0 -0
  465. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/e2e/test_solve_jax_jit_brachistochrone.py +0 -0
  466. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/e2e/test_solve_jax_vmap_brachistochrone.py +0 -0
  467. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/e2e/test_solve_jax_vmap_converged_no_drift.py +0 -0
  468. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/fixtures/brachistochrone.json +0 -0
  469. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/fixtures/brachistochrone.yaml +0 -0
  470. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/hohmann_analytical.py +0 -0
  471. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/integrations/__init__.py +0 -0
  472. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/integrations/test_mjx.py +0 -0
  473. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/integrations/test_mjx_dynamics.py +0 -0
  474. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/solvers/__init__.py +0 -0
  475. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/solvers/_iteration_callback_helpers.py +0 -0
  476. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/solvers/test_cvxpy_callback_jit_spike.py +0 -0
  477. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/solvers/test_iteration_callback_cvxpy.py +0 -0
  478. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/solvers/test_iteration_callback_moreau.py +0 -0
  479. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/solvers/test_iteration_callback_qpax.py +0 -0
  480. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/solvers/test_iteration_callback_vmap.py +0 -0
  481. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/solvers/test_moreau_ptr_solver.py +0 -0
  482. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/solvers/test_qpax_ptr_solver.py +0 -0
  483. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/solvers/test_subproblem_pytree.py +0 -0
  484. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/__init__.py +0 -0
  485. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/__init__.py +0 -0
  486. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_arithmetic.py +0 -0
  487. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_array.py +0 -0
  488. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_autodiff.py +0 -0
  489. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_constraint.py +0 -0
  490. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_expr.py +0 -0
  491. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_guess_expr.py +0 -0
  492. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_lie.py +0 -0
  493. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_linalg.py +0 -0
  494. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_logic.py +0 -0
  495. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_node_reference.py +0 -0
  496. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_parameters.py +0 -0
  497. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_scaling.py +0 -0
  498. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_spatial.py +0 -0
  499. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_stl.py +0 -0
  500. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_variable.py +0 -0
  501. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/expr/test_vmap.py +0 -0
  502. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/parser/__init__.py +0 -0
  503. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/parser/test_array.py +0 -0
  504. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/parser/test_constraint.py +0 -0
  505. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/parser/test_lie.py +0 -0
  506. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/parser/test_linalg.py +0 -0
  507. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/parser/test_load.py +0 -0
  508. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/parser/test_logic.py +0 -0
  509. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/parser/test_parser.py +0 -0
  510. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/parser/test_spatial.py +0 -0
  511. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/parser/test_stl.py +0 -0
  512. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/parser/test_tokenizer.py +0 -0
  513. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/parser/test_vmap.py +0 -0
  514. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/test_augmentation.py +0 -0
  515. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/test_gmsr.py +0 -0
  516. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/test_hashing.py +0 -0
  517. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/test_latex_formulation.py +0 -0
  518. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/test_lower_cvxpy.py +0 -0
  519. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/test_lower_jax.py +0 -0
  520. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/test_preprocessing.py +0 -0
  521. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/test_sparsity.py +0 -0
  522. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/symbolic/test_unified.py +0 -0
  523. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/test_autotuning.py +0 -0
  524. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/test_cvxpygen_optional.py +0 -0
  525. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/test_discretization.py +0 -0
  526. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/test_expert.py +0 -0
  527. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/test_init.py +0 -0
  528. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/test_initialize_syncs_guesses.py +0 -0
  529. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/test_integrators.py +0 -0
  530. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/test_optimization_results.py +0 -0
  531. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/test_post_process_batched_tau_clamp.py +0 -0
  532. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/test_results_parameters.py +0 -0
  533. {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev53}/tests/test_solve_batched_inference.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscvx
3
- Version: 0.5.3.dev51
3
+ Version: 0.5.3.dev53
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
@@ -274,8 +274,8 @@ For fully interactive 3D visualization with animated playback, gates, and thrust
274
274
 
275
275
  ## Further Reading
276
276
 
277
- - [Complete Drone Racing Example](../Examples/drone/dr_double_integrator.md)
278
277
  - [Full 6-DOF Drone Racing](../Examples/drone/drone_racing.md) — adds attitude dynamics
278
+ - [Double-Integrator Racing MPC](../Examples/mpc/double_integrator_drone_racing.md) — the same simplified model raced in closed loop
279
279
  - [API Reference: Constraints](../Reference/symbolic/expr/constraint.md)
280
280
  - [Obstacle Avoidance: 6-DOF Dynamics, Parameters, and Vmap](03_obstacle_avoidance_vmap.md)
281
281
  - [Viewpoint Constraints: Custom Functions and Perception](04_viewpoint_constraints.md)
@@ -414,7 +414,7 @@ For further information about visualization with viser see [Tutorial 05 Visualiz
414
414
  ## Further Reading
415
415
 
416
416
  - [Complete 6-DOF Obstacle Avoidance Example](../Examples/drone/obstacle_avoidance.md)
417
- - [Complete Vmap Obstacle Avoidance Example](../Examples/drone/obstacle_avoidance_vmap.md)
417
+ - [Complete Vmap Obstacle Avoidance Example](../Examples/double_integrator/obstacle_avoidance_vmap.md)
418
418
  - [Real-Time Obstacle Avoidance Example](https://github.com/OpenSCvx/OpenSCvx/blob/main/examples/realtime/obstacle_avoidance_realtime.py)
419
419
  - [Real-Time Drone Racing Example](https://github.com/OpenSCvx/OpenSCvx/blob/main/examples/realtime/drone_racing_realtime.py)
420
420
  - [API Reference: Spatial Utilities](../Reference/symbolic/expr/spatial.md)
@@ -127,6 +127,18 @@ The `openscvx.plotting.viser` module gives you:
127
127
 
128
128
  This approach means you're never fighting against our assumptions about what a "correct" visualization looks like.
129
129
 
130
+ Every primitive that adds a node to the scene takes a keyword-only `name=` giving that
131
+ node's scene path, defaulting to a sensible one (`"/trail"`, `"/current_pos"`,
132
+ `"/body_frame"`, …). viser keys nodes by path, so pass distinct names when a scene holds
133
+ more than one of something — two vehicles, two sensors, two constraint cones:
134
+
135
+ ```python
136
+ add_animated_trail(server, pos_a, colors_a, name="/chaser/trail")
137
+ add_animated_trail(server, pos_b, colors_b, name="/target/trail")
138
+ ```
139
+
140
+ Leaving `name` alone gives you the single-vehicle default, which is what most problems want.
141
+
130
142
  ### Animation Mechanism
131
143
 
132
144
  The animation system uses a simple callback pattern. Understanding this upfront makes everything else click:
@@ -195,9 +207,24 @@ The templates demonstrate common patterns:
195
207
  | Template | Use Case |
196
208
  |----------|----------|
197
209
  | `create_animated_plotting_server()` | General 3D trajectory animation with trail, thrust vectors, attitude frames, viewcones |
210
+ | `create_snapshot_plotting_server()` | Static multi-pose snapshot of a trajectory, for figures rather than playback |
198
211
  | `create_scp_animated_plotting_server()` | 3D SCP iteration convergence visualization |
199
212
  | `create_pdg_animated_plotting_server()` | Powered descent guidance (rockets) with glideslope cone |
200
213
 
214
+ Unlike the primitives above, these templates are deliberately **monolithic**: each takes a
215
+ long list of keyword arguments and builds an entire scene in one call, so that the common
216
+ case is a single line and no thinking. That is a different design goal from
217
+ `openscvx.plotting.viser`, and the two should not be confused — the primitives are what you
218
+ compose when the template does not fit, and the template is only ever a starting point.
219
+
220
+ !!! note "Contributing an example to OpenSCvx?"
221
+
222
+ The advice to *copy and customize* is for **your own project**. If you are adding an
223
+ example to this repository, do not copy a template into it — share the code instead,
224
+ via `examples/<family>/_plotting.py`. A copy inside the repo is not a customization;
225
+ it is a fork that has to be maintained forever, and it is how a family of examples ends
226
+ up with five near-identical thousand-line visualization blocks.
227
+
201
228
  The next section walks through exactly how `create_animated_plotting_server` is built, teaching you the pattern, so you can create your own.
202
229
 
203
230
  ---
@@ -219,7 +246,7 @@ from openscvx.plotting.viser import compute_velocity_colors, create_server
219
246
  # Extract trajectory arrays (handles JAX arrays automatically)
220
247
  pos = results.trajectory["position"]
221
248
  vel = results.trajectory["velocity"]
222
- thrust = results.trajectory.get("thrust_force") # May be None
249
+ thrust = results.trajectory.get("force") # May be None; see `thrust_key`
223
250
  attitude = results.trajectory.get("attitude") # May be None for 3-DOF
224
251
  traj_time = results.trajectory["time"]
225
252
 
@@ -0,0 +1,492 @@
1
+ """Maze generation and JAX wavefront path planning, shared by the maze examples.
2
+
3
+ Why an examples tree ships a planner
4
+ ------------------------------------
5
+ SCP refines an initial iterate; it does not search. In a maze there is no
6
+ straight line from start to goal, so the usual "interpolate the boundary
7
+ conditions" guess is not merely suboptimal — it threads straight through walls,
8
+ and every subsequent linearisation is taken about a point deep inside the
9
+ infeasible set. What SCP needs first is a *topologically* correct guess: a
10
+ path that goes around the walls the way the solution has to. That is what this
11
+ module produces, and nothing more — the dynamics, the constraints and the
12
+ optimisation all stay in the example files.
13
+
14
+ The planner
15
+ -----------
16
+ The maze is treated purely as collision geometry. Walls are rasterised into a
17
+ binary occupancy grid (inflated for clearance), and a cost-to-go field is
18
+ flooded outward from the goal over *every* free cell at once. One BFS
19
+ relaxation is ``dist ← min(dist, min(shift(dist)) + 1)`` — a handful of
20
+ shifted-array minimums that JAX fuses into a single kernel — iterated inside
21
+ ``lax.while_loop`` so the whole search stays on-device with no Python loop.
22
+ This is the data-parallel analogue of Dijkstra / A* and scales to fine grids
23
+ trivially. A path is then recovered by steepest descent on the cost-to-go
24
+ field, cleaned up by an exact analytical line-of-sight shortcutter, and
25
+ resampled onto the SCP node grid in a way that preserves every corner.
26
+
27
+ Consumers: ``examples/double_integrator/maze_rrt_scp.py`` (planar) and
28
+ ``examples/drone/maze_scp.py`` (6-DOF). Rendering lives in
29
+ ``examples/_maze_viz.py``; this module is pure NumPy/JAX geometry.
30
+ """
31
+
32
+ from __future__ import annotations
33
+
34
+ from functools import partial
35
+
36
+ import jax
37
+ import jax.numpy as jnp
38
+ import numpy as np
39
+
40
+ # ── Planner tuning ─────────────────────────────────────────────────────────────
41
+ PLAN_RES = 8 # planning-grid resolution [cells / metre]
42
+ PLAN_CLEARANCE = 0.08 # obstacle inflation applied when rasterising [m]
43
+ SHORTCUT_CLEARANCE = 0.10 # clearance for line-of-sight shortcutting [m]
44
+
45
+ BFS_INF = 1 << 30 # "unreached" sentinel: cost-to-go of a cell not yet flooded
46
+
47
+
48
+ # ── Maze generation ────────────────────────────────────────────────────────────
49
+
50
+
51
+ def make_maze_walls(
52
+ n_cols: int,
53
+ n_rows: int,
54
+ *,
55
+ cell_w: float = 1.0,
56
+ cell_h: float = 1.0,
57
+ wall_t: float = 0.10,
58
+ seed: int = 0,
59
+ ) -> np.ndarray:
60
+ """Generate a perfect maze by DFS backtracking and return its walls.
61
+
62
+ "Perfect" means exactly one path connects any two cells: the maze has no
63
+ loops and no isolated regions, so a plan always exists and is unique up to
64
+ shortcutting.
65
+
66
+ Args:
67
+ n_cols, n_rows: Maze size in cells. The domain spans
68
+ ``[0, n_cols * cell_w] × [0, n_rows * cell_h]``.
69
+ cell_w, cell_h: Cell size [m].
70
+ wall_t: Wall thickness [m], centred on the grid edge it occupies.
71
+ seed: RNG seed for the DFS.
72
+
73
+ Returns:
74
+ ``(n_walls, 4)`` float64 array of axis-aligned rectangles
75
+ ``(x0, y0, x1, y1)`` — the form both the collision tests and the
76
+ infinity-norm CTCS constraints consume directly.
77
+ """
78
+ rng = np.random.default_rng(seed)
79
+
80
+ # h_walls[r, c]: horizontal wall between cell (c, r) and (c, r+1)
81
+ h_walls = np.ones((n_rows - 1, n_cols), dtype=bool)
82
+ # v_walls[r, c]: vertical wall between cell (c, r) and (c+1, r)
83
+ v_walls = np.ones((n_rows, n_cols - 1), dtype=bool)
84
+ visited = np.zeros((n_rows, n_cols), dtype=bool)
85
+
86
+ # Iterative DFS: carve a wall whenever we step into an unvisited cell.
87
+ stack = [(0, 0)]
88
+ visited[0, 0] = True
89
+ while stack:
90
+ r, c = stack[-1]
91
+ nbrs: list[tuple[str, int, int]] = []
92
+ if r > 0 and not visited[r - 1, c]:
93
+ nbrs.append(("D", r - 1, c))
94
+ if r < n_rows - 1 and not visited[r + 1, c]:
95
+ nbrs.append(("U", r + 1, c))
96
+ if c > 0 and not visited[r, c - 1]:
97
+ nbrs.append(("L", r, c - 1))
98
+ if c < n_cols - 1 and not visited[r, c + 1]:
99
+ nbrs.append(("R", r, c + 1))
100
+ if nbrs:
101
+ d, nr, nc = nbrs[rng.integers(len(nbrs))]
102
+ if d in ("U", "D"):
103
+ h_walls[min(r, nr), c] = False
104
+ else:
105
+ v_walls[r, min(c, nc)] = False
106
+ visited[nr, nc] = True
107
+ stack.append((nr, nc))
108
+ else:
109
+ stack.pop()
110
+
111
+ half_t = wall_t / 2.0
112
+ walls: list[tuple[float, float, float, float]] = []
113
+ # Horizontal walls, centred at y = (r + 1) * cell_h.
114
+ for r in range(n_rows - 1):
115
+ yc = (r + 1) * cell_h
116
+ for c in range(n_cols):
117
+ if h_walls[r, c]:
118
+ walls.append((c * cell_w, yc - half_t, (c + 1) * cell_w, yc + half_t))
119
+ # Vertical walls, centred at x = (c + 1) * cell_w.
120
+ for r in range(n_rows):
121
+ for c in range(n_cols - 1):
122
+ if v_walls[r, c]:
123
+ xc = (c + 1) * cell_w
124
+ walls.append((xc - half_t, r * cell_h, xc + half_t, (r + 1) * cell_h))
125
+
126
+ return np.array(walls, dtype=np.float64)
127
+
128
+
129
+ # ── Collision geometry ─────────────────────────────────────────────────────────
130
+
131
+
132
+ def segment_collides(
133
+ walls: np.ndarray,
134
+ p1: np.ndarray,
135
+ p2: np.ndarray,
136
+ *,
137
+ clearance: float = SHORTCUT_CLEARANCE,
138
+ ) -> bool:
139
+ """Test a segment against every wall at once, exactly.
140
+
141
+ Uses the slab method: decompose the segment into 1-D parametric intervals
142
+ along each axis and intersect them. Correct for any wall thickness — no
143
+ sampling artefacts, which matters because the shortcutter trusts this test
144
+ to certify long diagonal chords through a thin-walled maze.
145
+
146
+ Args:
147
+ walls: ``(n_walls, 4)`` rectangles from :func:`make_maze_walls`.
148
+ p1, p2: Segment endpoints, shape ``(2,)``.
149
+ clearance: Expand every wall by this margin before testing [m].
150
+
151
+ Returns:
152
+ True if ``[p1, p2]`` intersects any inflated wall.
153
+ """
154
+ dx = float(p2[0] - p1[0])
155
+ dy = float(p2[1] - p1[1])
156
+
157
+ wx0 = walls[:, 0] - clearance
158
+ wy0 = walls[:, 1] - clearance
159
+ wx1 = walls[:, 2] + clearance
160
+ wy1 = walls[:, 3] + clearance
161
+
162
+ n = len(walls)
163
+ t_min = np.zeros(n)
164
+ t_max = np.ones(n)
165
+
166
+ # X slab: the t-interval over which the segment lies inside [wx0, wx1].
167
+ if abs(dx) < 1e-12:
168
+ # Axis-parallel in x; outside the slab → no hit for that wall.
169
+ t_max = np.where((p1[0] < wx0) | (p1[0] > wx1), -1.0, t_max)
170
+ else:
171
+ ta = (wx0 - p1[0]) / dx
172
+ tb = (wx1 - p1[0]) / dx
173
+ t_min = np.maximum(t_min, np.minimum(ta, tb))
174
+ t_max = np.minimum(t_max, np.maximum(ta, tb))
175
+
176
+ # Y slab.
177
+ if abs(dy) < 1e-12:
178
+ t_max = np.where((p1[1] < wy0) | (p1[1] > wy1), -1.0, t_max)
179
+ else:
180
+ ta = (wy0 - p1[1]) / dy
181
+ tb = (wy1 - p1[1]) / dy
182
+ t_min = np.maximum(t_min, np.minimum(ta, tb))
183
+ t_max = np.minimum(t_max, np.maximum(ta, tb))
184
+
185
+ return bool((t_min <= t_max).any())
186
+
187
+
188
+ def build_occupancy(
189
+ walls: np.ndarray,
190
+ domain: tuple[np.ndarray, np.ndarray],
191
+ res: int,
192
+ clearance: float,
193
+ ) -> np.ndarray:
194
+ """Rasterise walls into the boolean occupancy grid the wavefront floods.
195
+
196
+ Each rectangle is inflated by ``clearance`` and every grid cell whose extent
197
+ overlaps it is marked occupied (floor/ceil span coverage), so thin walls can
198
+ never leak between grid lines regardless of alignment.
199
+
200
+ Args:
201
+ walls: ``(n_walls, 4)`` rectangles from :func:`make_maze_walls`.
202
+ domain: ``(lo, hi)`` corners of the planning region, each ``(2,)``.
203
+ res: Grid resolution [cells / metre].
204
+ clearance: Obstacle inflation [m].
205
+
206
+ Returns:
207
+ ``(ny, nx)`` bool array indexed ``occ[row=y, col=x]``; True = blocked.
208
+ """
209
+ lo, hi = domain
210
+ nx = int(round((hi[0] - lo[0]) * res))
211
+ ny = int(round((hi[1] - lo[1]) * res))
212
+ occ = np.zeros((ny, nx), dtype=bool)
213
+
214
+ for x0, y0, x1, y1 in walls:
215
+ i0 = max(int(np.floor((x0 - clearance - lo[0]) * res)), 0)
216
+ i1 = min(int(np.ceil((x1 + clearance - lo[0]) * res)), nx)
217
+ j0 = max(int(np.floor((y0 - clearance - lo[1]) * res)), 0)
218
+ j1 = min(int(np.ceil((y1 + clearance - lo[1]) * res)), ny)
219
+ occ[j0:j1, i0:i1] = True
220
+
221
+ return occ
222
+
223
+
224
+ # ── Wavefront flood ────────────────────────────────────────────────────────────
225
+
226
+
227
+ def _relax(dist: jnp.ndarray, free: jnp.ndarray) -> jnp.ndarray:
228
+ """One BFS relaxation sweep over the whole grid (4-connectivity).
229
+
230
+ ``dist`` is the current cost-to-go field; ``free`` masks traversable cells.
231
+ Occupied cells are pinned to ``BFS_INF`` so paths cannot cut through walls.
232
+ """
233
+ ny, nx = dist.shape
234
+ pad = jnp.pad(dist, 1, constant_values=BFS_INF)
235
+ up = pad[0:ny, 1 : nx + 1]
236
+ down = pad[2 : ny + 2, 1 : nx + 1]
237
+ left = pad[1 : ny + 1, 0:nx]
238
+ right = pad[1 : ny + 1, 2 : nx + 2]
239
+ nmin = jnp.minimum(jnp.minimum(up, down), jnp.minimum(left, right))
240
+ cand = jnp.minimum(dist, nmin + 1)
241
+ return jnp.where(free, cand, BFS_INF)
242
+
243
+
244
+ @partial(jax.jit, static_argnames=("start_rc", "max_iters"))
245
+ def _wavefront(
246
+ free: jnp.ndarray,
247
+ dist0: jnp.ndarray,
248
+ start_rc: tuple[int, int],
249
+ max_iters: int,
250
+ ) -> tuple[jnp.ndarray, jnp.ndarray]:
251
+ """Flood cost-to-go until the start is reached, entirely on-device.
252
+
253
+ One relaxation sweep per BFS layer inside ``lax.while_loop``, terminating as
254
+ soon as the start cell has a finite cost-to-go or the cap is hit.
255
+
256
+ Args:
257
+ free: ``(ny, nx)`` bool traversability mask.
258
+ dist0: ``(ny, nx)`` int32 field, ``BFS_INF`` everywhere but the goal.
259
+ start_rc: ``(row, col)`` of the start cell — static, drives early exit.
260
+ max_iters: Hard cap on relaxation sweeps.
261
+
262
+ Returns:
263
+ ``(dist, n_iter)`` — final cost-to-go field and sweeps performed.
264
+ """
265
+ si, sj = start_rc
266
+
267
+ def cond(state):
268
+ dist, it = state
269
+ return jnp.logical_and(it < max_iters, dist[si, sj] >= BFS_INF)
270
+
271
+ def body(state):
272
+ dist, it = state
273
+ return _relax(dist, free), it + 1
274
+
275
+ return jax.lax.while_loop(cond, body, (dist0, jnp.int32(0)))
276
+
277
+
278
+ def _descend_path(dist: np.ndarray, start_rc, goal_rc) -> list[tuple[int, int]]:
279
+ """Recover a cell path by steepest descent on the goal-sourced cost-to-go.
280
+
281
+ From the start cell, repeatedly step to the 4-neighbour whose cost-to-go is
282
+ exactly one lower. For a BFS field this always reaches the goal (cost 0).
283
+ """
284
+ ny, nx = dist.shape
285
+ cur = tuple(int(v) for v in start_rc)
286
+ goal = tuple(int(v) for v in goal_rc)
287
+ cells = [cur]
288
+ while cur != goal:
289
+ r, c = cur
290
+ target = dist[r, c] - 1
291
+ nxt = None
292
+ for dr, dc in ((-1, 0), (1, 0), (0, -1), (0, 1)):
293
+ rr, cc = r + dr, c + dc
294
+ if 0 <= rr < ny and 0 <= cc < nx and dist[rr, cc] == target:
295
+ nxt = (rr, cc)
296
+ break
297
+ if nxt is None: # dead end (should not happen)
298
+ break
299
+ cur = nxt
300
+ cells.append(cur)
301
+ return cells
302
+
303
+
304
+ def _shortcut_with_history(
305
+ walls: np.ndarray,
306
+ path: np.ndarray,
307
+ clearance: float,
308
+ ) -> tuple[np.ndarray, list[np.ndarray]]:
309
+ """Greedy line-of-sight shortcut, keeping each intermediate polyline.
310
+
311
+ From each kept waypoint, jump as far ahead as an exact collision test
312
+ allows. The intermediate polylines are what the viser animation replays.
313
+ """
314
+ smoothed = [path[0]]
315
+ stages: list[np.ndarray] = [np.array([path[0]])]
316
+ i = 0
317
+ while i < len(path) - 1:
318
+ j = len(path) - 1
319
+ while j > i + 1 and segment_collides(walls, path[i], path[j], clearance=clearance):
320
+ j -= 1
321
+ smoothed.append(path[j])
322
+ stages.append(np.array(smoothed))
323
+ i = j
324
+ return np.array(smoothed), stages
325
+
326
+
327
+ def wavefront_solve(
328
+ walls: np.ndarray,
329
+ start: np.ndarray,
330
+ goal: np.ndarray,
331
+ domain: tuple[np.ndarray, np.ndarray],
332
+ *,
333
+ res: int = PLAN_RES,
334
+ clearance: float = PLAN_CLEARANCE,
335
+ shortcut_clearance: float = SHORTCUT_CLEARANCE,
336
+ record_history: bool = False,
337
+ history_stride: int = 12,
338
+ ) -> np.ndarray | tuple[np.ndarray, dict]:
339
+ """Plan a collision-free polyline through the maze: flood, descend, shortcut.
340
+
341
+ Args:
342
+ walls: ``(n_walls, 4)`` rectangles from :func:`make_maze_walls`.
343
+ start, goal: Physical positions, shape ``(2,)``.
344
+ domain: ``(lo, hi)`` corners of the planning region, each ``(2,)``.
345
+ res: Planning-grid resolution [cells / metre].
346
+ clearance: Obstacle inflation when rasterising [m].
347
+ shortcut_clearance: Clearance for the line-of-sight shortcutter [m].
348
+ record_history: Also capture the intermediate planner states the viser
349
+ animation replays. This runs the flood sweep-by-sweep on the host
350
+ instead of inside ``lax.while_loop``, so it is slower — pass False
351
+ when only the path is wanted.
352
+ history_stride: Record one cost-to-go snapshot every this many sweeps.
353
+
354
+ Returns:
355
+ ``plan_path`` — ``(K, 2)`` ordered collision-free waypoints. When
356
+ ``record_history``, returns ``(plan_path, history)`` where ``history``
357
+ carries ``dist_frames``, ``free``, ``lo``, ``res``, ``n_sweeps``,
358
+ ``shortcut_stages`` and ``raw_path`` for
359
+ :func:`examples._maze_viz.animate_wavefront`.
360
+
361
+ Raises:
362
+ RuntimeError: If the flood never reaches the start cell — the start or
363
+ goal is inside an inflated wall, or the maze is disconnected.
364
+ """
365
+ lo, _ = domain
366
+ occ = build_occupancy(walls, domain, res, clearance)
367
+ ny, nx = occ.shape
368
+ free = jnp.asarray(~occ)
369
+
370
+ def _rc(p):
371
+ col = min(max(int((p[0] - lo[0]) * res), 0), nx - 1)
372
+ row = min(max(int((p[1] - lo[1]) * res), 0), ny - 1)
373
+ return row, col
374
+
375
+ start_rc = _rc(start)
376
+ goal_rc = _rc(goal)
377
+
378
+ dist0 = np.full((ny, nx), BFS_INF, dtype=np.int32)
379
+ dist0[goal_rc[0], goal_rc[1]] = 0
380
+
381
+ dist_frames: list[np.ndarray] = []
382
+ if record_history:
383
+ dist_np = dist0.copy()
384
+ dist_frames.append(dist_np.copy())
385
+ sweep = 0
386
+ max_iters = nx * ny
387
+ while dist_np[start_rc[0], start_rc[1]] >= BFS_INF and sweep < max_iters:
388
+ dist_np = np.asarray(_relax(jnp.asarray(dist_np), free))
389
+ sweep += 1
390
+ if sweep % history_stride == 0 or dist_np[start_rc[0], start_rc[1]] < BFS_INF:
391
+ dist_frames.append(dist_np.copy())
392
+ n_iter = sweep
393
+ dist = dist_np
394
+ else:
395
+ dist_j, n_iter = _wavefront(free, jnp.asarray(dist0), start_rc, nx * ny)
396
+ dist = np.asarray(dist_j)
397
+
398
+ if dist[start_rc[0], start_rc[1]] >= BFS_INF:
399
+ raise RuntimeError("Wavefront planner failed to reach the start cell.")
400
+
401
+ cells = _descend_path(dist, start_rc, goal_rc)
402
+ pts = np.array([[lo[0] + (c + 0.5) / res, lo[1] + (r + 0.5) / res] for r, c in cells])
403
+ raw_path = np.vstack([start.copy(), pts, goal.copy()])
404
+ deduped = [raw_path[0]]
405
+ for wp in raw_path[1:]:
406
+ if np.linalg.norm(wp - deduped[-1]) > 1e-9:
407
+ deduped.append(wp)
408
+ raw_path = np.array(deduped)
409
+
410
+ plan_path, shortcut_stages = _shortcut_with_history(walls, raw_path, shortcut_clearance)
411
+ if not record_history:
412
+ return plan_path
413
+
414
+ history = {
415
+ "dist_frames": dist_frames,
416
+ "free": np.asarray(~occ),
417
+ "lo": np.asarray(lo).copy(),
418
+ "res": res,
419
+ "n_sweeps": int(n_iter),
420
+ "shortcut_stages": shortcut_stages,
421
+ "raw_path": raw_path,
422
+ }
423
+ return plan_path, history
424
+
425
+
426
+ # ── Guess construction ─────────────────────────────────────────────────────────
427
+
428
+
429
+ def path_to_guess(
430
+ path: np.ndarray,
431
+ n_nodes: int,
432
+ t_total: float,
433
+ ) -> tuple[np.ndarray, np.ndarray]:
434
+ """Resample a collision-free polyline onto ``n_nodes`` SCP nodes, keeping corners.
435
+
436
+ Uniform arc-length resampling places nodes at evenly spaced arc positions
437
+ that almost never coincide with the polyline's corners. In a maze the path
438
+ turns ~90° at every corner, so a chord between two nodes straddling a corner
439
+ cuts diagonally across the wall — the resampled guess passes through
440
+ obstacles even though the polyline does not.
441
+
442
+ This resampler keeps every original vertex as a node and only ever *inserts*
443
+ nodes into segment interiors (distributed by segment length, largest
444
+ remainder rounding to hit the count exactly). Every consecutive node pair
445
+ therefore lies on a single original segment, so the guess is collision-free
446
+ by construction — provided ``n_nodes >= len(path)``.
447
+
448
+ Args:
449
+ path: ``(K, 2)`` ordered collision-free waypoints.
450
+ n_nodes: Number of SCP nodes; should be ``>= K``. Below that the
451
+ corner-preserving property is impossible and this falls back to
452
+ uniform resampling, which may clip corners.
453
+ t_total: Assumed total traversal time, used to finite-difference the
454
+ velocity guess [s].
455
+
456
+ Returns:
457
+ ``(position, velocity)``, each ``(n_nodes, 2)``. Endpoint velocities
458
+ are zeroed to match the usual rest-to-rest boundary conditions.
459
+ """
460
+ K = len(path)
461
+ seg_len = np.linalg.norm(np.diff(path, axis=0), axis=1)
462
+
463
+ if n_nodes < K:
464
+ arc = np.concatenate([[0.0], np.cumsum(seg_len)])
465
+ arc /= arc[-1]
466
+ s = np.linspace(0.0, 1.0, n_nodes)
467
+ pos = np.column_stack([np.interp(s, arc, path[:, 0]), np.interp(s, arc, path[:, 1])])
468
+ else:
469
+ extra = n_nodes - K
470
+ raw = seg_len / seg_len.sum() * extra
471
+ interior = np.floor(raw).astype(int)
472
+ deficit = extra - int(interior.sum())
473
+ if deficit > 0:
474
+ order = np.argsort(-(raw - interior))
475
+ interior[order[:deficit]] += 1
476
+
477
+ chunks: list[np.ndarray] = []
478
+ for i in range(K - 1):
479
+ chunks.append(path[i][None, :])
480
+ if interior[i] > 0:
481
+ ts = np.linspace(0.0, 1.0, interior[i] + 2)[1:-1, None]
482
+ chunks.append(path[i] * (1.0 - ts) + path[i + 1] * ts)
483
+ chunks.append(path[-1][None, :])
484
+ pos = np.vstack(chunks)
485
+
486
+ # Node spacing is non-uniform, so hand np.gradient the per-node time stamps.
487
+ node_arc = np.concatenate([[0.0], np.cumsum(np.linalg.norm(np.diff(pos, axis=0), axis=1))])
488
+ t_nodes = t_total * node_arc / node_arc[-1]
489
+ vel = np.gradient(pos, t_nodes, axis=0)
490
+ vel[0] = 0.0
491
+ vel[-1] = 0.0
492
+ return pos, vel