openscvx 0.3.2.dev173__tar.gz → 0.3.2.dev195__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.3.2.dev173/openscvx.egg-info → openscvx-0.3.2.dev195}/PKG-INFO +1 -1
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/drone/dr_vp.py +18 -15
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/drone/dr_vp_nodal.py +18 -15
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/drone/dr_vp_polytope.py +13 -12
- openscvx-0.3.2.dev195/examples/drone/obstacle_avoidance_vmap.py +238 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/plotting_viser.py +6 -2
- openscvx-0.3.2.dev195/examples/spacecraft/proxops_cw.py +188 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/__init__.py +3 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/_version.py +3 -3
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/plotting/viser/primitives.py +37 -17
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/plotting/viser/server.py +10 -7
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/__init__.py +5 -0
- openscvx-0.3.2.dev195/openscvx/symbolic/expr/vmap.py +321 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/lowerers/jax.py +71 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195/openscvx.egg-info}/PKG-INFO +1 -1
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx.egg-info/SOURCES.txt +5 -1
- openscvx-0.3.2.dev195/tests/symbolic/expr/test_vmap.py +414 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/.github/assets/logo.svg +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/.github/release-drafter.yml +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/.github/workflows/docs.yml +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/.github/workflows/lint.yml +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/.github/workflows/release.yml +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/.github/workflows/tests-integration.yml +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/.github/workflows/tests-unit.yml +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/.gitignore +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/CONTRIBUTING.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/LICENSE +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/README.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Overview/constraint_reformulation.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Overview/control_parameterization.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Overview/discretization.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Overview/ocp.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Overview/scvx.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Overview/time_dilation.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Usage/advanced_problem_setup.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Usage/api.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Usage/api_constraints.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Usage/api_control.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Usage/api_integrators.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Usage/api_state.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Usage/api_trajoptproblem.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Usage/api_variable.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Usage/basic_problem_setup.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Usage/tutorial_6dof_los_guidance.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Usage/tutorial_6dof_obstacle_avoidance.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/Usage/tutorials.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/assets/favicon.png +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/assets/logo.svg +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/citation.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/examples.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/getting-started.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/index.md +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/abstract/3DoF_pdg.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/arm/three_link_arm.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/car/dubins_car.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/car/dubins_car_stljax.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/drone/cinema_vp.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/drone/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/drone/drone_racing.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/drone/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/plotting.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/figures/video_preview.png +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/1-background.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/1-background@1x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/1-background@2x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/1-background@3x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/1-background@4x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/2-mars.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/2-mars@1x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/2-mars@2x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/2-mars@3x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/2-mars@4x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/3-moon.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/3-moon@1x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/3-moon@2x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/3-moon@3x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/3-moon@4x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/4-sat1.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/4-sat1@1x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/4-sat1@2x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/4-sat1@3x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/4-sat1@4x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/5-space.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/5-space@1x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/5-space@2x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/5-space@3x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/5-space@4x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/6-earth.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/6-earth@1x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/6-earth@2x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/6-earth@3x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/images/layers/6-earth@4x.avif +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/javascripts/parallax.js +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/logo.svg +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/assets/stylesheets/parallax.css +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/home.html +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/main.html +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/partials/parallax/hero.html +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/material/overrides/partials/parallax.html +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/mkdocs.yml +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/algorithms/autotuning.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/algorithms/base.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/algorithms/penalized_trust_region.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/config.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/discretization/discretization.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/expert/byof.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/expert/validation.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/plotting/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/plotting/plotting.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/problem.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/solvers/cvxpy.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/augmentation.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/builder.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/lower.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/lowerers/cvxpy.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/time.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/utils/cache.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/utils/caching.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/utils/printing.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx/utils/utils.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx.egg-info/requires.txt +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/pyproject.toml +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/scripts/gen_example_pages.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/setup.cfg +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/test_augmentation.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/test_brachistochrone.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/test_discretization.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/test_examples.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/test_expert.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/test_integrators.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/test_plotting.py +0 -0
- {openscvx-0.3.2.dev173 → openscvx-0.3.2.dev195}/tests/test_propagation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.3.2.
|
|
3
|
+
Version: 0.3.2.dev195
|
|
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
|
|
@@ -116,14 +116,13 @@ for center in gate_centers:
|
|
|
116
116
|
### End Gate Parameters ###
|
|
117
117
|
|
|
118
118
|
n_subs = 10
|
|
119
|
-
init_poses = []
|
|
120
119
|
np.random.seed(0)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
120
|
+
init_poses = np.array(
|
|
121
|
+
[
|
|
122
|
+
[100.0 + np.random.random() * 20.0, -60.0 + np.random.random() * 20.0, 20.0]
|
|
123
|
+
for _ in range(n_subs)
|
|
124
|
+
]
|
|
125
|
+
) # Shape: (n_subs, 3)
|
|
127
126
|
|
|
128
127
|
|
|
129
128
|
# Define list of all states (needed for Problem and constraints)
|
|
@@ -142,9 +141,16 @@ constraints = []
|
|
|
142
141
|
for state in states:
|
|
143
142
|
constraints.extend([ox.ctcs(state <= state.max), ox.ctcs(state.min <= state)])
|
|
144
143
|
|
|
145
|
-
# Add visibility constraints using
|
|
146
|
-
|
|
147
|
-
|
|
144
|
+
# Add visibility constraints using Vmap for parallel evaluation
|
|
145
|
+
# Single CTCS constraint with vectorized evaluation over all target poses
|
|
146
|
+
visibility_constraint = ox.ctcs(
|
|
147
|
+
ox.Vmap(
|
|
148
|
+
lambda pose: g_vp(pose, position, attitude),
|
|
149
|
+
batch=init_poses,
|
|
150
|
+
)
|
|
151
|
+
<= 0.0
|
|
152
|
+
)
|
|
153
|
+
constraints.append(visibility_constraint)
|
|
148
154
|
|
|
149
155
|
# Add gate constraints using symbolic expressions
|
|
150
156
|
for node, cen in zip(gate_nodes, A_gate_cen):
|
|
@@ -207,12 +213,9 @@ for _ in range(n_gates + 1):
|
|
|
207
213
|
# Modify attitude to point sensor at targets
|
|
208
214
|
R_sb = R_sb # Sensor to body frame
|
|
209
215
|
b = R_sb @ np.array([0, 1, 0])
|
|
216
|
+
mean_target = np.mean(init_poses, axis=0) # Average target position
|
|
210
217
|
for k in range(n):
|
|
211
|
-
|
|
212
|
-
for pose in init_poses:
|
|
213
|
-
kp.append(pose)
|
|
214
|
-
kp = np.mean(kp, axis=0)
|
|
215
|
-
a = kp - position_bar[k]
|
|
218
|
+
a = mean_target - position_bar[k]
|
|
216
219
|
# Determine the direction cosine matrix that aligns the z-axis of the sensor frame with the
|
|
217
220
|
# relative position vector
|
|
218
221
|
q_xyz = np.cross(b, a)
|
|
@@ -116,14 +116,13 @@ for center in gate_centers:
|
|
|
116
116
|
### End Gate Parameters ###
|
|
117
117
|
|
|
118
118
|
n_subs = 10
|
|
119
|
-
init_poses = []
|
|
120
119
|
np.random.seed(5)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
120
|
+
init_poses = np.array(
|
|
121
|
+
[
|
|
122
|
+
[100.0 + np.random.random() * 20.0, -70.0 + np.random.random() * 20.0, 20.0]
|
|
123
|
+
for _ in range(n_subs)
|
|
124
|
+
]
|
|
125
|
+
) # Shape: (n_subs, 3)
|
|
127
126
|
|
|
128
127
|
|
|
129
128
|
# Define list of all states (needed for Problem and constraints)
|
|
@@ -142,9 +141,16 @@ constraints = []
|
|
|
142
141
|
for state in states:
|
|
143
142
|
constraints.extend([ox.ctcs(state <= state.max), ox.ctcs(state.min <= state)])
|
|
144
143
|
|
|
145
|
-
# Add visibility constraints using
|
|
146
|
-
|
|
147
|
-
|
|
144
|
+
# Add visibility constraints using Vmap for parallel evaluation
|
|
145
|
+
# Single nodal constraint with vectorized evaluation over all target poses
|
|
146
|
+
visibility_constraint = (
|
|
147
|
+
ox.Vmap(
|
|
148
|
+
lambda pose: g_vp(pose, position, attitude),
|
|
149
|
+
batch=init_poses,
|
|
150
|
+
)
|
|
151
|
+
<= 0.0
|
|
152
|
+
)
|
|
153
|
+
constraints.append(visibility_constraint)
|
|
148
154
|
|
|
149
155
|
# Add gate constraints using symbolic expressions
|
|
150
156
|
for node, cen in zip(gate_nodes, A_gate_cen):
|
|
@@ -207,12 +213,9 @@ for _ in range(n_gates + 1):
|
|
|
207
213
|
# Modify attitude to point sensor at targets
|
|
208
214
|
R_sb = R_sb # Sensor to body frame
|
|
209
215
|
b = R_sb @ np.array([0, 1, 0])
|
|
216
|
+
mean_target = np.mean(init_poses, axis=0) # Average target position
|
|
210
217
|
for k in range(n):
|
|
211
|
-
|
|
212
|
-
for pose in init_poses:
|
|
213
|
-
kp.append(pose)
|
|
214
|
-
kp = np.mean(kp, axis=0)
|
|
215
|
-
a = kp - position_bar[k]
|
|
218
|
+
a = mean_target - position_bar[k]
|
|
216
219
|
# Determine the direction cosine matrix that aligns the z-axis of the sensor frame with the
|
|
217
220
|
# relative position vector
|
|
218
221
|
q_xyz = np.cross(b, a)
|
|
@@ -111,10 +111,7 @@ polytope_point = np.array(
|
|
|
111
111
|
[107.47, -50.00, 22.85],
|
|
112
112
|
]
|
|
113
113
|
)
|
|
114
|
-
init_poses =
|
|
115
|
-
for point in polytope_point:
|
|
116
|
-
init_poses.append(point)
|
|
117
|
-
init_poses = init_poses
|
|
114
|
+
init_poses = polytope_point # Shape: (20, 3)
|
|
118
115
|
### Gate Parameters ###
|
|
119
116
|
n_gates = 10
|
|
120
117
|
gate_centers = [
|
|
@@ -162,9 +159,16 @@ constraints = []
|
|
|
162
159
|
for state in states:
|
|
163
160
|
constraints.extend([ox.ctcs(state <= state.max), ox.ctcs(state.min <= state)])
|
|
164
161
|
|
|
165
|
-
# Add visibility constraints
|
|
166
|
-
|
|
167
|
-
|
|
162
|
+
# Add visibility constraints using Vmap for parallel evaluation
|
|
163
|
+
# Single CTCS constraint with vectorized evaluation over all polytope points
|
|
164
|
+
visibility_constraint = ox.ctcs(
|
|
165
|
+
ox.Vmap(
|
|
166
|
+
lambda pose: g_vp(pose, position, attitude),
|
|
167
|
+
batch=init_poses,
|
|
168
|
+
)
|
|
169
|
+
<= 0.0
|
|
170
|
+
)
|
|
171
|
+
constraints.append(visibility_constraint)
|
|
168
172
|
|
|
169
173
|
# Add gate constraints using symbolic expressions
|
|
170
174
|
for node, cen in zip(gate_nodes, A_gate_cen):
|
|
@@ -227,12 +231,9 @@ for _ in range(n_gates + 1):
|
|
|
227
231
|
# Modify attitude to point sensor at targets
|
|
228
232
|
R_sb = R_sb # Sensor to body frame
|
|
229
233
|
b = R_sb @ np.array([0, 1, 0])
|
|
234
|
+
mean_target = np.mean(init_poses, axis=0) # Average target position
|
|
230
235
|
for k in range(n):
|
|
231
|
-
|
|
232
|
-
for pose in init_poses:
|
|
233
|
-
kp.append(pose)
|
|
234
|
-
kp = np.mean(kp, axis=0)
|
|
235
|
-
a = kp - position_bar[k]
|
|
236
|
+
a = mean_target - position_bar[k]
|
|
236
237
|
# Determine the direction cosine matrix that aligns the z-axis of the sensor frame with the
|
|
237
238
|
# relative position vector
|
|
238
239
|
q_xyz = np.cross(b, a)
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"""Double integrator obstacle avoidance with Vmap for parallel constraint evaluation.
|
|
2
|
+
|
|
3
|
+
This example demonstrates using ox.Vmap directly in constraints for data-parallel
|
|
4
|
+
obstacle avoidance with numerous spherical obstacles.
|
|
5
|
+
|
|
6
|
+
The approach:
|
|
7
|
+
|
|
8
|
+
1. Stack all obstacle centers into a single array
|
|
9
|
+
2. Use Vmap directly in the constraint to compute distances in parallel
|
|
10
|
+
3. The vector-valued constraint is enforced element-wise
|
|
11
|
+
|
|
12
|
+
Compare with:
|
|
13
|
+
- obstacle_avoidance.py (manual loop over 3 obstacles)
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
import sys
|
|
18
|
+
|
|
19
|
+
import numpy as np
|
|
20
|
+
|
|
21
|
+
# Add grandparent directory to path to import examples.plotting
|
|
22
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
23
|
+
grandparent_dir = os.path.dirname(os.path.dirname(current_dir))
|
|
24
|
+
sys.path.append(grandparent_dir)
|
|
25
|
+
|
|
26
|
+
import openscvx as ox
|
|
27
|
+
from examples.plotting_viser import (
|
|
28
|
+
create_animated_plotting_server,
|
|
29
|
+
create_scp_animated_plotting_server,
|
|
30
|
+
)
|
|
31
|
+
from openscvx import Problem
|
|
32
|
+
|
|
33
|
+
n = 6 # Number of nodes
|
|
34
|
+
total_time = 10.0 # Total time for the simulation
|
|
35
|
+
|
|
36
|
+
# =============================================================================
|
|
37
|
+
# State and Control Definitions
|
|
38
|
+
# =============================================================================
|
|
39
|
+
|
|
40
|
+
# 3D position
|
|
41
|
+
position = ox.State("position", shape=(3,))
|
|
42
|
+
position.max = np.array([15.0, 15.0, 15.0])
|
|
43
|
+
position.min = np.array([-15.0, -15.0, 0.0])
|
|
44
|
+
position.initial = np.array([-10.0, -10.0, 2.0])
|
|
45
|
+
position.final = np.array([10.0, 10.0, 2.0])
|
|
46
|
+
|
|
47
|
+
# 3D velocity
|
|
48
|
+
velocity = ox.State("velocity", shape=(3,))
|
|
49
|
+
velocity.max = np.array([10.0, 10.0, 10.0])
|
|
50
|
+
velocity.min = np.array([-10.0, -10.0, -10.0])
|
|
51
|
+
velocity.initial = np.array([0.0, 0.0, 0.0])
|
|
52
|
+
velocity.final = [("free", 0.0), ("free", 0.0), ("free", 0.0)]
|
|
53
|
+
|
|
54
|
+
# Control force
|
|
55
|
+
force = ox.Control("force", shape=(3,))
|
|
56
|
+
f_max = 20.0
|
|
57
|
+
force.max = np.array([f_max, f_max, f_max])
|
|
58
|
+
force.min = np.array([-f_max, -f_max, -f_max])
|
|
59
|
+
|
|
60
|
+
# Physical parameters
|
|
61
|
+
m = 1.0 # Mass
|
|
62
|
+
g = -9.81 # Gravity
|
|
63
|
+
|
|
64
|
+
# =============================================================================
|
|
65
|
+
# Obstacle Configuration (3D grid)
|
|
66
|
+
# =============================================================================
|
|
67
|
+
|
|
68
|
+
obstacle_radius_min, obstacle_radius_max = 1.0, 2.5
|
|
69
|
+
|
|
70
|
+
# Generate obstacle positions in a 3D grid pattern between start and goal
|
|
71
|
+
np.random.seed(42)
|
|
72
|
+
obstacle_centers = []
|
|
73
|
+
|
|
74
|
+
# Tweak number of obstacles by changing the grid sizes
|
|
75
|
+
n_rows = 4
|
|
76
|
+
n_cols = 4
|
|
77
|
+
n_lays = 4
|
|
78
|
+
|
|
79
|
+
# Create a 3D field of obstacles: rows (x) x columns (y) x layers (z)
|
|
80
|
+
for i in range(n_rows):
|
|
81
|
+
for j in range(n_cols):
|
|
82
|
+
for k in range(n_lays):
|
|
83
|
+
# Base grid position
|
|
84
|
+
x = -6.0 + i * 6.0
|
|
85
|
+
y = -7.5 + j * 5.0
|
|
86
|
+
z = 1.0 + k * 2.5 # Layers at z = 1.0, 3.5, 6.0
|
|
87
|
+
# Add some randomness
|
|
88
|
+
x += np.random.uniform(-1.0, 1.0)
|
|
89
|
+
y += np.random.uniform(-1.0, 1.0)
|
|
90
|
+
z += np.random.uniform(-0.5, 0.5)
|
|
91
|
+
obstacle_centers.append([x, y, z])
|
|
92
|
+
|
|
93
|
+
n_obstacles = len(obstacle_centers) # 36 obstacles
|
|
94
|
+
|
|
95
|
+
obstacle_centers = np.array(obstacle_centers) # Shape: (n_obstacles, 3)
|
|
96
|
+
obstacle_radii = np.random.uniform(obstacle_radius_min, obstacle_radius_max, size=n_obstacles)
|
|
97
|
+
|
|
98
|
+
print(f"Created {n_obstacles} obstacles")
|
|
99
|
+
print(f"Obstacle centers shape: {obstacle_centers.shape}")
|
|
100
|
+
|
|
101
|
+
# =============================================================================
|
|
102
|
+
# Dynamics (simple double integrator)
|
|
103
|
+
# =============================================================================
|
|
104
|
+
|
|
105
|
+
dynamics = {
|
|
106
|
+
"position": velocity,
|
|
107
|
+
"velocity": (1.0 / m) * force + np.array([0.0, 0.0, g]),
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# =============================================================================
|
|
111
|
+
# Constraints
|
|
112
|
+
# =============================================================================
|
|
113
|
+
|
|
114
|
+
states = [position, velocity]
|
|
115
|
+
controls = [force]
|
|
116
|
+
|
|
117
|
+
constraints = []
|
|
118
|
+
|
|
119
|
+
# Box constraints on states
|
|
120
|
+
for state in states:
|
|
121
|
+
constraints.extend(
|
|
122
|
+
[
|
|
123
|
+
ox.ctcs(state <= state.max),
|
|
124
|
+
ox.ctcs(state.min <= state),
|
|
125
|
+
]
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# Box constraints on controls
|
|
129
|
+
constraints.extend(
|
|
130
|
+
[
|
|
131
|
+
force <= force.max,
|
|
132
|
+
force.min <= force,
|
|
133
|
+
]
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
# =============================================================================
|
|
137
|
+
# Obstacle Avoidance
|
|
138
|
+
# =============================================================================
|
|
139
|
+
# Two approaches are shown below for benchmarking. Comment/uncomment to toggle.
|
|
140
|
+
|
|
141
|
+
# --- APPROACH 1: Vmap (single constraint, vectorized) ---
|
|
142
|
+
# - Single CTCS constraint with vectorized evaluation
|
|
143
|
+
# - Vmap computes distance to all obstacles in parallel
|
|
144
|
+
|
|
145
|
+
obstacle_avoidance = ox.ctcs(
|
|
146
|
+
obstacle_radii
|
|
147
|
+
<= ox.Vmap(
|
|
148
|
+
lambda obs_center: ox.linalg.Norm(position - obs_center),
|
|
149
|
+
batch=obstacle_centers,
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
constraints.append(obstacle_avoidance)
|
|
153
|
+
|
|
154
|
+
# --- APPROACH 2: Individual constraints (loop, no vmap) ---
|
|
155
|
+
# - Creates n_obstacles separate CTCS constraints
|
|
156
|
+
# - Each constraint is lowered and traced independently
|
|
157
|
+
|
|
158
|
+
# for i in range(n_obstacles):
|
|
159
|
+
# obs_center = obstacle_centers[i]
|
|
160
|
+
# radius = obstacle_radii[i]
|
|
161
|
+
# obstacle_constraint = ox.ctcs(
|
|
162
|
+
# radius <= ox.linalg.Norm(position - obs_center)
|
|
163
|
+
# )
|
|
164
|
+
# constraints.append(obstacle_constraint)
|
|
165
|
+
|
|
166
|
+
# =============================================================================
|
|
167
|
+
# Initial Guesses
|
|
168
|
+
# =============================================================================
|
|
169
|
+
|
|
170
|
+
straight_line = np.linspace(position.initial, position.final, n)
|
|
171
|
+
position.guess = straight_line
|
|
172
|
+
velocity.guess = np.zeros((n, 3))
|
|
173
|
+
force.guess = np.tile([0.0, 0.0, -m * g], (n, 1)) # Hover thrust
|
|
174
|
+
|
|
175
|
+
# =============================================================================
|
|
176
|
+
# Problem Setup
|
|
177
|
+
# =============================================================================
|
|
178
|
+
|
|
179
|
+
time = ox.Time(
|
|
180
|
+
initial=0.0,
|
|
181
|
+
final=("minimize", total_time),
|
|
182
|
+
min=0.0,
|
|
183
|
+
max=total_time,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
problem = Problem(
|
|
187
|
+
dynamics=dynamics,
|
|
188
|
+
states=states,
|
|
189
|
+
controls=controls,
|
|
190
|
+
time=time,
|
|
191
|
+
constraints=constraints,
|
|
192
|
+
N=n,
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
# SCP settings
|
|
196
|
+
problem.settings.prp.dt = 0.01
|
|
197
|
+
problem.settings.scp.w_tr = 5e0
|
|
198
|
+
problem.settings.scp.lam_cost = 1e0
|
|
199
|
+
problem.settings.scp.lam_vc = 1e2
|
|
200
|
+
problem.settings.scp.ep_tr = 1e-3
|
|
201
|
+
problem.settings.scp.ep_vb = 1e-4
|
|
202
|
+
problem.settings.scp.ep_vc = 1e-8
|
|
203
|
+
problem.settings.scp.cost_drop = 5
|
|
204
|
+
problem.settings.scp.cost_relax = 0.7
|
|
205
|
+
problem.settings.scp.w_tr_adapt = 1.5
|
|
206
|
+
|
|
207
|
+
# =============================================================================
|
|
208
|
+
# Solve and Visualize
|
|
209
|
+
# =============================================================================
|
|
210
|
+
|
|
211
|
+
if __name__ == "__main__":
|
|
212
|
+
problem.initialize()
|
|
213
|
+
results = problem.solve()
|
|
214
|
+
results = problem.post_process()
|
|
215
|
+
|
|
216
|
+
# Store obstacle info for visualization
|
|
217
|
+
results.update(
|
|
218
|
+
{
|
|
219
|
+
"obstacles_centers": [c for c in obstacle_centers],
|
|
220
|
+
"obstacles_radii": [[1 / r, 1 / r, 1 / r] for r in obstacle_radii],
|
|
221
|
+
"obstacles_axes": [np.eye(3) for _ in range(n_obstacles)],
|
|
222
|
+
}
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
# Create viser visualization servers
|
|
226
|
+
traj_server = create_animated_plotting_server(
|
|
227
|
+
results,
|
|
228
|
+
thrust_key="force",
|
|
229
|
+
viewcone_scale=5.0,
|
|
230
|
+
)
|
|
231
|
+
scp_server = create_scp_animated_plotting_server(
|
|
232
|
+
results,
|
|
233
|
+
attitude_stride=3,
|
|
234
|
+
frame_duration_ms=200,
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
# Keep servers running
|
|
238
|
+
traj_server.sleep_forever()
|
|
@@ -58,6 +58,7 @@ def create_animated_plotting_server(
|
|
|
58
58
|
target_radius: float = 1.0,
|
|
59
59
|
show_control_plot: str | None = None,
|
|
60
60
|
show_control_norm_plot: str | None = None,
|
|
61
|
+
show_grid: bool = True,
|
|
61
62
|
) -> viser.ViserServer:
|
|
62
63
|
"""Create an animated trajectory visualization server.
|
|
63
64
|
|
|
@@ -101,6 +102,7 @@ def create_animated_plotting_server(
|
|
|
101
102
|
showing each control component vs time with animated markers
|
|
102
103
|
show_control_norm_plot: If provided with a control name, displays norm plot
|
|
103
104
|
showing ‖control‖₂ vs time with animated marker
|
|
105
|
+
show_grid: Whether to show the grid (default True)
|
|
104
106
|
|
|
105
107
|
Returns:
|
|
106
108
|
ViserServer instance (animation runs in background thread)
|
|
@@ -135,7 +137,7 @@ def create_animated_plotting_server(
|
|
|
135
137
|
colors = compute_velocity_colors(vel)
|
|
136
138
|
|
|
137
139
|
# Create server
|
|
138
|
-
server = create_server(pos)
|
|
140
|
+
server = create_server(pos, show_grid=show_grid)
|
|
139
141
|
|
|
140
142
|
# Add static elements
|
|
141
143
|
if "vertices" in results:
|
|
@@ -257,6 +259,7 @@ def create_scp_animated_plotting_server(
|
|
|
257
259
|
frame_duration_ms: int = 500,
|
|
258
260
|
scene_scale: float = 1.0,
|
|
259
261
|
cmap_name: str = "viridis",
|
|
262
|
+
show_grid: bool = True,
|
|
260
263
|
) -> viser.ViserServer:
|
|
261
264
|
"""Create an animated visualization of SCP iteration convergence.
|
|
262
265
|
|
|
@@ -289,6 +292,7 @@ def create_scp_animated_plotting_server(
|
|
|
289
292
|
scene_scale: Divide all positions by this factor. Use >1 for large-scale
|
|
290
293
|
trajectories (e.g., 100.0 for km-scale problems).
|
|
291
294
|
cmap_name: Matplotlib colormap name for iteration coloring (default: "viridis")
|
|
295
|
+
show_grid: Whether to show the grid (default True)
|
|
292
296
|
|
|
293
297
|
Returns:
|
|
294
298
|
ViserServer instance (animation runs in background thread)
|
|
@@ -322,7 +326,7 @@ def create_scp_animated_plotting_server(
|
|
|
322
326
|
attitudes = [X[:, attitude_slice] for X in X_history]
|
|
323
327
|
|
|
324
328
|
# Create server using final iteration's positions for grid sizing
|
|
325
|
-
server = create_server(positions[-1])
|
|
329
|
+
server = create_server(positions[-1], show_grid=show_grid)
|
|
326
330
|
|
|
327
331
|
# Add static elements (gates, obstacles) if present
|
|
328
332
|
if "vertices" in results:
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"""Proximity Operations (ProxOps) using Clohessy-Wiltshire dynamics.
|
|
2
|
+
|
|
3
|
+
This example demonstrates optimal trajectory generation for spacecraft
|
|
4
|
+
proximity operations and docking using the Clohessy-Wiltshire (CW) equations
|
|
5
|
+
for relative motion in a circular orbit.
|
|
6
|
+
See [Clohessy-Wiltshire equations](https://en.wikipedia.org/wiki/Clohessy%E2%80%93Wiltshire_equations)
|
|
7
|
+
for further details.
|
|
8
|
+
The problem includes:
|
|
9
|
+
|
|
10
|
+
- 3D relative position and velocity dynamics (CW equations)
|
|
11
|
+
- Fuel-optimal control (minimize delta-v)
|
|
12
|
+
- Thrust magnitude constraints
|
|
13
|
+
- Approach cone constraint for safe docking corridor
|
|
14
|
+
- Final docking at target (origin)
|
|
15
|
+
|
|
16
|
+
!!! tip "The CW frame convention:"
|
|
17
|
+
- x: radial direction (outward from Earth)
|
|
18
|
+
- y: along-track direction (velocity direction)
|
|
19
|
+
- z: cross-track direction (normal to orbit plane)
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import os
|
|
23
|
+
import sys
|
|
24
|
+
|
|
25
|
+
import numpy as np
|
|
26
|
+
|
|
27
|
+
# Add grandparent directory to path to import examples.plotting
|
|
28
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
29
|
+
grandparent_dir = os.path.dirname(os.path.dirname(current_dir))
|
|
30
|
+
sys.path.append(grandparent_dir)
|
|
31
|
+
|
|
32
|
+
import openscvx as ox
|
|
33
|
+
from examples.plotting_viser import (
|
|
34
|
+
create_animated_plotting_server,
|
|
35
|
+
create_scp_animated_plotting_server,
|
|
36
|
+
)
|
|
37
|
+
from openscvx import Problem
|
|
38
|
+
from openscvx.plotting import plot_scp_iterations
|
|
39
|
+
from openscvx.plotting.viser import add_glideslope_cone
|
|
40
|
+
|
|
41
|
+
# Problem parameters
|
|
42
|
+
n_nodes = 5 # Number of discretization nodes
|
|
43
|
+
total_time = 180.0 # Total maneuver time in seconds
|
|
44
|
+
|
|
45
|
+
# Orbital parameters (ISS-like orbit at ~400 km altitude)
|
|
46
|
+
mu = 3.986004418e14 # Earth gravitational parameter [m^3/s^2]
|
|
47
|
+
a = 6.778e6 # Semi-major axis [m] (Earth radius + 400 km)
|
|
48
|
+
n = np.sqrt(mu / a**3) # Mean motion [rad/s] (~0.00113 rad/s)
|
|
49
|
+
|
|
50
|
+
# Define state components
|
|
51
|
+
# Position in CW frame [x, y, z] in meters
|
|
52
|
+
position = ox.State("position", shape=(3,))
|
|
53
|
+
position.max = np.array([100.0, 100.0, 100.0])
|
|
54
|
+
position.min = np.array([-100.0, -100.0, -100.0])
|
|
55
|
+
position.initial = np.array([0.0, -100.0, 0.0]) # Start 100m behind target (V-bar position)
|
|
56
|
+
position.final = np.array([0.0, 0.0, 0.0]) # Dock at origin
|
|
57
|
+
position.guess = np.linspace(position.initial, position.final, n_nodes)
|
|
58
|
+
|
|
59
|
+
# Velocity in CW frame [vx, vy, vz] in m/s
|
|
60
|
+
velocity = ox.State("velocity", shape=(3,))
|
|
61
|
+
v_max = 2.0 # Maximum relative velocity [m/s]
|
|
62
|
+
velocity.max = np.array([v_max, v_max, v_max])
|
|
63
|
+
velocity.min = np.array([-v_max, -v_max, -v_max])
|
|
64
|
+
velocity.initial = [0.0, 2.0, 0.0]
|
|
65
|
+
velocity.final = np.array([0.0, 0.0, 0.0]) # Zero relative velocity at docking
|
|
66
|
+
velocity.guess = np.zeros((n_nodes, 3))
|
|
67
|
+
|
|
68
|
+
# Define control: acceleration from thrusters [ax, ay, az] in m/s^2
|
|
69
|
+
accel = ox.Control("accel", shape=(3,))
|
|
70
|
+
a_max = 0.1 # Maximum acceleration [m/s^2] (typical for reaction control thrusters)
|
|
71
|
+
accel.max = np.array([a_max, a_max, a_max])
|
|
72
|
+
accel.min = np.array([-a_max, -a_max, -a_max])
|
|
73
|
+
accel.guess = np.zeros((n_nodes, 3))
|
|
74
|
+
|
|
75
|
+
# Define list of all states and controls
|
|
76
|
+
states = [position, velocity]
|
|
77
|
+
controls = [accel]
|
|
78
|
+
|
|
79
|
+
# Generate constraints
|
|
80
|
+
constraints = []
|
|
81
|
+
|
|
82
|
+
# Box constraints for states
|
|
83
|
+
for state in states:
|
|
84
|
+
constraints.extend(
|
|
85
|
+
[
|
|
86
|
+
ox.ctcs(state <= state.max),
|
|
87
|
+
ox.ctcs(state.min <= state),
|
|
88
|
+
]
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# R-bar approach cone constraint (from below, -x direction)
|
|
92
|
+
# Enforces sqrt(y^2 + z^2) <= tan(theta) * (-x)
|
|
93
|
+
# This requires the spacecraft to approach from negative x (below target)
|
|
94
|
+
# and stay within a cone centered on the -x axis
|
|
95
|
+
cone_half_angle = 20 * np.pi / 180 # 20 degree half-angle
|
|
96
|
+
constraints.append(
|
|
97
|
+
ox.ctcs(ox.linalg.Norm(position[1:]) <= np.tan(cone_half_angle) * (-position[0])).over(
|
|
98
|
+
(n_nodes - 3, n_nodes - 1)
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
# Enforce entrance to the cone at safe distance
|
|
102
|
+
constraints.append((-position[0] >= 20.0).at([n_nodes - 3]))
|
|
103
|
+
|
|
104
|
+
# Clohessy-Wiltshire dynamics
|
|
105
|
+
dynamics = {
|
|
106
|
+
"position": velocity,
|
|
107
|
+
"velocity": ox.Concat(
|
|
108
|
+
3 * n**2 * position[0] + 2 * n * velocity[1] + accel[0],
|
|
109
|
+
-2 * n * velocity[0] + accel[1],
|
|
110
|
+
-(n**2) * position[2] + accel[2],
|
|
111
|
+
),
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
# Time configuration (free final time to minimize fuel)
|
|
115
|
+
time = ox.Time(
|
|
116
|
+
initial=0.0,
|
|
117
|
+
final=("free", total_time),
|
|
118
|
+
min=0.0,
|
|
119
|
+
max=total_time,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# Build the problem
|
|
123
|
+
problem = Problem(
|
|
124
|
+
dynamics=dynamics,
|
|
125
|
+
states=states,
|
|
126
|
+
controls=controls,
|
|
127
|
+
time=time,
|
|
128
|
+
constraints=constraints,
|
|
129
|
+
N=n_nodes,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Solver settings (FOH is default, no need to set explicitly)
|
|
133
|
+
problem.settings.dis.dis_type = "ZOH"
|
|
134
|
+
problem.settings.scp.k_max = 100
|
|
135
|
+
problem.settings.scp.w_tr = 1e0
|
|
136
|
+
problem.settings.scp.w_tr_adapt = 1.2
|
|
137
|
+
problem.settings.scp.lam_cost = 1e-1
|
|
138
|
+
problem.settings.scp.lam_vc = 1e1
|
|
139
|
+
problem.settings.scp.lam_vb = 1e0
|
|
140
|
+
|
|
141
|
+
# Plotting metadata
|
|
142
|
+
plotting_dict = {
|
|
143
|
+
"mean_motion": n,
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if __name__ == "__main__":
|
|
147
|
+
problem.initialize()
|
|
148
|
+
results = problem.solve()
|
|
149
|
+
results = problem.post_process()
|
|
150
|
+
results.update(plotting_dict)
|
|
151
|
+
|
|
152
|
+
# Plot results
|
|
153
|
+
plot_scp_iterations(results).show()
|
|
154
|
+
|
|
155
|
+
# Create animation
|
|
156
|
+
traj_server = create_animated_plotting_server(results, thrust_key="accel", show_grid=False)
|
|
157
|
+
|
|
158
|
+
# Add R-bar approach cone (opens in -x direction)
|
|
159
|
+
add_glideslope_cone(
|
|
160
|
+
traj_server,
|
|
161
|
+
apex=(0, 0, 0),
|
|
162
|
+
height=20.0, # Cone extends 100m in -x direction
|
|
163
|
+
glideslope_angle_deg=cone_half_angle * 180 / np.pi,
|
|
164
|
+
axis=(-1, 0, 0), # R-bar: negative radial direction
|
|
165
|
+
color=(200, 80, 80),
|
|
166
|
+
opacity=0.5,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
# Create SCP iteration visualization
|
|
170
|
+
scp_server = create_scp_animated_plotting_server(
|
|
171
|
+
results,
|
|
172
|
+
frame_duration_ms=200,
|
|
173
|
+
scene_scale=1.0,
|
|
174
|
+
show_grid=False,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
# Add R-bar approach cone to SCP visualization
|
|
178
|
+
add_glideslope_cone(
|
|
179
|
+
scp_server,
|
|
180
|
+
apex=(0, 0, 0),
|
|
181
|
+
height=20.0,
|
|
182
|
+
glideslope_angle_deg=cone_half_angle * 180 / np.pi,
|
|
183
|
+
axis=(-1, 0, 0),
|
|
184
|
+
color=(200, 80, 80),
|
|
185
|
+
opacity=0.5,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
scp_server.sleep_forever()
|
|
@@ -51,6 +51,7 @@ from openscvx.symbolic.expr import (
|
|
|
51
51
|
Sum,
|
|
52
52
|
Tan,
|
|
53
53
|
Variable,
|
|
54
|
+
Vmap,
|
|
54
55
|
Vstack,
|
|
55
56
|
ctcs,
|
|
56
57
|
)
|
|
@@ -113,6 +114,8 @@ __all__ = [
|
|
|
113
114
|
"NodalConstraint",
|
|
114
115
|
"CTCS",
|
|
115
116
|
"ctcs",
|
|
117
|
+
# Data parallelism
|
|
118
|
+
"Vmap",
|
|
116
119
|
# Submodules
|
|
117
120
|
"stl",
|
|
118
121
|
"spatial",
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.3.2.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 3, 2, '
|
|
31
|
+
__version__ = version = '0.3.2.dev195'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 3, 2, 'dev195')
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'ged5d19a8c'
|