openscvx 0.3.2.dev228__tar.gz → 0.3.2.dev234__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.dev228/openscvx.egg-info → openscvx-0.3.2.dev234}/PKG-INFO +1 -1
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/drone/dr_double_integrator.py +5 -19
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/drone/dr_vp.py +11 -31
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/drone/dr_vp_nodal.py +11 -31
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/drone/dr_vp_polytope.py +11 -31
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/drone/drone_racing.py +4 -19
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/__init__.py +2 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/_version.py +3 -3
- openscvx-0.3.2.dev234/openscvx/init/__init__.py +30 -0
- openscvx-0.3.2.dev234/openscvx/init/interpolation.py +327 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/preprocessing.py +6 -1
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234/openscvx.egg-info}/PKG-INFO +1 -1
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx.egg-info/SOURCES.txt +3 -0
- openscvx-0.3.2.dev234/tests/test_init.py +153 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/.github/assets/logo.svg +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/.github/release-drafter.yml +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/.github/workflows/docs.yml +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/.github/workflows/lint.yml +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/.github/workflows/release.yml +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/.github/workflows/tests-integration.yml +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/.github/workflows/tests-unit.yml +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/.gitignore +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/CONTRIBUTING.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/LICENSE +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/README.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Overview/constraint_reformulation.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Overview/control_parameterization.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Overview/discretization.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Overview/ocp.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Overview/scvx.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Overview/time_dilation.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Usage/advanced_problem_setup.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Usage/api.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Usage/api_constraints.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Usage/api_control.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Usage/api_integrators.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Usage/api_state.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Usage/api_trajoptproblem.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Usage/api_variable.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Usage/basic_problem_setup.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Usage/tutorial_6dof_los_guidance.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Usage/tutorial_6dof_obstacle_avoidance.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/Usage/tutorials.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/assets/favicon.png +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/assets/logo.svg +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/citation.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/examples.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/getting-started.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/index.md +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/abstract/3DoF_pdg.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/arm/three_link_arm.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/car/dubins_car.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/car/dubins_car_stljax.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/drone/cinema_vp.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/drone/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/drone/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/plotting.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/plotting_viser.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/figures/video_preview.png +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/1-background.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/1-background@1x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/1-background@2x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/1-background@3x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/1-background@4x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/2-mars.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/2-mars@1x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/2-mars@2x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/2-mars@3x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/2-mars@4x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/3-moon.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/3-moon@1x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/3-moon@2x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/3-moon@3x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/3-moon@4x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/4-sat1.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/4-sat1@1x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/4-sat1@2x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/4-sat1@3x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/4-sat1@4x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/5-space.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/5-space@1x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/5-space@2x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/5-space@3x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/5-space@4x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/6-earth.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/6-earth@1x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/6-earth@2x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/6-earth@3x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/images/layers/6-earth@4x.avif +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/javascripts/parallax.js +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/logo.svg +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/assets/stylesheets/parallax.css +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/home.html +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/main.html +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/partials/parallax/hero.html +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/material/overrides/partials/parallax.html +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/mkdocs.yml +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/algorithms/autotuning.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/algorithms/base.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/algorithms/penalized_trust_region.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/config.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/discretization/discretization.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/expert/byof.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/expert/validation.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/plotting/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/plotting/plotting.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/problem.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/solvers/cvxpy.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/augmentation.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/builder.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/lower.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/lowerers/cvxpy.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/lowerers/jax.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/time.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/utils/cache.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/utils/caching.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/utils/printing.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx/utils/utils.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx.egg-info/requires.txt +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/pyproject.toml +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/scripts/gen_example_pages.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/setup.cfg +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/test_augmentation.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/test_brachistochrone.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/test_discretization.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/test_examples.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/test_expert.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/test_integrators.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/tests/test_plotting.py +0 -0
- {openscvx-0.3.2.dev228 → openscvx-0.3.2.dev234}/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.dev234
|
|
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
|
|
@@ -115,25 +115,11 @@ dynamics = {
|
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
for center in gate_centers:
|
|
124
|
-
origins.append(center)
|
|
125
|
-
ends.append(center)
|
|
126
|
-
ends.append(position.final)
|
|
127
|
-
gate_idx = 0
|
|
128
|
-
for _ in range(n_gates + 1):
|
|
129
|
-
for k in range(n // (n_gates + 1)):
|
|
130
|
-
position_bar[i] = origins[gate_idx] + (k / (n // (n_gates + 1))) * (
|
|
131
|
-
ends[gate_idx] - origins[gate_idx]
|
|
132
|
-
)
|
|
133
|
-
i += 1
|
|
134
|
-
gate_idx += 1
|
|
135
|
-
|
|
136
|
-
position.guess = position_bar
|
|
118
|
+
# Generate initial guess for position trajectory through gates
|
|
119
|
+
position.guess = ox.init.linspace(
|
|
120
|
+
keyframes=[position.initial] + gate_centers + [position.final],
|
|
121
|
+
nodes=[0] + list(gate_nodes) + [n - 1],
|
|
122
|
+
)
|
|
137
123
|
|
|
138
124
|
t = ox.Time(
|
|
139
125
|
initial=0.0,
|
|
@@ -187,33 +187,16 @@ dynamics = {
|
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
|
|
190
|
-
#
|
|
191
|
-
position_bar =
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
#
|
|
197
|
-
i = 0
|
|
198
|
-
origins = [position.initial]
|
|
199
|
-
ends = []
|
|
200
|
-
for center in gate_centers:
|
|
201
|
-
origins.append(center)
|
|
202
|
-
ends.append(center)
|
|
203
|
-
ends.append(position.final)
|
|
204
|
-
gate_idx = 0
|
|
205
|
-
for _ in range(n_gates + 1):
|
|
206
|
-
for k in range(n // (n_gates + 1)):
|
|
207
|
-
position_bar[i] = origins[gate_idx] + (k / (n // (n_gates + 1))) * (
|
|
208
|
-
ends[gate_idx] - origins[gate_idx]
|
|
209
|
-
)
|
|
210
|
-
i += 1
|
|
211
|
-
gate_idx += 1
|
|
212
|
-
|
|
213
|
-
# Modify attitude to point sensor at targets
|
|
214
|
-
R_sb = R_sb # Sensor to body frame
|
|
190
|
+
# Generate initial guess for position trajectory through gates
|
|
191
|
+
position_bar = ox.init.linspace(
|
|
192
|
+
keyframes=[position.initial] + gate_centers + [position.final],
|
|
193
|
+
nodes=[0] + list(gate_nodes) + [n - 1],
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
# Generate attitude guess to point sensor at mean target position
|
|
215
197
|
b = R_sb @ np.array([0, 1, 0])
|
|
216
|
-
mean_target = np.mean(init_poses, axis=0)
|
|
198
|
+
mean_target = np.mean(init_poses, axis=0)
|
|
199
|
+
attitude_bar = np.zeros((n, 4))
|
|
217
200
|
for k in range(n):
|
|
218
201
|
a = mean_target - position_bar[k]
|
|
219
202
|
# Determine the direction cosine matrix that aligns the z-axis of the sensor frame with the
|
|
@@ -221,14 +204,11 @@ for k in range(n):
|
|
|
221
204
|
q_xyz = np.cross(b, a)
|
|
222
205
|
q_w = np.sqrt(la.norm(a) ** 2 + la.norm(b) ** 2) + np.dot(a, b)
|
|
223
206
|
q_no_norm = np.hstack((q_w, q_xyz))
|
|
224
|
-
|
|
225
|
-
attitude_bar[k] = q
|
|
207
|
+
attitude_bar[k] = q_no_norm / la.norm(q_no_norm)
|
|
226
208
|
|
|
227
|
-
# Set
|
|
209
|
+
# Set guesses
|
|
228
210
|
position.guess = position_bar
|
|
229
|
-
velocity.guess = velocity_bar
|
|
230
211
|
attitude.guess = attitude_bar
|
|
231
|
-
angular_velocity.guess = angular_velocity_bar
|
|
232
212
|
|
|
233
213
|
time = ox.Time(
|
|
234
214
|
initial=0.0,
|
|
@@ -187,33 +187,16 @@ dynamics = {
|
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
|
|
190
|
-
#
|
|
191
|
-
position_bar =
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
#
|
|
197
|
-
i = 0
|
|
198
|
-
origins = [position.initial]
|
|
199
|
-
ends = []
|
|
200
|
-
for center in gate_centers:
|
|
201
|
-
origins.append(center)
|
|
202
|
-
ends.append(center)
|
|
203
|
-
ends.append(position.final)
|
|
204
|
-
gate_idx = 0
|
|
205
|
-
for _ in range(n_gates + 1):
|
|
206
|
-
for k in range(n // (n_gates + 1)):
|
|
207
|
-
position_bar[i] = origins[gate_idx] + (k / (n // (n_gates + 1))) * (
|
|
208
|
-
ends[gate_idx] - origins[gate_idx]
|
|
209
|
-
)
|
|
210
|
-
i += 1
|
|
211
|
-
gate_idx += 1
|
|
212
|
-
|
|
213
|
-
# Modify attitude to point sensor at targets
|
|
214
|
-
R_sb = R_sb # Sensor to body frame
|
|
190
|
+
# Generate initial guess for position trajectory through gates
|
|
191
|
+
position_bar = ox.init.linspace(
|
|
192
|
+
keyframes=[position.initial] + gate_centers + [position.final],
|
|
193
|
+
nodes=[0] + list(gate_nodes) + [n - 1],
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
# Generate attitude guess to point sensor at mean target position
|
|
215
197
|
b = R_sb @ np.array([0, 1, 0])
|
|
216
|
-
mean_target = np.mean(init_poses, axis=0)
|
|
198
|
+
mean_target = np.mean(init_poses, axis=0)
|
|
199
|
+
attitude_bar = np.zeros((n, 4))
|
|
217
200
|
for k in range(n):
|
|
218
201
|
a = mean_target - position_bar[k]
|
|
219
202
|
# Determine the direction cosine matrix that aligns the z-axis of the sensor frame with the
|
|
@@ -221,14 +204,11 @@ for k in range(n):
|
|
|
221
204
|
q_xyz = np.cross(b, a)
|
|
222
205
|
q_w = np.sqrt(la.norm(a) ** 2 + la.norm(b) ** 2) + np.dot(a, b)
|
|
223
206
|
q_no_norm = np.hstack((q_w, q_xyz))
|
|
224
|
-
|
|
225
|
-
attitude_bar[k] = q
|
|
207
|
+
attitude_bar[k] = q_no_norm / la.norm(q_no_norm)
|
|
226
208
|
|
|
227
|
-
# Set
|
|
209
|
+
# Set guesses
|
|
228
210
|
position.guess = position_bar
|
|
229
|
-
velocity.guess = velocity_bar
|
|
230
211
|
attitude.guess = attitude_bar
|
|
231
|
-
angular_velocity.guess = angular_velocity_bar
|
|
232
212
|
|
|
233
213
|
time = ox.Time(
|
|
234
214
|
initial=0.0,
|
|
@@ -205,33 +205,16 @@ dynamics = {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
|
|
208
|
-
#
|
|
209
|
-
position_bar =
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
#
|
|
215
|
-
i = 0
|
|
216
|
-
origins = [position.initial]
|
|
217
|
-
ends = []
|
|
218
|
-
for center in gate_centers:
|
|
219
|
-
origins.append(center)
|
|
220
|
-
ends.append(center)
|
|
221
|
-
ends.append(position.final)
|
|
222
|
-
gate_idx = 0
|
|
223
|
-
for _ in range(n_gates + 1):
|
|
224
|
-
for k in range(n // (n_gates + 1)):
|
|
225
|
-
position_bar[i] = origins[gate_idx] + (k / (n // (n_gates + 1))) * (
|
|
226
|
-
ends[gate_idx] - origins[gate_idx]
|
|
227
|
-
)
|
|
228
|
-
i += 1
|
|
229
|
-
gate_idx += 1
|
|
230
|
-
|
|
231
|
-
# Modify attitude to point sensor at targets
|
|
232
|
-
R_sb = R_sb # Sensor to body frame
|
|
208
|
+
# Generate initial guess for position trajectory through gates
|
|
209
|
+
position_bar = ox.init.linspace(
|
|
210
|
+
keyframes=[position.initial] + gate_centers + [position.final],
|
|
211
|
+
nodes=[0] + list(gate_nodes) + [n - 1],
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
# Generate attitude guess to point sensor at mean target position
|
|
233
215
|
b = R_sb @ np.array([0, 1, 0])
|
|
234
|
-
mean_target = np.mean(init_poses, axis=0)
|
|
216
|
+
mean_target = np.mean(init_poses, axis=0)
|
|
217
|
+
attitude_bar = np.zeros((n, 4))
|
|
235
218
|
for k in range(n):
|
|
236
219
|
a = mean_target - position_bar[k]
|
|
237
220
|
# Determine the direction cosine matrix that aligns the z-axis of the sensor frame with the
|
|
@@ -239,14 +222,11 @@ for k in range(n):
|
|
|
239
222
|
q_xyz = np.cross(b, a)
|
|
240
223
|
q_w = np.sqrt(la.norm(a) ** 2 + la.norm(b) ** 2) + np.dot(a, b)
|
|
241
224
|
q_no_norm = np.hstack((q_w, q_xyz))
|
|
242
|
-
|
|
243
|
-
attitude_bar[k] = q
|
|
225
|
+
attitude_bar[k] = q_no_norm / la.norm(q_no_norm)
|
|
244
226
|
|
|
245
|
-
# Set
|
|
227
|
+
# Set guesses
|
|
246
228
|
position.guess = position_bar
|
|
247
|
-
velocity.guess = velocity_bar
|
|
248
229
|
attitude.guess = attitude_bar
|
|
249
|
-
angular_velocity.guess = angular_velocity_bar
|
|
250
230
|
time = ox.Time(
|
|
251
231
|
initial=0.0,
|
|
252
232
|
final=("minimize", total_time),
|
|
@@ -233,25 +233,10 @@ dynamics = {
|
|
|
233
233
|
|
|
234
234
|
|
|
235
235
|
# Generate initial guess for position trajectory through gates
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
ends = []
|
|
241
|
-
for center in modified_centers: # Use modified centers for initial guess
|
|
242
|
-
origins.append(center)
|
|
243
|
-
ends.append(center)
|
|
244
|
-
ends.append(position.final)
|
|
245
|
-
gate_idx = 0
|
|
246
|
-
for _ in range(n_gates + 1):
|
|
247
|
-
for k in range(n // (n_gates + 1)):
|
|
248
|
-
position_bar[i] = origins[gate_idx] + (k / (n // (n_gates + 1))) * (
|
|
249
|
-
ends[gate_idx] - origins[gate_idx]
|
|
250
|
-
)
|
|
251
|
-
i += 1
|
|
252
|
-
gate_idx += 1
|
|
253
|
-
|
|
254
|
-
position.guess = position_bar
|
|
236
|
+
position.guess = ox.init.linspace(
|
|
237
|
+
keyframes=[position.initial] + modified_centers + [position.final],
|
|
238
|
+
nodes=[0] + list(gate_nodes) + [n - 1],
|
|
239
|
+
)
|
|
255
240
|
|
|
256
241
|
time = ox.Time(
|
|
257
242
|
initial=0.0,
|
|
@@ -5,6 +5,7 @@ os.environ["EQX_ON_ERROR"] = "nan"
|
|
|
5
5
|
|
|
6
6
|
# Cache management
|
|
7
7
|
# Core symbolic expressions - flat namespace for most common functions
|
|
8
|
+
import openscvx.init as init
|
|
8
9
|
import openscvx.symbolic.expr.lie as lie
|
|
9
10
|
import openscvx.symbolic.expr.linalg as linalg
|
|
10
11
|
import openscvx.symbolic.expr.spatial as spatial
|
|
@@ -123,6 +124,7 @@ __all__ = [
|
|
|
123
124
|
# Data parallelism
|
|
124
125
|
"Vmap",
|
|
125
126
|
# Submodules
|
|
127
|
+
"init",
|
|
126
128
|
"stl",
|
|
127
129
|
"spatial",
|
|
128
130
|
"linalg",
|
|
@@ -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.dev234'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 3, 2, 'dev234')
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g81cc96a04'
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Trajectory initialization utilities.
|
|
2
|
+
|
|
3
|
+
This module provides functions for generating initial trajectory guesses
|
|
4
|
+
using various interpolation methods. Keyframe-based APIs allow specifying
|
|
5
|
+
values at specific nodes with automatic interpolation for intermediate nodes.
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
Generate initial guess for a quadrotor passing through gates::
|
|
9
|
+
|
|
10
|
+
import openscvx as ox
|
|
11
|
+
|
|
12
|
+
n = 50
|
|
13
|
+
position.guess = ox.init.linspace(
|
|
14
|
+
keyframes=[start_pos, gate1, gate2, end_pos],
|
|
15
|
+
nodes=[0, 15, 35, n-1],
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
attitude.guess = ox.init.nlerp(
|
|
19
|
+
keyframes=[q_start, q_gate1, q_gate2, q_end],
|
|
20
|
+
nodes=[0, 15, 35, n-1],
|
|
21
|
+
)
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from openscvx.init.interpolation import linspace, nlerp, slerp
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"linspace",
|
|
28
|
+
"nlerp",
|
|
29
|
+
"slerp",
|
|
30
|
+
]
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
"""Trajectory initialization utilities for generating initial guesses.
|
|
2
|
+
|
|
3
|
+
This module provides interpolation methods for constructing initial trajectory
|
|
4
|
+
guesses from keyframe values at specified nodes. Keyframes define values at
|
|
5
|
+
specific nodes, and the interpolation fills in values for all intermediate nodes.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import List, Sequence, Tuple, Union
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
# Type aliases for clarity
|
|
13
|
+
Quaternion = Union[np.ndarray, Tuple[float, float, float, float], List[float]]
|
|
14
|
+
Keyframe = Union[np.ndarray, Sequence[float], float]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def linspace(
|
|
18
|
+
keyframes: Sequence[Keyframe],
|
|
19
|
+
nodes: Sequence[int],
|
|
20
|
+
) -> np.ndarray:
|
|
21
|
+
"""Generate trajectory guess via piecewise linear interpolation between keyframes.
|
|
22
|
+
|
|
23
|
+
Keyframes specify values at particular nodes, and linear interpolation fills
|
|
24
|
+
in the values for all nodes in between. This generalizes np.linspace to support
|
|
25
|
+
multiple waypoints.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
keyframes: Sequence of values at keyframe nodes. Each keyframe should be
|
|
29
|
+
array-like with the same shape, or a scalar.
|
|
30
|
+
nodes: Sequence of node indices where keyframes occur. Must be sorted in
|
|
31
|
+
ascending order and have the same length as keyframes. The last node
|
|
32
|
+
determines the output size (N = nodes[-1] + 1).
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
np.ndarray of shape (N, *keyframe_shape) containing interpolated values
|
|
36
|
+
for all nodes, where N = nodes[-1] + 1.
|
|
37
|
+
|
|
38
|
+
Raises:
|
|
39
|
+
ValueError: If keyframes and nodes have different lengths, or nodes are
|
|
40
|
+
not sorted.
|
|
41
|
+
|
|
42
|
+
Note:
|
|
43
|
+
The first node should typically be 0 and the last node should be N-1
|
|
44
|
+
(where N is your trajectory length). Nodes before the first keyframe
|
|
45
|
+
or after the last will be left as zeros.
|
|
46
|
+
|
|
47
|
+
Example:
|
|
48
|
+
Interpolate position through three waypoints::
|
|
49
|
+
|
|
50
|
+
import openscvx as ox
|
|
51
|
+
|
|
52
|
+
position_guess = ox.init.linspace(
|
|
53
|
+
keyframes=[[0, 0, 0], [5, 10, 5], [10, 0, 0]],
|
|
54
|
+
nodes=[0, 25, 49],
|
|
55
|
+
) # Returns shape (50, 3)
|
|
56
|
+
position.guess = position_guess
|
|
57
|
+
|
|
58
|
+
Simple start-to-end interpolation (equivalent to np.linspace)::
|
|
59
|
+
|
|
60
|
+
position_guess = ox.init.linspace(
|
|
61
|
+
keyframes=[[0, 0, 0], [10, 0, 0]],
|
|
62
|
+
nodes=[0, 49],
|
|
63
|
+
) # Returns shape (50, 3)
|
|
64
|
+
"""
|
|
65
|
+
_validate_keyframe_inputs(keyframes, nodes)
|
|
66
|
+
N = nodes[-1] + 1
|
|
67
|
+
|
|
68
|
+
# Convert keyframes to numpy arrays
|
|
69
|
+
keyframes_arr = [np.atleast_1d(np.asarray(kf, dtype=np.float64)) for kf in keyframes]
|
|
70
|
+
keyframe_shape = keyframes_arr[0].shape
|
|
71
|
+
|
|
72
|
+
# Validate all keyframes have the same shape
|
|
73
|
+
for i, kf in enumerate(keyframes_arr):
|
|
74
|
+
if kf.shape != keyframe_shape:
|
|
75
|
+
raise ValueError(f"Keyframe {i} has shape {kf.shape}, expected {keyframe_shape}")
|
|
76
|
+
|
|
77
|
+
# Initialize output array
|
|
78
|
+
result = np.zeros((N, *keyframe_shape), dtype=np.float64)
|
|
79
|
+
|
|
80
|
+
# Interpolate between consecutive keyframe pairs
|
|
81
|
+
for i in range(len(nodes) - 1):
|
|
82
|
+
start_node = nodes[i]
|
|
83
|
+
end_node = nodes[i + 1]
|
|
84
|
+
start_val = keyframes_arr[i]
|
|
85
|
+
end_val = keyframes_arr[i + 1]
|
|
86
|
+
|
|
87
|
+
# Number of nodes in this segment (inclusive of start, exclusive of end)
|
|
88
|
+
n_segment = end_node - start_node
|
|
89
|
+
|
|
90
|
+
for j in range(n_segment):
|
|
91
|
+
t = j / n_segment
|
|
92
|
+
result[start_node + j] = (1 - t) * start_val + t * end_val
|
|
93
|
+
|
|
94
|
+
# Set the final keyframe value
|
|
95
|
+
result[nodes[-1]] = keyframes_arr[-1]
|
|
96
|
+
|
|
97
|
+
return result
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def nlerp(
|
|
101
|
+
keyframes: Sequence[Quaternion],
|
|
102
|
+
nodes: Sequence[int],
|
|
103
|
+
) -> np.ndarray:
|
|
104
|
+
"""Generate quaternion trajectory guess via normalized linear interpolation.
|
|
105
|
+
|
|
106
|
+
NLERP performs linear interpolation between quaternions followed by
|
|
107
|
+
normalization. This is faster than SLERP but produces non-constant angular
|
|
108
|
+
velocity. For initial guesses this is typically sufficient.
|
|
109
|
+
|
|
110
|
+
Quaternion convention: [w, x, y, z] (scalar-first).
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
keyframes: Sequence of unit quaternions at keyframe nodes. Each quaternion
|
|
114
|
+
should be array-like with shape (4,) in [w, x, y, z] order.
|
|
115
|
+
nodes: Sequence of node indices where keyframes occur. Must be sorted in
|
|
116
|
+
ascending order and have the same length as keyframes.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
np.ndarray of shape (N, 4) containing normalized interpolated quaternions
|
|
120
|
+
for all nodes, where N = nodes[-1] + 1.
|
|
121
|
+
|
|
122
|
+
Raises:
|
|
123
|
+
ValueError: If keyframes and nodes have different lengths, nodes are not
|
|
124
|
+
sorted, or quaternions don't have shape (4,).
|
|
125
|
+
|
|
126
|
+
Note:
|
|
127
|
+
The first node should typically be 0 and the last node should be N-1.
|
|
128
|
+
Nodes outside the keyframe range will be left as zeros.
|
|
129
|
+
|
|
130
|
+
Example:
|
|
131
|
+
Interpolate attitude from identity to 180-degree rotation about z-axis::
|
|
132
|
+
|
|
133
|
+
import openscvx as ox
|
|
134
|
+
|
|
135
|
+
attitude_guess = ox.init.nlerp(
|
|
136
|
+
keyframes=[
|
|
137
|
+
[1, 0, 0, 0], # Identity quaternion
|
|
138
|
+
[0, 0, 0, 1], # 180 deg about z
|
|
139
|
+
],
|
|
140
|
+
nodes=[0, 49],
|
|
141
|
+
) # Returns shape (50, 4)
|
|
142
|
+
attitude.guess = attitude_guess
|
|
143
|
+
|
|
144
|
+
Interpolate through intermediate attitudes::
|
|
145
|
+
|
|
146
|
+
attitude_guess = ox.init.nlerp(
|
|
147
|
+
keyframes=[
|
|
148
|
+
[1, 0, 0, 0], # Identity
|
|
149
|
+
[0.707, 0, 0, 0.707], # 90 deg about z
|
|
150
|
+
[0, 0, 0, 1], # 180 deg about z
|
|
151
|
+
],
|
|
152
|
+
nodes=[0, 25, 49],
|
|
153
|
+
)
|
|
154
|
+
"""
|
|
155
|
+
_validate_keyframe_inputs(keyframes, nodes)
|
|
156
|
+
N = nodes[-1] + 1
|
|
157
|
+
|
|
158
|
+
# Convert keyframes to numpy arrays and validate shape
|
|
159
|
+
keyframes_arr = []
|
|
160
|
+
for i, kf in enumerate(keyframes):
|
|
161
|
+
q = np.asarray(kf, dtype=np.float64)
|
|
162
|
+
if q.shape != (4,):
|
|
163
|
+
raise ValueError(f"Keyframe {i} has shape {q.shape}, expected (4,) for quaternion")
|
|
164
|
+
# Normalize input quaternions
|
|
165
|
+
q = q / np.linalg.norm(q)
|
|
166
|
+
keyframes_arr.append(q)
|
|
167
|
+
|
|
168
|
+
# Initialize output array
|
|
169
|
+
result = np.zeros((N, 4), dtype=np.float64)
|
|
170
|
+
|
|
171
|
+
# Interpolate between consecutive keyframe pairs
|
|
172
|
+
for i in range(len(nodes) - 1):
|
|
173
|
+
start_node = nodes[i]
|
|
174
|
+
end_node = nodes[i + 1]
|
|
175
|
+
q0 = keyframes_arr[i]
|
|
176
|
+
q1 = keyframes_arr[i + 1]
|
|
177
|
+
|
|
178
|
+
# Ensure shortest path interpolation
|
|
179
|
+
if np.dot(q0, q1) < 0:
|
|
180
|
+
q1 = -q1
|
|
181
|
+
|
|
182
|
+
n_segment = end_node - start_node
|
|
183
|
+
|
|
184
|
+
for j in range(n_segment):
|
|
185
|
+
t = j / n_segment
|
|
186
|
+
# Linear interpolation
|
|
187
|
+
q_interp = (1 - t) * q0 + t * q1
|
|
188
|
+
# Normalize
|
|
189
|
+
result[start_node + j] = q_interp / np.linalg.norm(q_interp)
|
|
190
|
+
|
|
191
|
+
# Set the final keyframe value (normalized)
|
|
192
|
+
result[nodes[-1]] = keyframes_arr[-1]
|
|
193
|
+
|
|
194
|
+
return result
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def slerp(
|
|
198
|
+
keyframes: Sequence[Quaternion],
|
|
199
|
+
nodes: Sequence[int],
|
|
200
|
+
) -> np.ndarray:
|
|
201
|
+
"""Generate quaternion trajectory guess via spherical linear interpolation.
|
|
202
|
+
|
|
203
|
+
SLERP interpolates along the great arc on the unit quaternion sphere,
|
|
204
|
+
producing constant angular velocity between keyframes. This is more accurate
|
|
205
|
+
than NLERP but slightly more expensive to compute.
|
|
206
|
+
|
|
207
|
+
Quaternion convention: [w, x, y, z] (scalar-first).
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
keyframes: Sequence of unit quaternions at keyframe nodes. Each quaternion
|
|
211
|
+
should be array-like with shape (4,) in [w, x, y, z] order.
|
|
212
|
+
nodes: Sequence of node indices where keyframes occur. Must be sorted in
|
|
213
|
+
ascending order and have the same length as keyframes.
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
np.ndarray of shape (N, 4) containing interpolated quaternions for all nodes,
|
|
217
|
+
where N = nodes[-1] + 1.
|
|
218
|
+
|
|
219
|
+
Raises:
|
|
220
|
+
ValueError: If keyframes and nodes have different lengths, nodes are not
|
|
221
|
+
sorted, or quaternions don't have shape (4,).
|
|
222
|
+
|
|
223
|
+
Note:
|
|
224
|
+
The first node should typically be 0 and the last node should be N-1.
|
|
225
|
+
Nodes outside the keyframe range will be left as zeros.
|
|
226
|
+
|
|
227
|
+
Example:
|
|
228
|
+
Interpolate attitude with constant angular velocity::
|
|
229
|
+
|
|
230
|
+
import openscvx as ox
|
|
231
|
+
|
|
232
|
+
attitude_guess = ox.init.slerp(
|
|
233
|
+
keyframes=[
|
|
234
|
+
[1, 0, 0, 0], # Identity quaternion
|
|
235
|
+
[0, 0, 0, 1], # 180 deg about z
|
|
236
|
+
],
|
|
237
|
+
nodes=[0, 49],
|
|
238
|
+
) # Returns shape (50, 4)
|
|
239
|
+
attitude.guess = attitude_guess
|
|
240
|
+
"""
|
|
241
|
+
_validate_keyframe_inputs(keyframes, nodes)
|
|
242
|
+
N = nodes[-1] + 1
|
|
243
|
+
|
|
244
|
+
# Convert keyframes to numpy arrays and validate shape
|
|
245
|
+
keyframes_arr = []
|
|
246
|
+
for i, kf in enumerate(keyframes):
|
|
247
|
+
q = np.asarray(kf, dtype=np.float64)
|
|
248
|
+
if q.shape != (4,):
|
|
249
|
+
raise ValueError(f"Keyframe {i} has shape {q.shape}, expected (4,) for quaternion")
|
|
250
|
+
# Normalize input quaternions
|
|
251
|
+
q = q / np.linalg.norm(q)
|
|
252
|
+
keyframes_arr.append(q)
|
|
253
|
+
|
|
254
|
+
# Initialize output array
|
|
255
|
+
result = np.zeros((N, 4), dtype=np.float64)
|
|
256
|
+
|
|
257
|
+
# Interpolate between consecutive keyframe pairs
|
|
258
|
+
for i in range(len(nodes) - 1):
|
|
259
|
+
start_node = nodes[i]
|
|
260
|
+
end_node = nodes[i + 1]
|
|
261
|
+
q0 = keyframes_arr[i]
|
|
262
|
+
q1 = keyframes_arr[i + 1]
|
|
263
|
+
|
|
264
|
+
# Ensure shortest path interpolation
|
|
265
|
+
dot = np.dot(q0, q1)
|
|
266
|
+
if dot < 0:
|
|
267
|
+
q1 = -q1
|
|
268
|
+
dot = -dot
|
|
269
|
+
|
|
270
|
+
n_segment = end_node - start_node
|
|
271
|
+
|
|
272
|
+
# Handle near-identical quaternions (fall back to NLERP)
|
|
273
|
+
if dot > 0.9995:
|
|
274
|
+
for j in range(n_segment):
|
|
275
|
+
t = j / n_segment
|
|
276
|
+
q_interp = (1 - t) * q0 + t * q1
|
|
277
|
+
result[start_node + j] = q_interp / np.linalg.norm(q_interp)
|
|
278
|
+
else:
|
|
279
|
+
# SLERP formula
|
|
280
|
+
theta = np.arccos(dot)
|
|
281
|
+
sin_theta = np.sin(theta)
|
|
282
|
+
|
|
283
|
+
for j in range(n_segment):
|
|
284
|
+
t = j / n_segment
|
|
285
|
+
s0 = np.sin((1 - t) * theta) / sin_theta
|
|
286
|
+
s1 = np.sin(t * theta) / sin_theta
|
|
287
|
+
result[start_node + j] = s0 * q0 + s1 * q1
|
|
288
|
+
|
|
289
|
+
# Set the final keyframe value (normalized)
|
|
290
|
+
result[nodes[-1]] = keyframes_arr[-1]
|
|
291
|
+
|
|
292
|
+
return result
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def _validate_keyframe_inputs(
|
|
296
|
+
keyframes: Sequence,
|
|
297
|
+
nodes: Sequence[int],
|
|
298
|
+
) -> None:
|
|
299
|
+
"""Validate common inputs for keyframe interpolation functions.
|
|
300
|
+
|
|
301
|
+
Args:
|
|
302
|
+
keyframes: Sequence of keyframe values
|
|
303
|
+
nodes: Sequence of node indices
|
|
304
|
+
|
|
305
|
+
Raises:
|
|
306
|
+
ValueError: If inputs are invalid
|
|
307
|
+
"""
|
|
308
|
+
if len(keyframes) != len(nodes):
|
|
309
|
+
raise ValueError(
|
|
310
|
+
f"keyframes and nodes must have the same length, "
|
|
311
|
+
f"got {len(keyframes)} keyframes and {len(nodes)} nodes"
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
if len(keyframes) < 2:
|
|
315
|
+
raise ValueError("At least 2 keyframes are required for interpolation")
|
|
316
|
+
|
|
317
|
+
# Check nodes are sorted
|
|
318
|
+
for i in range(len(nodes) - 1):
|
|
319
|
+
if nodes[i] >= nodes[i + 1]:
|
|
320
|
+
raise ValueError(
|
|
321
|
+
f"nodes must be strictly increasing, "
|
|
322
|
+
f"but nodes[{i}]={nodes[i]} >= nodes[{i + 1}]={nodes[i + 1]}"
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
# Check first node is non-negative
|
|
326
|
+
if nodes[0] < 0:
|
|
327
|
+
raise ValueError(f"Node indices must be >= 0, got nodes[0]={nodes[0]}")
|
|
@@ -770,11 +770,16 @@ def fill_default_guesses(states: List[State], N: int) -> None:
|
|
|
770
770
|
states: List of State objects to fill guesses for
|
|
771
771
|
N: Number of discretization nodes
|
|
772
772
|
"""
|
|
773
|
+
from openscvx.init import linspace
|
|
774
|
+
|
|
773
775
|
for state in states:
|
|
774
776
|
if state.guess is None and state.initial is not None and state.final is not None:
|
|
775
777
|
# state.initial and state.final are already numpy arrays of values
|
|
776
778
|
# (the setter handles parsing tuples like ("free", value))
|
|
777
|
-
state.guess =
|
|
779
|
+
state.guess = linspace(
|
|
780
|
+
keyframes=[state.initial, state.final],
|
|
781
|
+
nodes=[0, N - 1],
|
|
782
|
+
)
|
|
778
783
|
|
|
779
784
|
|
|
780
785
|
def validate_boundary_conditions(states: List[State]) -> None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.3.2.
|
|
3
|
+
Version: 0.3.2.dev234
|
|
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
|
|
@@ -138,6 +138,8 @@ openscvx/expert/__init__.py
|
|
|
138
138
|
openscvx/expert/byof.py
|
|
139
139
|
openscvx/expert/lowering.py
|
|
140
140
|
openscvx/expert/validation.py
|
|
141
|
+
openscvx/init/__init__.py
|
|
142
|
+
openscvx/init/interpolation.py
|
|
141
143
|
openscvx/integrators/__init__.py
|
|
142
144
|
openscvx/integrators/runge_kutta.py
|
|
143
145
|
openscvx/lowered/__init__.py
|
|
@@ -207,6 +209,7 @@ tests/test_cvxpygen_optional.py
|
|
|
207
209
|
tests/test_discretization.py
|
|
208
210
|
tests/test_examples.py
|
|
209
211
|
tests/test_expert.py
|
|
212
|
+
tests/test_init.py
|
|
210
213
|
tests/test_integrators.py
|
|
211
214
|
tests/test_plotting.py
|
|
212
215
|
tests/test_propagation.py
|