openscvx 0.4.1.dev4__tar.gz → 0.4.1.dev11__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 (270) hide show
  1. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/.github/workflows/tests-integration.yml +1 -1
  2. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/.github/workflows/tests-unit.yml +1 -1
  3. {openscvx-0.4.1.dev4/openscvx.egg-info → openscvx-0.4.1.dev11}/PKG-INFO +3 -2
  4. openscvx-0.4.1.dev11/examples/drone/logo.py +440 -0
  5. openscvx-0.4.1.dev11/examples/drone/logo_utils/acl_logo.svg +1 -0
  6. openscvx-0.4.1.dev11/examples/drone/logo_utils/svg_path_utils.py +49 -0
  7. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/plotting_viser.py +450 -44
  8. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/_version.py +3 -3
  9. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/plotting/viser/animated.py +19 -7
  10. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/plotting/viser/server.py +26 -6
  11. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/problem.py +148 -1
  12. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/logic.py +39 -3
  13. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/math.py +2 -2
  14. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11/openscvx.egg-info}/PKG-INFO +3 -2
  15. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx.egg-info/SOURCES.txt +3 -0
  16. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx.egg-info/requires.txt +2 -1
  17. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/pyproject.toml +2 -1
  18. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/test_examples.py +9 -0
  19. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/.github/assets/logo.svg +0 -0
  20. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/.github/release-drafter.yml +0 -0
  21. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/.github/workflows/_docs.yml +0 -0
  22. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/.github/workflows/branch-name.yml +0 -0
  23. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/.github/workflows/docs.yml +0 -0
  24. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/.github/workflows/lint.yml +0 -0
  25. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/.github/workflows/nightly.yml +0 -0
  26. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/.github/workflows/release-drafter.yml +0 -0
  27. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/.github/workflows/release.yml +0 -0
  28. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/.gitignore +0 -0
  29. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/CONTRIBUTING.md +0 -0
  30. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/LICENSE +0 -0
  31. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/README.md +0 -0
  32. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/Foundations/constraint_reformulation.md +0 -0
  33. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/Foundations/control_parameterization.md +0 -0
  34. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/Foundations/discretization.md +0 -0
  35. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/Foundations/ocp.md +0 -0
  36. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/Foundations/scvx.md +0 -0
  37. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/Foundations/time_dilation.md +0 -0
  38. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/UnderTheHood/lowering_architecture.md +0 -0
  39. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
  40. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/UsersGuide/00_introduction.md +0 -0
  41. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/UsersGuide/01_hello_world_brachistochrone.md +0 -0
  42. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/UsersGuide/02_drone_racing_constraints.md +0 -0
  43. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/UsersGuide/03_obstacle_avoidance_vmap.md +0 -0
  44. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/UsersGuide/04_viewpoint_constraints.md +0 -0
  45. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/UsersGuide/05_visualization.md +0 -0
  46. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/UsersGuide/06_logic.md +0 -0
  47. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/UsersGuide/07_lie.md +0 -0
  48. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/assets/favicon.png +0 -0
  49. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/assets/images/ct-scvx_dark.png +0 -0
  50. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/assets/images/ct-scvx_light.png +0 -0
  51. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/assets/images/ctcs_dark.png +0 -0
  52. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/assets/images/ctcs_light.png +0 -0
  53. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/assets/images/problem_class_dark.png +0 -0
  54. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/assets/images/problem_class_light.png +0 -0
  55. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/assets/logo.svg +0 -0
  56. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/citation.md +0 -0
  57. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/examples.md +0 -0
  58. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/getting-started.md +0 -0
  59. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/index.md +0 -0
  60. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/docs/javascripts/mathjax.js +0 -0
  61. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/abstract/brachistochrone.py +0 -0
  62. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/arm/three_link_arm.py +0 -0
  63. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/car/dubins_car.py +0 -0
  64. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/car/dubins_car_conditional.py +0 -0
  65. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/car/dubins_car_disjoint.py +0 -0
  66. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/car/dubins_car_stljax.py +0 -0
  67. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/drone/cinema_vp.py +0 -0
  68. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/drone/dr_double_integrator.py +0 -0
  69. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/drone/dr_vp.py +0 -0
  70. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/drone/dr_vp_nodal.py +0 -0
  71. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/drone/dr_vp_polytope.py +0 -0
  72. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/drone/drone_racing.py +0 -0
  73. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/drone/obstacle_avoidance.py +0 -0
  74. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/drone/obstacle_avoidance_nodal.py +0 -0
  75. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/drone/obstacle_avoidance_vmap.py +0 -0
  76. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/plotting.py +0 -0
  77. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/realtime/base_problems/cinema_vp_realtime_base.py +0 -0
  78. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/realtime/base_problems/drone_racing_realtime_base.py +0 -0
  79. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/realtime/base_problems/obstacle_avoidance_realtime_base.py +0 -0
  80. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/realtime/cinema_vp_realtime.py +0 -0
  81. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/realtime/drone_racing_realtime.py +0 -0
  82. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/realtime/dubins_car_realtime.py +0 -0
  83. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
  84. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/rocket/3DoF_pdg.py +0 -0
  85. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/examples/spacecraft/proxops_cw.py +0 -0
  86. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/figures/ctlos_cine.gif +0 -0
  87. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/figures/ctlos_dr.gif +0 -0
  88. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/figures/dtlos_cine.gif +0 -0
  89. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/figures/dtlos_dr.gif +0 -0
  90. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/figures/openscvx_logo.svg +0 -0
  91. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/figures/openscvx_logo_square.png +0 -0
  92. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/figures/oscvx_structure_full_dark.svg +0 -0
  93. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/figures/video_preview.png +0 -0
  94. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/__init__.py +0 -0
  95. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/1-background.avif +0 -0
  96. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/1-background@1x.avif +0 -0
  97. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/1-background@2x.avif +0 -0
  98. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/1-background@3x.avif +0 -0
  99. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/1-background@4x.avif +0 -0
  100. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/2-mars.avif +0 -0
  101. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/2-mars@1x.avif +0 -0
  102. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/2-mars@2x.avif +0 -0
  103. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/2-mars@3x.avif +0 -0
  104. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/2-mars@4x.avif +0 -0
  105. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/3-moon.avif +0 -0
  106. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/3-moon@1x.avif +0 -0
  107. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/3-moon@2x.avif +0 -0
  108. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/3-moon@3x.avif +0 -0
  109. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/3-moon@4x.avif +0 -0
  110. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/4-sat1.avif +0 -0
  111. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/4-sat1@1x.avif +0 -0
  112. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/4-sat1@2x.avif +0 -0
  113. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/4-sat1@3x.avif +0 -0
  114. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/4-sat1@4x.avif +0 -0
  115. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/5-space.avif +0 -0
  116. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/5-space@1x.avif +0 -0
  117. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/5-space@2x.avif +0 -0
  118. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/5-space@3x.avif +0 -0
  119. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/5-space@4x.avif +0 -0
  120. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/6-earth.avif +0 -0
  121. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/6-earth@1x.avif +0 -0
  122. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/6-earth@2x.avif +0 -0
  123. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/6-earth@3x.avif +0 -0
  124. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/images/layers/6-earth@4x.avif +0 -0
  125. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/javascripts/parallax.js +0 -0
  126. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/logo.svg +0 -0
  127. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/stylesheets/custom.css +0 -0
  128. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/assets/stylesheets/parallax.css +0 -0
  129. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/home.html +0 -0
  130. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/main.html +0 -0
  131. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/partials/parallax/hero.html +0 -0
  132. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/material/overrides/partials/parallax.html +0 -0
  133. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/mkdocs.yml +0 -0
  134. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/__init__.py +0 -0
  135. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/algorithms/__init__.py +0 -0
  136. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/algorithms/autotuning.py +0 -0
  137. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/algorithms/base.py +0 -0
  138. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/algorithms/optimization_results.py +0 -0
  139. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/algorithms/penalized_trust_region.py +0 -0
  140. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/config.py +0 -0
  141. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/discretization/__init__.py +0 -0
  142. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/discretization/discretization.py +0 -0
  143. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/expert/__init__.py +0 -0
  144. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/expert/byof.py +0 -0
  145. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/expert/lowering.py +0 -0
  146. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/expert/validation.py +0 -0
  147. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/init/__init__.py +0 -0
  148. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/init/interpolation.py +0 -0
  149. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/integrators/__init__.py +0 -0
  150. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/integrators/runge_kutta.py +0 -0
  151. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/lowered/__init__.py +0 -0
  152. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/lowered/cvxpy_constraints.py +0 -0
  153. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/lowered/cvxpy_variables.py +0 -0
  154. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/lowered/dynamics.py +0 -0
  155. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/lowered/jax_constraints.py +0 -0
  156. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/lowered/parameters.py +0 -0
  157. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/lowered/problem.py +0 -0
  158. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/lowered/unified.py +0 -0
  159. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/plotting/__init__.py +0 -0
  160. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/plotting/plotting.py +0 -0
  161. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/plotting/scp_iteration.py +0 -0
  162. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/plotting/viser/__init__.py +0 -0
  163. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/plotting/viser/plotly_integration.py +0 -0
  164. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/plotting/viser/primitives.py +0 -0
  165. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/plotting/viser/scp.py +0 -0
  166. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/propagation/__init__.py +0 -0
  167. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/propagation/post_processing.py +0 -0
  168. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/propagation/propagation.py +0 -0
  169. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/solvers/__init__.py +0 -0
  170. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/solvers/base.py +0 -0
  171. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/solvers/ptr_solver.py +0 -0
  172. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/__init__.py +0 -0
  173. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/augmentation.py +0 -0
  174. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/builder.py +0 -0
  175. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/constraint_set.py +0 -0
  176. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/__init__.py +0 -0
  177. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/arithmetic.py +0 -0
  178. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/array.py +0 -0
  179. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/constraint.py +0 -0
  180. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/control.py +0 -0
  181. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/expr.py +0 -0
  182. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/lie/__init__.py +0 -0
  183. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
  184. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/lie/se3.py +0 -0
  185. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/lie/so3.py +0 -0
  186. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/linalg.py +0 -0
  187. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/logic.py +0 -0
  188. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/math.py +0 -0
  189. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/spatial.py +0 -0
  190. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/state.py +0 -0
  191. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/stl.py +0 -0
  192. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/variable.py +0 -0
  193. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/expr/vmap.py +0 -0
  194. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/hashing.py +0 -0
  195. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lower.py +0 -0
  196. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/__init__.py +0 -0
  197. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/cvxpy/__init__.py +0 -0
  198. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/cvxpy/_lowerer.py +0 -0
  199. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/cvxpy/_registry.py +0 -0
  200. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/cvxpy/arithmetic.py +0 -0
  201. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/cvxpy/array.py +0 -0
  202. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/cvxpy/constraint.py +0 -0
  203. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/cvxpy/control.py +0 -0
  204. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/cvxpy/expr.py +0 -0
  205. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/cvxpy/linalg.py +0 -0
  206. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/cvxpy/logic.py +0 -0
  207. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/cvxpy/math.py +0 -0
  208. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/cvxpy/state.py +0 -0
  209. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/__init__.py +0 -0
  210. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/_lowerer.py +0 -0
  211. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/_registry.py +0 -0
  212. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/arithmetic.py +0 -0
  213. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/array.py +0 -0
  214. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/constraint.py +0 -0
  215. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/control.py +0 -0
  216. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/expr.py +0 -0
  217. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/lie.py +0 -0
  218. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/linalg.py +0 -0
  219. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/spatial.py +0 -0
  220. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/state.py +0 -0
  221. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/stl.py +0 -0
  222. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/lowerers/jax/vmap.py +0 -0
  223. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/preprocessing.py +0 -0
  224. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/problem.py +0 -0
  225. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/time.py +0 -0
  226. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/symbolic/unified.py +0 -0
  227. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/utils/__init__.py +0 -0
  228. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/utils/cache.py +0 -0
  229. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/utils/caching.py +0 -0
  230. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/utils/printing.py +0 -0
  231. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/utils/profiling.py +0 -0
  232. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx/utils/utils.py +0 -0
  233. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx.egg-info/dependency_links.txt +0 -0
  234. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/openscvx.egg-info/top_level.txt +0 -0
  235. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/scripts/gen_example_pages.py +0 -0
  236. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/scripts/gen_ref_pages.py +0 -0
  237. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/setup.cfg +0 -0
  238. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/__init__.py +0 -0
  239. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/brachistochrone_analytical.py +0 -0
  240. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/__init__.py +0 -0
  241. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/expr/__init__.py +0 -0
  242. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/expr/test_arithmetic.py +0 -0
  243. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/expr/test_array.py +0 -0
  244. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/expr/test_constraint.py +0 -0
  245. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/expr/test_expr.py +0 -0
  246. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/expr/test_lie.py +0 -0
  247. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/expr/test_linalg.py +0 -0
  248. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/expr/test_logic.py +0 -0
  249. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/expr/test_math.py +0 -0
  250. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/expr/test_node_reference.py +0 -0
  251. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/expr/test_parameters.py +0 -0
  252. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/expr/test_scaling.py +0 -0
  253. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/expr/test_spatial.py +0 -0
  254. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/expr/test_variable.py +0 -0
  255. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/expr/test_vmap.py +0 -0
  256. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/test_augmentation.py +0 -0
  257. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/test_hashing.py +0 -0
  258. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/test_lower_cvxpy.py +0 -0
  259. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/test_lower_jax.py +0 -0
  260. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/test_preprocessing.py +0 -0
  261. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/symbolic/test_unified.py +0 -0
  262. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/test_autotuning.py +0 -0
  263. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/test_brachistochrone.py +0 -0
  264. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/test_cvxpygen_optional.py +0 -0
  265. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/test_discretization.py +0 -0
  266. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/test_expert.py +0 -0
  267. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/test_init.py +0 -0
  268. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/test_integrators.py +0 -0
  269. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/test_plotting.py +0 -0
  270. {openscvx-0.4.1.dev4 → openscvx-0.4.1.dev11}/tests/test_propagation.py +0 -0
@@ -17,7 +17,7 @@ jobs:
17
17
  fail-fast: false # Continue testing other examples even if one fails
18
18
  matrix:
19
19
  os: [ubuntu-latest, macos-latest]
20
- python-version: ['3.10', '3.11', '3.12', '3.13']
20
+ python-version: ['3.11', '3.12', '3.13']
21
21
 
22
22
  steps:
23
23
  - name: Checkout repository
@@ -18,7 +18,7 @@ jobs:
18
18
  fail-fast: false # Continue testing other versions even if one fails
19
19
  matrix:
20
20
  os: [ubuntu-latest, macos-latest]
21
- python-version: ['3.10', '3.11', '3.12', '3.13']
21
+ python-version: ['3.11', '3.12', '3.13']
22
22
 
23
23
  steps:
24
24
  - name: Checkout repository
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscvx
3
- Version: 0.4.1.dev4
3
+ Version: 0.4.1.dev11
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
@@ -10,7 +10,7 @@ Classifier: License :: OSI Approved :: Apache Software License
10
10
  Requires-Python: >=3.9
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
- Requires-Dist: cvxpy==1.7.5
13
+ Requires-Dist: cvxpy>=1.8.1
14
14
  Requires-Dist: qoco
15
15
  Requires-Dist: numpy
16
16
  Requires-Dist: jax
@@ -38,6 +38,7 @@ Provides-Extra: test
38
38
  Requires-Dist: pytest; extra == "test"
39
39
  Requires-Dist: scipy; extra == "test"
40
40
  Requires-Dist: jaxlie; extra == "test"
41
+ Requires-Dist: svgpathtools; extra == "test"
41
42
  Dynamic: license-file
42
43
 
43
44
  <a id="readme-top"></a>
@@ -0,0 +1,440 @@
1
+ """6-DOF quadrotor tracing out the Autonomous Controls Laboratory Logo
2
+
3
+ This example demonstrates trajectory planning for a quadrotor tracing out the Autonomous Controls Laboratory Logo. The problem includes:
4
+
5
+ - 6-DOF rigid body dynamics (position, velocity, attitude quaternion, angular velocity)
6
+ - Utilizes the BYOF framework to model the angle between the boresight vector and the vector to the target.
7
+ """
8
+
9
+
10
+ import os
11
+ import sys
12
+
13
+ import jax.numpy as jnp
14
+ import numpy as np
15
+ import numpy.linalg as la
16
+
17
+ current_dir = os.path.dirname(os.path.abspath(__file__))
18
+ grandparent_dir = os.path.dirname(os.path.dirname(current_dir))
19
+ sys.path.append(grandparent_dir)
20
+
21
+ import openscvx as ox
22
+ from openscvx import ByofSpec, Free, Minimize, Problem
23
+ from examples.plotting_viser import create_animated_plotting_server
24
+
25
+ # Prompt the user to instal svgpathtools if not already installed via pip
26
+ try:
27
+ import svgpathtools
28
+ except ImportError:
29
+ print("svgpathtools not found. Please install it with: pip install svgpathtools")
30
+ sys.exit(1)
31
+
32
+ from examples.drone.logo_utils.svg_path_utils import get_svg_path_function
33
+
34
+ # -----------------------------------------------------------------------------
35
+ # SVG path utilities
36
+ # -----------------------------------------------------------------------------
37
+
38
+ # Load the SVG path function, using only Path 0 (the logo, no border)
39
+ svg_path_function = get_svg_path_function("examples/drone/logo_utils/acl_logo.svg", path_indices=[0])
40
+
41
+
42
+ # -----------------------------------------------------------------------------
43
+ # JAX helpers (numeric versions of spatial utilities)
44
+ # -----------------------------------------------------------------------------
45
+
46
+ def qdcm(q: jnp.ndarray) -> jnp.ndarray:
47
+ """Quaternion to DCM using [w, x, y, z] convention."""
48
+ q_norm = jnp.linalg.norm(q)
49
+ q_norm = jnp.where(q_norm > 1e-12, q_norm, 1e-12)
50
+ w, qx, qy, qz = q / q_norm
51
+ return jnp.array(
52
+ [
53
+ [1 - 2 * (qy**2 + qz**2), 2 * (qx * qy - qz * w), 2 * (qx * qz + qy * w)],
54
+ [2 * (qx * qy + qz * w), 1 - 2 * (qx**2 + qz**2), 2 * (qy * qz - qx * w)],
55
+ [2 * (qx * qz - qy * w), 2 * (qy * qz + qx * w), 1 - 2 * (qx**2 + qy**2)],
56
+ ]
57
+ )
58
+
59
+
60
+ def SSMP(w: jnp.ndarray) -> jnp.ndarray:
61
+ """4x4 skew-symmetric matrix for quaternion dynamics."""
62
+ wx, wy, wz = w[0], w[1], w[2]
63
+ return jnp.array(
64
+ [
65
+ [0, -wx, -wy, -wz],
66
+ [wx, 0, wz, -wy],
67
+ [wy, -wz, 0, wx],
68
+ [wz, wy, -wx, 0],
69
+ ]
70
+ )
71
+
72
+
73
+ def SSM(w: jnp.ndarray) -> jnp.ndarray:
74
+ """3x3 skew-symmetric matrix for cross products."""
75
+ wx, wy, wz = w[0], w[1], w[2]
76
+ return jnp.array([[0, -wz, wy], [wz, 0, -wx], [-wy, wx, 0]])
77
+
78
+
79
+ # -----------------------------------------------------------------------------
80
+ # Problem setup
81
+ # -----------------------------------------------------------------------------
82
+
83
+ n = 500 # Number of Nodes
84
+ total_time = 20.0 # Total time for the simulation
85
+
86
+ # Fixed initial and final positions
87
+ initial_pos = np.array([-15.0, 0.0, 5.0])
88
+ final_pos = np.array([-14.0, -10.0, 5.0])
89
+
90
+ # State components (like other drone examples)
91
+ position = ox.State("position", shape=(3,))
92
+ position.max = np.array([20.0, 20.0, 20.0])
93
+ position.min = np.array([-20.0, -20.0, -5.0])
94
+ position.initial = [Free(initial_pos[0]), Free(initial_pos[1]), Free(initial_pos[2])]
95
+ position.final = [Free(final_pos[0]), Free(final_pos[1]), Free(final_pos[2])]
96
+
97
+ velocity = ox.State("velocity", shape=(3,))
98
+ velocity.max = np.array([20.0, 20.0, 20.0])
99
+ velocity.min = np.array([-20.0, -20.0, -20.0])
100
+ velocity.initial = [0.0, 0.0, 0.0]
101
+ velocity.final = [0.0, 0.0, 0.0]
102
+
103
+ attitude = ox.State("attitude", shape=(4,)) # Quaternion [w, x, y, z]
104
+ attitude.max = np.array([1.0, 1.0, 1.0, 1.0])
105
+ attitude.min = np.array([-1.0, -1.0, -1.0, -1.0])
106
+ attitude.initial = [Free(1.0), Free(0), Free(0), Free(0)]
107
+ attitude.final = [Free(1.0), Free(0), Free(0), Free(0)]
108
+
109
+ angular_velocity = ox.State("angular_velocity", shape=(3,))
110
+ angular_velocity.max = np.array([10.0, 10.0, 10.0])
111
+ angular_velocity.min = np.array([-10.0, -10.0, -10.0])
112
+ angular_velocity.initial = np.array([0.0, 0.0, 0.0])
113
+ angular_velocity.final = [Free(0), Free(0), Free(0)]
114
+
115
+ angle_metric = ox.State("angle_metric", shape=(1,)) # Viewing angle (minimize at final)
116
+ angle_metric.max = np.array([0.3])
117
+ angle_metric.min = np.array([0.0])
118
+ angle_metric.initial = np.array([0.0])
119
+ angle_metric.final = [Minimize(0.0)]
120
+
121
+ time_state = ox.Time(
122
+ initial=0.0,
123
+ final=total_time,
124
+ min=0.0,
125
+ max=total_time,
126
+ )
127
+
128
+ # Control components
129
+ thrust_force = ox.Control("thrust_force", shape=(3,))
130
+ thrust_force.max = np.array([0.0, 0.0, 4.179446268 * 9.81])
131
+ thrust_force.min = np.array([0.0, 0.0, 0.0])
132
+ thrust_force.guess = np.repeat(np.array([[0.0, 0.0, 10.0]]), n, axis=0)
133
+
134
+ torque = ox.Control("torque", shape=(3,))
135
+ torque.max = np.array([10.0, 10.0, 1.0])
136
+ torque.min = np.array([-10.0, -10.0, -1.0])
137
+ torque.guess = np.zeros((n, 3))
138
+
139
+ # Offset from the SVG path for the drone to follow
140
+ path_offset = np.array([0.0, 0.0, 3.0]) # 3 meters above the path
141
+
142
+ # Boresight vector in body frame (x-axis of the drone)
143
+ boresight_body = jnp.array([1.0, 0.0, 0.0])
144
+
145
+
146
+ def get_kp_pose(t_normalized):
147
+ """
148
+ Get the target position along the SVG path at normalized time t, applying rotations about y and x axes.
149
+ Args:
150
+ t_normalized: Normalized time in [0, 1] (scalar or array)
151
+ Returns:
152
+ Target position [x, y, z]
153
+ """
154
+ original_pos = jnp.array(svg_path_function(t_normalized))
155
+
156
+ scale_factor = 0.5
157
+ scaled_pos = original_pos * scale_factor
158
+
159
+ theta_y = jnp.pi / 2
160
+ cos_y = jnp.cos(theta_y)
161
+ sin_y = jnp.sin(theta_y)
162
+ R_y = jnp.array([
163
+ [cos_y, 0, sin_y],
164
+ [0, 1, 0],
165
+ [-sin_y, 0, cos_y]
166
+ ])
167
+
168
+ theta_x = jnp.pi / 2
169
+ cos_x = jnp.cos(theta_x)
170
+ sin_x = jnp.sin(theta_x)
171
+ R_x = jnp.array([
172
+ [1, 0, 0],
173
+ [0, cos_x, -sin_x],
174
+ [0, sin_x, cos_x]
175
+ ])
176
+
177
+ rotated_pos = R_x @ (R_y @ scaled_pos)
178
+ return rotated_pos + path_offset
179
+
180
+
181
+ # -----------------------------------------------------------------------------
182
+ # BYOF: angle_metric derivative (uses get_kp_pose, not easily symbolic)
183
+ # -----------------------------------------------------------------------------
184
+
185
+ def angle_to_target_components(pos: jnp.ndarray, att: jnp.ndarray, t_val: float) -> jnp.ndarray:
186
+ """Compute angle between boresight and vector to target from position, attitude, and time."""
187
+ t_normalized = t_val / total_time
188
+ target_pos = get_kp_pose(t_normalized)
189
+
190
+ to_target_inertial = target_pos - pos
191
+ boresight_inertial = qdcm(att) @ boresight_body
192
+
193
+ to_target_norm = jnp.linalg.norm(to_target_inertial)
194
+ boresight_norm = jnp.linalg.norm(boresight_inertial)
195
+
196
+ lhs = jnp.dot(to_target_inertial, boresight_inertial) / (to_target_norm * boresight_norm)
197
+
198
+ angle = jnp.arccos(lhs)
199
+ return angle
200
+
201
+ def dynamics_angle_metric(x, u, node, params):
202
+ """BYOF dynamics for angle_metric: derivative = time-weighted angle to target."""
203
+ pos = x[position.slice]
204
+ att = x[attitude.slice]
205
+ t_val = x[time_state.slice][0]
206
+ angle = angle_to_target_components(pos, att, t_val)
207
+ return jnp.array([angle])
208
+
209
+
210
+ # -----------------------------------------------------------------------------
211
+ # Symbolic dynamics (drone: same as drone_racing / cinema_vp)
212
+ # -----------------------------------------------------------------------------
213
+
214
+ m = 1.0
215
+ g_const = -9.18
216
+ J_b = 1e-5 * jnp.array([1.0, 1.0, 1.0])
217
+ J_b_inv = 1.0 / J_b
218
+ J_b_diag = ox.linalg.Diag(J_b)
219
+
220
+ # Normalize quaternion for dynamics
221
+ q_norm = ox.linalg.Norm(attitude)
222
+ attitude_normalized = attitude / q_norm
223
+
224
+ dynamics = {
225
+ "position": velocity,
226
+ "velocity": (1.0 / m) * ox.spatial.QDCM(attitude_normalized) @ thrust_force
227
+ + ox.Constant(np.array([0, 0, g_const], dtype=np.float64)),
228
+ "attitude": 0.5 * ox.spatial.SSMP(angular_velocity) @ attitude_normalized,
229
+ "angular_velocity": ox.linalg.Diag(J_b_inv)
230
+ @ (torque - ox.spatial.SSM(angular_velocity) @ J_b_diag @ angular_velocity),
231
+ "time": 1.0,
232
+ }
233
+
234
+ # -----------------------------------------------------------------------------
235
+ # Plotting patch: full_subject_traj_time for moving target
236
+ # -----------------------------------------------------------------------------
237
+
238
+ import examples.plotting
239
+
240
+
241
+ def patched_full_subject_traj_time(results, params):
242
+ t_full = results.t_full
243
+ t_nodes = results.nodes["time"].flatten() if "time" in results.nodes else np.linspace(0, total_time, n)
244
+
245
+ subs_traj = []
246
+ subs_traj_node = []
247
+ subs_traj_sen = []
248
+ subs_traj_sen_node = []
249
+
250
+ if "moving_subject" in results.plotting_data and "get_kp_pose" in results.plotting_data:
251
+ custom_get_kp_pose = results.plotting_data["get_kp_pose"]
252
+
253
+ target_positions_full = []
254
+ target_positions_nodes = []
255
+ for i in range(len(t_full)):
256
+ t_normalized = t_full[i] / total_time
257
+ target_positions_full.append(np.asarray(custom_get_kp_pose(t_normalized)))
258
+ for i in range(len(t_nodes)):
259
+ t_normalized = t_nodes[i] / total_time
260
+ target_positions_nodes.append(np.asarray(custom_get_kp_pose(t_normalized)))
261
+
262
+ subs_traj.append(np.array(target_positions_full))
263
+ subs_traj_node.append(np.array(target_positions_nodes))
264
+ elif "init_poses" in results.plotting_data:
265
+ init_poses = results.plotting_data["init_poses"]
266
+ n_full = len(t_full)
267
+ n_nodes = len(t_nodes)
268
+ for pose in init_poses:
269
+ pose_full = np.repeat(pose[:, np.newaxis], n_full, axis=1).T
270
+ pose_node = np.repeat(pose[:, np.newaxis], n_nodes, axis=1).T
271
+ subs_traj.append(pose_full)
272
+ subs_traj_node.append(pose_node)
273
+ else:
274
+ raise ValueError("No valid method to get keypoint poses.")
275
+
276
+ subs_traj_sen = []
277
+ subs_traj_sen_node = []
278
+ return subs_traj, subs_traj_sen, subs_traj_node, subs_traj_sen_node
279
+
280
+
281
+ examples.plotting.full_subject_traj_time = patched_full_subject_traj_time
282
+
283
+
284
+ def angle_to_target(x_):
285
+ """Compute the angle between boresight vector and vector to target (for analysis/plotting)."""
286
+ pos = x_[:3]
287
+ att = x_[6:10]
288
+ t_val = x_[14]
289
+ return angle_to_target_components(pos, att, t_val)
290
+
291
+
292
+ # -----------------------------------------------------------------------------
293
+ # States, controls, constraints, initial guess
294
+ # -----------------------------------------------------------------------------
295
+
296
+ states = [position, velocity, attitude, angular_velocity, angle_metric, time_state]
297
+ controls = [thrust_force, torque]
298
+
299
+ constraints = []
300
+ for state in states:
301
+ constraints.extend([ox.ctcs(state <= state.max), ox.ctcs(state.min <= state)])
302
+
303
+
304
+ byof: ByofSpec = {
305
+ "dynamics": {
306
+ "angle_metric": dynamics_angle_metric,
307
+ }
308
+ }
309
+
310
+ # Initial guess: position drone to maintain LoS with moving target
311
+ position_bar = np.linspace(initial_pos, final_pos, n)
312
+ velocity_bar = np.zeros((n, 3))
313
+ angular_velocity_bar = np.zeros((n, 3))
314
+ angle_metric_bar = np.zeros((n, 1))
315
+ time_bar = np.linspace(0, total_time, n).reshape(-1, 1)
316
+
317
+ b = np.array([1, 0, 0])
318
+ attitude_bar = np.tile([1.0, 0.0, 0.0, 0.0], (n, 1))
319
+ for k in range(n):
320
+ t_normalized = k / (n - 1)
321
+ target_pos = np.asarray(get_kp_pose(t_normalized))
322
+ a = target_pos - position_bar[k]
323
+ if np.linalg.norm(a) > 1e-6:
324
+ q_xyz = np.cross(b, a)
325
+ q_w = np.sqrt(la.norm(a) ** 2 + la.norm(b) ** 2) + np.dot(a, b)
326
+ q_no_norm = np.hstack((q_w, q_xyz))
327
+ q = q_no_norm / la.norm(q_no_norm)
328
+ attitude_bar[k] = q
329
+
330
+ # attitude.initial = attitude_bar[0]
331
+
332
+ position.guess = position_bar
333
+ velocity.guess = velocity_bar
334
+ attitude.guess = attitude_bar
335
+ angular_velocity.guess = angular_velocity_bar
336
+ angle_metric.guess = angle_metric_bar
337
+ # time_state guess is typically set by the framework; set explicitly if needed
338
+ time_state.guess = time_bar
339
+
340
+ # -----------------------------------------------------------------------------
341
+ # Problem
342
+ # -----------------------------------------------------------------------------
343
+
344
+ problem = Problem(
345
+ dynamics=dynamics,
346
+ states=states,
347
+ controls=controls,
348
+ time=time_state,
349
+ constraints=constraints,
350
+ N=n,
351
+ byof=byof,
352
+ time_dilation_factor_min=0.001,
353
+ time_dilation_factor_max=3.0,
354
+ autotuner=ox.RampProximalWeight(),
355
+ float_dtype="float64",
356
+ )
357
+
358
+ # problem.settings.scp.ep_tr = 1.6e-3
359
+ problem.settings.scp.autotuner.ramp_factor = 1.06
360
+ problem.settings.scp.autotuner.lam_prox_max = 1e3
361
+
362
+ problem.settings.scp.lam_vc = 1e3
363
+ problem.settings.scp.lam_cost = 6e0
364
+ problem.settings.cvx.solver_args = {"canon_backend": "COO", "enforce_dpp": True}
365
+
366
+
367
+ plotting_dict = {
368
+ "svg_path_function": svg_path_function,
369
+ "path_offset": path_offset,
370
+ "total_time": total_time,
371
+ "initial_pos": initial_pos,
372
+ "final_pos": final_pos,
373
+ "boresight_body": boresight_body,
374
+ "moving_subject": True,
375
+ "get_kp_pose": get_kp_pose,
376
+ "angle_to_target": angle_to_target,
377
+ "extend_boresight": True,
378
+ "relative_vector": True,
379
+ }
380
+
381
+ if __name__ == "__main__":
382
+ problem.initialize()
383
+ results = problem.solve()
384
+ results = problem.post_process()
385
+
386
+ results.update_plotting_data(**plotting_dict)
387
+
388
+ # Define the plane the logo actually lies in (from three points on the logo)
389
+ p0 = np.asarray(get_kp_pose(0.0))
390
+ p1 = np.asarray(get_kp_pose(0.33))
391
+ p2 = np.asarray(get_kp_pose(0.67))
392
+ v1 = p1 - p0
393
+ v2 = p2 - p0
394
+ plane_normal = np.cross(v1, v2)
395
+ nrm = np.linalg.norm(plane_normal)
396
+ if nrm < 1e-10:
397
+ plane_normal = np.array([1.0, 0.0, 0.0]) # fallback
398
+ else:
399
+ plane_normal = plane_normal / nrm
400
+ plane_point = p0
401
+
402
+ def ray_plane_intersection(ray_origin, ray_direction, p_plane, n_plane):
403
+ denom = np.dot(ray_direction, n_plane)
404
+ if abs(denom) < 1e-10:
405
+ return None
406
+ t = np.dot(p_plane - ray_origin, n_plane) / denom
407
+ if t < 0:
408
+ return None
409
+ return ray_origin + t * ray_direction
410
+
411
+ pos_traj = np.asarray(results.trajectory["position"])
412
+ tt = np.asarray(results.trajectory["time"]).reshape(-1)
413
+ total_time_f = float(total_time)
414
+ target_traj = np.stack(
415
+ [np.asarray(get_kp_pose(float(t) / total_time_f)) for t in tt],
416
+ axis=0,
417
+ )
418
+ traced_path = []
419
+ for i in range(len(pos_traj)):
420
+ rel = target_traj[i] - pos_traj[i]
421
+ nrm = np.linalg.norm(rel)
422
+ rel_dir = rel / nrm
423
+ pt = ray_plane_intersection(pos_traj[i], rel_dir, plane_point, plane_normal)
424
+ traced_path.append(pt if pt is not None else target_traj[i])
425
+ results["traced_path_on_plane"] = np.array(traced_path, dtype=np.float64)
426
+ results["logo_plane_point"] = plane_point
427
+ results["logo_plane_normal"] = plane_normal
428
+
429
+ from openscvx.plotting import plot_states, plot_controls, plot_virtual_control_heatmap, plot_trust_region_heatmap
430
+ plot_states(results).show()
431
+ plot_controls(results).show()
432
+ plot_virtual_control_heatmap(results).show()
433
+ plot_trust_region_heatmap(results).show()
434
+
435
+ server = create_animated_plotting_server(
436
+ results,
437
+ thrust_key="thrust_force",
438
+ show_grid=True,
439
+ )
440
+ server.sleep_forever()
@@ -0,0 +1 @@
1
+ <svg width="2677" height="1585" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" overflow="hidden"><defs><clipPath id="clip0"><rect x="861" y="55" width="2677" height="1585"/></clipPath><clipPath id="clip1"><rect x="861" y="55" width="2677" height="1585"/></clipPath></defs><g clip-path="url(#clip0)" transform="translate(-861 -55)"><g clip-path="url(#clip1)"><path d="M1241.55 59.0003 1264.22 59.5552C1592.31 75.6573 1859.59 322.995 1906.33 641.936L1907.45 653.344 1929.38 632.908C1945.48 618.885 1962.1 605.359 1979.2 592.376 2081.06 515.049 2262.42 453.475 2425.92 474.972 2591.85 496.79 2668.15 670.343 2502.8 846.804 2438.38 915.551 2404.12 930.752 2346.19 967.571 2328.7 975.467 2311.2 987.945 2307.46 960.328L2339.06 881.296C2369.29 844.685 2428.99 834.397 2488.83 740.664 2572.4 609.772 2503.13 559.768 2367.17 553.844 2246.18 548.572 2131.6 582.52 2005.85 670.926 1757.83 845.292 1675.63 1128.42 1741.75 1361.31 1794.22 1546.17 2082.48 1720.61 2555.24 1315.28 2567.16 1305.51 2575.66 1298.86 2582.43 1295.07L2591.32 1291.58 2551.48 1266.51C2544.07 1261.85 2541.84 1252.06 2546.51 1244.66L2584.48 1184.39 2576.78 1179.55 2567.63 1194.08C2563.95 1199.92 2557.24 1202.7 2550.82 1201.65L2544.79 1199.36 2544.78 1199.39 2378.12 1094.52 2369.99 1056.08 2381.99 1053.7 2383.11 1059 2419.87 1000.65 2373.16 1012 2378.57 1037.56 2366.57 1039.94 2362.77 1021.96 2362.95 1021.68 2362.49 1020.65 2362.38 1020.11 2362.17 1013.44C2362.55 1011.11 2363.4 1008.82 2364.73 1006.69 2366.07 1004.57 2367.78 1002.81 2369.72 1001.46L2375.82 998.77 2376.36 998.638 2377.49 998.603 2377.64 998.368 2377.62 998.332 2449.76 980.803 2449.76 980.802 2616.27 1085.59C2622.12 1089.27 2624.89 1095.97 2623.85 1102.38L2621.8 1107.78 2630.24 1094.38 2630.38 1094.47 2612.81 1122.35 2619.54 1126.59 2642.65 1089.91 2633.89 1078.93C2623.34 1060.99 2618.72 1043.56 2621.45 1029.01L2623.11 1024.71 2662.44 1046.36 2662.64 1050.45C2669.6 1066.36 2694.41 1090.07 2727.59 1110.95 2771.83 1138.79 2814.18 1151.05 2822.19 1138.34 2828.2 1128.81 2813.18 1107.93 2786.63 1086.35L2769.98 1074.47 2755.7 1097.14C2754.09 1099.7 2750.71 1100.47 2748.15 1098.86L2729.62 1087.2C2727.06 1085.59 2726.29 1082.21 2727.9 1079.65L2742.19 1056.98 2724.27 1047.11C2706.86 1038.9 2691.23 1033.88 2679.82 1032.75L2672.21 1032.9 2631.29 1010.38 2635.12 1006.11C2658.51 987.345 2706.5 990.997 2755.54 1015.07L2765.19 1020.46 2788.59 983.321 2786.42 978.399C2784.74 971.032 2785.88 963.026 2790.23 956.127 2796.74 945.78 2808.63 940.863 2819.99 942.716 2823.78 943.334 2827.51 944.704 2830.96 946.876 2844.76 955.563 2848.91 973.79 2840.21 987.586 2835.87 994.485 2829.14 998.969 2821.77 1000.64L2816.38 1000.81 2792.99 1037.95 2802.02 1044.32C2851.07 1082.94 2875.45 1131.86 2857.31 1160.66 2846.93 1177.13 2824.64 1183.91 2796.97 1181.56L2783.29 1178.41 2760.18 1215.09 2766.91 1219.33 2775.78 1205.24 2775.84 1205.28 2780.16 1200.75C2783.71 1198.27 2788.12 1197.27 2792.4 1197.97L2797.89 1200.06 2797.97 1199.93 2965.1 1305.1 2980.37 1377.27 2979.85 1377.34 2979.7 1377.58 2980.25 1378.84 2980.09 1379.72 3002.34 1379.72 3002.34 509.89C3002.34 499.812 3010.51 491.642 3020.6 491.642L3093.63 491.642C3103.71 491.642 3111.88 499.812 3111.88 509.89L3111.88 1400.68 3159.91 1400.68 3159.91 1418.1 3138.07 1418.1 3160.39 1436.3 3115.45 1455.46 3160.39 1474.74 3137.74 1493.32 3219.59 1493.32 3209.72 1478.69C3206.73 1471.63 3205.08 1463.86 3205.08 1455.71 3205.08 1447.56 3206.73 1439.79 3209.72 1432.73L3219.59 1418.1 3176.41 1418.1 3176.41 1400.68 3185.55 1400.68 3150.93 1325.54 3149.42 1318.07C3149.42 1310 3154.33 1303.08 3161.33 1300.12L3167.63 1298.85 3242.33 1299.51 3244.57 1298.59 3246.9 1299.55 3252.71 1299.61 3257.75 1304.05 3258.35 1304.29 3258.82 1304.99 3367.41 1400.68 3471.69 1400.68C3474.21 1400.68 3476.61 1401.19 3478.79 1402.11L3479.36 1402.5 3479.36 1401.59 3531.75 1443.25 3531.74 1444.66 3532.56 1445C3535.3 1447.74 3537 1451.53 3537 1455.71 3537 1459.89 3535.3 1463.68 3532.56 1466.42L3531.58 1466.83 3531.58 1467.74 3479.36 1509.26 3479.36 1508.35 3478.79 1508.73C3476.61 1509.66 3474.21 1510.17 3471.69 1510.17L3365.99 1510.17 3258.79 1604.38 3258.35 1605.03 3257.78 1605.26 3252.71 1609.72 3246.89 1609.77 3244.57 1610.74 3242.34 1609.81 3167.63 1610.48 3161.33 1609.2C3154.33 1606.25 3149.42 1599.32 3149.42 1591.25L3150.9 1583.92 3151.16 1583.36 3151.35 1583.08 3151.32 1583.02 3184.97 1510.17 3095.07 1510.17 3093.63 1510.76 3020.6 1510.76C3010.51 1510.76 3002.34 1502.59 3002.34 1492.52L3002.34 1491.92 3002.34 1418.93 3002.34 1396.21 2974.89 1396.21 2974.89 1394.64 2966.53 1400.61 2965.16 1400.66 2964.61 1401.53 2956.86 1403.41 2955.11 1391.26 2970.06 1387.62 2960.11 1340.62 2923.35 1398.97 2939 1395.17 2940.75 1407.32 2893.46 1418.82 2893.46 1418.82 2726.33 1313.65 2726.41 1313.52 2722.15 1309.47C2718.44 1304.14 2718.04 1296.89 2721.72 1291.05L2730.87 1276.52 2723.18 1271.68 2685.21 1331.94C2680.55 1339.35 2670.76 1341.57 2663.34 1336.91L2620.13 1309.71 2622.43 1316.82C2622.3 1322.01 2620.35 1328.2 2615.66 1335.56 2596.9 1364.99 2569.36 1403.68 2486.74 1468.61 2096.43 1779.1 1753.84 1602.75 1686.08 1446.94 1588.14 1221.71 1648.07 970.487 1799.6 771.311L1832.58 730.938 1832.21 729.155 1832.21 729.155 1831.74 710.8C1816.11 402.635 1568.64 155.603 1260.18 140.464L1246.95 140.14 1246.95 198.467 1257.27 198.719C1535.85 212.391 1759.35 435.491 1773.46 713.802L1773.88 730.123 1773.09 733.993C1771.78 737.094 1769.3 739.579 1766.19 740.89L1761.77 741.782 1705.31 741.782 1700.8 740.89C1697.7 739.59 1695.2 737.114 1693.88 734.018L1692.87 729.155 1692.8 729.077 1692.51 717.97C1680.5 481.124 1490.3 291.263 1253.23 279.628L1246.95 279.475 1246.95 338.211 1270.24 339.349C1468.07 358.799 1624.07 520.657 1634.23 720.972L1634.51 731.935 1634.09 733.993C1632.78 737.094 1630.3 739.579 1627.19 740.891L1622.78 741.781 1563.34 741.781 1561.05 741.33C1557.95 740.029 1555.45 737.554 1554.13 734.457L1553.13 729.595 1553.09 729.557 1552.04 708.718C1536.5 555.841 1414.42 434.444 1261.18 419.866L1246.95 419.193 1246.95 477.938 1284.64 481.498C1399.46 503.486 1488.21 598.815 1500.2 716.824 1499.4 976.483 1504.25 1358.34 1501.58 1490.11 1501.58 1499.7 1493.8 1507.48 1484.21 1507.48L1414.71 1507.48C1405.11 1507.48 1397.34 1499.7 1397.34 1490.11L1397.34 1229.61 1070.62 1229.61 1070.62 1490.83C1070.62 1500.42 1062.84 1508.19 1053.25 1508.19L983.749 1508.19C974.153 1508.19 966.373 1500.42 966.373 1490.83L966.373 1229.61 879.156 1229.61 877.461 1229.09 877.092 1228.52 867.833 1224.69 867.225 1223.95 863 1213.76 864.748 1209.54 864.191 1208.68 908.799 1133.91 909.757 1133.47 911.023 1130.42C913.784 1127.66 917.597 1125.95 921.81 1125.95L922.502 1126.24 922.624 1125.7 1070.77 1125.7 1070.77 1126.09 1399.58 1126.09 1399.58 744.828 1399.19 744.828C1399.19 654.187 1325.67 580.708 1234.98 580.708 1144.29 580.708 1070.77 654.187 1070.77 744.828L1070.77 954.745 1070.62 954.623 1070.62 1109.2 966.428 1109.2 967.755 716.824C979.746 598.815 1068.5 503.486 1183.32 481.498L1230.45 477.045 1230.45 406.668 1230.3 405.943 1230.14 405.787 1230.14 350.054 1230.45 348.51 1230.45 267.384 1230.3 266.659 1230.14 266.503 1230.14 210.768 1230.45 209.226 1230.45 128.277 1230.3 127.554 1230.14 127.397 1230.14 71.2757 1231.06 66.6685C1232.36 63.5624 1234.83 61.0685 1237.93 59.745Z" fill="#000000" fill-rule="evenodd" fill-opacity="1"/></g></g></svg>
@@ -0,0 +1,49 @@
1
+ import numpy as np
2
+ import jax.numpy as jnp
3
+ from svgpathtools import svg2paths, svg2paths2
4
+
5
+ def print_svg_path_attributes(svg_file_path):
6
+ """
7
+ Print the attributes of all paths in the SVG file for inspection.
8
+ """
9
+ paths, attributes, svg_attr = svg2paths2(svg_file_path)
10
+ for i, attr in enumerate(attributes):
11
+ print(f"Path {i}: {attr}")
12
+
13
+ def extract_svg_path(svg_file_path, n_points=2000, flip_y=True, path_indices=None):
14
+ """
15
+ Extract a continuous, high-resolution path from an SVG file using svgpathtools.
16
+ Optionally, only use specific path indices.
17
+ """
18
+ paths, attributes, svg_attr = svg2paths2(svg_file_path)
19
+ if path_indices is not None:
20
+ paths = [paths[i] for i in path_indices]
21
+ all_points = []
22
+ for path in paths:
23
+ for seg in path:
24
+ seg_len = seg.length()
25
+ n_seg_points = max(2, int(n_points * seg_len / path.length()))
26
+ ts = np.linspace(0, 1, n_seg_points, endpoint=False)
27
+ for t in ts:
28
+ pt = seg.point(t)
29
+ all_points.append([pt.real, pt.imag])
30
+ all_points = np.array(all_points)
31
+ min_x, max_x = np.min(all_points[:, 0]), np.max(all_points[:, 0])
32
+ min_y, max_y = np.min(all_points[:, 1]), np.max(all_points[:, 1])
33
+ if flip_y:
34
+ all_points[:, 1] = max_y - (all_points[:, 1] - min_y)
35
+ all_points[:, 0] = 20 * (all_points[:, 0] - min_x) / (max_x - min_x) - 10
36
+ all_points[:, 1] = 20 * (all_points[:, 1] - min_y) / (max_y - min_y) - 10
37
+ all_points = np.column_stack([all_points, np.full(len(all_points), 2.0)])
38
+ idxs = np.linspace(0, len(all_points) - 1, n_points).astype(int)
39
+ sampled_points = all_points[idxs]
40
+ # Convert to JAX array for JAX-compatible indexing
41
+ sampled_points_jax = jnp.array(sampled_points)
42
+ def path_function(t):
43
+ t = jnp.clip(t, 0, 1)
44
+ idx = jnp.clip(jnp.floor(t * (n_points - 1)), 0, n_points - 1).astype(int)
45
+ return sampled_points_jax[idx]
46
+ return path_function
47
+
48
+ def get_svg_path_function(svg_file_path, path_indices=None):
49
+ return extract_svg_path(svg_file_path, n_points=2000, flip_y=True, path_indices=path_indices)