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.
Files changed (231) hide show
  1. {openscvx-0.3.2.dev143/openscvx.egg-info → openscvx-0.3.2.dev157}/PKG-INFO +4 -1
  2. openscvx-0.3.2.dev157/examples/arm/three_link_arm.py +253 -0
  3. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/__init__.py +2 -0
  4. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/_version.py +3 -3
  5. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/__init__.py +28 -0
  6. openscvx-0.3.2.dev157/openscvx/symbolic/expr/lie/__init__.py +87 -0
  7. openscvx-0.3.2.dev157/openscvx/symbolic/expr/lie/adjoint.py +357 -0
  8. openscvx-0.3.2.dev157/openscvx/symbolic/expr/lie/se3.py +172 -0
  9. openscvx-0.3.2.dev157/openscvx/symbolic/expr/lie/so3.py +138 -0
  10. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/lowerers/jax.py +275 -0
  11. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157/openscvx.egg-info}/PKG-INFO +4 -1
  12. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx.egg-info/SOURCES.txt +6 -0
  13. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx.egg-info/requires.txt +4 -0
  14. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/pyproject.toml +4 -0
  15. openscvx-0.3.2.dev157/tests/symbolic/expr/test_lie.py +1244 -0
  16. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/assets/logo.svg +0 -0
  17. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/release-drafter.yml +0 -0
  18. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/_docs.yml +0 -0
  19. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/docs.yml +0 -0
  20. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/lint.yml +0 -0
  21. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/nightly.yml +0 -0
  22. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/release-drafter.yml +0 -0
  23. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/release.yml +0 -0
  24. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/tests-integration.yml +0 -0
  25. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.github/workflows/tests-unit.yml +0 -0
  26. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/.gitignore +0 -0
  27. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/CONTRIBUTING.md +0 -0
  28. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/LICENSE +0 -0
  29. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/README.md +0 -0
  30. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Overview/constraint_reformulation.md +0 -0
  31. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Overview/control_parameterization.md +0 -0
  32. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Overview/discretization.md +0 -0
  33. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Overview/ocp.md +0 -0
  34. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Overview/scvx.md +0 -0
  35. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Overview/time_dilation.md +0 -0
  36. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/UnderTheHood/lowering_architecture.md +0 -0
  37. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
  38. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/advanced_problem_setup.md +0 -0
  39. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/api.md +0 -0
  40. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/api_constraints.md +0 -0
  41. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/api_control.md +0 -0
  42. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/api_integrators.md +0 -0
  43. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/api_state.md +0 -0
  44. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/api_trajoptproblem.md +0 -0
  45. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/api_variable.md +0 -0
  46. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/basic_problem_setup.md +0 -0
  47. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/tutorial_6dof_los_guidance.md +0 -0
  48. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/tutorial_6dof_obstacle_avoidance.md +0 -0
  49. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/Usage/tutorials.md +0 -0
  50. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/favicon.png +0 -0
  51. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/images/ct-scvx_dark.png +0 -0
  52. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/images/ct-scvx_light.png +0 -0
  53. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/images/ctcs_dark.png +0 -0
  54. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/images/ctcs_light.png +0 -0
  55. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/images/problem_class_dark.png +0 -0
  56. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/images/problem_class_light.png +0 -0
  57. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/assets/logo.svg +0 -0
  58. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/citation.md +0 -0
  59. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/examples.md +0 -0
  60. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/getting-started.md +0 -0
  61. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/index.md +0 -0
  62. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/docs/javascripts/mathjax.js +0 -0
  63. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/abstract/3DoF_pdg.py +0 -0
  64. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/abstract/brachistochrone.py +0 -0
  65. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/car/dubins_car.py +0 -0
  66. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/car/dubins_car_disjoint.py +0 -0
  67. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/car/dubins_car_stljax.py +0 -0
  68. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/cinema_vp.py +0 -0
  69. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/cinema_vp_realtime_base.py +0 -0
  70. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/dr_double_integrator.py +0 -0
  71. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/dr_vp.py +0 -0
  72. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/dr_vp_nodal.py +0 -0
  73. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/dr_vp_polytope.py +0 -0
  74. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/drone_racing.py +0 -0
  75. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/obstacle_avoidance.py +0 -0
  76. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/obstacle_avoidance_nodal.py +0 -0
  77. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/drone/obstacle_avoidance_realtime_base.py +0 -0
  78. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/plotting.py +0 -0
  79. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/plotting_viser.py +0 -0
  80. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/realtime/cinema_vp_realtime.py +0 -0
  81. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/realtime/drone_racing_realtime.py +0 -0
  82. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/realtime/dubins_car_realtime.py +0 -0
  83. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
  84. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/ctlos_cine.gif +0 -0
  85. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/ctlos_dr.gif +0 -0
  86. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/dtlos_cine.gif +0 -0
  87. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/dtlos_dr.gif +0 -0
  88. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/openscvx_logo.svg +0 -0
  89. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/openscvx_logo_square.png +0 -0
  90. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/oscvx_structure_full_dark.svg +0 -0
  91. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/figures/video_preview.png +0 -0
  92. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/__init__.py +0 -0
  93. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/1-background.avif +0 -0
  94. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/1-background@1x.avif +0 -0
  95. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/1-background@2x.avif +0 -0
  96. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/1-background@3x.avif +0 -0
  97. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/1-background@4x.avif +0 -0
  98. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/2-mars.avif +0 -0
  99. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/2-mars@1x.avif +0 -0
  100. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/2-mars@2x.avif +0 -0
  101. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/2-mars@3x.avif +0 -0
  102. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/2-mars@4x.avif +0 -0
  103. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/3-moon.avif +0 -0
  104. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/3-moon@1x.avif +0 -0
  105. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/3-moon@2x.avif +0 -0
  106. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/3-moon@3x.avif +0 -0
  107. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/3-moon@4x.avif +0 -0
  108. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/4-sat1.avif +0 -0
  109. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/4-sat1@1x.avif +0 -0
  110. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/4-sat1@2x.avif +0 -0
  111. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/4-sat1@3x.avif +0 -0
  112. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/4-sat1@4x.avif +0 -0
  113. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/5-space.avif +0 -0
  114. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/5-space@1x.avif +0 -0
  115. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/5-space@2x.avif +0 -0
  116. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/5-space@3x.avif +0 -0
  117. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/5-space@4x.avif +0 -0
  118. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/6-earth.avif +0 -0
  119. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/6-earth@1x.avif +0 -0
  120. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/6-earth@2x.avif +0 -0
  121. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/6-earth@3x.avif +0 -0
  122. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/images/layers/6-earth@4x.avif +0 -0
  123. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/javascripts/parallax.js +0 -0
  124. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/logo.svg +0 -0
  125. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/stylesheets/custom.css +0 -0
  126. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/assets/stylesheets/parallax.css +0 -0
  127. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/home.html +0 -0
  128. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/main.html +0 -0
  129. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/partials/parallax/hero.html +0 -0
  130. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/material/overrides/partials/parallax.html +0 -0
  131. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/mkdocs.yml +0 -0
  132. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/algorithms/__init__.py +0 -0
  133. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/algorithms/autotuning.py +0 -0
  134. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/algorithms/base.py +0 -0
  135. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/algorithms/optimization_results.py +0 -0
  136. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/algorithms/penalized_trust_region.py +0 -0
  137. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/config.py +0 -0
  138. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/discretization/__init__.py +0 -0
  139. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/discretization/discretization.py +0 -0
  140. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/expert/__init__.py +0 -0
  141. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/expert/byof.py +0 -0
  142. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/expert/lowering.py +0 -0
  143. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/expert/validation.py +0 -0
  144. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/integrators/__init__.py +0 -0
  145. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/integrators/runge_kutta.py +0 -0
  146. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/__init__.py +0 -0
  147. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/cvxpy_constraints.py +0 -0
  148. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/cvxpy_variables.py +0 -0
  149. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/dynamics.py +0 -0
  150. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/jax_constraints.py +0 -0
  151. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/parameters.py +0 -0
  152. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/problem.py +0 -0
  153. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/lowered/unified.py +0 -0
  154. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/__init__.py +0 -0
  155. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/plotting.py +0 -0
  156. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/scp_iteration.py +0 -0
  157. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/viser/__init__.py +0 -0
  158. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/viser/animated.py +0 -0
  159. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/viser/plotly_integration.py +0 -0
  160. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/viser/primitives.py +0 -0
  161. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/viser/scp.py +0 -0
  162. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/plotting/viser/server.py +0 -0
  163. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/problem.py +0 -0
  164. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/propagation/__init__.py +0 -0
  165. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/propagation/post_processing.py +0 -0
  166. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/propagation/propagation.py +0 -0
  167. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/solvers/__init__.py +0 -0
  168. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/solvers/cvxpy.py +0 -0
  169. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/__init__.py +0 -0
  170. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/augmentation.py +0 -0
  171. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/builder.py +0 -0
  172. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/constraint_set.py +0 -0
  173. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/arithmetic.py +0 -0
  174. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/array.py +0 -0
  175. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/constraint.py +0 -0
  176. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/control.py +0 -0
  177. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/expr.py +0 -0
  178. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/linalg.py +0 -0
  179. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/math.py +0 -0
  180. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/spatial.py +0 -0
  181. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/state.py +0 -0
  182. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/stl.py +0 -0
  183. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/expr/variable.py +0 -0
  184. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/hashing.py +0 -0
  185. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/lower.py +0 -0
  186. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/lowerers/__init__.py +0 -0
  187. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/lowerers/cvxpy.py +0 -0
  188. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/preprocessing.py +0 -0
  189. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/problem.py +0 -0
  190. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/time.py +0 -0
  191. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/symbolic/unified.py +0 -0
  192. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/utils/__init__.py +0 -0
  193. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/utils/cache.py +0 -0
  194. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/utils/caching.py +0 -0
  195. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/utils/printing.py +0 -0
  196. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/utils/profiling.py +0 -0
  197. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx/utils/utils.py +0 -0
  198. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx.egg-info/dependency_links.txt +0 -0
  199. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/openscvx.egg-info/top_level.txt +0 -0
  200. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/scripts/gen_example_pages.py +0 -0
  201. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/scripts/gen_ref_pages.py +0 -0
  202. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/setup.cfg +0 -0
  203. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/__init__.py +0 -0
  204. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/brachistochrone_analytical.py +0 -0
  205. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/__init__.py +0 -0
  206. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/__init__.py +0 -0
  207. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_arithmetic.py +0 -0
  208. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_array.py +0 -0
  209. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_constraint.py +0 -0
  210. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_expr.py +0 -0
  211. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_linalg.py +0 -0
  212. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_math.py +0 -0
  213. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_node_reference.py +0 -0
  214. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_parameters.py +0 -0
  215. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_scaling.py +0 -0
  216. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_spatial.py +0 -0
  217. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/expr/test_variable.py +0 -0
  218. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/test_augmentation.py +0 -0
  219. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/test_hashing.py +0 -0
  220. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/test_lower_cvxpy.py +0 -0
  221. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/test_lower_jax.py +0 -0
  222. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/test_preprocessing.py +0 -0
  223. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/symbolic/test_unified.py +0 -0
  224. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/test_brachistochrone.py +0 -0
  225. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/test_cvxpygen_optional.py +0 -0
  226. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/test_discretization.py +0 -0
  227. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/test_examples.py +0 -0
  228. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/test_expert.py +0 -0
  229. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/test_integrators.py +0 -0
  230. {openscvx-0.3.2.dev143 → openscvx-0.3.2.dev157}/tests/test_plotting.py +0 -0
  231. {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.dev143
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.dev143'
32
- __version_tuple__ = version_tuple = (0, 3, 2, 'dev143')
31
+ __version__ = version = '0.3.2.dev157'
32
+ __version_tuple__ = version_tuple = (0, 3, 2, 'dev157')
33
33
 
34
- __commit_id__ = commit_id = 'gfab08d1d7'
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
+ ]