openscvx 0.4.1.dev169__tar.gz → 0.4.1.dev171__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.4.1.dev169/openscvx.egg-info → openscvx-0.4.1.dev171}/PKG-INFO +1 -1
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/07_lie.md +93 -0
- openscvx-0.4.1.dev171/examples/arm/7_dof_arm_collision.py +507 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/_version.py +3 -3
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/solvers/base.py +8 -1
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/solvers/ptr_solver.py +16 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171/openscvx.egg-info}/PKG-INFO +1 -1
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx.egg-info/SOURCES.txt +1 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/assets/logo.svg +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/release-drafter.yml +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/branch-name.yml +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/docs.yml +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/lint.yml +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/release.yml +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/tests-integration.yml +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/tests-unit.yml +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.gitignore +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/CONTRIBUTING.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/LICENSE +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/README.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/Foundations/constraint_reformulation.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/Foundations/control_parameterization.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/Foundations/discretization.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/Foundations/ocp.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/Foundations/scvx.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/Foundations/time_dilation.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/00_introduction.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/05_visualization.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/06_logic.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/08_mpcc.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/favicon.png +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/logo.svg +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/citation.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/examples.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/getting-started.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/index.md +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/abstract/impulsive.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/abstract/stl_integer_variable.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/abstract/stl_or.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/arm/3_dof_arm.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/arm/7_dof_arm.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/arm/7_dof_arm_vp.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/car/dubins_car.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/car/dubins_car_obstacle_conditional.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/car/dubins_car_obstacle_stl.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/car/dubins_car_stl_or.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/car/dubins_car_waypoint_stl.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/cinema_vp.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/dr_vp.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/drone_racing.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/logo.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/logo_utils/acl_logo.svg +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/logo_utils/svg_path_utils.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/mpc/double_integrator_discrete.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/mpc/double_integrator_drone_racing.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/mpc/dubins_car_circle_analytical.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/mpc/dubins_car_circle_discrete.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/plotting.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/plotting_viser.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/3DoF_pdg_realtime.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/6DoF_pdg_realtime.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/rocket/6DoF_pdg.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/spacecraft/halo_orbit.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/spacecraft/hohmann_transfer.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/video_preview.png +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/1-background.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/1-background@1x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/1-background@2x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/1-background@3x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/1-background@4x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/2-mars.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/2-mars@1x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/2-mars@2x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/2-mars@3x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/2-mars@4x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/3-moon.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/3-moon@1x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/3-moon@2x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/3-moon@3x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/3-moon@4x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/4-sat1.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/4-sat1@1x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/4-sat1@2x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/4-sat1@3x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/4-sat1@4x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/5-space.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/5-space@1x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/5-space@2x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/5-space@3x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/5-space@4x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/6-earth.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/6-earth@1x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/6-earth@2x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/6-earth@3x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/6-earth@4x.avif +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/javascripts/parallax.js +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/logo.svg +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/stylesheets/parallax.css +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/home.html +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/main.html +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/partials/parallax/hero.html +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/partials/parallax.html +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/mkdocs.yml +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/__main__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/augmented_lagrangian.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/base.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/constant_proximal_weight.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/penalized_trust_region.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/ramp_proximal_weight.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/weights.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/config.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/base.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/discretize_linearize.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/linearize_discretize.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/sparse_utils/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/expert/byof.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/expert/validation.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/init/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/init/interpolation.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/init/inverse_kinematics.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/integrators/diffrax.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/loader.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/plotting.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/viser/orbits.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/problem.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/augmentation.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/builder.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/parameter.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/stljax.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/time.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/vmap.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lower.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/array.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/control.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/math.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/state.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/_registry.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/array.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/constraint.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/lie.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/linalg.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/logic.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/math.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/parser.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/spatial.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/stl.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/stljax.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/tokenizer.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/sparsity.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/utils/cache.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/utils/caching.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/utils/printing.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/utils/utils.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx.egg-info/entry_points.txt +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx.egg-info/requires.txt +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/pyproject.toml +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/scripts/gen_example_pages.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/setup.cfg +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/expr/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/expr/test_gmsr.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/fixtures/brachistochrone.json +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/fixtures/brachistochrone.yaml +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/hohmann_analytical.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_stl.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_vmap.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/__init__.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_array.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_constraint.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_lie.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_linalg.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_load.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_logic.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_math.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_parser.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_spatial.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_stl.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_tokenizer.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_vmap.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/test_augmentation.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/test_sparsity.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_autotuning.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_brachistochrone.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_discretization.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_examples.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_expert.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_impulsive.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_init.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_integrators.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_loader.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_optimization_results.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_plotting.py +0 -0
- {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_propagation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.4.1.
|
|
3
|
+
Version: 0.4.1.dev171
|
|
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
|
|
@@ -364,6 +364,98 @@ results = problem.post_process()
|
|
|
364
364
|
|
|
365
365
|
After solving, `results.trajectory["T_ee"]` gives you the dense end-effector transform along the propagated trajectory, ready to feed straight into a viser animation or a downstream controller.
|
|
366
366
|
|
|
367
|
+
## Extension: Self-Collision and Obstacle Avoidance
|
|
368
|
+
|
|
369
|
+
The same intermediate `joint_transforms` we snapshotted above give us everything we need to constrain the *arm itself*, not just its end-effector. The [7-DOF arm with collisions](../Examples/arm/7_dof_arm_collision.md) example extends the pick-and-place setup with two extra constraints:
|
|
370
|
+
|
|
371
|
+
- **Self-collision** between every pair of non-adjacent links.
|
|
372
|
+
- **Obstacle avoidance** between every link and a spherical obstacle placed on the table.
|
|
373
|
+
|
|
374
|
+
The idea is to approximate each link as a **capsule** (a sphere-swept line segment) between two consecutive keypoints, sample each capsule at a small grid of parameters $t \in [0, 1]$, and enforce a pairwise distance bound at every sample. `ox.Vmap` turns the inner loop into a single batched evaluation.
|
|
375
|
+
|
|
376
|
+
First, lift each keypoint from its home position into the world frame using the transforms we already built. We pad with a trailing `1` so the $4 \times 4$ homogeneous transform acts on it correctly:
|
|
377
|
+
|
|
378
|
+
```python
|
|
379
|
+
keypoint_home_pos = {
|
|
380
|
+
"base": np.array([0.0, 0.0, 0.0, 1.0]),
|
|
381
|
+
"shoulder": np.array([0.0, 0.0, d1, 1.0]),
|
|
382
|
+
"elbow": np.array([a2, 0.0, d1, 1.0]),
|
|
383
|
+
"wrist": np.array([a2 + a3, 0.0, d1, 1.0]),
|
|
384
|
+
"ee": np.array([a2 + a3 + a4, 0.0, d1, 1.0]),
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
def _keypoint_world(name):
|
|
388
|
+
p_hom = joint_transforms[name] @ ox.Constant(keypoint_home_pos[name])
|
|
389
|
+
return ox.Concat(p_hom[0], p_hom[1], p_hom[2])
|
|
390
|
+
|
|
391
|
+
kp = {name: _keypoint_world(name) for name in joint_names}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
Then describe each link as `(start, end, radius)`:
|
|
395
|
+
|
|
396
|
+
```python
|
|
397
|
+
link_specs = [
|
|
398
|
+
("base", "shoulder", 0.06),
|
|
399
|
+
("shoulder", "elbow", 0.05),
|
|
400
|
+
("elbow", "wrist", 0.04),
|
|
401
|
+
("wrist", "ee", 0.035),
|
|
402
|
+
]
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Self-collision
|
|
406
|
+
|
|
407
|
+
For every pair of non-adjacent capsules, sample both segments on a $t \times t$ grid and enforce that the sum of radii stays under the sampled distance:
|
|
408
|
+
|
|
409
|
+
```python
|
|
410
|
+
n_samples = 4
|
|
411
|
+
ts = np.linspace(0.0, 1.0, n_samples)
|
|
412
|
+
tt = np.stack(np.meshgrid(ts, ts, indexing="ij"), axis=-1).reshape(-1, 2)
|
|
413
|
+
|
|
414
|
+
for i in range(len(link_specs)):
|
|
415
|
+
for j in range(i + 2, len(link_specs)): # skip adjacent (shared joint)
|
|
416
|
+
a_start, a_end, r_a = link_specs[i]
|
|
417
|
+
b_start, b_end, r_b = link_specs[j]
|
|
418
|
+
pa0, pa1 = kp[a_start], kp[a_end]
|
|
419
|
+
pb0, pb1 = kp[b_start], kp[b_end]
|
|
420
|
+
r_sum = r_a + r_b
|
|
421
|
+
|
|
422
|
+
dists = ox.Vmap(
|
|
423
|
+
lambda t, pa0=pa0, pa1=pa1, pb0=pb0, pb1=pb1: ox.linalg.Norm(
|
|
424
|
+
((1 - t[0]) * pa0 + t[0] * pa1)
|
|
425
|
+
- ((1 - t[1]) * pb0 + t[1] * pb1)
|
|
426
|
+
),
|
|
427
|
+
batch=tt,
|
|
428
|
+
)
|
|
429
|
+
constraints.append(ox.ctcs(r_sum <= dists))
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
Skipping `j = i + 1` matters: adjacent capsules share a joint, so their minimum distance is identically zero and enforcing a strict capsule-capsule bound between them would be infeasible by construction.
|
|
433
|
+
|
|
434
|
+
### Obstacle avoidance
|
|
435
|
+
|
|
436
|
+
The same pattern handles a spherical obstacle — sample every link and keep it outside the inflated sphere:
|
|
437
|
+
|
|
438
|
+
```python
|
|
439
|
+
obstacle_center = np.array([0.35, 0.0, 0.25])
|
|
440
|
+
obstacle_radius = 0.06
|
|
441
|
+
|
|
442
|
+
for a_start, a_end, r_link in link_specs:
|
|
443
|
+
pa0, pa1 = kp[a_start], kp[a_end]
|
|
444
|
+
r_clear = obstacle_radius + r_link
|
|
445
|
+
obs_dists = ox.Vmap(
|
|
446
|
+
lambda t, pa0=pa0, pa1=pa1: ox.linalg.Norm(
|
|
447
|
+
((1 - t) * pa0 + t * pa1) - ox.Constant(obstacle_center)
|
|
448
|
+
),
|
|
449
|
+
batch=ts,
|
|
450
|
+
)
|
|
451
|
+
constraints.append(ox.ctcs(r_clear <= obs_dists))
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
Because each bound is wrapped in `ox.ctcs`, distances are enforced **continuously** along the trajectory — capsules cannot tunnel between nodes.
|
|
455
|
+
|
|
456
|
+
!!! warning "Numerical performance"
|
|
457
|
+
Solve times on this example are currently noticeably slower than we would like when self-collision checking is included; expect a meaningful jump compared to the raw pick-and-place. We are actively working on it.
|
|
458
|
+
|
|
367
459
|
## Key Takeaways
|
|
368
460
|
|
|
369
461
|
1. **Start simple with the minimal representation.** Joint angles + velocities give a pure ODE that drops cleanly into OpenSCvx's modeling stack — the easiest place to begin. Maximal coordinates are also a strong (and in some respects superior) choice for trajopt and will get their own tutorial in the future. The consequence of working in joint space is that task-space quantities are no longer states — they are symbolic functions of the state.
|
|
@@ -377,4 +469,5 @@ After solving, `results.trajectory["T_ee"]` gives you the dense end-effector tra
|
|
|
377
469
|
- [API Reference: Lie algebra](../Reference/symbolic/expr/lie/index.md)
|
|
378
470
|
- [Three-link arm Example](../Examples/arm/3_dof_arm.md)
|
|
379
471
|
- [Seven-link arm Example](../Examples/arm/7_dof_arm.md)
|
|
472
|
+
- [Seven-link arm with self-collision Example](../Examples/arm/7_dof_arm_collision.md)
|
|
380
473
|
- [Seven-link arm with viewcone Example](../Examples/arm/7_dof_arm_vp.md)
|
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
"""7-DOF redundant arm pick-and-place with Product of Exponentials FK.
|
|
2
|
+
|
|
3
|
+
This example demonstrates trajectory optimization for a 7-DOF spatial arm
|
|
4
|
+
performing a full pick-and-place motion: home -> pre-grasp -> grasp ->
|
|
5
|
+
pre-place -> place. Uses Lie algebra operations for forward kinematics
|
|
6
|
+
and IK-generated initial guesses.
|
|
7
|
+
|
|
8
|
+
- 7 revolute joints with alternating z-y rotation axes
|
|
9
|
+
- Product of Exponentials (PoE) forward kinematics using SE3Exp
|
|
10
|
+
- Multi-waypoint pick-and-place trajectory
|
|
11
|
+
- EE position constraints at each waypoint
|
|
12
|
+
- Downward orientation constraints at grasp/place waypoints
|
|
13
|
+
- IK-generated initial guess via damped least-squares
|
|
14
|
+
- Joint torque control inputs
|
|
15
|
+
|
|
16
|
+
The PoE formula computes forward kinematics as:
|
|
17
|
+
T_ee(q) = exp(ξ₁q₁) @ ... @ exp(ξ₇q₇) @ T_home
|
|
18
|
+
|
|
19
|
+
Requires jaxlie: pip install openscvx[lie]
|
|
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 openscvx.plotting import plot_controls, plot_scp_iterations
|
|
34
|
+
|
|
35
|
+
# =============================================================================
|
|
36
|
+
# Robot Parameters
|
|
37
|
+
# =============================================================================
|
|
38
|
+
|
|
39
|
+
N_JOINTS = 7
|
|
40
|
+
|
|
41
|
+
# Link lengths (meters)
|
|
42
|
+
d1 = 0.340 # Base height
|
|
43
|
+
a2 = 0.300 # Shoulder to elbow
|
|
44
|
+
a3 = 0.250 # Elbow to wrist
|
|
45
|
+
a4 = 0.150 # Wrist to end-effector
|
|
46
|
+
|
|
47
|
+
# Joint inertias (simplified, kg*m^2) — decreasing from base to tip
|
|
48
|
+
inertia = np.array([0.08, 0.06, 0.05, 0.04, 0.02, 0.01, 0.005])
|
|
49
|
+
|
|
50
|
+
# Number of discretization nodes (parameterized by segments between waypoints)
|
|
51
|
+
nodes_per_segment = 2
|
|
52
|
+
total_time = 4.0
|
|
53
|
+
|
|
54
|
+
# =============================================================================
|
|
55
|
+
# Pick-and-Place Waypoints
|
|
56
|
+
# =============================================================================
|
|
57
|
+
# Orientation: Ry(90°) points body +x toward world -z (EE facing down)
|
|
58
|
+
q_down = np.array([np.cos(np.pi / 4), 0.0, np.sin(np.pi / 4), 0.0])
|
|
59
|
+
q_identity = np.array([1.0, 0.0, 0.0, 0.0])
|
|
60
|
+
|
|
61
|
+
pre_height = 0.15 # height above grasp/place positions
|
|
62
|
+
|
|
63
|
+
grasp_pos = np.array([0.35, -0.25, 0.05])
|
|
64
|
+
place_pos = np.array([0.35, 0.25, 0.05])
|
|
65
|
+
home_pos = np.array([a2 + a3 + a4 - 0.01, 0.0, d1])
|
|
66
|
+
pre_grasp_pos = grasp_pos + np.array([0.0, 0.0, pre_height])
|
|
67
|
+
pre_place_pos = place_pos + np.array([0.0, 0.0, pre_height])
|
|
68
|
+
|
|
69
|
+
waypoint_names = ["home", "pre_grasp", "grasp", "pre_grasp", "pre_place", "place"]
|
|
70
|
+
waypoint_positions = [home_pos, pre_grasp_pos, grasp_pos, pre_grasp_pos, pre_place_pos, place_pos]
|
|
71
|
+
waypoint_orientations = [q_identity, q_down, q_down, q_down, q_down, q_down]
|
|
72
|
+
|
|
73
|
+
n_segments = len(waypoint_positions) - 1
|
|
74
|
+
n = nodes_per_segment * n_segments + 1
|
|
75
|
+
waypoint_nodes = [i * nodes_per_segment for i in range(len(waypoint_positions))]
|
|
76
|
+
|
|
77
|
+
# =============================================================================
|
|
78
|
+
# Screw Axes for Product of Exponentials
|
|
79
|
+
# =============================================================================
|
|
80
|
+
# Alternating z-y rotation axes (iiwa/Panda-like layout).
|
|
81
|
+
# Home configuration: arm extended along +x at height d1.
|
|
82
|
+
#
|
|
83
|
+
# Each screw axis ξ = [v; ω] where ω is the rotation axis and v = -ω × q
|
|
84
|
+
# for a point q on the joint axis.
|
|
85
|
+
|
|
86
|
+
screw_axes = np.array(
|
|
87
|
+
[
|
|
88
|
+
# Joint 1: z-rotation at origin (base yaw)
|
|
89
|
+
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
|
|
90
|
+
# Joint 2: y-rotation at [0, 0, d1] (shoulder pitch)
|
|
91
|
+
[-d1, 0.0, 0.0, 0.0, 1.0, 0.0],
|
|
92
|
+
# Joint 3: z-rotation at [a2, 0, d1] (upper arm roll)
|
|
93
|
+
[0.0, -a2, 0.0, 0.0, 0.0, 1.0],
|
|
94
|
+
# Joint 4: y-rotation at [a2, 0, d1] (elbow pitch)
|
|
95
|
+
[-d1, 0.0, a2, 0.0, 1.0, 0.0],
|
|
96
|
+
# Joint 5: z-rotation at [a2+a3, 0, d1] (forearm roll)
|
|
97
|
+
[0.0, -(a2 + a3), 0.0, 0.0, 0.0, 1.0],
|
|
98
|
+
# Joint 6: y-rotation at [a2+a3, 0, d1] (wrist pitch)
|
|
99
|
+
[-d1, 0.0, a2 + a3, 0.0, 1.0, 0.0],
|
|
100
|
+
# Joint 7: z-rotation at [a2+a3+a4, 0, d1] (tool roll)
|
|
101
|
+
[0.0, -(a2 + a3 + a4), 0.0, 0.0, 0.0, 1.0],
|
|
102
|
+
]
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Home configuration: EE at [a2+a3+a4, 0, d1] with identity rotation
|
|
106
|
+
T_home = np.array(
|
|
107
|
+
[
|
|
108
|
+
[1.0, 0.0, 0.0, a2 + a3 + a4],
|
|
109
|
+
[0.0, 1.0, 0.0, 0.0],
|
|
110
|
+
[0.0, 0.0, 1.0, d1],
|
|
111
|
+
[0.0, 0.0, 0.0, 1.0],
|
|
112
|
+
]
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# =============================================================================
|
|
116
|
+
# States
|
|
117
|
+
# =============================================================================
|
|
118
|
+
|
|
119
|
+
# Joint angles (7,)
|
|
120
|
+
angle = ox.State("angle", shape=(N_JOINTS,))
|
|
121
|
+
angle.max = np.deg2rad([170, 120, 170, 120, 170, 120, 175])
|
|
122
|
+
angle.min = -angle.max
|
|
123
|
+
angle.initial = np.zeros(N_JOINTS)
|
|
124
|
+
angle.final = [("free", 0.0)] * N_JOINTS
|
|
125
|
+
|
|
126
|
+
# Joint velocities (7,)
|
|
127
|
+
velocity = ox.State("velocity", shape=(N_JOINTS,))
|
|
128
|
+
velocity.max = np.full(N_JOINTS, 3.0)
|
|
129
|
+
velocity.min = -velocity.max
|
|
130
|
+
velocity.initial = np.zeros(N_JOINTS)
|
|
131
|
+
velocity.final = np.zeros(N_JOINTS)
|
|
132
|
+
|
|
133
|
+
states = [angle, velocity]
|
|
134
|
+
|
|
135
|
+
# =============================================================================
|
|
136
|
+
# Controls
|
|
137
|
+
# =============================================================================
|
|
138
|
+
|
|
139
|
+
# Joint torques (7,) — decreasing limits from base to tip
|
|
140
|
+
torque = ox.Control("torque", shape=(N_JOINTS,))
|
|
141
|
+
torque.max = np.array([8.0, 8.0, 4.0, 4.0, 2.0, 1.0, 0.5])
|
|
142
|
+
torque.min = -torque.max
|
|
143
|
+
|
|
144
|
+
controls = [torque]
|
|
145
|
+
|
|
146
|
+
# =============================================================================
|
|
147
|
+
# Forward Kinematics using Product of Exponentials
|
|
148
|
+
# =============================================================================
|
|
149
|
+
# T_ee(q) = exp(ξ₁q₁) @ ... @ exp(ξ₇q₇) @ T_home
|
|
150
|
+
#
|
|
151
|
+
# We build the FK chain incrementally so we can capture the intermediate
|
|
152
|
+
# transforms at each keypoint (base, shoulder, elbow, wrist, ee) for
|
|
153
|
+
# visualization via algebraic_prop.
|
|
154
|
+
|
|
155
|
+
joint_names = ["base", "shoulder", "elbow", "wrist", "ee"]
|
|
156
|
+
keypoint_after_joint = [0, 1, 2, 4, 7] # how many joints precede each keypoint
|
|
157
|
+
|
|
158
|
+
T_chain = ox.Constant(np.eye(4))
|
|
159
|
+
joint_idx = 0
|
|
160
|
+
joint_transforms = {}
|
|
161
|
+
for name, n_joints in zip(joint_names, keypoint_after_joint):
|
|
162
|
+
while joint_idx < n_joints:
|
|
163
|
+
xi = ox.Constant(screw_axes[joint_idx])
|
|
164
|
+
T_chain = T_chain @ ox.lie.SE3Exp(xi * angle[joint_idx])
|
|
165
|
+
joint_idx += 1
|
|
166
|
+
joint_transforms[name] = T_chain
|
|
167
|
+
|
|
168
|
+
T_ee = T_chain @ ox.Constant(T_home)
|
|
169
|
+
|
|
170
|
+
# Extract end-effector position from homogeneous transform
|
|
171
|
+
p_ee = ox.Concat(T_ee[0, 3], T_ee[1, 3], T_ee[2, 3])
|
|
172
|
+
|
|
173
|
+
# =============================================================================
|
|
174
|
+
# Dynamics (simplified second-order)
|
|
175
|
+
# =============================================================================
|
|
176
|
+
# Using simplified dynamics: I * qdd = tau
|
|
177
|
+
#
|
|
178
|
+
# Note: Full manipulator dynamics M(q)q̈ + C(q,q̇)q̇ + G(q) = τ are not needed
|
|
179
|
+
# here. This example demonstrates the Lie algebra functionality (SE3Exp for
|
|
180
|
+
# Product of Exponentials FK), which is independent of the dynamics model.
|
|
181
|
+
|
|
182
|
+
I_inv = ox.Constant(1.0 / inertia)
|
|
183
|
+
|
|
184
|
+
dynamics = {
|
|
185
|
+
"angle": velocity,
|
|
186
|
+
"velocity": I_inv * torque,
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
# =============================================================================
|
|
190
|
+
# Constraints
|
|
191
|
+
# =============================================================================
|
|
192
|
+
|
|
193
|
+
# Box constraints
|
|
194
|
+
constraints = []
|
|
195
|
+
for state in states:
|
|
196
|
+
constraints.extend(
|
|
197
|
+
[
|
|
198
|
+
ox.ctcs(state <= state.max),
|
|
199
|
+
ox.ctcs(state.min <= state),
|
|
200
|
+
]
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
# EE stays above the table
|
|
204
|
+
constraints.append(ox.ctcs(p_ee[2] >= 0.0))
|
|
205
|
+
|
|
206
|
+
# EE position constraint at each waypoint
|
|
207
|
+
ee_tolerance = 0.01 # 1cm tolerance
|
|
208
|
+
for i, (wp, node) in enumerate(zip(waypoint_positions, waypoint_nodes)):
|
|
209
|
+
wp_param = ox.Parameter(f"waypoint_{waypoint_names[i]}", shape=(3,), value=wp)
|
|
210
|
+
constraints.append((ox.linalg.Norm(p_ee - wp_param, ord=2) <= ee_tolerance).at([node]))
|
|
211
|
+
|
|
212
|
+
# Downward orientation constraint at task waypoints (pre_grasp, grasp, pre_place, place)
|
|
213
|
+
w, x, y, z = q_down
|
|
214
|
+
R_des = np.array(
|
|
215
|
+
[
|
|
216
|
+
[1 - 2 * (y * y + z * z), 2 * (x * y - w * z), 2 * (x * z + w * y)],
|
|
217
|
+
[2 * (x * y + w * z), 1 - 2 * (x * x + z * z), 2 * (y * z - w * x)],
|
|
218
|
+
[2 * (x * z - w * y), 2 * (y * z + w * x), 1 - 2 * (x * x + y * y)],
|
|
219
|
+
]
|
|
220
|
+
)
|
|
221
|
+
ori_error = ox.lie.SO3Log(R_des.T @ T_ee[:3, :3]) # (3,) rotation error vector
|
|
222
|
+
ori_norm = ox.linalg.Norm(ori_error, ord=2)
|
|
223
|
+
|
|
224
|
+
# Loose tolerance during transit, tight during grasp/place approach
|
|
225
|
+
ori_tolerance = np.deg2rad(5.0)
|
|
226
|
+
ori_tolerance_tight = np.deg2rad(0.1)
|
|
227
|
+
|
|
228
|
+
# Tight: pre_grasp -> grasp -> pre_grasp
|
|
229
|
+
constraints.append((ori_norm <= ori_tolerance_tight).over((waypoint_nodes[1], waypoint_nodes[3])))
|
|
230
|
+
# Tight: pre_place -> place
|
|
231
|
+
constraints.append((ori_norm <= ori_tolerance_tight).over((waypoint_nodes[4], waypoint_nodes[5])))
|
|
232
|
+
|
|
233
|
+
# Self-collision: capsule-capsule distance between non-adjacent link pairs,
|
|
234
|
+
# approximated by sampling points along each link and enforcing pairwise
|
|
235
|
+
# sphere-swept distance >= sum of link radii.
|
|
236
|
+
keypoint_home_pos = {
|
|
237
|
+
"base": np.array([0.0, 0.0, 0.0, 1.0]),
|
|
238
|
+
"shoulder": np.array([0.0, 0.0, d1, 1.0]),
|
|
239
|
+
"elbow": np.array([a2, 0.0, d1, 1.0]),
|
|
240
|
+
"wrist": np.array([a2 + a3, 0.0, d1, 1.0]),
|
|
241
|
+
"ee": np.array([a2 + a3 + a4, 0.0, d1, 1.0]),
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def _keypoint_world(name):
|
|
246
|
+
p_hom = joint_transforms[name] @ ox.Constant(keypoint_home_pos[name])
|
|
247
|
+
return ox.Concat(p_hom[0], p_hom[1], p_hom[2])
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
kp = {name: _keypoint_world(name) for name in joint_names}
|
|
251
|
+
|
|
252
|
+
link_specs = [
|
|
253
|
+
("base", "shoulder", 0.06),
|
|
254
|
+
("shoulder", "elbow", 0.05),
|
|
255
|
+
("elbow", "wrist", 0.04),
|
|
256
|
+
("wrist", "ee", 0.035),
|
|
257
|
+
]
|
|
258
|
+
|
|
259
|
+
n_samples = 4
|
|
260
|
+
ts = np.linspace(0.0, 1.0, n_samples)
|
|
261
|
+
tt = np.stack(np.meshgrid(ts, ts, indexing="ij"), axis=-1).reshape(-1, 2)
|
|
262
|
+
|
|
263
|
+
for i in range(len(link_specs)):
|
|
264
|
+
for j in range(i + 2, len(link_specs)): # skip adjacent pairs (shared joint)
|
|
265
|
+
a_start, a_end, r_a = link_specs[i]
|
|
266
|
+
b_start, b_end, r_b = link_specs[j]
|
|
267
|
+
pa0, pa1 = kp[a_start], kp[a_end]
|
|
268
|
+
pb0, pb1 = kp[b_start], kp[b_end]
|
|
269
|
+
r_sum = r_a + r_b
|
|
270
|
+
|
|
271
|
+
dists = ox.Vmap(
|
|
272
|
+
lambda t, pa0=pa0, pa1=pa1, pb0=pb0, pb1=pb1: ox.linalg.Norm(
|
|
273
|
+
((1 - t[0]) * pa0 + t[0] * pa1) - ((1 - t[1]) * pb0 + t[1] * pb1)
|
|
274
|
+
),
|
|
275
|
+
batch=tt,
|
|
276
|
+
)
|
|
277
|
+
constraints.append(ox.ctcs(r_sum <= dists))
|
|
278
|
+
|
|
279
|
+
# Spherical obstacle avoidance: sample each link and enforce distance from
|
|
280
|
+
# obstacle center >= obstacle_radius + link_radius.
|
|
281
|
+
obstacle_center = np.array([0.35, 0.0, 0.25])
|
|
282
|
+
obstacle_radius = 0.06
|
|
283
|
+
|
|
284
|
+
for a_start, a_end, r_link in link_specs:
|
|
285
|
+
pa0, pa1 = kp[a_start], kp[a_end]
|
|
286
|
+
r_clear = obstacle_radius + r_link
|
|
287
|
+
obs_dists = ox.Vmap(
|
|
288
|
+
lambda t, pa0=pa0, pa1=pa1: ox.linalg.Norm(
|
|
289
|
+
((1 - t) * pa0 + t * pa1) - ox.Constant(obstacle_center)
|
|
290
|
+
),
|
|
291
|
+
batch=ts,
|
|
292
|
+
)
|
|
293
|
+
constraints.append(ox.ctcs(r_clear <= obs_dists))
|
|
294
|
+
|
|
295
|
+
# =============================================================================
|
|
296
|
+
# Initial Guesses (via IK)
|
|
297
|
+
# =============================================================================
|
|
298
|
+
|
|
299
|
+
angle.guess = ox.init.ik_interpolation(
|
|
300
|
+
keyframes=list(zip(waypoint_positions, waypoint_orientations)),
|
|
301
|
+
nodes=waypoint_nodes,
|
|
302
|
+
screw_axes=screw_axes,
|
|
303
|
+
T_home=T_home,
|
|
304
|
+
angles_init=angle.initial,
|
|
305
|
+
angles_min=angle.min,
|
|
306
|
+
angles_max=angle.max,
|
|
307
|
+
sequential=True,
|
|
308
|
+
)
|
|
309
|
+
angle.initial = np.clip(angle.guess[0], angle.min, angle.max)
|
|
310
|
+
velocity.guess = np.zeros((n, N_JOINTS))
|
|
311
|
+
torque.guess = np.zeros((n, N_JOINTS))
|
|
312
|
+
|
|
313
|
+
# =============================================================================
|
|
314
|
+
# Problem Setup
|
|
315
|
+
# =============================================================================
|
|
316
|
+
|
|
317
|
+
time = ox.Time(
|
|
318
|
+
initial=0.0,
|
|
319
|
+
final=ox.Minimize(total_time),
|
|
320
|
+
min=0.0,
|
|
321
|
+
max=total_time,
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
problem = ox.Problem(
|
|
325
|
+
dynamics=dynamics,
|
|
326
|
+
states=states,
|
|
327
|
+
controls=controls,
|
|
328
|
+
time=time,
|
|
329
|
+
constraints=constraints,
|
|
330
|
+
N=n,
|
|
331
|
+
algorithm={"lam_vb": 1e1, "lam_vc": 1e2, "autotuner": ox.AugmentedLagrangian(eta_lambda=1e0)},
|
|
332
|
+
algebraic_prop={
|
|
333
|
+
"ee_position": p_ee,
|
|
334
|
+
**{f"T_{name}": T for name, T in joint_transforms.items()},
|
|
335
|
+
},
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
problem.settings.prp.dt = 0.01
|
|
339
|
+
|
|
340
|
+
if __name__ == "__main__":
|
|
341
|
+
print("7-DOF Arm Pick-and-Place Trajectory Optimization with PoE FK")
|
|
342
|
+
print("=" * 60)
|
|
343
|
+
print(f"Link lengths: d1={d1}m, a2={a2}m, a3={a3}m, a4={a4}m")
|
|
344
|
+
print(f"Nodes: {n} ({nodes_per_segment} per segment, {n_segments} segments)")
|
|
345
|
+
for name, pos, node in zip(waypoint_names, waypoint_positions, waypoint_nodes):
|
|
346
|
+
print(f" {name:>12s} (node {node:2d}): {list(pos)}")
|
|
347
|
+
print()
|
|
348
|
+
|
|
349
|
+
problem.initialize()
|
|
350
|
+
results = problem.solve()
|
|
351
|
+
results = problem.post_process()
|
|
352
|
+
|
|
353
|
+
# Extract results
|
|
354
|
+
final_q = results.trajectory["angle"][-1]
|
|
355
|
+
ee_pos = results.trajectory["ee_position"] # (T, 3) from algebraic_prop
|
|
356
|
+
|
|
357
|
+
print()
|
|
358
|
+
print("Results:")
|
|
359
|
+
print(f"Final joint angles [deg]: {np.round(np.rad2deg(final_q), 1)}")
|
|
360
|
+
for name, pos, node in zip(waypoint_names, waypoint_positions, waypoint_nodes):
|
|
361
|
+
# Find the closest propagated frame to each waypoint node
|
|
362
|
+
t_node = node / (n - 1)
|
|
363
|
+
frame_idx = int(round(t_node * (len(ee_pos) - 1)))
|
|
364
|
+
ee_at_wp = ee_pos[frame_idx]
|
|
365
|
+
err = np.linalg.norm(ee_at_wp - pos)
|
|
366
|
+
print(
|
|
367
|
+
f" {name:>12s}: pos=[{ee_at_wp[0]:.3f}, {ee_at_wp[1]:.3f}, {ee_at_wp[2]:.3f}] "
|
|
368
|
+
f"err={err:.4f}m"
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
plot_scp_iterations(results).show()
|
|
372
|
+
plot_controls(results).show()
|
|
373
|
+
|
|
374
|
+
# =========================================================================
|
|
375
|
+
# Viser 3D Arm Animation
|
|
376
|
+
# =========================================================================
|
|
377
|
+
|
|
378
|
+
import jaxlie
|
|
379
|
+
|
|
380
|
+
from openscvx.plotting.viser import (
|
|
381
|
+
add_animated_trail,
|
|
382
|
+
add_animation_controls,
|
|
383
|
+
add_ellipsoid_obstacles,
|
|
384
|
+
add_ghost_trajectory,
|
|
385
|
+
add_position_marker,
|
|
386
|
+
add_target_markers,
|
|
387
|
+
compute_velocity_colors,
|
|
388
|
+
create_server,
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
# -- Extract joint keypoint positions from propagated transforms -------------
|
|
392
|
+
# Each T_{name} is (T, 4, 4) from algebraic_prop. Apply the keypoint's
|
|
393
|
+
# home position to get the world-frame position at each timestep.
|
|
394
|
+
|
|
395
|
+
keypoint_home_positions = {
|
|
396
|
+
"base": np.array([0.0, 0.0, 0.0]),
|
|
397
|
+
"shoulder": np.array([0.0, 0.0, d1]),
|
|
398
|
+
"elbow": np.array([a2, 0.0, d1]),
|
|
399
|
+
"wrist": np.array([a2 + a3, 0.0, d1]),
|
|
400
|
+
"ee": np.array([a2 + a3 + a4, 0.0, d1]),
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
n_frames = len(ee_pos)
|
|
404
|
+
keypoints = np.zeros((n_frames, 5, 3))
|
|
405
|
+
joint_quats = np.zeros((n_frames, 5, 4))
|
|
406
|
+
for k, name in enumerate(joint_names):
|
|
407
|
+
T_k = np.asarray(results.trajectory[f"T_{name}"]) # (T, 4, 4)
|
|
408
|
+
p_home = np.append(keypoint_home_positions[name], 1.0)
|
|
409
|
+
keypoints[:, k] = (T_k @ p_home)[:, :3]
|
|
410
|
+
joint_quats[:, k] = np.array(
|
|
411
|
+
[jaxlie.SO3.from_matrix(T_k[t, :3, :3]).wxyz for t in range(n_frames)]
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
# -- Create viser server ----------------------------------------------------
|
|
415
|
+
|
|
416
|
+
server = create_server(ee_pos, show_grid=False)
|
|
417
|
+
server.scene.add_grid("/grid", width=1.5, height=1.5, cell_size=0.25)
|
|
418
|
+
server.scene.add_frame("/origin", axes_length=0.1, axes_radius=0.003)
|
|
419
|
+
|
|
420
|
+
# Waypoint markers: grasp/place in red, pre-grasp/pre-place in orange, home in blue
|
|
421
|
+
marker_colors = {
|
|
422
|
+
"home": (100, 150, 255),
|
|
423
|
+
"pre_grasp": (255, 180, 50),
|
|
424
|
+
"grasp": (255, 50, 50),
|
|
425
|
+
"pre_place": (255, 180, 50),
|
|
426
|
+
"place": (255, 50, 50),
|
|
427
|
+
}
|
|
428
|
+
add_target_markers(
|
|
429
|
+
server,
|
|
430
|
+
waypoint_positions,
|
|
431
|
+
radius=0.015,
|
|
432
|
+
colors=[marker_colors[name] for name in waypoint_names],
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
add_ellipsoid_obstacles(
|
|
436
|
+
server,
|
|
437
|
+
centers=[obstacle_center],
|
|
438
|
+
radii=[np.full(3, 1.0 / obstacle_radius)],
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
# Ghost EE trajectory (faint full path)
|
|
442
|
+
ee_colors = compute_velocity_colors(np.asarray(results.trajectory.get("velocity")))
|
|
443
|
+
add_ghost_trajectory(server, ee_pos, ee_colors, point_size=0.005)
|
|
444
|
+
|
|
445
|
+
# Animated EE trail
|
|
446
|
+
_, update_trail = add_animated_trail(server, ee_pos, ee_colors, point_size=0.008)
|
|
447
|
+
|
|
448
|
+
# Animated EE position marker
|
|
449
|
+
_, update_marker = add_position_marker(server, ee_pos, radius=0.015)
|
|
450
|
+
|
|
451
|
+
# Animated arm links (line segments between consecutive keypoints)
|
|
452
|
+
# Per-segment colors: (N_segments, 2, 3) — same color at both endpoints
|
|
453
|
+
link_rgb = np.array(
|
|
454
|
+
[
|
|
455
|
+
[180, 180, 180], # base -> shoulder
|
|
456
|
+
[100, 180, 255], # shoulder -> elbow
|
|
457
|
+
[100, 255, 150], # elbow -> wrist
|
|
458
|
+
[255, 200, 100], # wrist -> ee
|
|
459
|
+
],
|
|
460
|
+
dtype=np.uint8,
|
|
461
|
+
)
|
|
462
|
+
link_colors = np.stack([link_rgb, link_rgb], axis=1) # (4, 2, 3)
|
|
463
|
+
|
|
464
|
+
# Initial arm segments: (4, 2, 3)
|
|
465
|
+
init_points = np.stack(
|
|
466
|
+
[np.stack([keypoints[0, k], keypoints[0, k + 1]]) for k in range(4)]
|
|
467
|
+
).astype(np.float32)
|
|
468
|
+
|
|
469
|
+
arm_handle = server.scene.add_line_segments(
|
|
470
|
+
"/arm_links",
|
|
471
|
+
points=init_points,
|
|
472
|
+
colors=link_colors,
|
|
473
|
+
line_width=5.0,
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
# Joint coordinate frames
|
|
477
|
+
joint_frame_handles = []
|
|
478
|
+
for k in range(5):
|
|
479
|
+
h = server.scene.add_frame(
|
|
480
|
+
f"/joint_{joint_names[k]}",
|
|
481
|
+
wxyz=joint_quats[0, k].astype(np.float32),
|
|
482
|
+
position=keypoints[0, k].astype(np.float32),
|
|
483
|
+
axes_length=0.06,
|
|
484
|
+
axes_radius=0.002,
|
|
485
|
+
)
|
|
486
|
+
joint_frame_handles.append(h)
|
|
487
|
+
|
|
488
|
+
def update_arm(frame_idx: int) -> None:
|
|
489
|
+
pts = np.stack(
|
|
490
|
+
[np.stack([keypoints[frame_idx, k], keypoints[frame_idx, k + 1]]) for k in range(4)]
|
|
491
|
+
).astype(np.float32)
|
|
492
|
+
arm_handle.points = pts
|
|
493
|
+
for k, h in enumerate(joint_frame_handles):
|
|
494
|
+
h.position = keypoints[frame_idx, k].astype(np.float32)
|
|
495
|
+
h.wxyz = joint_quats[frame_idx, k].astype(np.float32)
|
|
496
|
+
|
|
497
|
+
# Animation controls
|
|
498
|
+
traj_time = np.asarray(results.trajectory["time"])
|
|
499
|
+
add_animation_controls(
|
|
500
|
+
server,
|
|
501
|
+
traj_time,
|
|
502
|
+
[update_trail, update_marker, update_arm],
|
|
503
|
+
loop=True,
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
# Keep server running
|
|
507
|
+
server.sleep_forever()
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.4.1.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 4, 1, '
|
|
21
|
+
__version__ = version = '0.4.1.dev171'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 4, 1, 'dev171')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'gc410cdf9e'
|
|
@@ -245,7 +245,14 @@ _SOLVER_MAP: Dict[str, type] = {} # populated by __init__.py after all classes
|
|
|
245
245
|
|
|
246
246
|
|
|
247
247
|
class SolverSpec(BaseModel):
|
|
248
|
-
"""Validates solver configuration from dict/YAML input.
|
|
248
|
+
"""Validates solver configuration from dict/YAML input.
|
|
249
|
+
|
|
250
|
+
!!! warning
|
|
251
|
+
Enabling ``cvxpygen`` currently disables sparse parameter declarations.
|
|
252
|
+
cvxpygen does not yet support the N-D sparsity indices used by
|
|
253
|
+
OpenSCvx's tiled parameters, so all parameters are created as dense
|
|
254
|
+
when code generation is active.
|
|
255
|
+
"""
|
|
249
256
|
|
|
250
257
|
type: Literal["PTRSolver"] = "PTRSolver"
|
|
251
258
|
cvx_solver: str = "QOCO"
|
|
@@ -119,6 +119,14 @@ class PTRSolver(ConvexSolver):
|
|
|
119
119
|
``{"abstol": 1e-6, "reltol": 1e-9, "enforce_dpp": True}``.
|
|
120
120
|
cvxpygen: Enable CVXPy code generation for faster solves.
|
|
121
121
|
Defaults to ``False``.
|
|
122
|
+
|
|
123
|
+
!!! warning
|
|
124
|
+
Enabling cvxpygen currently disables sparse parameter
|
|
125
|
+
declarations. cvxpygen does not yet support the N-D sparsity
|
|
126
|
+
indices used by OpenSCvx's tiled parameters, so all parameters
|
|
127
|
+
are created as dense when code generation is active. This may
|
|
128
|
+
increase the generated solver's memory footprint and compile
|
|
129
|
+
time but does not affect solution correctness.
|
|
122
130
|
cvxpygen_override: Overwrite existing generated solver directory
|
|
123
131
|
without prompting. Defaults to ``False``.
|
|
124
132
|
|
|
@@ -234,6 +242,14 @@ class PTRSolver(ConvexSolver):
|
|
|
234
242
|
B_d_sp = _tile_sparsity(B_d_pat, N - 1)
|
|
235
243
|
C_d_sp = _tile_sparsity(C_d_pat, N - 1)
|
|
236
244
|
|
|
245
|
+
# TODO: (griffin-norris) Remove once cvxpygen supports N-D sparsity
|
|
246
|
+
# indices. cvxpygen's handle_sparsity() assumes 2-D (rows, cols) but
|
|
247
|
+
# our tiled parameters produce 3-D indices (slices, rows, cols).
|
|
248
|
+
# Dropping sparsity here is safe — it only affects codegen performance.
|
|
249
|
+
if self.cvxpygen:
|
|
250
|
+
A_d_sp = B_d_sp = C_d_sp = None
|
|
251
|
+
constraint_sparsity = None
|
|
252
|
+
|
|
237
253
|
# Create all CVXPy variables for the OCP
|
|
238
254
|
self._ocp_vars = create_cvxpy_variables(
|
|
239
255
|
N=N,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.4.1.
|
|
3
|
+
Version: 0.4.1.dev171
|
|
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
|