openscvx 0.3.2.dev143__tar.gz → 0.3.2.dev157__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.dev143/openscvx.egg-info → openscvx-0.3.2.dev157}/PKG-INFO +4 -1
- openscvx-0.3.2.dev157/examples/arm/three_link_arm.py +253 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/__init__.py +2 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/_version.py +3 -3
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/__init__.py +28 -0
- openscvx-0.3.2.dev157/openscvx/symbolic/expr/lie/__init__.py +87 -0
- openscvx-0.3.2.dev157/openscvx/symbolic/expr/lie/adjoint.py +357 -0
- openscvx-0.3.2.dev157/openscvx/symbolic/expr/lie/se3.py +172 -0
- openscvx-0.3.2.dev157/openscvx/symbolic/expr/lie/so3.py +138 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/lowerers/jax.py +275 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157/openscvx.egg-info}/PKG-INFO +4 -1
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx.egg-info/SOURCES.txt +6 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx.egg-info/requires.txt +4 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/pyproject.toml +4 -0
- openscvx-0.3.2.dev157/tests/symbolic/expr/test_lie.py +1244 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/assets/logo.svg +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/release-drafter.yml +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/docs.yml +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/lint.yml +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/release.yml +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/tests-integration.yml +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/tests-unit.yml +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.gitignore +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/CONTRIBUTING.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/LICENSE +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/README.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Overview/constraint_reformulation.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Overview/control_parameterization.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Overview/discretization.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Overview/ocp.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Overview/scvx.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Overview/time_dilation.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/advanced_problem_setup.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/api.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/api_constraints.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/api_control.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/api_integrators.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/api_state.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/api_trajoptproblem.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/api_variable.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/basic_problem_setup.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/tutorial_6dof_los_guidance.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/tutorial_6dof_obstacle_avoidance.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/tutorials.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/favicon.png +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/logo.svg +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/citation.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/examples.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/getting-started.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/index.md +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/abstract/3DoF_pdg.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/car/dubins_car.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/car/dubins_car_stljax.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/cinema_vp.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/dr_vp.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/drone_racing.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/plotting.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/plotting_viser.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/video_preview.png +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/1-background.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/1-background@1x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/1-background@2x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/1-background@3x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/1-background@4x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/2-mars.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/2-mars@1x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/2-mars@2x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/2-mars@3x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/2-mars@4x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/3-moon.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/3-moon@1x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/3-moon@2x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/3-moon@3x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/3-moon@4x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/4-sat1.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/4-sat1@1x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/4-sat1@2x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/4-sat1@3x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/4-sat1@4x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/5-space.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/5-space@1x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/5-space@2x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/5-space@3x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/5-space@4x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/6-earth.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/6-earth@1x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/6-earth@2x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/6-earth@3x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/6-earth@4x.avif +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/javascripts/parallax.js +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/logo.svg +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/stylesheets/parallax.css +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/home.html +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/main.html +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/partials/parallax/hero.html +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/partials/parallax.html +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/mkdocs.yml +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/algorithms/autotuning.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/algorithms/base.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/algorithms/penalized_trust_region.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/config.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/discretization/discretization.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/expert/byof.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/expert/validation.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/plotting.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/problem.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/solvers/cvxpy.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/augmentation.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/builder.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/lower.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/lowerers/cvxpy.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/preprocessing.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/time.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/utils/cache.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/utils/caching.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/utils/printing.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/utils/utils.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/scripts/gen_example_pages.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/setup.cfg +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_scaling.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_variable.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/test_augmentation.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/test_brachistochrone.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/test_discretization.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/test_examples.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/test_expert.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/test_integrators.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/test_plotting.py +0 -0
- {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/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.dev157
|
|
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
|
|
@@ -32,9 +32,12 @@ Requires-Dist: cvxpygen; extra == "cvxpygen"
|
|
|
32
32
|
Requires-Dist: qocogen; extra == "cvxpygen"
|
|
33
33
|
Provides-Extra: stl
|
|
34
34
|
Requires-Dist: stljax; extra == "stl"
|
|
35
|
+
Provides-Extra: lie
|
|
36
|
+
Requires-Dist: jaxlie; extra == "lie"
|
|
35
37
|
Provides-Extra: test
|
|
36
38
|
Requires-Dist: pytest; extra == "test"
|
|
37
39
|
Requires-Dist: scipy; extra == "test"
|
|
40
|
+
Requires-Dist: jaxlie; extra == "test"
|
|
38
41
|
Dynamic: license-file
|
|
39
42
|
|
|
40
43
|
<a id="readme-top"></a>
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"""3-link robotic arm with Product of Exponentials forward kinematics.
|
|
2
|
+
|
|
3
|
+
This example demonstrates trajectory optimization for a 3-link spatial arm
|
|
4
|
+
using Lie algebra operations for forward kinematics. The problem includes:
|
|
5
|
+
|
|
6
|
+
- 3 revolute joints with angle and velocity states
|
|
7
|
+
- Product of Exponentials (PoE) forward kinematics using SE3Exp
|
|
8
|
+
- End-effector position tracking objective
|
|
9
|
+
- Joint torque control inputs
|
|
10
|
+
|
|
11
|
+
The PoE formula computes forward kinematics as:
|
|
12
|
+
T_ee(q) = exp(ξ₁q₁) @ exp(ξ₂q₂) @ exp(ξ₃q₃) @ T_home
|
|
13
|
+
|
|
14
|
+
where ξᵢ are the screw axes and T_home is the end-effector pose at q=0.
|
|
15
|
+
|
|
16
|
+
Requires jaxlie: pip install openscvx[lie]
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import os
|
|
20
|
+
import sys
|
|
21
|
+
|
|
22
|
+
import numpy as np
|
|
23
|
+
|
|
24
|
+
# Add grandparent directory to path to import examples.plotting
|
|
25
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
26
|
+
grandparent_dir = os.path.dirname(os.path.dirname(current_dir))
|
|
27
|
+
sys.path.append(grandparent_dir)
|
|
28
|
+
|
|
29
|
+
import openscvx as ox
|
|
30
|
+
from openscvx import Problem
|
|
31
|
+
from openscvx.plotting import plot_scp_iterations
|
|
32
|
+
|
|
33
|
+
# =============================================================================
|
|
34
|
+
# Robot Parameters
|
|
35
|
+
# =============================================================================
|
|
36
|
+
|
|
37
|
+
# Link lengths (meters)
|
|
38
|
+
L1 = 0.4 # Base to shoulder
|
|
39
|
+
L2 = 0.3 # Shoulder to elbow
|
|
40
|
+
L3 = 0.2 # Elbow to end-effector
|
|
41
|
+
|
|
42
|
+
# Joint inertias (simplified, kg*m^2)
|
|
43
|
+
inertia = np.array([0.05, 0.03, 0.01])
|
|
44
|
+
|
|
45
|
+
# Number of discretization nodes
|
|
46
|
+
n = 3
|
|
47
|
+
total_time = 2.0
|
|
48
|
+
|
|
49
|
+
# =============================================================================
|
|
50
|
+
# Screw Axes for Product of Exponentials
|
|
51
|
+
# =============================================================================
|
|
52
|
+
# Each screw axis ξ = [v; ω] where:
|
|
53
|
+
# ω = unit rotation axis
|
|
54
|
+
# v = -ω × q (q = point on the axis)
|
|
55
|
+
#
|
|
56
|
+
# Robot configuration at home (q=0):
|
|
57
|
+
# - Joint 1: z-rotation at origin
|
|
58
|
+
# - Joint 2: y-rotation at height L1
|
|
59
|
+
# - Joint 3: y-rotation at height L1, reach L2 in x
|
|
60
|
+
|
|
61
|
+
# Screw axes as rows of a 3x6 matrix
|
|
62
|
+
screw_axes = np.array(
|
|
63
|
+
[
|
|
64
|
+
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0], # Joint 1: z-rotation at origin
|
|
65
|
+
[-L1, 0.0, 0.0, 0.0, 1.0, 0.0], # Joint 2: y-rotation at [0, 0, L1]
|
|
66
|
+
[-L1, 0.0, L2, 0.0, 1.0, 0.0], # Joint 3: y-rotation at [L2, 0, L1]
|
|
67
|
+
]
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Home configuration: end-effector at [L2+L3, 0, L1] with identity rotation
|
|
71
|
+
T_home = np.array(
|
|
72
|
+
[
|
|
73
|
+
[1.0, 0.0, 0.0, L2 + L3],
|
|
74
|
+
[0.0, 1.0, 0.0, 0.0],
|
|
75
|
+
[0.0, 0.0, 1.0, L1],
|
|
76
|
+
[0.0, 0.0, 0.0, 1.0],
|
|
77
|
+
]
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# =============================================================================
|
|
81
|
+
# States
|
|
82
|
+
# =============================================================================
|
|
83
|
+
|
|
84
|
+
# Joint angles (3,)
|
|
85
|
+
angle = ox.State("angle", shape=(3,))
|
|
86
|
+
angle.max = np.array([np.pi, np.pi / 2, np.pi])
|
|
87
|
+
angle.min = np.array([-np.pi, -np.pi / 2, -np.pi])
|
|
88
|
+
angle.initial = np.array([0.0, 0.0, 0.0])
|
|
89
|
+
angle.final = [("free", 0.0), ("free", 0.0), ("free", 0.0)]
|
|
90
|
+
|
|
91
|
+
# Joint velocities (3,)
|
|
92
|
+
velocity = ox.State("velocity", shape=(3,))
|
|
93
|
+
velocity.max = np.array([5.0, 5.0, 5.0])
|
|
94
|
+
velocity.min = np.array([-5.0, -5.0, -5.0])
|
|
95
|
+
velocity.initial = np.array([0.0, 0.0, 0.0])
|
|
96
|
+
velocity.final = np.array([0.0, 0.0, 0.0])
|
|
97
|
+
|
|
98
|
+
states = [angle, velocity]
|
|
99
|
+
|
|
100
|
+
# =============================================================================
|
|
101
|
+
# Controls
|
|
102
|
+
# =============================================================================
|
|
103
|
+
|
|
104
|
+
# Joint torques (3,)
|
|
105
|
+
torque = ox.Control("torque", shape=(3,))
|
|
106
|
+
torque.max = np.array([10.0, 5.0, 2.0])
|
|
107
|
+
torque.min = np.array([-10.0, -5.0, -2.0])
|
|
108
|
+
|
|
109
|
+
controls = [torque]
|
|
110
|
+
|
|
111
|
+
# =============================================================================
|
|
112
|
+
# Forward Kinematics using Product of Exponentials
|
|
113
|
+
# =============================================================================
|
|
114
|
+
# T_ee(q) = exp(ξ₁q₁) @ exp(ξ₂q₂) @ exp(ξ₃q₃) @ T_home
|
|
115
|
+
|
|
116
|
+
# Symbolic screw axis expressions scaled by joint angles
|
|
117
|
+
xi_1 = ox.Constant(screw_axes[0])
|
|
118
|
+
xi_2 = ox.Constant(screw_axes[1])
|
|
119
|
+
xi_3 = ox.Constant(screw_axes[2])
|
|
120
|
+
|
|
121
|
+
twist_1 = xi_1 * angle[0]
|
|
122
|
+
twist_2 = xi_2 * angle[1]
|
|
123
|
+
twist_3 = xi_3 * angle[2]
|
|
124
|
+
|
|
125
|
+
# Exponential maps for each joint
|
|
126
|
+
T_01 = ox.lie.SE3Exp(twist_1) # 4x4 transform
|
|
127
|
+
T_12 = ox.lie.SE3Exp(twist_2)
|
|
128
|
+
T_23 = ox.lie.SE3Exp(twist_3)
|
|
129
|
+
|
|
130
|
+
# Chain the transforms: T_ee = T_01 @ T_12 @ T_23 @ T_home
|
|
131
|
+
T_0_home = ox.Constant(T_home)
|
|
132
|
+
T_ee = T_01 @ T_12 @ T_23 @ T_0_home
|
|
133
|
+
|
|
134
|
+
# Extract end-effector position from homogeneous transform
|
|
135
|
+
p_ee = ox.Concat(T_ee[0, 3], T_ee[1, 3], T_ee[2, 3])
|
|
136
|
+
|
|
137
|
+
# =============================================================================
|
|
138
|
+
# Dynamics (simplified second-order)
|
|
139
|
+
# =============================================================================
|
|
140
|
+
# Using simplified dynamics: I * qdd = tau
|
|
141
|
+
#
|
|
142
|
+
# Note: Full manipulator dynamics M(q)q̈ + C(q,q̇)q̇ + G(q) = τ are not needed
|
|
143
|
+
# here. This example demonstrates the Lie algebra functionality (SE3Exp for
|
|
144
|
+
# Product of Exponentials FK), which is independent of the dynamics model.
|
|
145
|
+
|
|
146
|
+
I_inv = ox.Constant(1.0 / inertia)
|
|
147
|
+
|
|
148
|
+
dynamics = {
|
|
149
|
+
"angle": velocity,
|
|
150
|
+
"velocity": I_inv * torque, # Element-wise: qdd_i = tau_i / I_i
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
# =============================================================================
|
|
154
|
+
# Constraints
|
|
155
|
+
# =============================================================================
|
|
156
|
+
|
|
157
|
+
# Target end-effector position
|
|
158
|
+
target = ox.Parameter("target", shape=(3,), value=np.array([0.3, 0.3, 0.5]))
|
|
159
|
+
|
|
160
|
+
# Box constraints
|
|
161
|
+
constraints = []
|
|
162
|
+
for state in states:
|
|
163
|
+
constraints.extend(
|
|
164
|
+
[
|
|
165
|
+
ox.ctcs(state <= state.max),
|
|
166
|
+
ox.ctcs(state.min <= state),
|
|
167
|
+
]
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
# End-effector target constraint at final node (commented out for debugging)
|
|
171
|
+
ee_tolerance = 0.01 # 1cm tolerance
|
|
172
|
+
ee_target_constraint = (ox.linalg.Norm(p_ee - target, ord=2) <= ee_tolerance).at([n - 1])
|
|
173
|
+
constraints.append(ee_target_constraint)
|
|
174
|
+
|
|
175
|
+
# =============================================================================
|
|
176
|
+
# Initial Guesses
|
|
177
|
+
# =============================================================================
|
|
178
|
+
|
|
179
|
+
np.random.seed(42) # For reproducibility
|
|
180
|
+
# Terminal angles that reach the target (from workspace analysis)
|
|
181
|
+
q_terminal = np.deg2rad([47.8, -38.6, 62.4])
|
|
182
|
+
angle.guess = np.linspace(angle.initial, q_terminal, n)
|
|
183
|
+
velocity.guess = np.zeros((n, 3))
|
|
184
|
+
torque.guess = np.zeros((n, 3))
|
|
185
|
+
|
|
186
|
+
# =============================================================================
|
|
187
|
+
# Problem Setup
|
|
188
|
+
# =============================================================================
|
|
189
|
+
|
|
190
|
+
time = ox.Time(
|
|
191
|
+
initial=0.0,
|
|
192
|
+
final=total_time,
|
|
193
|
+
min=0.0,
|
|
194
|
+
max=total_time,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
problem = Problem(
|
|
198
|
+
dynamics=dynamics,
|
|
199
|
+
states=states,
|
|
200
|
+
controls=controls,
|
|
201
|
+
time=time,
|
|
202
|
+
constraints=constraints,
|
|
203
|
+
N=n,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
# Solver settings
|
|
207
|
+
problem.settings.prp.dt = 0.01
|
|
208
|
+
problem.settings.scp.w_tr = 1e1
|
|
209
|
+
problem.settings.scp.lam_cost = 1e2
|
|
210
|
+
problem.settings.scp.lam_vc = 1e1
|
|
211
|
+
problem.settings.scp.lam_vb = 1e2
|
|
212
|
+
|
|
213
|
+
if __name__ == "__main__":
|
|
214
|
+
print("3-Link Arm Trajectory Optimization with Product of Exponentials FK")
|
|
215
|
+
print("=" * 60)
|
|
216
|
+
print(f"Link lengths: L1={L1}m, L2={L2}m, L3={L3}m")
|
|
217
|
+
print(f"Home EE position: [{L2 + L3:.2f}, 0.00, {L1:.2f}]")
|
|
218
|
+
print(f"Target position: {target.value}")
|
|
219
|
+
print()
|
|
220
|
+
|
|
221
|
+
problem.initialize()
|
|
222
|
+
results = problem.solve()
|
|
223
|
+
results = problem.post_process()
|
|
224
|
+
|
|
225
|
+
# Extract final joint angles
|
|
226
|
+
final_q = results.trajectory["angle"][-1]
|
|
227
|
+
|
|
228
|
+
print()
|
|
229
|
+
print("Results:")
|
|
230
|
+
print(
|
|
231
|
+
f"Final joint angles [deg]: q1={np.rad2deg(final_q[0]):.1f}, "
|
|
232
|
+
f"q2={np.rad2deg(final_q[1]):.1f}, q3={np.rad2deg(final_q[2]):.1f}"
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
# Compute final EE position (using jaxlie for verification)
|
|
236
|
+
import jaxlie
|
|
237
|
+
|
|
238
|
+
def compute_ee_position(q_vals):
|
|
239
|
+
T1 = jaxlie.SE3.exp(screw_axes[0] * q_vals[0]).as_matrix()
|
|
240
|
+
T2 = jaxlie.SE3.exp(screw_axes[1] * q_vals[1]).as_matrix()
|
|
241
|
+
T3 = jaxlie.SE3.exp(screw_axes[2] * q_vals[2]).as_matrix()
|
|
242
|
+
T_final = T1 @ T2 @ T3 @ T_home
|
|
243
|
+
return T_final[:3, 3]
|
|
244
|
+
|
|
245
|
+
plot_scp_iterations(results).show()
|
|
246
|
+
|
|
247
|
+
tgt = target.value
|
|
248
|
+
final_ee = compute_ee_position(final_q)
|
|
249
|
+
error = np.linalg.norm(final_ee - tgt)
|
|
250
|
+
|
|
251
|
+
print(f"Final EE position: [{final_ee[0]:.3f}, {final_ee[1]:.3f}, {final_ee[2]:.3f}]")
|
|
252
|
+
print(f"Target position: [{tgt[0]:.3f}, {tgt[1]:.3f}, {tgt[2]:.3f}]")
|
|
253
|
+
print(f"Position error: {error:.4f} m")
|
|
@@ -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.symbolic.expr.lie as lie
|
|
8
9
|
import openscvx.symbolic.expr.linalg as linalg
|
|
9
10
|
import openscvx.symbolic.expr.spatial as spatial
|
|
10
11
|
import openscvx.symbolic.expr.stl as stl
|
|
@@ -106,6 +107,7 @@ __all__ = [
|
|
|
106
107
|
"stl",
|
|
107
108
|
"spatial",
|
|
108
109
|
"linalg",
|
|
110
|
+
"lie",
|
|
109
111
|
# Expert mode types
|
|
110
112
|
"ByofSpec",
|
|
111
113
|
]
|
|
@@ -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.dev157'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 3, 2, 'dev157')
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'ga9bc61751'
|
|
@@ -54,6 +54,13 @@ Module Organization:
|
|
|
54
54
|
Direction Cosine Matrix), `SSMP` (4×4 skew-symmetric matrix for quaternion
|
|
55
55
|
dynamics), and `SSM` (3×3 skew-symmetric matrix for cross products).
|
|
56
56
|
|
|
57
|
+
Lie Algebra Operations (lie.py):
|
|
58
|
+
Lie algebra operations for rigid body dynamics. Built-in operators include
|
|
59
|
+
`AdjointDual` (coadjoint for Coriolis/centrifugal forces) and `Adjoint`
|
|
60
|
+
(Lie bracket). jaxlie-backed operators (requires `pip install openscvx[lie]`)
|
|
61
|
+
include `SO3Exp`, `SO3Log`, `SE3Exp`, and `SE3Log` for exponential and
|
|
62
|
+
logarithm maps on rotation and rigid transformation groups.
|
|
63
|
+
|
|
57
64
|
Constraint Specifications (constraint.py):
|
|
58
65
|
`NodalConstraint` for enforcing constraints at discrete nodes and `CTCS` for
|
|
59
66
|
continuous-time constraint satisfaction.
|
|
@@ -93,6 +100,18 @@ from .expr import (
|
|
|
93
100
|
traverse,
|
|
94
101
|
)
|
|
95
102
|
|
|
103
|
+
# Lie algebra operations
|
|
104
|
+
from .lie import (
|
|
105
|
+
Adjoint,
|
|
106
|
+
AdjointDual,
|
|
107
|
+
SE3Adjoint,
|
|
108
|
+
SE3AdjointDual,
|
|
109
|
+
SE3Exp,
|
|
110
|
+
SE3Log,
|
|
111
|
+
SO3Exp,
|
|
112
|
+
SO3Log,
|
|
113
|
+
)
|
|
114
|
+
|
|
96
115
|
# Linear algebra operations
|
|
97
116
|
from .linalg import Diag, Norm, Sum, Transpose
|
|
98
117
|
|
|
@@ -183,6 +202,15 @@ __all__ = [
|
|
|
183
202
|
"QDCM",
|
|
184
203
|
"SSMP",
|
|
185
204
|
"SSM",
|
|
205
|
+
# Lie algebra operations
|
|
206
|
+
"AdjointDual",
|
|
207
|
+
"Adjoint",
|
|
208
|
+
"SE3Adjoint",
|
|
209
|
+
"SE3AdjointDual",
|
|
210
|
+
"SO3Exp",
|
|
211
|
+
"SO3Log",
|
|
212
|
+
"SE3Exp",
|
|
213
|
+
"SE3Log",
|
|
186
214
|
# Specialized constraints
|
|
187
215
|
"NodalConstraint",
|
|
188
216
|
"CrossNodeConstraint",
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Lie algebra operations for rigid body dynamics.
|
|
2
|
+
|
|
3
|
+
This module provides symbolic expression nodes for Lie algebra operations
|
|
4
|
+
commonly used in 6-DOF rigid body dynamics, robotics, and geometric mechanics.
|
|
5
|
+
These operations enable elegant formulations of Newton-Euler dynamics using
|
|
6
|
+
spatial vectors (twists and wrenches).
|
|
7
|
+
|
|
8
|
+
The module provides two tiers of functionality:
|
|
9
|
+
|
|
10
|
+
**Built-in operators** work out of the box and include adjoint/coadjoint
|
|
11
|
+
operators for dynamics (_e.g._ ``Adjoint``, ``AdjointDual``) and frame transformations
|
|
12
|
+
(_e.g._ ``SE3Adjoint``, ``SE3AdjointDual``).
|
|
13
|
+
|
|
14
|
+
**jaxlie-backed operators** require ``pip install openscvx[lie]`` and provide
|
|
15
|
+
exponential/logarithm maps for SO(3) and SE(3) groups (_e.g._ ``SO3Exp``, ``SO3Log``,
|
|
16
|
+
``SE3Exp``, ``SE3Log``).
|
|
17
|
+
|
|
18
|
+
Conventions:
|
|
19
|
+
- Twist (spatial velocity): ξ = [v; ω] where v ∈ ℝ³ is linear velocity
|
|
20
|
+
and ω ∈ ℝ³ is angular velocity (both in body frame)
|
|
21
|
+
- Wrench (spatial force): F = [f; τ] where f ∈ ℝ³ is force and τ ∈ ℝ³
|
|
22
|
+
is torque (both in body frame)
|
|
23
|
+
|
|
24
|
+
Note:
|
|
25
|
+
The twist convention [v; ω] (linear first, angular second) matches jaxlie's
|
|
26
|
+
SE3 tangent parameterization, so no reordering is needed during lowering.
|
|
27
|
+
|
|
28
|
+
Example:
|
|
29
|
+
Newton-Euler dynamics for a rigid body using the coadjoint operator::
|
|
30
|
+
|
|
31
|
+
import openscvx as ox
|
|
32
|
+
|
|
33
|
+
twist = ox.State("twist", shape=(6,))
|
|
34
|
+
M = ox.Parameter("M", shape=(6, 6), value=spatial_inertia)
|
|
35
|
+
wrench = ox.Control("wrench", shape=(6,))
|
|
36
|
+
|
|
37
|
+
momentum = M @ twist
|
|
38
|
+
bias_force = ox.lie.AdjointDual(twist, momentum)
|
|
39
|
+
twist_dot = M_inv @ (wrench - bias_force)
|
|
40
|
+
|
|
41
|
+
Product of Exponentials forward kinematics (requires jaxlie)::
|
|
42
|
+
|
|
43
|
+
screw_axis = ox.Constant(np.array([0, 0, 0, 0, 0, 1]))
|
|
44
|
+
theta = ox.State("theta", shape=(1,))
|
|
45
|
+
T_joint = ox.lie.SE3Exp(screw_axis * theta) # 4×4 matrix
|
|
46
|
+
|
|
47
|
+
References:
|
|
48
|
+
- Murray, Li, Sastry: "A Mathematical Introduction to Robotic Manipulation"
|
|
49
|
+
- Featherstone: "Rigid Body Dynamics Algorithms"
|
|
50
|
+
- Sola et al.: "A micro Lie theory for state estimation in robotics"
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
# Core operators - no dependencies
|
|
54
|
+
from .adjoint import Adjoint, AdjointDual, SE3Adjoint, SE3AdjointDual
|
|
55
|
+
|
|
56
|
+
# jaxlie-backed operators - optional dependency
|
|
57
|
+
try:
|
|
58
|
+
from .se3 import SE3Exp, SE3Log
|
|
59
|
+
from .so3 import SO3Exp, SO3Log
|
|
60
|
+
|
|
61
|
+
_JAXLIE_AVAILABLE = True
|
|
62
|
+
except ImportError:
|
|
63
|
+
_JAXLIE_AVAILABLE = False
|
|
64
|
+
|
|
65
|
+
def _make_stub(name: str):
|
|
66
|
+
"""Create a stub class that raises ImportError on instantiation."""
|
|
67
|
+
|
|
68
|
+
def __init__(self, *args, **kwargs):
|
|
69
|
+
raise ImportError(f"{name} requires jaxlie. Install with: pip install openscvx[lie]")
|
|
70
|
+
|
|
71
|
+
return type(name, (), {"__init__": __init__})
|
|
72
|
+
|
|
73
|
+
SO3Exp = _make_stub("SO3Exp")
|
|
74
|
+
SO3Log = _make_stub("SO3Log")
|
|
75
|
+
SE3Exp = _make_stub("SE3Exp")
|
|
76
|
+
SE3Log = _make_stub("SE3Log")
|
|
77
|
+
|
|
78
|
+
__all__ = [
|
|
79
|
+
"AdjointDual",
|
|
80
|
+
"Adjoint",
|
|
81
|
+
"SE3Adjoint",
|
|
82
|
+
"SE3AdjointDual",
|
|
83
|
+
"SO3Exp",
|
|
84
|
+
"SO3Log",
|
|
85
|
+
"SE3Exp",
|
|
86
|
+
"SE3Log",
|
|
87
|
+
]
|