openscvx 0.4.1.dev170__tar.gz → 0.4.1.dev172__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 (354) hide show
  1. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/.gitignore +3 -0
  2. {openscvx-0.4.1.dev170/openscvx.egg-info → openscvx-0.4.1.dev172}/PKG-INFO +1 -1
  3. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/UsersGuide/07_lie.md +93 -0
  4. openscvx-0.4.1.dev172/examples/animations/7_dof_arm.py +225 -0
  5. openscvx-0.4.1.dev172/examples/animations/_camera.py +142 -0
  6. openscvx-0.4.1.dev172/examples/animations/_render.py +261 -0
  7. openscvx-0.4.1.dev172/examples/animations/_sensor_view.py +306 -0
  8. openscvx-0.4.1.dev172/examples/animations/dr_vp_polytope.py +180 -0
  9. openscvx-0.4.1.dev172/examples/animations/logo.py +154 -0
  10. openscvx-0.4.1.dev172/examples/animations/obstacle_avoidance_vmap.py +151 -0
  11. openscvx-0.4.1.dev172/examples/arm/7_dof_arm_collision.py +507 -0
  12. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/plotting_viser.py +138 -68
  13. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/_version.py +3 -3
  14. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/plotting/viser/animated.py +37 -12
  15. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172/openscvx.egg-info}/PKG-INFO +1 -1
  16. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx.egg-info/SOURCES.txt +8 -0
  17. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/test_examples.py +4 -2
  18. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/.github/assets/logo.svg +0 -0
  19. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/.github/release-drafter.yml +0 -0
  20. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/.github/workflows/_docs.yml +0 -0
  21. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/.github/workflows/branch-name.yml +0 -0
  22. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/.github/workflows/docs.yml +0 -0
  23. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/.github/workflows/lint.yml +0 -0
  24. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/.github/workflows/nightly.yml +0 -0
  25. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/.github/workflows/release-drafter.yml +0 -0
  26. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/.github/workflows/release.yml +0 -0
  27. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/.github/workflows/tests-integration.yml +0 -0
  28. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/.github/workflows/tests-unit.yml +0 -0
  29. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/CONTRIBUTING.md +0 -0
  30. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/LICENSE +0 -0
  31. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/README.md +0 -0
  32. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/Foundations/constraint_reformulation.md +0 -0
  33. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/Foundations/control_parameterization.md +0 -0
  34. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/Foundations/discretization.md +0 -0
  35. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/Foundations/ocp.md +0 -0
  36. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/Foundations/scvx.md +0 -0
  37. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/Foundations/time_dilation.md +0 -0
  38. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/UnderTheHood/lowering_architecture.md +0 -0
  39. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
  40. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/UsersGuide/00_introduction.md +0 -0
  41. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
  42. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
  43. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
  44. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
  45. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/UsersGuide/05_visualization.md +0 -0
  46. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/UsersGuide/06_logic.md +0 -0
  47. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/UsersGuide/08_mpcc.md +0 -0
  48. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/assets/favicon.png +0 -0
  49. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/assets/images/ct-scvx_dark.png +0 -0
  50. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/assets/images/ct-scvx_light.png +0 -0
  51. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/assets/images/ctcs_dark.png +0 -0
  52. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/assets/images/ctcs_light.png +0 -0
  53. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/assets/images/problem_class_dark.png +0 -0
  54. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/assets/images/problem_class_light.png +0 -0
  55. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/assets/logo.svg +0 -0
  56. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/citation.md +0 -0
  57. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/examples.md +0 -0
  58. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/getting-started.md +0 -0
  59. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/index.md +0 -0
  60. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/docs/javascripts/mathjax.js +0 -0
  61. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/abstract/brachistochrone.py +0 -0
  62. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/abstract/impulsive.py +0 -0
  63. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/abstract/stl_integer_variable.py +0 -0
  64. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/abstract/stl_or.py +0 -0
  65. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/arm/3_dof_arm.py +0 -0
  66. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/arm/7_dof_arm.py +0 -0
  67. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/arm/7_dof_arm_vp.py +0 -0
  68. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/car/dubins_car.py +0 -0
  69. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/car/dubins_car_disjoint.py +0 -0
  70. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/car/dubins_car_obstacle_conditional.py +0 -0
  71. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/car/dubins_car_obstacle_stl.py +0 -0
  72. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/car/dubins_car_stl_or.py +0 -0
  73. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/car/dubins_car_waypoint_stl.py +0 -0
  74. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/drone/cinema_vp.py +0 -0
  75. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/drone/dr_double_integrator.py +0 -0
  76. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/drone/dr_vp.py +0 -0
  77. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/drone/dr_vp_nodal.py +0 -0
  78. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/drone/dr_vp_polytope.py +0 -0
  79. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/drone/drone_racing.py +0 -0
  80. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/drone/logo.py +0 -0
  81. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/drone/logo_utils/acl_logo.svg +0 -0
  82. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/drone/logo_utils/svg_path_utils.py +0 -0
  83. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/drone/obstacle_avoidance.py +0 -0
  84. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/drone/obstacle_avoidance_nodal.py +0 -0
  85. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/drone/obstacle_avoidance_vmap.py +0 -0
  86. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/mpc/double_integrator_discrete.py +0 -0
  87. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/mpc/double_integrator_drone_racing.py +0 -0
  88. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/mpc/dubins_car_circle_analytical.py +0 -0
  89. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/mpc/dubins_car_circle_discrete.py +0 -0
  90. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/mpc/realtime_double_integrator_drone_racing.py +0 -0
  91. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/plotting.py +0 -0
  92. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/realtime/3DoF_pdg_realtime.py +0 -0
  93. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/realtime/6DoF_pdg_realtime.py +0 -0
  94. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/realtime/base_problems/3DoF_pdg_realtime_base.py +0 -0
  95. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/realtime/base_problems/6DoF_pdg_realtime_base.py +0 -0
  96. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
  97. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
  98. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/realtime/base_problems/dubins_car_realtime_base.py +0 -0
  99. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
  100. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/realtime/cinema_vp_realtime.py +0 -0
  101. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/realtime/drone_racing_realtime.py +0 -0
  102. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/realtime/dubins_car_realtime.py +0 -0
  103. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
  104. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/rocket/3DoF_pdg.py +0 -0
  105. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/rocket/6DoF_pdg.py +0 -0
  106. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/spacecraft/halo_orbit.py +0 -0
  107. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/spacecraft/hohmann_transfer.py +0 -0
  108. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/examples/spacecraft/proxops_cw.py +0 -0
  109. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/figures/ctlos_cine.gif +0 -0
  110. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/figures/ctlos_dr.gif +0 -0
  111. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/figures/dtlos_cine.gif +0 -0
  112. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/figures/dtlos_dr.gif +0 -0
  113. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/figures/openscvx_logo.svg +0 -0
  114. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/figures/openscvx_logo_square.png +0 -0
  115. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/figures/oscvx_structure_full_dark.svg +0 -0
  116. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/figures/video_preview.png +0 -0
  117. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/__init__.py +0 -0
  118. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/1-background.avif +0 -0
  119. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/1-background@1x.avif +0 -0
  120. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/1-background@2x.avif +0 -0
  121. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/1-background@3x.avif +0 -0
  122. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/1-background@4x.avif +0 -0
  123. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/2-mars.avif +0 -0
  124. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/2-mars@1x.avif +0 -0
  125. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/2-mars@2x.avif +0 -0
  126. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/2-mars@3x.avif +0 -0
  127. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/2-mars@4x.avif +0 -0
  128. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/3-moon.avif +0 -0
  129. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/3-moon@1x.avif +0 -0
  130. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/3-moon@2x.avif +0 -0
  131. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/3-moon@3x.avif +0 -0
  132. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/3-moon@4x.avif +0 -0
  133. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/4-sat1.avif +0 -0
  134. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/4-sat1@1x.avif +0 -0
  135. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/4-sat1@2x.avif +0 -0
  136. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/4-sat1@3x.avif +0 -0
  137. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/4-sat1@4x.avif +0 -0
  138. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/5-space.avif +0 -0
  139. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/5-space@1x.avif +0 -0
  140. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/5-space@2x.avif +0 -0
  141. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/5-space@3x.avif +0 -0
  142. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/5-space@4x.avif +0 -0
  143. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/6-earth.avif +0 -0
  144. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/6-earth@1x.avif +0 -0
  145. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/6-earth@2x.avif +0 -0
  146. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/6-earth@3x.avif +0 -0
  147. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/images/layers/6-earth@4x.avif +0 -0
  148. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/javascripts/parallax.js +0 -0
  149. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/logo.svg +0 -0
  150. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/stylesheets/custom.css +0 -0
  151. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/assets/stylesheets/parallax.css +0 -0
  152. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/home.html +0 -0
  153. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/main.html +0 -0
  154. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/partials/parallax/hero.html +0 -0
  155. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/material/overrides/partials/parallax.html +0 -0
  156. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/mkdocs.yml +0 -0
  157. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/__init__.py +0 -0
  158. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/__main__.py +0 -0
  159. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/algorithms/__init__.py +0 -0
  160. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/algorithms/augmented_lagrangian.py +0 -0
  161. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/algorithms/base.py +0 -0
  162. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/algorithms/constant_proximal_weight.py +0 -0
  163. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/algorithms/optimization_results.py +0 -0
  164. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/algorithms/penalized_trust_region.py +0 -0
  165. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/algorithms/ramp_proximal_weight.py +0 -0
  166. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/algorithms/weights.py +0 -0
  167. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/config.py +0 -0
  168. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/discretization/__init__.py +0 -0
  169. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/discretization/base.py +0 -0
  170. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/discretization/discretize_linearize.py +0 -0
  171. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/discretization/linearize_discretize.py +0 -0
  172. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/discretization/linearize_discretize_sparse.py +0 -0
  173. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/discretization/sparse_utils/__init__.py +0 -0
  174. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/discretization/sparse_utils/bcoo_helpers.py +0 -0
  175. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/discretization/sparse_utils/sparse_jacobian.py +0 -0
  176. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/expert/__init__.py +0 -0
  177. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/expert/byof.py +0 -0
  178. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/expert/lowering.py +0 -0
  179. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/expert/validation.py +0 -0
  180. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/init/__init__.py +0 -0
  181. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/init/interpolation.py +0 -0
  182. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/init/inverse_kinematics.py +0 -0
  183. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/integrators/__init__.py +0 -0
  184. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/integrators/diffrax.py +0 -0
  185. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/integrators/runge_kutta.py +0 -0
  186. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/loader.py +0 -0
  187. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/lowered/__init__.py +0 -0
  188. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/lowered/cvxpy_constraints.py +0 -0
  189. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/lowered/cvxpy_variables.py +0 -0
  190. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/lowered/dynamics.py +0 -0
  191. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/lowered/jax_constraints.py +0 -0
  192. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/lowered/parameters.py +0 -0
  193. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/lowered/problem.py +0 -0
  194. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/lowered/unified.py +0 -0
  195. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/plotting/__init__.py +0 -0
  196. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/plotting/plotting.py +0 -0
  197. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/plotting/scp_iteration.py +0 -0
  198. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/plotting/viser/__init__.py +0 -0
  199. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/plotting/viser/orbits.py +0 -0
  200. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/plotting/viser/plotly_integration.py +0 -0
  201. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/plotting/viser/primitives.py +0 -0
  202. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/plotting/viser/scp.py +0 -0
  203. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/plotting/viser/server.py +0 -0
  204. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/problem.py +0 -0
  205. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/propagation/__init__.py +0 -0
  206. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/propagation/post_processing.py +0 -0
  207. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/propagation/propagation.py +0 -0
  208. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/solvers/__init__.py +0 -0
  209. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/solvers/base.py +0 -0
  210. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/solvers/ptr_solver.py +0 -0
  211. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/__init__.py +0 -0
  212. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/augmentation.py +0 -0
  213. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/builder.py +0 -0
  214. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/constraint_set.py +0 -0
  215. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/__init__.py +0 -0
  216. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/arithmetic.py +0 -0
  217. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/array.py +0 -0
  218. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/constraint.py +0 -0
  219. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/control.py +0 -0
  220. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/expr.py +0 -0
  221. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/lie/__init__.py +0 -0
  222. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
  223. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/lie/se3.py +0 -0
  224. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/lie/so3.py +0 -0
  225. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/linalg.py +0 -0
  226. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/logic.py +0 -0
  227. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/math.py +0 -0
  228. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/parameter.py +0 -0
  229. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/spatial.py +0 -0
  230. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/state.py +0 -0
  231. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/stl.py +0 -0
  232. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/stljax.py +0 -0
  233. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/time.py +0 -0
  234. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/variable.py +0 -0
  235. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/expr/vmap.py +0 -0
  236. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/hashing.py +0 -0
  237. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lower.py +0 -0
  238. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/__init__.py +0 -0
  239. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
  240. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
  241. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
  242. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
  243. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
  244. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
  245. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
  246. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
  247. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
  248. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
  249. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
  250. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
  251. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
  252. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
  253. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
  254. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
  255. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/array.py +0 -0
  256. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
  257. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/control.py +0 -0
  258. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
  259. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
  260. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
  261. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/logic.py +0 -0
  262. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/math.py +0 -0
  263. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
  264. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/state.py +0 -0
  265. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
  266. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/stljax.py +0 -0
  267. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
  268. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/parser/__init__.py +0 -0
  269. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/parser/_registry.py +0 -0
  270. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/parser/array.py +0 -0
  271. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/parser/constraint.py +0 -0
  272. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/parser/lie.py +0 -0
  273. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/parser/linalg.py +0 -0
  274. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/parser/logic.py +0 -0
  275. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/parser/math.py +0 -0
  276. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/parser/parser.py +0 -0
  277. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/parser/spatial.py +0 -0
  278. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/parser/stl.py +0 -0
  279. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/parser/stljax.py +0 -0
  280. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/parser/tokenizer.py +0 -0
  281. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/preprocessing.py +0 -0
  282. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/problem.py +0 -0
  283. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/sparsity.py +0 -0
  284. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/symbolic/unified.py +0 -0
  285. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/utils/__init__.py +0 -0
  286. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/utils/cache.py +0 -0
  287. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/utils/caching.py +0 -0
  288. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/utils/printing.py +0 -0
  289. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/utils/profiling.py +0 -0
  290. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx/utils/utils.py +0 -0
  291. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx.egg-info/dependency_links.txt +0 -0
  292. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx.egg-info/entry_points.txt +0 -0
  293. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx.egg-info/requires.txt +0 -0
  294. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/openscvx.egg-info/top_level.txt +0 -0
  295. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/pyproject.toml +0 -0
  296. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/scripts/gen_example_pages.py +0 -0
  297. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/scripts/gen_ref_pages.py +0 -0
  298. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/setup.cfg +0 -0
  299. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/__init__.py +0 -0
  300. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/brachistochrone_analytical.py +0 -0
  301. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/expr/__init__.py +0 -0
  302. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/expr/test_gmsr.py +0 -0
  303. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/fixtures/brachistochrone.json +0 -0
  304. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/fixtures/brachistochrone.yaml +0 -0
  305. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/hohmann_analytical.py +0 -0
  306. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/__init__.py +0 -0
  307. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/__init__.py +0 -0
  308. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/test_arithmetic.py +0 -0
  309. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/test_array.py +0 -0
  310. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/test_constraint.py +0 -0
  311. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/test_expr.py +0 -0
  312. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/test_lie.py +0 -0
  313. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/test_linalg.py +0 -0
  314. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/test_logic.py +0 -0
  315. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/test_math.py +0 -0
  316. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/test_node_reference.py +0 -0
  317. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/test_parameters.py +0 -0
  318. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/test_scaling.py +0 -0
  319. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/test_spatial.py +0 -0
  320. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/test_stl.py +0 -0
  321. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/test_variable.py +0 -0
  322. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/expr/test_vmap.py +0 -0
  323. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/parser/__init__.py +0 -0
  324. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/parser/test_array.py +0 -0
  325. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/parser/test_constraint.py +0 -0
  326. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/parser/test_lie.py +0 -0
  327. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/parser/test_linalg.py +0 -0
  328. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/parser/test_load.py +0 -0
  329. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/parser/test_logic.py +0 -0
  330. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/parser/test_math.py +0 -0
  331. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/parser/test_parser.py +0 -0
  332. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/parser/test_spatial.py +0 -0
  333. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/parser/test_stl.py +0 -0
  334. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/parser/test_tokenizer.py +0 -0
  335. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/parser/test_vmap.py +0 -0
  336. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/test_augmentation.py +0 -0
  337. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/test_hashing.py +0 -0
  338. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/test_lower_cvxpy.py +0 -0
  339. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/test_lower_jax.py +0 -0
  340. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/test_preprocessing.py +0 -0
  341. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/test_sparsity.py +0 -0
  342. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/symbolic/test_unified.py +0 -0
  343. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/test_autotuning.py +0 -0
  344. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/test_brachistochrone.py +0 -0
  345. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/test_cvxpygen_optional.py +0 -0
  346. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/test_discretization.py +0 -0
  347. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/test_expert.py +0 -0
  348. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/test_impulsive.py +0 -0
  349. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/test_init.py +0 -0
  350. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/test_integrators.py +0 -0
  351. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/test_loader.py +0 -0
  352. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/test_optimization_results.py +0 -0
  353. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/test_plotting.py +0 -0
  354. {openscvx-0.4.1.dev170 → openscvx-0.4.1.dev172}/tests/test_propagation.py +0 -0
@@ -27,6 +27,9 @@ solver/*
27
27
  # Images
28
28
  *.eps
29
29
 
30
+ # Animation renders
31
+ examples/animations/mp4/
32
+
30
33
  # Numpy files
31
34
  *.npy
32
35
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscvx
3
- Version: 0.4.1.dev170
3
+ Version: 0.4.1.dev172
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,225 @@
1
+ """Cinematic offline render of the 7-DOF arm pick-and-place example.
2
+
3
+ The trajectory optimization problem itself lives in
4
+ ``examples/arm/7_dof_arm.py``; this file imports that ``problem`` and the
5
+ robot parameters, solves it, builds a viser scene with arm links / joint
6
+ frames / EE trail, and drives it frame-by-frame while piping raw RGB into
7
+ ffmpeg to produce an mp4.
8
+
9
+ Run it with::
10
+
11
+ python examples/animations/7_dof_arm.py
12
+
13
+ The script prints a viser URL and waits. Open the URL in a browser — as soon
14
+ as the client connects, the render begins. Requires ``ffmpeg`` on ``PATH``;
15
+ ``openscvx`` does not depend on it.
16
+
17
+ Only one camera mode is provided — ``"overview"`` — a static elevated camera
18
+ that frames the full pick-and-place workspace.
19
+
20
+ Tweak ``OUTPUT_PATH`` / ``WIDTH`` / ``HEIGHT`` / ``FPS`` below for different
21
+ output variants.
22
+ """
23
+
24
+ import importlib
25
+ import os
26
+ import sys
27
+
28
+ import numpy as np
29
+
30
+ # Add the project root so `examples.*` imports resolve.
31
+ current_dir = os.path.dirname(os.path.abspath(__file__))
32
+ grandparent_dir = os.path.dirname(os.path.dirname(current_dir))
33
+ sys.path.append(grandparent_dir)
34
+
35
+ from examples.animations._camera import overview_pose
36
+ from examples.animations._render import render_animation_to_video
37
+ from examples.plotting_viser import AnimatedServerHandle
38
+ from openscvx.plotting.viser import (
39
+ add_animated_trail,
40
+ add_ellipsoid_obstacles,
41
+ add_ghost_trajectory,
42
+ add_position_marker,
43
+ add_target_markers,
44
+ compute_velocity_colors,
45
+ create_server,
46
+ )
47
+
48
+ # Import the arm example by path (filename starts with a digit).
49
+ _arm_spec = importlib.util.spec_from_file_location(
50
+ "arm_7dof", os.path.join(grandparent_dir, "examples", "arm", "7_dof_arm_collision.py")
51
+ )
52
+ _arm_mod = importlib.util.module_from_spec(_arm_spec)
53
+ _arm_spec.loader.exec_module(_arm_mod)
54
+
55
+ problem = _arm_mod.problem
56
+ d1 = _arm_mod.d1
57
+ a2 = _arm_mod.a2
58
+ a3 = _arm_mod.a3
59
+ a4 = _arm_mod.a4
60
+ joint_names = _arm_mod.joint_names
61
+ waypoint_names = _arm_mod.waypoint_names
62
+ waypoint_positions = _arm_mod.waypoint_positions
63
+ obstacle_center = _arm_mod.obstacle_center
64
+ obstacle_radius = _arm_mod.obstacle_radius
65
+
66
+ # Keypoint home positions (derived from link lengths — defined in __main__ of
67
+ # the arm example, so we replicate them here).
68
+ keypoint_home_positions = {
69
+ "base": np.array([0.0, 0.0, 0.0]),
70
+ "shoulder": np.array([0.0, 0.0, d1]),
71
+ "elbow": np.array([a2, 0.0, d1]),
72
+ "wrist": np.array([a2 + a3, 0.0, d1]),
73
+ "ee": np.array([a2 + a3 + a4, 0.0, d1]),
74
+ }
75
+
76
+ # --- Render settings ---------------------------------------------------------
77
+ OUTPUT_PATH = os.path.join(current_dir, "mp4", "7_dof_arm_overview.mp4")
78
+ WIDTH = 1080
79
+ HEIGHT = 1080
80
+ FPS = 60
81
+ CRF = 16
82
+
83
+ # Oversampling for smooth trails.
84
+ STRIDE = 4
85
+ PROPAGATION_HZ = FPS * STRIDE
86
+
87
+ # --- Camera settings ---------------------------------------------------------
88
+ OVERVIEW_AZIMUTH = np.radians(60.0)
89
+ OVERVIEW_ELEVATION = np.radians(15.0)
90
+ OVERVIEW_RADIUS_MARGIN = 1.0
91
+ OVERVIEW_FOV_DEG = 60.0
92
+
93
+
94
+ if __name__ == "__main__":
95
+ import jaxlie
96
+
97
+ problem.settings.prp.dt = 1.0 / PROPAGATION_HZ
98
+ problem.initialize()
99
+ problem.solve()
100
+ results = problem.post_process()
101
+
102
+ ee_pos = np.asarray(results.trajectory["ee_position"], dtype=np.float64)
103
+ n_frames = len(ee_pos)
104
+
105
+ # -- Extract joint keypoint positions from propagated transforms -----------
106
+ keypoints = np.zeros((n_frames, 5, 3))
107
+ joint_quats = np.zeros((n_frames, 5, 4))
108
+ for k, name in enumerate(joint_names):
109
+ T_k = np.asarray(results.trajectory[f"T_{name}"]) # (T, 4, 4)
110
+ p_home = np.append(keypoint_home_positions[name], 1.0)
111
+ keypoints[:, k] = (T_k @ p_home)[:, :3]
112
+ joint_quats[:, k] = np.array(
113
+ [jaxlie.SO3.from_matrix(T_k[t, :3, :3]).wxyz for t in range(n_frames)]
114
+ )
115
+
116
+ # -- Build viser scene (mirrors examples/arm/7_dof_arm.py) -----------------
117
+ server = create_server(ee_pos, show_grid=False)
118
+ server.scene.add_grid("/grid", width=1.5, height=1.5, cell_size=0.25)
119
+ server.scene.add_frame("/origin", axes_length=0.1, axes_radius=0.003)
120
+
121
+ # Waypoint markers
122
+ marker_colors = {
123
+ "home": (100, 150, 255),
124
+ "pre_grasp": (255, 180, 50),
125
+ "grasp": (255, 50, 50),
126
+ "pre_place": (255, 180, 50),
127
+ "place": (255, 50, 50),
128
+ }
129
+ add_target_markers(
130
+ server,
131
+ waypoint_positions,
132
+ radius=0.015,
133
+ colors=[marker_colors[name] for name in waypoint_names],
134
+ )
135
+
136
+ add_ellipsoid_obstacles(
137
+ server,
138
+ centers=[obstacle_center],
139
+ radii=[np.full(3, 1.0 / obstacle_radius)],
140
+ )
141
+
142
+ # Ghost EE trajectory + animated trail
143
+ ee_colors = compute_velocity_colors(np.asarray(results.trajectory.get("velocity")))
144
+ add_ghost_trajectory(server, ee_pos, ee_colors, point_size=0.005)
145
+ _, update_trail = add_animated_trail(server, ee_pos, ee_colors, point_size=0.008)
146
+
147
+ # Animated EE position marker
148
+ _, update_marker = add_position_marker(server, ee_pos, radius=0.015)
149
+
150
+ # Animated arm links (line segments between consecutive keypoints)
151
+ link_rgb = np.array(
152
+ [
153
+ [180, 180, 180], # base -> shoulder
154
+ [100, 180, 255], # shoulder -> elbow
155
+ [100, 255, 150], # elbow -> wrist
156
+ [255, 200, 100], # wrist -> ee
157
+ ],
158
+ dtype=np.uint8,
159
+ )
160
+ link_colors = np.stack([link_rgb, link_rgb], axis=1) # (4, 2, 3)
161
+
162
+ init_points = np.stack(
163
+ [np.stack([keypoints[0, k], keypoints[0, k + 1]]) for k in range(4)]
164
+ ).astype(np.float32)
165
+
166
+ arm_handle = server.scene.add_line_segments(
167
+ "/arm_links",
168
+ points=init_points,
169
+ colors=link_colors,
170
+ line_width=5.0,
171
+ )
172
+
173
+ # Joint coordinate frames
174
+ joint_frame_handles = []
175
+ for k in range(5):
176
+ h = server.scene.add_frame(
177
+ f"/joint_{joint_names[k]}",
178
+ wxyz=joint_quats[0, k].astype(np.float32),
179
+ position=keypoints[0, k].astype(np.float32),
180
+ axes_length=0.06,
181
+ axes_radius=0.002,
182
+ )
183
+ joint_frame_handles.append(h)
184
+
185
+ def update_arm(frame_idx: int) -> None:
186
+ pts = np.stack(
187
+ [np.stack([keypoints[frame_idx, k], keypoints[frame_idx, k + 1]]) for k in range(4)]
188
+ ).astype(np.float32)
189
+ arm_handle.points = pts
190
+ for k, h in enumerate(joint_frame_handles):
191
+ h.position = keypoints[frame_idx, k].astype(np.float32)
192
+ h.wxyz = joint_quats[frame_idx, k].astype(np.float32)
193
+
194
+ # -- Manual-step handle for the renderer -----------------------------------
195
+ traj_time = np.asarray(results.trajectory["time"], dtype=np.float64).flatten()
196
+ handle = AnimatedServerHandle(
197
+ server=server,
198
+ traj_time=traj_time,
199
+ update_callbacks=[update_trail, update_marker, update_arm],
200
+ )
201
+
202
+ # -- Camera: overview framing the full workspace ---------------------------
203
+ # Frame on waypoint positions + EE path so the full motion is visible.
204
+ all_points = np.vstack([ee_pos, np.array(waypoint_positions)])
205
+ static_pose = overview_pose(
206
+ all_points,
207
+ azimuth=OVERVIEW_AZIMUTH,
208
+ elevation=OVERVIEW_ELEVATION,
209
+ radius_margin=OVERVIEW_RADIUS_MARGIN,
210
+ fov_deg=OVERVIEW_FOV_DEG,
211
+ )
212
+
213
+ def camera_pose_fn(frame_idx: int):
214
+ return static_pose
215
+
216
+ render_animation_to_video(
217
+ handle,
218
+ OUTPUT_PATH,
219
+ camera_pose_fn,
220
+ width=WIDTH,
221
+ height=HEIGHT,
222
+ fps=FPS,
223
+ crf=CRF,
224
+ stride=STRIDE,
225
+ )
@@ -0,0 +1,142 @@
1
+ """Reusable camera pose helpers for viser animation rendering.
2
+
3
+ All functions return ``(cam_position, cam_wxyz, look_at)`` tuples suitable for
4
+ passing to ``render_animation_to_video``'s ``camera_pose_fn`` argument. They
5
+ depend only on numpy and ``viser.transforms`` — no openscvx imports.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import numpy as np
11
+ import viser.transforms as vtf
12
+
13
+
14
+ def look_at_wxyz(pos: np.ndarray, target: np.ndarray, up: np.ndarray) -> np.ndarray:
15
+ """Quaternion (w,x,y,z) for a camera at ``pos`` looking at ``target``.
16
+
17
+ Uses the OpenCV camera convention that viser expects: +X right, +Y down,
18
+ +Z forward. See ``examples/animations/camera_control_notes.md``.
19
+ """
20
+ forward = target - pos
21
+ forward /= np.linalg.norm(forward)
22
+ right = np.cross(forward, up)
23
+ right_norm = np.linalg.norm(right)
24
+ if right_norm < 1e-6:
25
+ # Gimbal lock: forward is (nearly) parallel to up. Pick an arbitrary
26
+ # world axis that isn't, so the camera stays defined. The chosen axis
27
+ # determines the "roll" of the camera at the singularity — not great
28
+ # cinematically, but prevents a NaN crash.
29
+ fallback = np.array([1.0, 0.0, 0.0]) if abs(forward[0]) < 0.9 else np.array([0.0, 1.0, 0.0])
30
+ right = np.cross(forward, fallback)
31
+ right_norm = np.linalg.norm(right)
32
+ right /= right_norm
33
+ cam_down = np.cross(forward, right) # = -world_up projected perp to forward
34
+ R_world_cam = np.stack([right, cam_down, forward], axis=1)
35
+ return vtf.SO3.from_matrix(R_world_cam).wxyz
36
+
37
+
38
+ def chase_pose(
39
+ subject: np.ndarray,
40
+ focus: np.ndarray,
41
+ *,
42
+ chase_distance: float = 15.0,
43
+ vertical_offset: float = 2.0,
44
+ up=(0.0, 0.0, 1.0),
45
+ ) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
46
+ """Return ``(cam_pos, cam_wxyz, look_at)`` for a chase camera behind ``subject``.
47
+
48
+ The camera sits on the ray from ``focus`` through ``subject``, extended
49
+ ``chase_distance`` units past the subject, then lifted along world up by
50
+ ``vertical_offset``. It always looks at ``focus``.
51
+ """
52
+ subject = np.asarray(subject, dtype=np.float64)
53
+ focus = np.asarray(focus, dtype=np.float64)
54
+ up = np.asarray(up, dtype=np.float64)
55
+
56
+ ray = subject - focus
57
+ ray_norm = np.linalg.norm(ray)
58
+ if ray_norm < 1e-6:
59
+ cam_pos = subject + vertical_offset * up
60
+ else:
61
+ cam_pos = subject + chase_distance * (ray / ray_norm) + vertical_offset * up
62
+
63
+ wxyz = look_at_wxyz(cam_pos, focus, up)
64
+ return cam_pos, wxyz, focus
65
+
66
+
67
+ def onboard_pose(
68
+ position: np.ndarray,
69
+ attitude_wxyz: np.ndarray,
70
+ R_sb: np.ndarray,
71
+ *,
72
+ forward_offset: float = 0.0,
73
+ ) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
74
+ """Return ``(cam_pos, cam_wxyz, look_at)`` for a sensor-mounted FPV camera.
75
+
76
+ Places the camera at ``position`` (shifted slightly forward along the sensor
77
+ boresight by ``forward_offset``) with orientation matching the sensor frame —
78
+ i.e. looking along the sensor boresight (+Z in sensor frame, mapped through
79
+ ``R_sb`` and the body attitude to world coordinates).
80
+ """
81
+ # R_body_to_world from the attitude quaternion (w, x, y, z)
82
+ w, x, y, z = attitude_wxyz
83
+ R_bw = np.array(
84
+ [
85
+ [1 - 2 * (y * y + z * z), 2 * (x * y - z * w), 2 * (x * z + y * w)],
86
+ [2 * (x * y + z * w), 1 - 2 * (x * x + z * z), 2 * (y * z - x * w)],
87
+ [2 * (x * z - y * w), 2 * (y * z + x * w), 1 - 2 * (x * x + y * y)],
88
+ ],
89
+ dtype=np.float64,
90
+ )
91
+
92
+ # Sensor-to-world: columns are the sensor axes in world coords.
93
+ # R_sb is body-to-sensor, so R_sb.T is sensor-to-body.
94
+ R_sensor_to_world = R_bw @ R_sb.T
95
+
96
+ # Viser uses OpenCV convention (+X right, +Y DOWN, +Z forward).
97
+ # The sensor frame has +Y UP, so we rotate 180deg around the boresight (Z)
98
+ # to flip both X and Y, converting to the convention viser expects.
99
+ R_opencv_from_sensor = np.diag([-1.0, -1.0, 1.0])
100
+ R_cam_to_world = R_sensor_to_world @ R_opencv_from_sensor
101
+
102
+ wxyz = vtf.SO3.from_matrix(R_cam_to_world).wxyz
103
+ # Boresight is sensor +Z expressed in world frame (unchanged by the flip).
104
+ boresight_world = R_sensor_to_world[:, 2]
105
+ cam_pos = position + forward_offset * boresight_world
106
+ look_at = cam_pos + 10.0 * boresight_world
107
+ return cam_pos, wxyz, look_at
108
+
109
+
110
+ def overview_pose(
111
+ positions: np.ndarray,
112
+ *,
113
+ azimuth: float = np.radians(135.0),
114
+ elevation: float = np.radians(25.0),
115
+ radius_margin: float = 0.75,
116
+ fov_deg: float = 60.0,
117
+ up=(0.0, 0.0, 1.0),
118
+ ) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
119
+ """Return a static ``(cam_pos, cam_wxyz, look_at)`` that frames all ``positions``.
120
+
121
+ The camera is placed on a sphere around the centroid of ``positions``,
122
+ parameterized by ``azimuth`` (angle in XY from +X, CCW) and ``elevation``
123
+ (angle above the horizon). The radius is auto-computed so the full extent
124
+ fits within ``fov_deg``, then scaled by ``radius_margin``.
125
+ """
126
+ up = np.asarray(up, dtype=np.float64)
127
+ center = positions.mean(axis=0)
128
+ max_extent = np.max(np.linalg.norm(positions - center, axis=1))
129
+ half_fov_rad = np.radians(fov_deg / 2.0)
130
+ radius = max_extent / np.sin(half_fov_rad) * radius_margin
131
+
132
+ cos_el = np.cos(elevation)
133
+ cam_pos = center + radius * np.array(
134
+ [
135
+ cos_el * np.cos(azimuth),
136
+ cos_el * np.sin(azimuth),
137
+ np.sin(elevation),
138
+ ]
139
+ )
140
+ look_at = center.copy()
141
+ wxyz = look_at_wxyz(cam_pos, look_at, up)
142
+ return cam_pos, wxyz, look_at