openscvx 0.5.3.dev51__tar.gz → 0.5.3.dev52__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openscvx-0.5.3.dev51/openscvx.egg-info → openscvx-0.5.3.dev52}/PKG-INFO +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/UsersGuide/02_drone_racing_constraints.md +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/UsersGuide/05_visualization.md +28 -1
- openscvx-0.5.3.dev52/examples/_maze.py +492 -0
- openscvx-0.5.3.dev52/examples/_maze_viz.py +464 -0
- openscvx-0.5.3.dev52/examples/abstract/chen_allgoewer.py +266 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/abstract/flappy_bird.py +139 -96
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/animations/7_dof_arm.py +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/animations/_render.py +128 -6
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/animations/franka_fr3v2_pick_place.py +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/animations/obstacle_avoidance_vmap.py +2 -2
- openscvx-0.5.3.dev52/examples/animations/senss_hop_lidar_camera.py +226 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/arm/7_dof_arm.py +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/arm/7_dof_arm_collision.py +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/arm/7_dof_arm_vp.py +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/arm/franka_fr3v2_pick_place.py +0 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/arm/franka_fr3v2_viewplanning.py +1 -2
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/arm/franka_fr3v2_viewplanning_nodal.py +1 -2
- openscvx-0.5.3.dev52/examples/car/racing/_plotting.py +311 -0
- openscvx-0.5.3.dev52/examples/car/racing/_time2spatial.py +140 -0
- openscvx-0.5.3.dev52/examples/car/racing/_tracks/LMS_Track.txt +256 -0
- openscvx-0.5.3.dev52/examples/car/racing/_tracks/LMS_Track_x4.txt +260 -0
- openscvx-0.5.3.dev52/examples/car/racing/_tracks/readDataFcn.py +47 -0
- openscvx-0.5.3.dev52/examples/car/racing/_viser.py +908 -0
- openscvx-0.5.3.dev52/examples/car/racing/race_car_hybrid.py +571 -0
- openscvx-0.5.3.dev52/examples/car/racing/race_car_ice.py +369 -0
- openscvx-0.5.3.dev52/examples/car/racing/race_car_mpc.py +537 -0
- openscvx-0.5.3.dev52/examples/car/racing/race_car_multi_agent.py +860 -0
- openscvx-0.5.3.dev52/examples/car/racing/race_car_multi_agent_mpcc.py +1154 -0
- openscvx-0.5.3.dev52/examples/car/racing/race_car_multi_agent_mpcc_ice.py +985 -0
- openscvx-0.5.3.dev52/examples/car/racing/race_car_openscvx.py +380 -0
- openscvx-0.5.3.dev52/examples/double_integrator/double_integrator_static.py +138 -0
- openscvx-0.5.3.dev52/examples/double_integrator/maze_rrt_scp.py +346 -0
- openscvx-0.5.3.dev52/examples/double_integrator/multiphase_velocity.py +155 -0
- {openscvx-0.5.3.dev51/examples/drone → openscvx-0.5.3.dev52/examples/double_integrator}/obstacle_avoidance_vmap_2d.py +58 -96
- openscvx-0.5.3.dev52/examples/drone/_plotting.py +330 -0
- openscvx-0.5.3.dev52/examples/drone/_terrain.py +143 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/logo.py +0 -53
- openscvx-0.5.3.dev52/examples/drone/lunar_terrain_agl.py +255 -0
- openscvx-0.5.3.dev52/examples/drone/maze_scp.py +592 -0
- openscvx-0.5.3.dev52/examples/drone/moving_safe_columns.py +254 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/openscvx_logo.py +4 -57
- openscvx-0.5.3.dev52/examples/drone/quadrotor_hector.py +348 -0
- openscvx-0.5.3.dev52/examples/drone/quadrotor_zigzag.py +230 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/frax/panda_frax.py +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/frax/panda_frax_viewplanning.py +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/frax/panda_frax_waypoint.py +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/mjx/triple_cartpole_3d_mjx.py +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/mjx/triple_cartpole_mjx.py +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/mpc/double_integrator_discrete.py +4 -3
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/mpc/double_integrator_drone_racing.py +4 -3
- openscvx-0.5.3.dev52/examples/multi_agent/ilqgames_three_agent.py +520 -0
- openscvx-0.5.3.dev52/examples/multi_agent/ilqgames_three_agent_lqr.py +467 -0
- {openscvx-0.5.3.dev51/examples/drone → openscvx-0.5.3.dev52/examples/multi_agent}/multi_agent_circle_swap.py +18 -31
- openscvx-0.5.3.dev52/examples/pendulum/pendulum_swingup_ocp.py +247 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/plotting.py +16 -807
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/plotting_viser.py +43 -45
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/realtime/3DoF_pdg_realtime.py +3 -2
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/realtime/6DoF_pdg_realtime.py +3 -2
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/realtime/cinema_vp_realtime.py +3 -3
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/realtime/drone_racing_realtime.py +3 -3
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/realtime/obstacle_avoidance_realtime.py +3 -3
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/rocket/6DoF_pdg.py +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/rocket/6DoF_pdg_batched_ic.py +5 -17
- openscvx-0.5.3.dev52/examples/rocket/6DoF_pdg_stc.py +726 -0
- openscvx-0.5.3.dev52/examples/rocket/6DoF_pdg_stc_ifthen.py +707 -0
- openscvx-0.5.3.dev52/examples/rocket/_cstc_plotting.py +1003 -0
- openscvx-0.5.3.dev52/examples/rocket/reusable_launch_vehicle.py +229 -0
- openscvx-0.5.3.dev52/examples/rocket/rocket_ilqr.py +392 -0
- openscvx-0.5.3.dev52/examples/rocket/senss/6DoF_pdg_dem.py +872 -0
- openscvx-0.5.3.dev52/examples/rocket/senss/6DoF_pdg_dem_static.py +381 -0
- openscvx-0.5.3.dev52/examples/rocket/senss/6DoF_pdg_stc_senss.py +817 -0
- openscvx-0.5.3.dev52/examples/rocket/senss/6DoF_pdg_stc_senss_gimbal.py +809 -0
- openscvx-0.5.3.dev52/examples/rocket/senss/6DoF_pdg_stc_senss_gimbal_hop.py +871 -0
- openscvx-0.5.3.dev52/examples/rocket/senss/6DoF_pdg_stc_senss_hop.py +870 -0
- openscvx-0.5.3.dev52/examples/rocket/senss/6DoF_pdg_stc_senss_planar.py +802 -0
- openscvx-0.5.3.dev52/examples/rocket/senss/_dem.py +363 -0
- openscvx-0.5.3.dev52/examples/rocket/senss/_halo/__init__.py +16 -0
- openscvx-0.5.3.dev52/examples/rocket/senss/_halo/dem.py +307 -0
- openscvx-0.5.3.dev52/examples/rocket/senss/_halo/lidar.py +277 -0
- openscvx-0.5.3.dev52/examples/rocket/senss/_hop_lidar_overlay.py +481 -0
- openscvx-0.5.3.dev52/examples/rocket/senss/senss_dem.png +0 -0
- openscvx-0.5.3.dev52/examples/scaling/scaling_study.py +1267 -0
- openscvx-0.5.3.dev52/examples/spacecraft/capstone/capstone.bin +0 -0
- openscvx-0.5.3.dev52/examples/spacecraft/capstone/capstone.gltf +616 -0
- openscvx-0.5.3.dev52/examples/spacecraft/capstone/capstone_albedo.jpg +0 -0
- openscvx-0.5.3.dev52/examples/spacecraft/capstone/capstone_ao.jpg +0 -0
- openscvx-0.5.3.dev52/examples/spacecraft/capstone/capstone_normals.png +0 -0
- openscvx-0.5.3.dev52/examples/spacecraft/capstone/capstone_pbr_jpg.jpg +0 -0
- openscvx-0.5.3.dev52/examples/spacecraft/capstone/capstone_plot_mesh.npz +0 -0
- openscvx-0.5.3.dev52/examples/spacecraft/capstone/foil_normal.jpg +0 -0
- openscvx-0.5.3.dev52/examples/spacecraft/dual_deputy_inspection_cw.py +672 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/spacecraft/let_transfer.py +8 -36
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/__init__.py +2 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/_version.py +3 -3
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/plotting/__init__.py +15 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/plotting/plotting.py +16 -10
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/plotting/publication.py +78 -26
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/plotting/scp_iteration.py +6 -4
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/plotting/viser/__init__.py +17 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/plotting/viser/animated.py +69 -20
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/plotting/viser/primitives.py +28 -10
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/plotting/viser/server.py +73 -11
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/__init__.py +3 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/math.py +47 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/cvxpy/math.py +12 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/math.py +9 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/math.py +9 -2
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/parser/math.py +9 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52/openscvx.egg-info}/PKG-INFO +1 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx.egg-info/SOURCES.txt +61 -5
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx.egg-info/scm_file_list.json +61 -5
- openscvx-0.5.3.dev52/openscvx.egg-info/scm_version.json +8 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/scripts/gen_example_pages.py +10 -3
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_math.py +40 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/parser/test_math.py +7 -1
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/test_lower_latex.py +6 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/test_examples.py +12 -3
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/test_plotting.py +316 -1
- openscvx-0.5.3.dev51/examples/drone/2d_obstacle_avoidance_batched_ic.py +0 -326
- openscvx-0.5.3.dev51/examples/drone/dr_double_integrator.py +0 -163
- openscvx-0.5.3.dev51/openscvx.egg-info/scm_version.json +0 -8
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/assets/logo.svg +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/release-drafter.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/workflows/_extra.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/workflows/branch-name.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/workflows/docs.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/workflows/lint.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/workflows/release.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/workflows/tests-cvxpygen.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/workflows/tests-examples.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/workflows/tests-lie.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/workflows/tests-mjx.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/workflows/tests-qpax.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.github/workflows/tests.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.gitignore +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/.gitmodules +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/CITATION.cff +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/CONTRIBUTING.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/LICENSE +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/README.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/Foundations/constraint_reformulation.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/Foundations/control_parameterization.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/Foundations/discretization.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/Foundations/ocp.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/Foundations/scvx.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/Foundations/time_dilation.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/UnderTheHood/batching_jit_grad.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/UnderTheHood/custom_algorithms_autotuners.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/UsersGuide/00_introduction.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/UsersGuide/06_logic.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/UsersGuide/07_lie.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/UsersGuide/08_mpcc.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/UsersGuide/09_mjx_dynamics.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/assets/favicon.png +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/assets/logo.svg +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/assets/openscvx_logo_square.png +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/assets/viser-client/index.html +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/assets/viser-recordings/drone_racing.viser +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/assets/viser-recordings/franka_fr3v2_pick_place.viser +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/changelog.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/citation.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/examples.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/index.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/installation.md +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/llms.txt +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/versions.json +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/_viser_embed_export.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/abstract/brachistochrone_batched.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/abstract/hypersensitive.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/abstract/impulsive.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/abstract/stl_integer_variable.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/abstract/stl_or.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/aircraft/dynamic_soaring.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/aircraft/supersonic_time_to_climb.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/animations/_camera.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/animations/_sensor_view.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/animations/dr_vp_polytope.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/animations/logo.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/arm/3_dof_arm.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/car/dubins_car.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/car/dubins_car_obstacle_conditional.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/car/dubins_car_obstacle_stl.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/car/dubins_car_stl_or.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/car/dubins_car_waypoint_stl.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/double_integrator/_plotting.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/double_integrator/moving_safe_zones.py +0 -0
- {openscvx-0.5.3.dev51/examples/drone → openscvx-0.5.3.dev52/examples/double_integrator}/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/boresight_trace_mpcc.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/cinema_vp.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/cinema_vp_nodal.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/dr_vp.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/drone_racing.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/drone_racing_batched_gates.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/logo_utils/acl_logo.svg +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/logo_utils/circle.svg +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/logo_utils/openscvx_logo_single.svg +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/logo_utils/quadrotor_mesh.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/logo_utils/svg_path_utils.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/frax/panda_frax_pick_place.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/frax/ur5e_assets/ur5e.urdf +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/frax/ur5e_pen_trace.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/frax/ur5e_pen_trace_mpcc.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/mjx/cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/mjx/double_cartpole_mjx.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/mjx/skydio_x2_mjx.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/mjx/triple_cartpole_game.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/mpc/dubins_car_circle_analytical.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/mpc/dubins_car_circle_discrete.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/rocket/ascent_launch_vehicle.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/spacecraft/halo_orbit.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/spacecraft/hohmann_transfer.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/examples/spacecraft/relative_loitering.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/figures/video_preview.png +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/material/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/material/overrides/assets/stylesheets/home-dropin.css +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/material/overrides/assets/stylesheets/home-hero.css +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/material/overrides/assets/stylesheets/home-viser.css +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/material/overrides/home.html +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/material/overrides/main.html +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/material/overrides/partials/home-diagram.html +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/material/overrides/partials/home-dropin-banner.html +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/material/overrides/partials/home-hero.html +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/material/overrides/partials/home-pipeline.html +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/material/overrides/partials/home-viser-strip.html +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/material/overrides/sitemap.xml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/mkdocs.yml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/__main__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/autotuner/acceptance_ratio.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/autotuner/adaptive_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/autotuner/augmented_lagrangian.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/autotuner/base.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/autotuner/constant_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/autotuner/ramp_proximal_weight.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/base.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/history.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/hyperparams.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/loop.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/penalty.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/scvx/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/scvx/iteration.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/scvx/penalized_trust_region.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/state.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/algorithms/weights.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/config.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/discretization/base.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/discretization/discretize_linearize.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/discretization/linearize_discretize.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/discretization/sparse_utils/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/expert/byof.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/expert/validation.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/init/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/init/interpolation.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/init/inverse_kinematics.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/integrations/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/integrations/_utils.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/integrations/base.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/integrations/frax.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/integrations/menagerie.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/integrations/mjx.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/integrators/diffrax.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/loader.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/plotting/viser/coordinates.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/plotting/viser/orbits.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/problem.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/solvers/base.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/solvers/cones.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/solvers/cvxpy_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/solvers/moreau_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/solvers/ptr_solver.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/solvers/qpax_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/affine.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/augmentation.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/builder.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/canonicalize.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/autodiff.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/parameter.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/stljax.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/time.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lower.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/cvxpy/autodiff.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/array.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/autodiff.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/control.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/state.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/_lowerer.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/_registry.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/arithmetic.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/array.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/autodiff.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/constraint.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/control.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/expr.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/formulation.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/lie.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/linalg.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/logic.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/spatial.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/state.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/stl.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/lowerers/latex/vmap.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/parser/_registry.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/parser/array.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/parser/constraint.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/parser/lie.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/parser/linalg.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/parser/logic.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/parser/parser.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/parser/spatial.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/parser/stl.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/parser/stljax.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/parser/tokenizer.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/sparsity.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/utils/cache.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/utils/caching.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/utils/printing.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx/utils/utils.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx.egg-info/entry_points.txt +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx.egg-info/requires.txt +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/pyproject.toml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/scripts/mkdocs_copy_viser_client_hook.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/scripts/mkdocs_seo_hook.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/setup.cfg +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/algorithms/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/algorithms/_iteration_helpers.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/algorithms/autotuner/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/algorithms/autotuner/test_defaults_agreement.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/algorithms/autotuner/test_hyper_overrides.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/algorithms/autotuner/test_update_weights_jit.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/algorithms/test_algorithm_state_pytree.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/algorithms/test_iteration_fn_jit.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/algorithms/test_iteration_fn_parity.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/algorithms/test_make_solve_loop.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/conftest.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/e2e/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/e2e/test_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/e2e/test_impulsive.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/e2e/test_multishot_propagation.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/e2e/test_solve_batched_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/e2e/test_solve_batched_cvxpy_export_errors.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/e2e/test_solve_batched_export_roundtrip.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/e2e/test_solve_jax_bare_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/e2e/test_solve_jax_jit_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/e2e/test_solve_jax_vmap_brachistochrone.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/e2e/test_solve_jax_vmap_converged_no_drift.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/fixtures/brachistochrone.json +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/fixtures/brachistochrone.yaml +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/hohmann_analytical.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/integrations/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/integrations/test_mjx.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/integrations/test_mjx_dynamics.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/solvers/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/solvers/_iteration_callback_helpers.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/solvers/test_cvxpy_callback_jit_spike.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/solvers/test_iteration_callback_cvxpy.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/solvers/test_iteration_callback_moreau.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/solvers/test_iteration_callback_qpax.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/solvers/test_iteration_callback_vmap.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/solvers/test_moreau_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/solvers/test_qpax_ptr_solver.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/solvers/test_subproblem_pytree.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_autodiff.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_guess_expr.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_stl.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/parser/__init__.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/parser/test_array.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/parser/test_constraint.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/parser/test_lie.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/parser/test_linalg.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/parser/test_load.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/parser/test_logic.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/parser/test_parser.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/parser/test_spatial.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/parser/test_stl.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/parser/test_tokenizer.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/parser/test_vmap.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/test_augmentation.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/test_gmsr.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/test_latex_formulation.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/test_sparsity.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/test_autotuning.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/test_discretization.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/test_expert.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/test_init.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/test_initialize_syncs_guesses.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/test_integrators.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/test_loader.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/test_optimization_results.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/test_post_process_batched_tau_clamp.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/test_propagation.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/tests/test_results_parameters.py +0 -0
- {openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/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.
|
|
3
|
+
Version: 0.5.3.dev52
|
|
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
|
{openscvx-0.5.3.dev51 → openscvx-0.5.3.dev52}/docs/UsersGuide/02_drone_racing_constraints.md
RENAMED
|
@@ -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/
|
|
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("
|
|
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
|