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.
Files changed (347) hide show
  1. {openscvx-0.4.1.dev169/openscvx.egg-info → openscvx-0.4.1.dev171}/PKG-INFO +1 -1
  2. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/07_lie.md +93 -0
  3. openscvx-0.4.1.dev171/examples/arm/7_dof_arm_collision.py +507 -0
  4. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/_version.py +3 -3
  5. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/solvers/base.py +8 -1
  6. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/solvers/ptr_solver.py +16 -0
  7. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171/openscvx.egg-info}/PKG-INFO +1 -1
  8. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx.egg-info/SOURCES.txt +1 -0
  9. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/assets/logo.svg +0 -0
  10. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/release-drafter.yml +0 -0
  11. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/_docs.yml +0 -0
  12. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/branch-name.yml +0 -0
  13. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/docs.yml +0 -0
  14. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/lint.yml +0 -0
  15. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/nightly.yml +0 -0
  16. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/release-drafter.yml +0 -0
  17. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/release.yml +0 -0
  18. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/tests-integration.yml +0 -0
  19. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.github/workflows/tests-unit.yml +0 -0
  20. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/.gitignore +0 -0
  21. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/CONTRIBUTING.md +0 -0
  22. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/LICENSE +0 -0
  23. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/README.md +0 -0
  24. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/Foundations/constraint_reformulation.md +0 -0
  25. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/Foundations/control_parameterization.md +0 -0
  26. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/Foundations/discretization.md +0 -0
  27. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/Foundations/ocp.md +0 -0
  28. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/Foundations/scvx.md +0 -0
  29. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/Foundations/time_dilation.md +0 -0
  30. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UnderTheHood/lowering_architecture.md +0 -0
  31. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
  32. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/00_introduction.md +0 -0
  33. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
  34. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
  35. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
  36. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
  37. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/05_visualization.md +0 -0
  38. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/06_logic.md +0 -0
  39. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/UsersGuide/08_mpcc.md +0 -0
  40. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/favicon.png +0 -0
  41. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/images/ct-scvx_dark.png +0 -0
  42. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/images/ct-scvx_light.png +0 -0
  43. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/images/ctcs_dark.png +0 -0
  44. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/images/ctcs_light.png +0 -0
  45. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/images/problem_class_dark.png +0 -0
  46. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/images/problem_class_light.png +0 -0
  47. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/assets/logo.svg +0 -0
  48. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/citation.md +0 -0
  49. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/examples.md +0 -0
  50. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/getting-started.md +0 -0
  51. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/index.md +0 -0
  52. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/docs/javascripts/mathjax.js +0 -0
  53. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/abstract/brachistochrone.py +0 -0
  54. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/abstract/impulsive.py +0 -0
  55. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/abstract/stl_integer_variable.py +0 -0
  56. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/abstract/stl_or.py +0 -0
  57. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/arm/3_dof_arm.py +0 -0
  58. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/arm/7_dof_arm.py +0 -0
  59. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/arm/7_dof_arm_vp.py +0 -0
  60. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/car/dubins_car.py +0 -0
  61. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/car/dubins_car_disjoint.py +0 -0
  62. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/car/dubins_car_obstacle_conditional.py +0 -0
  63. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/car/dubins_car_obstacle_stl.py +0 -0
  64. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/car/dubins_car_stl_or.py +0 -0
  65. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/car/dubins_car_waypoint_stl.py +0 -0
  66. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/cinema_vp.py +0 -0
  67. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/dr_double_integrator.py +0 -0
  68. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/dr_vp.py +0 -0
  69. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/dr_vp_nodal.py +0 -0
  70. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/dr_vp_polytope.py +0 -0
  71. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/drone_racing.py +0 -0
  72. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/logo.py +0 -0
  73. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/logo_utils/acl_logo.svg +0 -0
  74. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/logo_utils/svg_path_utils.py +0 -0
  75. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/obstacle_avoidance.py +0 -0
  76. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/obstacle_avoidance_nodal.py +0 -0
  77. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/drone/obstacle_avoidance_vmap.py +0 -0
  78. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/mpc/double_integrator_discrete.py +0 -0
  79. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/mpc/double_integrator_drone_racing.py +0 -0
  80. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/mpc/dubins_car_circle_analytical.py +0 -0
  81. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/mpc/dubins_car_circle_discrete.py +0 -0
  82. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
  83. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/plotting.py +0 -0
  84. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/plotting_viser.py +0 -0
  85. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/3DoF_pdg_realtime.py +0 -0
  86. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/6DoF_pdg_realtime.py +0 -0
  87. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
  88. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
  89. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
  90. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
  91. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
  92. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
  93. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/cinema_vp_realtime.py +0 -0
  94. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/drone_racing_realtime.py +0 -0
  95. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/dubins_car_realtime.py +0 -0
  96. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
  97. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/rocket/3DoF_pdg.py +0 -0
  98. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/rocket/6DoF_pdg.py +0 -0
  99. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/spacecraft/halo_orbit.py +0 -0
  100. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/spacecraft/hohmann_transfer.py +0 -0
  101. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/examples/spacecraft/proxops_cw.py +0 -0
  102. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/ctlos_cine.gif +0 -0
  103. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/ctlos_dr.gif +0 -0
  104. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/dtlos_cine.gif +0 -0
  105. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/dtlos_dr.gif +0 -0
  106. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/openscvx_logo.svg +0 -0
  107. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/openscvx_logo_square.png +0 -0
  108. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/oscvx_structure_full_dark.svg +0 -0
  109. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/figures/video_preview.png +0 -0
  110. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/__init__.py +0 -0
  111. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/1-background.avif +0 -0
  112. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/1-background@1x.avif +0 -0
  113. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/1-background@2x.avif +0 -0
  114. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/1-background@3x.avif +0 -0
  115. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/1-background@4x.avif +0 -0
  116. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/2-mars.avif +0 -0
  117. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/2-mars@1x.avif +0 -0
  118. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/2-mars@2x.avif +0 -0
  119. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/2-mars@3x.avif +0 -0
  120. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/2-mars@4x.avif +0 -0
  121. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/3-moon.avif +0 -0
  122. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/3-moon@1x.avif +0 -0
  123. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/3-moon@2x.avif +0 -0
  124. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/3-moon@3x.avif +0 -0
  125. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/3-moon@4x.avif +0 -0
  126. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/4-sat1.avif +0 -0
  127. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/4-sat1@1x.avif +0 -0
  128. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/4-sat1@2x.avif +0 -0
  129. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/4-sat1@3x.avif +0 -0
  130. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/4-sat1@4x.avif +0 -0
  131. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/5-space.avif +0 -0
  132. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/5-space@1x.avif +0 -0
  133. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/5-space@2x.avif +0 -0
  134. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/5-space@3x.avif +0 -0
  135. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/5-space@4x.avif +0 -0
  136. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/6-earth.avif +0 -0
  137. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/6-earth@1x.avif +0 -0
  138. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/6-earth@2x.avif +0 -0
  139. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/6-earth@3x.avif +0 -0
  140. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/images/layers/6-earth@4x.avif +0 -0
  141. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/javascripts/parallax.js +0 -0
  142. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/logo.svg +0 -0
  143. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/stylesheets/custom.css +0 -0
  144. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/assets/stylesheets/parallax.css +0 -0
  145. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/home.html +0 -0
  146. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/main.html +0 -0
  147. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/partials/parallax/hero.html +0 -0
  148. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/material/overrides/partials/parallax.html +0 -0
  149. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/mkdocs.yml +0 -0
  150. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/__init__.py +0 -0
  151. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/__main__.py +0 -0
  152. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/__init__.py +0 -0
  153. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/augmented_lagrangian.py +0 -0
  154. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/base.py +0 -0
  155. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/constant_proximal_weight.py +0 -0
  156. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/optimization_results.py +0 -0
  157. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/penalized_trust_region.py +0 -0
  158. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/ramp_proximal_weight.py +0 -0
  159. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/algorithms/weights.py +0 -0
  160. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/config.py +0 -0
  161. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/__init__.py +0 -0
  162. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/base.py +0 -0
  163. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/discretize_linearize.py +0 -0
  164. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/linearize_discretize.py +0 -0
  165. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
  166. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/sparse_utils/__init__.py +0 -0
  167. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
  168. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
  169. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/expert/__init__.py +0 -0
  170. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/expert/byof.py +0 -0
  171. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/expert/lowering.py +0 -0
  172. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/expert/validation.py +0 -0
  173. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/init/__init__.py +0 -0
  174. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/init/interpolation.py +0 -0
  175. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/init/inverse_kinematics.py +0 -0
  176. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/integrators/__init__.py +0 -0
  177. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/integrators/diffrax.py +0 -0
  178. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/integrators/runge_kutta.py +0 -0
  179. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/loader.py +0 -0
  180. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/__init__.py +0 -0
  181. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/cvxpy_constraints.py +0 -0
  182. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/cvxpy_variables.py +0 -0
  183. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/dynamics.py +0 -0
  184. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/jax_constraints.py +0 -0
  185. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/parameters.py +0 -0
  186. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/problem.py +0 -0
  187. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/lowered/unified.py +0 -0
  188. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/__init__.py +0 -0
  189. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/plotting.py +0 -0
  190. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/scp_iteration.py +0 -0
  191. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/viser/__init__.py +0 -0
  192. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/viser/animated.py +0 -0
  193. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/viser/orbits.py +0 -0
  194. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/viser/plotly_integration.py +0 -0
  195. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/viser/primitives.py +0 -0
  196. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/viser/scp.py +0 -0
  197. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/plotting/viser/server.py +0 -0
  198. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/problem.py +0 -0
  199. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/propagation/__init__.py +0 -0
  200. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/propagation/post_processing.py +0 -0
  201. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/propagation/propagation.py +0 -0
  202. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/solvers/__init__.py +0 -0
  203. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/__init__.py +0 -0
  204. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/augmentation.py +0 -0
  205. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/builder.py +0 -0
  206. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/constraint_set.py +0 -0
  207. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/__init__.py +0 -0
  208. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/arithmetic.py +0 -0
  209. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/array.py +0 -0
  210. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/constraint.py +0 -0
  211. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/control.py +0 -0
  212. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/expr.py +0 -0
  213. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/lie/__init__.py +0 -0
  214. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
  215. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/lie/se3.py +0 -0
  216. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/lie/so3.py +0 -0
  217. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/linalg.py +0 -0
  218. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/logic.py +0 -0
  219. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/math.py +0 -0
  220. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/parameter.py +0 -0
  221. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/spatial.py +0 -0
  222. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/state.py +0 -0
  223. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/stl.py +0 -0
  224. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/stljax.py +0 -0
  225. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/time.py +0 -0
  226. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/variable.py +0 -0
  227. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/expr/vmap.py +0 -0
  228. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/hashing.py +0 -0
  229. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lower.py +0 -0
  230. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/__init__.py +0 -0
  231. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
  232. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
  233. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
  234. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
  235. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
  236. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
  237. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
  238. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
  239. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
  240. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
  241. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
  242. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
  243. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
  244. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
  245. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
  246. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
  247. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/array.py +0 -0
  248. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
  249. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/control.py +0 -0
  250. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
  251. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
  252. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
  253. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
  254. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/math.py +0 -0
  255. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
  256. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/state.py +0 -0
  257. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
  258. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
  259. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
  260. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/__init__.py +0 -0
  261. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/_registry.py +0 -0
  262. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/array.py +0 -0
  263. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/constraint.py +0 -0
  264. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/lie.py +0 -0
  265. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/linalg.py +0 -0
  266. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/logic.py +0 -0
  267. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/math.py +0 -0
  268. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/parser.py +0 -0
  269. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/spatial.py +0 -0
  270. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/stl.py +0 -0
  271. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/stljax.py +0 -0
  272. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/parser/tokenizer.py +0 -0
  273. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/preprocessing.py +0 -0
  274. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/problem.py +0 -0
  275. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/sparsity.py +0 -0
  276. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/symbolic/unified.py +0 -0
  277. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/utils/__init__.py +0 -0
  278. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/utils/cache.py +0 -0
  279. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/utils/caching.py +0 -0
  280. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/utils/printing.py +0 -0
  281. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/utils/profiling.py +0 -0
  282. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx/utils/utils.py +0 -0
  283. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx.egg-info/dependency_links.txt +0 -0
  284. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx.egg-info/entry_points.txt +0 -0
  285. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx.egg-info/requires.txt +0 -0
  286. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/openscvx.egg-info/top_level.txt +0 -0
  287. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/pyproject.toml +0 -0
  288. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/scripts/gen_example_pages.py +0 -0
  289. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/scripts/gen_ref_pages.py +0 -0
  290. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/setup.cfg +0 -0
  291. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/__init__.py +0 -0
  292. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/brachistochrone_analytical.py +0 -0
  293. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/expr/__init__.py +0 -0
  294. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/expr/test_gmsr.py +0 -0
  295. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/fixtures/brachistochrone.json +0 -0
  296. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/fixtures/brachistochrone.yaml +0 -0
  297. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/hohmann_analytical.py +0 -0
  298. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/__init__.py +0 -0
  299. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/__init__.py +0 -0
  300. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_arithmetic.py +0 -0
  301. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_array.py +0 -0
  302. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_constraint.py +0 -0
  303. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_expr.py +0 -0
  304. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_lie.py +0 -0
  305. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_linalg.py +0 -0
  306. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_logic.py +0 -0
  307. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_math.py +0 -0
  308. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_node_reference.py +0 -0
  309. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_parameters.py +0 -0
  310. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_scaling.py +0 -0
  311. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_spatial.py +0 -0
  312. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_stl.py +0 -0
  313. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_variable.py +0 -0
  314. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/expr/test_vmap.py +0 -0
  315. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/__init__.py +0 -0
  316. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_array.py +0 -0
  317. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_constraint.py +0 -0
  318. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_lie.py +0 -0
  319. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_linalg.py +0 -0
  320. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_load.py +0 -0
  321. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_logic.py +0 -0
  322. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_math.py +0 -0
  323. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_parser.py +0 -0
  324. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_spatial.py +0 -0
  325. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_stl.py +0 -0
  326. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_tokenizer.py +0 -0
  327. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/parser/test_vmap.py +0 -0
  328. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/test_augmentation.py +0 -0
  329. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/test_hashing.py +0 -0
  330. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/test_lower_cvxpy.py +0 -0
  331. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/test_lower_jax.py +0 -0
  332. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/test_preprocessing.py +0 -0
  333. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/test_sparsity.py +0 -0
  334. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/symbolic/test_unified.py +0 -0
  335. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_autotuning.py +0 -0
  336. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_brachistochrone.py +0 -0
  337. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_cvxpygen_optional.py +0 -0
  338. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_discretization.py +0 -0
  339. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_examples.py +0 -0
  340. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_expert.py +0 -0
  341. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_impulsive.py +0 -0
  342. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_init.py +0 -0
  343. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_integrators.py +0 -0
  344. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_loader.py +0 -0
  345. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_optimization_results.py +0 -0
  346. {openscvx-0.4.1.dev169 → openscvx-0.4.1.dev171}/tests/test_plotting.py +0 -0
  347. {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.dev169
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.dev169'
22
- __version_tuple__ = version_tuple = (0, 4, 1, 'dev169')
21
+ __version__ = version = '0.4.1.dev171'
22
+ __version_tuple__ = version_tuple = (0, 4, 1, 'dev171')
23
23
 
24
- __commit_id__ = commit_id = 'gbc266779e'
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.dev169
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