openscvx 0.3.2.dev300__tar.gz → 0.3.2.dev315__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openscvx-0.3.2.dev300/openscvx.egg-info → openscvx-0.3.2.dev315}/PKG-INFO +1 -1
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/car/dubins_car_stljax.py +4 -14
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/drone/cinema_vp.py +4 -14
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/_version.py +3 -3
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/augmentation.py +21 -109
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/builder.py +19 -27
- openscvx-0.3.2.dev315/openscvx/symbolic/expr/vmap.py +510 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/lowerers/cvxpy.py +3 -1
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/lowerers/jax.py +93 -20
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/preprocessing.py +1 -78
- openscvx-0.3.2.dev315/openscvx/symbolic/time.py +84 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315/openscvx.egg-info}/PKG-INFO +1 -1
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/expr/test_scaling.py +9 -9
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/expr/test_variable.py +11 -7
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/expr/test_vmap.py +361 -4
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/test_augmentation.py +12 -201
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/test_brachistochrone.py +3 -3
- openscvx-0.3.2.dev300/openscvx/symbolic/expr/vmap.py +0 -321
- openscvx-0.3.2.dev300/openscvx/symbolic/time.py +0 -116
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/.github/assets/logo.svg +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/.github/release-drafter.yml +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/.github/workflows/_docs.yml +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/.github/workflows/branch-name.yml +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/.github/workflows/docs.yml +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/.github/workflows/lint.yml +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/.github/workflows/nightly.yml +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/.github/workflows/release-drafter.yml +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/.github/workflows/release.yml +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/.github/workflows/tests-integration.yml +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/.github/workflows/tests-unit.yml +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/.gitignore +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/CONTRIBUTING.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/LICENSE +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/README.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Overview/constraint_reformulation.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Overview/control_parameterization.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Overview/discretization.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Overview/ocp.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Overview/scvx.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Overview/time_dilation.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/UnderTheHood/lowering_architecture.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/UnderTheHood/vectorization_and_vmapping.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Usage/advanced_problem_setup.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Usage/api.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Usage/api_constraints.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Usage/api_control.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Usage/api_integrators.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Usage/api_state.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Usage/api_trajoptproblem.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Usage/api_variable.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Usage/basic_problem_setup.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Usage/tutorial_6dof_los_guidance.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Usage/tutorial_6dof_obstacle_avoidance.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/Usage/tutorials.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/assets/favicon.png +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/assets/images/ct-scvx_dark.png +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/assets/images/ct-scvx_light.png +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/assets/images/ctcs_dark.png +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/assets/images/ctcs_light.png +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/assets/images/problem_class_dark.png +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/assets/images/problem_class_light.png +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/assets/logo.svg +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/citation.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/examples.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/getting-started.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/index.md +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/docs/javascripts/mathjax.js +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/abstract/brachistochrone.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/arm/three_link_arm.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/car/dubins_car.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/car/dubins_car_conditional.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/car/dubins_car_disjoint.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/drone/cinema_vp_realtime_base.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/drone/dr_double_integrator.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/drone/dr_vp.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/drone/dr_vp_nodal.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/drone/dr_vp_polytope.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/drone/drone_racing.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/drone/obstacle_avoidance.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/drone/obstacle_avoidance_nodal.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/drone/obstacle_avoidance_realtime_base.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/drone/obstacle_avoidance_vmap.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/plotting.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/plotting_viser.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/realtime/cinema_vp_realtime.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/realtime/drone_racing_realtime.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/realtime/dubins_car_realtime.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/realtime/obstacle_avoidance_realtime.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/rocket/3DoF_pdg.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/examples/spacecraft/proxops_cw.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/figures/ctlos_cine.gif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/figures/ctlos_dr.gif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/figures/dtlos_cine.gif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/figures/dtlos_dr.gif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/figures/openscvx_logo.svg +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/figures/openscvx_logo_square.png +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/figures/oscvx_structure_full_dark.svg +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/figures/video_preview.png +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/1-background.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/1-background@1x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/1-background@2x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/1-background@3x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/1-background@4x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/2-mars.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/2-mars@1x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/2-mars@2x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/2-mars@3x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/2-mars@4x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/3-moon.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/3-moon@1x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/3-moon@2x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/3-moon@3x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/3-moon@4x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/4-sat1.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/4-sat1@1x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/4-sat1@2x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/4-sat1@3x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/4-sat1@4x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/5-space.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/5-space@1x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/5-space@2x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/5-space@3x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/5-space@4x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/6-earth.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/6-earth@1x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/6-earth@2x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/6-earth@3x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/images/layers/6-earth@4x.avif +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/javascripts/parallax.js +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/logo.svg +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/stylesheets/custom.css +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/assets/stylesheets/parallax.css +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/home.html +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/main.html +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/partials/parallax/hero.html +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/material/overrides/partials/parallax.html +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/mkdocs.yml +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/algorithms/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/algorithms/autotuning.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/algorithms/base.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/algorithms/optimization_results.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/algorithms/penalized_trust_region.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/config.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/discretization/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/discretization/discretization.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/expert/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/expert/byof.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/expert/lowering.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/expert/validation.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/init/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/init/interpolation.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/integrators/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/integrators/runge_kutta.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/lowered/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/lowered/cvxpy_constraints.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/lowered/cvxpy_variables.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/lowered/dynamics.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/lowered/jax_constraints.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/lowered/parameters.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/lowered/problem.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/lowered/unified.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/plotting/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/plotting/plotting.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/plotting/scp_iteration.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/plotting/viser/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/plotting/viser/animated.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/plotting/viser/plotly_integration.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/plotting/viser/primitives.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/plotting/viser/scp.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/plotting/viser/server.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/problem.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/propagation/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/propagation/post_processing.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/propagation/propagation.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/solvers/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/solvers/base.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/solvers/ptr_solver.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/constraint_set.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/arithmetic.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/array.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/constraint.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/control.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/expr.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/lie/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/lie/adjoint.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/lie/se3.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/lie/so3.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/linalg.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/logic.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/math.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/spatial.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/state.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/stl.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/expr/variable.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/hashing.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/lower.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/lowerers/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/problem.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/symbolic/unified.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/utils/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/utils/cache.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/utils/caching.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/utils/printing.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/utils/profiling.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx/utils/utils.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx.egg-info/SOURCES.txt +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx.egg-info/dependency_links.txt +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx.egg-info/requires.txt +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/openscvx.egg-info/top_level.txt +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/pyproject.toml +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/scripts/gen_example_pages.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/scripts/gen_ref_pages.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/setup.cfg +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/brachistochrone_analytical.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/expr/__init__.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/expr/test_arithmetic.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/expr/test_array.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/expr/test_constraint.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/expr/test_expr.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/expr/test_lie.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/expr/test_linalg.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/expr/test_logic.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/expr/test_math.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/expr/test_node_reference.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/expr/test_parameters.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/expr/test_spatial.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/test_hashing.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/test_lower_cvxpy.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/test_lower_jax.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/test_preprocessing.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/symbolic/test_unified.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/test_cvxpygen_optional.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/test_discretization.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/test_examples.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/test_expert.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/test_init.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/test_integrators.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/test_plotting.py +0 -0
- {openscvx-0.3.2.dev300 → openscvx-0.3.2.dev315}/tests/test_propagation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscvx
|
|
3
|
-
Version: 0.3.2.
|
|
3
|
+
Version: 0.3.2.dev315
|
|
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
|
|
@@ -55,12 +55,9 @@ angular_rate.min = np.array([-5])
|
|
|
55
55
|
angular_rate.max = np.array([5])
|
|
56
56
|
angular_rate.guess = np.zeros((n, 1))
|
|
57
57
|
|
|
58
|
-
# Define time
|
|
59
|
-
|
|
60
|
-
time.
|
|
61
|
-
time.min = np.array([0.0])
|
|
62
|
-
time.initial = np.array([0.0])
|
|
63
|
-
time.final = [ox.Minimize(total_time)]
|
|
58
|
+
# Define time (needed for time-dependent constraints)
|
|
59
|
+
# Time is a State subclass, so it can be used directly in expressions
|
|
60
|
+
time = ox.Time(initial=0.0, final=("minimize", total_time), min=0.0, max=10.0)
|
|
64
61
|
|
|
65
62
|
|
|
66
63
|
# Define list of all states and controls
|
|
@@ -97,20 +94,13 @@ wp2_pred = ox.linalg.Norm(position - wp2_center) <= wp2_radius
|
|
|
97
94
|
constraints.append(ox.stl.Or(wp1_pred, wp2_pred).over((3, 5)))
|
|
98
95
|
|
|
99
96
|
# Build the problem
|
|
100
|
-
time_config = ox.Time(
|
|
101
|
-
initial=0.0,
|
|
102
|
-
final=total_time,
|
|
103
|
-
min=0.0,
|
|
104
|
-
max=10,
|
|
105
|
-
)
|
|
106
|
-
|
|
107
97
|
constraints.append((time.at(5) - time.at(3) == 1.23).convex())
|
|
108
98
|
|
|
109
99
|
problem = Problem(
|
|
110
100
|
dynamics=dynamics,
|
|
111
101
|
states=states,
|
|
112
102
|
controls=controls,
|
|
113
|
-
time=
|
|
103
|
+
time=time, # Time is already defined above as ox.Time
|
|
114
104
|
constraints=constraints,
|
|
115
105
|
N=n,
|
|
116
106
|
)
|
|
@@ -64,12 +64,9 @@ fuel.min = np.array([0])
|
|
|
64
64
|
fuel.initial = np.array([0])
|
|
65
65
|
fuel.final = [("minimize", 0)]
|
|
66
66
|
|
|
67
|
-
# Define time
|
|
68
|
-
|
|
69
|
-
time
|
|
70
|
-
time.min = np.array([0.0])
|
|
71
|
-
time.initial = np.array([0.0])
|
|
72
|
-
time.final = np.array([total_time])
|
|
67
|
+
# Define time (needed for time-dependent constraints)
|
|
68
|
+
# Time is a State subclass, so it can be used directly in expressions
|
|
69
|
+
time = ox.Time(initial=0.0, final=total_time, min=0.0, max=total_time)
|
|
73
70
|
|
|
74
71
|
# Define control components
|
|
75
72
|
thrust_force = ox.Control("thrust_force", shape=(3,)) # Thrust forces [fx, fy, fz]
|
|
@@ -230,18 +227,11 @@ attitude.guess = attitude_bar
|
|
|
230
227
|
angular_velocity.guess = angular_velocity_bar
|
|
231
228
|
fuel.guess = fuel_bar
|
|
232
229
|
|
|
233
|
-
time_config = ox.Time(
|
|
234
|
-
initial=0.0,
|
|
235
|
-
final=total_time,
|
|
236
|
-
min=0.0,
|
|
237
|
-
max=total_time,
|
|
238
|
-
)
|
|
239
|
-
|
|
240
230
|
problem = Problem(
|
|
241
231
|
dynamics=dynamics,
|
|
242
232
|
states=states,
|
|
243
233
|
controls=controls,
|
|
244
|
-
time=
|
|
234
|
+
time=time, # Time is already defined above as ox.Time
|
|
245
235
|
constraints=constraints,
|
|
246
236
|
N=n,
|
|
247
237
|
licq_max=1e-8,
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.3.2.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 3, 2, '
|
|
31
|
+
__version__ = version = '0.3.2.dev315'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 3, 2, 'dev315')
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g0fafbcbb5'
|
|
@@ -53,7 +53,7 @@ Example:
|
|
|
53
53
|
# controls_aug includes original controls + time dilation
|
|
54
54
|
"""
|
|
55
55
|
|
|
56
|
-
from typing import Dict, List,
|
|
56
|
+
from typing import Dict, List, Tuple
|
|
57
57
|
|
|
58
58
|
import numpy as np
|
|
59
59
|
|
|
@@ -385,113 +385,6 @@ def get_nodal_constraints_from_ctcs(
|
|
|
385
385
|
return nodal_ctcs
|
|
386
386
|
|
|
387
387
|
|
|
388
|
-
def augment_with_time_state(
|
|
389
|
-
states: List[State],
|
|
390
|
-
constraints: ConstraintSet,
|
|
391
|
-
time_initial: float | tuple,
|
|
392
|
-
time_final: float | tuple,
|
|
393
|
-
time_min: float,
|
|
394
|
-
time_max: float,
|
|
395
|
-
N: int,
|
|
396
|
-
time_scaling_min: Optional[float] = None,
|
|
397
|
-
time_scaling_max: Optional[float] = None,
|
|
398
|
-
) -> Tuple[List[State], ConstraintSet]:
|
|
399
|
-
"""Augment problem with a time state variable.
|
|
400
|
-
|
|
401
|
-
Creates a time state variable if one doesn't already exist and adds it to the
|
|
402
|
-
states list. Also adds CTCS constraints to enforce time bounds continuously
|
|
403
|
-
throughout the trajectory.
|
|
404
|
-
|
|
405
|
-
The time state tracks physical time along the trajectory and is used for
|
|
406
|
-
time-optimal control problems. Boundary conditions can be fixed values or
|
|
407
|
-
free variables with initial guesses.
|
|
408
|
-
|
|
409
|
-
Args:
|
|
410
|
-
states: List of State objects (will not be modified, copy is returned)
|
|
411
|
-
constraints: ConstraintSet with unsorted constraints (will be modified in place)
|
|
412
|
-
time_initial: Initial time boundary condition:
|
|
413
|
-
- float: Fixed initial time
|
|
414
|
-
- tuple: ("free", guess) for free initial time with initial guess
|
|
415
|
-
time_final: Final time boundary condition (same format as time_initial)
|
|
416
|
-
time_min: Minimum bound for time variable throughout trajectory
|
|
417
|
-
time_max: Maximum bound for time variable throughout trajectory
|
|
418
|
-
N: Number of discretization nodes (for initial guess generation)
|
|
419
|
-
|
|
420
|
-
Returns:
|
|
421
|
-
Tuple of:
|
|
422
|
-
- Updated states list (original + time state if created)
|
|
423
|
-
- The same ConstraintSet with time CTCS constraints added to unsorted
|
|
424
|
-
|
|
425
|
-
Note:
|
|
426
|
-
If a state named "time" already exists, it is not modified and no
|
|
427
|
-
constraints are added.
|
|
428
|
-
|
|
429
|
-
Example:
|
|
430
|
-
Get augmented states::
|
|
431
|
-
|
|
432
|
-
x = ox.State("x", shape=(3,))
|
|
433
|
-
constraints = ConstraintSet()
|
|
434
|
-
states_aug, constraints = augment_with_time_state(
|
|
435
|
-
states=[x],
|
|
436
|
-
constraints=constraints,
|
|
437
|
-
time_initial=0.0,
|
|
438
|
-
time_final=("free", 10.0),
|
|
439
|
-
time_min=0.0,
|
|
440
|
-
time_max=100.0,
|
|
441
|
-
N=50
|
|
442
|
-
)
|
|
443
|
-
|
|
444
|
-
states_aug now includes time state with initial=0, final=free
|
|
445
|
-
"""
|
|
446
|
-
# Create copy of states to avoid mutating input
|
|
447
|
-
states_aug = list(states)
|
|
448
|
-
|
|
449
|
-
# Check if a time state already exists
|
|
450
|
-
time_state = None
|
|
451
|
-
for state in states_aug:
|
|
452
|
-
if state.name == "time":
|
|
453
|
-
time_state = state
|
|
454
|
-
break
|
|
455
|
-
|
|
456
|
-
if time_state is None:
|
|
457
|
-
# Create time State only if it doesn't exist
|
|
458
|
-
time_state = State("time", shape=(1,))
|
|
459
|
-
time_state.min = np.array([time_min])
|
|
460
|
-
time_state.max = np.array([time_max])
|
|
461
|
-
|
|
462
|
-
# Set time boundary conditions
|
|
463
|
-
time_state.initial = [time_initial]
|
|
464
|
-
time_state.final = [time_final]
|
|
465
|
-
|
|
466
|
-
# Create initial guess for time (linear interpolation)
|
|
467
|
-
time_guess_start = (
|
|
468
|
-
time_state.initial[0]
|
|
469
|
-
if isinstance(time_state.initial[0], (int, float))
|
|
470
|
-
else time_state.initial[0][1]
|
|
471
|
-
)
|
|
472
|
-
time_guess_end = (
|
|
473
|
-
time_state.final[0]
|
|
474
|
-
if isinstance(time_state.final[0], (int, float))
|
|
475
|
-
else time_state.final[0][1]
|
|
476
|
-
)
|
|
477
|
-
time_state.guess = np.linspace(time_guess_start, time_guess_end, N).reshape(-1, 1)
|
|
478
|
-
|
|
479
|
-
# Transfer scaling_min/max from Time object if provided
|
|
480
|
-
if time_scaling_min is not None:
|
|
481
|
-
time_state.scaling_min = np.array([time_scaling_min])
|
|
482
|
-
if time_scaling_max is not None:
|
|
483
|
-
time_state.scaling_max = np.array([time_scaling_max])
|
|
484
|
-
|
|
485
|
-
# Add time state to the list
|
|
486
|
-
states_aug.append(time_state)
|
|
487
|
-
|
|
488
|
-
# Add CTCS constraints for time bounds to unsorted
|
|
489
|
-
constraints.unsorted.append(CTCS(time_state <= time_state.max))
|
|
490
|
-
constraints.unsorted.append(CTCS(time_state.min <= time_state))
|
|
491
|
-
|
|
492
|
-
return states_aug, constraints
|
|
493
|
-
|
|
494
|
-
|
|
495
388
|
def augment_dynamics_with_ctcs(
|
|
496
389
|
xdot: Expr,
|
|
497
390
|
states: List[State],
|
|
@@ -623,7 +516,26 @@ def augment_dynamics_with_ctcs(
|
|
|
623
516
|
time_final = time_state.final[0]
|
|
624
517
|
time_dilation.min = np.array([time_dilation_factor_min * time_final])
|
|
625
518
|
time_dilation.max = np.array([time_dilation_factor_max * time_final])
|
|
626
|
-
|
|
519
|
+
|
|
520
|
+
# Compute initial guess for time_dilation from time.guess using finite differences
|
|
521
|
+
# The relationship is: dt/dtau = time_dilation, where tau is normalized time [0,1]
|
|
522
|
+
# With N nodes, dtau = 1/(N-1) between consecutive nodes
|
|
523
|
+
if time_state.guess is None:
|
|
524
|
+
raise ValueError("time state must have a guess set before augmentation")
|
|
525
|
+
|
|
526
|
+
if N > 1:
|
|
527
|
+
time_guess = time_state.guess.flatten() # Shape (N,)
|
|
528
|
+
time_dilation_guess = np.zeros(N)
|
|
529
|
+
dtau = 1.0 / (N - 1) # Normalized time step between nodes
|
|
530
|
+
# Compute finite difference: time_dilation[k] = (time[k+1] - time[k]) / dtau
|
|
531
|
+
for k in range(N - 1):
|
|
532
|
+
time_dilation_guess[k] = (time_guess[k + 1] - time_guess[k]) / dtau
|
|
533
|
+
# For the last node, use the previous value (extrapolate)
|
|
534
|
+
time_dilation_guess[N - 1] = time_dilation_guess[N - 2]
|
|
535
|
+
time_dilation.guess = time_dilation_guess.reshape(-1, 1)
|
|
536
|
+
else:
|
|
537
|
+
# Single node case: use time_final as guess
|
|
538
|
+
time_dilation.guess = np.ones([N, 1]) * time_final
|
|
627
539
|
|
|
628
540
|
controls_augmented.append(time_dilation)
|
|
629
541
|
|
|
@@ -35,7 +35,6 @@ import numpy as np
|
|
|
35
35
|
|
|
36
36
|
from openscvx.symbolic.augmentation import (
|
|
37
37
|
augment_dynamics_with_ctcs,
|
|
38
|
-
augment_with_time_state,
|
|
39
38
|
decompose_vector_nodal_constraints,
|
|
40
39
|
separate_constraints,
|
|
41
40
|
sort_ctcs_constraints,
|
|
@@ -57,7 +56,6 @@ from openscvx.symbolic.preprocessing import (
|
|
|
57
56
|
validate_dynamics_dimension,
|
|
58
57
|
validate_guesses,
|
|
59
58
|
validate_shapes,
|
|
60
|
-
validate_time_parameters,
|
|
61
59
|
validate_variable_names,
|
|
62
60
|
)
|
|
63
61
|
from openscvx.symbolic.problem import SymbolicProblem
|
|
@@ -200,31 +198,25 @@ def preprocess_symbolic_problem(
|
|
|
200
198
|
# Validate that all user-provided variables have guesses
|
|
201
199
|
validate_guesses(states + controls)
|
|
202
200
|
|
|
203
|
-
# ==================== PHASE 1: Time Handling
|
|
204
|
-
|
|
205
|
-
#
|
|
206
|
-
(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
time_min,
|
|
223
|
-
time_max,
|
|
224
|
-
N,
|
|
225
|
-
time_scaling_min=getattr(time, "scaling_min", None),
|
|
226
|
-
time_scaling_max=getattr(time, "scaling_max", None),
|
|
227
|
-
)
|
|
201
|
+
# ==================== PHASE 1: Time Handling ====================
|
|
202
|
+
|
|
203
|
+
# Check if time state already in states list
|
|
204
|
+
time_state = next((s for s in states if s.name == "time"), None)
|
|
205
|
+
|
|
206
|
+
if time_state is None:
|
|
207
|
+
# Add the Time object to states (Time is a State subclass)
|
|
208
|
+
states = list(states) + [time]
|
|
209
|
+
time_state = time
|
|
210
|
+
|
|
211
|
+
# Fill in default guess if needed (for Time instances)
|
|
212
|
+
if isinstance(time_state, Time) and time_state.guess is None:
|
|
213
|
+
time_state.guess = time_state._generate_default_guess(N)
|
|
214
|
+
|
|
215
|
+
# Add CTCS constraints for time bounds
|
|
216
|
+
from openscvx.symbolic.expr import CTCS
|
|
217
|
+
|
|
218
|
+
constraints.unsorted.append(CTCS(time_state <= time_state.max))
|
|
219
|
+
constraints.unsorted.append(CTCS(time_state.min <= time_state))
|
|
228
220
|
|
|
229
221
|
# Add time derivative to dynamics dict (if not already present)
|
|
230
222
|
# Time derivative is always 1.0 when using Time object
|