openscvx 0.1.2__py3-none-any.whl → 0.2.1.dev0__py3-none-any.whl

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.

Potentially problematic release.


This version of openscvx might be problematic. Click here for more details.

openscvx/utils.py CHANGED
@@ -1,6 +1,56 @@
1
1
  import jax
2
2
  import jax.numpy as jnp
3
3
  import numpy as np
4
+ import hashlib
5
+ import ast
6
+ import types
7
+ import inspect
8
+ import textwrap
9
+
10
+ def stable_function_hash(funcs, n_discretization_nodes=None, dt=None, total_time=None, state_max=None, state_min=None, control_max=None, control_min=None):
11
+ hasher = hashlib.sha256()
12
+
13
+ for func in funcs:
14
+ try:
15
+ src = inspect.getsource(func)
16
+ src = textwrap.dedent(src) # <<< Fix: remove extra indent
17
+ parsed = ast.parse(src)
18
+
19
+ # Remove docstrings from the AST
20
+ for node in ast.walk(parsed):
21
+ if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) and ast.get_docstring(node):
22
+ if isinstance(node.body[0], ast.Expr):
23
+ node.body = node.body[1:]
24
+
25
+ normalized = ast.dump(parsed, annotate_fields=True, include_attributes=False)
26
+ hasher.update(normalized.encode())
27
+
28
+ except Exception as e:
29
+ raise ValueError(f"Could not hash function {func}: {e}")
30
+
31
+ # Add additional parameters to the hash
32
+ if n_discretization_nodes is not None:
33
+ hasher.update(f"n_nodes:{n_discretization_nodes}".encode())
34
+
35
+ if dt is not None:
36
+ hasher.update(f"dt:{dt}".encode())
37
+
38
+ if total_time is not None:
39
+ hasher.update(f"total_time:{total_time}".encode())
40
+
41
+ if state_max is not None:
42
+ hasher.update(f"state_max:{state_max.tobytes()}".encode())
43
+
44
+ if state_min is not None:
45
+ hasher.update(f"state_min:{state_min.tobytes()}".encode())
46
+
47
+ if control_max is not None:
48
+ hasher.update(f"control_max:{control_max.tobytes()}".encode())
49
+
50
+ if control_min is not None:
51
+ hasher.update(f"control_min:{control_min.tobytes()}".encode())
52
+
53
+ return hasher.hexdigest()
4
54
 
5
55
 
6
56
  def qdcm(q: jnp.ndarray) -> jnp.ndarray:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscvx
3
- Version: 0.1.2
3
+ Version: 0.2.1.dev0
4
4
  Summary: A general Python-based successive convexification implementation which uses a JAX backend.
5
5
  Home-page: https://haynec.github.io/openscvx/
6
6
  Author: Chris Hayner and Griffin Norris
@@ -12,14 +12,23 @@ Requires-Python: >=3.9
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
14
  Requires-Dist: cvxpy
15
- Requires-Dist: cvxpygen
16
15
  Requires-Dist: qoco
17
- Requires-Dist: qocogen
18
16
  Requires-Dist: numpy
19
17
  Requires-Dist: jax
20
18
  Requires-Dist: plotly
21
19
  Requires-Dist: termcolor
22
20
  Requires-Dist: diffrax
21
+ Requires-Dist: absl-py
22
+ Requires-Dist: flatbuffers
23
+ Provides-Extra: gui
24
+ Requires-Dist: pyqtgraph; extra == "gui"
25
+ Requires-Dist: PyQt5; extra == "gui"
26
+ Requires-Dist: scipy; extra == "gui"
27
+ Requires-Dist: PyOpenGL; extra == "gui"
28
+ Requires-Dist: PyOpenGL_accelerate; extra == "gui"
29
+ Provides-Extra: cvxpygen
30
+ Requires-Dist: cvxpygen; extra == "cvxpygen"
31
+ Requires-Dist: qocogen; extra == "cvxpygen"
23
32
  Dynamic: license-file
24
33
 
25
34
  <a id="readme-top"></a>
@@ -33,7 +42,8 @@ Dynamic: license-file
33
42
  <p align="center">
34
43
  <a href="https://github.com//haynec/OpenSCvx/actions/workflows/ci.yml/badge.svg"><img src="https://github.com//haynec/OpenSCvx/actions/workflows/ci.yml/badge.svg"/></a>
35
44
  <a href="https://github.com//haynec/OpenSCvx/actions/workflows/nightly.yml/badge.svg"><img src="https://github.com//haynec/OpenSCvx/actions/workflows/nightly.yml/badge.svg"/></a>
36
- <a href="https://github.com//haynec/OpenSCvx/actions/workflows/release.yml/badge.svg"><img src="https://github.com//haynec/OpenSCvx/actions/workflows/release.yml/badge.svg"/></a>
45
+ <a href="https://github.com/haynec/OpenSCvx/actions/workflows/release.yml?event=release"><img src="https://github.com/haynec/OpenSCvx/actions/workflows/release.yml/badge.svg?event=release"/>
46
+ </a>
37
47
  </p>
38
48
 
39
49
  <!-- PROJECT LOGO -->
@@ -44,6 +54,9 @@ Dynamic: license-file
44
54
 
45
55
  ### Installation
46
56
 
57
+ <details>
58
+ <summary>Stable</summary>
59
+
47
60
  To grab the latest stable release simply run
48
61
 
49
62
  ```sh
@@ -51,28 +64,27 @@ pip install openscvx
51
64
  ```
52
65
 
53
66
  to install OpenSCVx in your python environment.
67
+ </details>
54
68
 
55
69
  <details>
56
- <summary>Install Development / Nightly Version</summary>
70
+ <summary>Nightly</summary>
57
71
 
58
- If you want the pre-release version, you can install the latest `nightly` build with:
72
+ For the latest development version (nightly), clone the repository and install in editable mode:
59
73
 
60
74
  ```sh
61
- python3 -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ --pre --upgrade openscvx
62
- ```
75
+ # Clone the repo
76
+ git clone https://github.com/haynec/OpenSCvx.git
77
+ cd OpenSCvx
63
78
 
64
- This command will also upgrade an existing `nightly` install to the latest version
65
- Or if you want a specific pre-release version this can be installed with
66
-
67
- ```sh
68
- python3 -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ openscvx==1.2.3.dev45
79
+ # Install in editable/development mode
80
+ pip install -e .
69
81
  ```
70
82
 
71
- where `1.2.3.dev45 => <major>.<minor>.<patch>.dev<XY>` corresponds to your exact version
72
- </details>
83
+ This will install the code as a package and allow you to make local changes.
73
84
 
85
+ </details>
74
86
 
75
- #### Dependencies
87
+ ### Dependencies
76
88
 
77
89
  The main packages are:
78
90
 
@@ -84,67 +96,132 @@ The main packages are:
84
96
  - `plotly` - is used for all visualizations
85
97
 
86
98
  These will be installed automatically, but can be installed via conda or pip if you are building from source.
99
+
100
+ #### GUI Dependencies (Optional)
101
+
102
+ For interactive 3D plotting and real-time visualization, additional packages are required:
103
+
104
+ - `pyqtgraph` - is used for interactive 3D plotting and real-time visualization
105
+ - `PyQt5` - provides the Qt5 GUI framework for pyqtgraph
106
+ - `scipy` - is used for spatial transformations in plotting functions
107
+ - `PyOpenGL` - provides OpenGL bindings for Python, required for 3D plotting
108
+ - `PyOpenGL_accelerate` - (optional) speeds up PyOpenGL
109
+
110
+
111
+ For local development:
112
+
113
+ ```sh
114
+ pip install -e ".[gui]"
115
+ ```
116
+
117
+ Or with conda:
118
+
119
+ ```sh
120
+ conda env update -f environment.yml
121
+ ```
122
+
123
+ The GUI features include:
124
+ - Interactive 3D trajectory visualization with `plot_animation_pyqtgraph()`
125
+ - SCP iteration animation with `plot_scp_animation_pyqtgraph()`
126
+ - Camera view animation with `plot_camera_animation_pyqtgraph()`
127
+ - Real-time optimization visualization in examples like `drone_racing_realtime.py`
128
+
129
+ #### CVXPYGen Dependencies (Optional)
130
+
131
+ For code generation and faster solver performance, CVXPYGen can be installed:
132
+
133
+ - `cvxpygen` - enables code generation for faster solver performance
134
+ - `qocogen` - custom solver backend for CVXPYGen (included with cvxpygen extras)
135
+
136
+ To install with CVXPYGen support:
137
+
138
+ ```sh
139
+ pip install openscvx[cvxpygen]
140
+ ```
141
+
142
+ Or for both GUI and CVXPYGen:
143
+
144
+ ```sh
145
+ pip install openscvx[gui,cvxpygen]
146
+ ```
147
+
148
+ CVXPYGen features include:
149
+ - Automatic C++ code generation for optimization problems
150
+ - Faster solver performance through compiled code
151
+ - Support for custom solver backends like QOCOGen
152
+
153
+ ### Local Development
154
+
155
+ This git repository can be installed using https
156
+
157
+ ```sh
158
+ git clone https://github.com/haynec/OpenSCvx.git
159
+ ```
160
+
161
+ or ssh
162
+
163
+ ```sh
164
+ git clone git@github.com:haynec/OpenSCvx.git
165
+ ```
166
+
167
+ Dependencies can then be installed using Conda or Pip
168
+
87
169
  <details>
88
170
  <summary>Via Conda</summary>
89
171
 
90
- 1. Clone the repo
91
- ```sh
92
- git clone https://github.com/haynec/OpenSCvx.git
93
- ```
172
+ 1. Clone the repo using https or ssh
94
173
  2. Install environment packages (this will take about a minute or two):
95
174
  ```sh
96
175
  conda env create -f environment.yml
97
176
  ```
98
177
  3. Activate the environment:
99
178
  ```sh
100
- conda activate los_guidance
179
+ conda activate openscvx
101
180
  ```
102
-
103
181
  </details>
104
182
 
105
183
  <details>
106
- <summary>Via Pip</summary>
184
+ <summary>Via pip</summary>
107
185
 
108
- 0. Prerequisites
186
+ 1. Prerequisites
109
187
  Python >= 3.9
110
- 1. Clone the repo
188
+ 2. Clone the repo using https or ssh
189
+ 3. Create virtual environment (called `venv` here) and source it
111
190
  ```sh
112
- git clone https://github.com/haynec/OpenSCvx.git
191
+ python3 -m venv venv
192
+ source venv/bin/activate
113
193
  ```
114
- 2. Install environment packages:
194
+ 4. Install environment packages:
115
195
  ```sh
116
196
  pip install -r requirements.txt
117
197
  ```
198
+
199
+ Or install with optional dependencies:
200
+ ```sh
201
+ pip install -e ".[gui,cvxpygen]"
202
+ ```
118
203
  </details>
119
204
 
120
205
  ### Running Trajectory Optimization
121
206
 
122
- See `examples/` folder for several example trajectory optimization problems.
123
- To run a problem simply run `examples/main.py` with:
207
+ See `examples/params/` folder for several example trajectory optimization problems.
208
+ To run a problem simply run any of the examples directly, for example:
124
209
 
125
210
  ```sh
126
- python3 examples/main.py
127
- ```
128
-
129
- To change which example is run by `main` simply replace the `problem` import line:
130
-
131
- ```python
132
- # other imports
133
- from examples.params.dr_vp import problem
134
- # rest of code
211
+ python3 examples/params/brachistochrone.py
135
212
  ```
136
-
137
213
  and adjust the plotting as needed.
214
+
138
215
  Check out the problem definitions inside `examples/params` to see how to define your own problems.
139
216
 
140
217
  ## ToDos
141
218
 
142
219
  - [X] Standardized Vehicle and Constraint classes
143
220
  - [X] Implement QOCOGen with CVPYGEN
144
- - [X] Non-Dilated Time Propagation
221
+ - [X] Non-Dilated Time Propagation
222
+ - [X] Save and reload the compiled JAX code
145
223
  - [ ] Auto-SCvx Weight Tuning
146
224
  - [ ] Compiled at the subproblem level with JAX
147
- - [ ] Save and reload the compiled JAX code
148
225
  - [ ] Single Shot propagation
149
226
  - [ ] Unified Mathematical Interface
150
227
 
@@ -193,3 +270,14 @@ Please cite the following works if you use the repository,
193
270
  url={https://arxiv.org/abs/2404.16826},
194
271
  }
195
272
  ```
273
+
274
+ ```tex
275
+ @misc{chari2025qoco,
276
+ title = {QOCO: A Quadratic Objective Conic Optimizer with Custom Solver Generation},
277
+ author = {Chari, Govind M and A{\c{c}}{\i}kme{\c{s}}e, Beh{\c{c}}et},
278
+ year = {2025},
279
+ eprint = {2503.12658},
280
+ archiveprefix = {arXiv},
281
+ primaryclass = {math.OC},
282
+ }
283
+ ```
@@ -0,0 +1,27 @@
1
+ openscvx/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ openscvx/_version.py,sha256=_2des7n12lftUvjY9UJSeK1IayWVPlmV2Doo-FT0ZAE,524
3
+ openscvx/config.py,sha256=BsMAZUWCBUMl43nvakQ2OOdf2iszsFv9VP27J4xDXEs,16106
4
+ openscvx/discretization.py,sha256=FBpJKoVTXYAxeE6PvaekbRFbLWeKY6EJfl214ib2tX8,7908
5
+ openscvx/dynamics.py,sha256=TQosmwDXpWvR22-ZL2JawDDjVkyoL-DN45Xuv7ecCnc,6417
6
+ openscvx/integrators.py,sha256=uDXWyLen30L10Cf4GFEwhY0qru0wOB9Y9eU6Z0nvIH4,8290
7
+ openscvx/io.py,sha256=1OTM2oqMHQamaY48uEQMfNb0qJAwNmxHkgYCaKsnEOA,9755
8
+ openscvx/ocp.py,sha256=HAM1qLAAQS0Pjx4KTJRhrRnwzEYWBxe2QKUip8AqDms,8345
9
+ openscvx/plotting.py,sha256=Rq9mCBTcQwDdh5m7tE9Xp1qGnQ2V42Balp-d_JhOuCI,22276
10
+ openscvx/post_processing.py,sha256=lbLQ4ZHGbSTmaMVw9RWDckxIzskOeRw7W-s4W9c1UXE,2573
11
+ openscvx/propagation.py,sha256=Pm3HHEwMmpGrN1VEkzISuYvIIJG7VarDQXzlwbhPOEo,7945
12
+ openscvx/ptr.py,sha256=LbUrKvZabOKYbmkh1Q-vr4R38QY2E38k366PA0WrZ2U,7050
13
+ openscvx/results.py,sha256=h7cEd8IXlxFSB3RHCXxV6VTeXB8wSse9R42d7S_gu0M,4618
14
+ openscvx/trajoptproblem.py,sha256=aBuZ4Wt7eBq2QT8XieZ5-94IZjpeZcPQW3J5nhp4CI0,24434
15
+ openscvx/utils.py,sha256=CEd_kjh-MUhRInZjoxogUjMddU5ExJ-IAOXq_Hn4KGY,4166
16
+ openscvx/augmentation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ openscvx/augmentation/ctcs.py,sha256=m1jdALXSqHq3WD6lCBAUI7FR0Sfs8aCYr66h0EwE4z4,1707
18
+ openscvx/augmentation/dynamics_augmentation.py,sha256=4lEeSRl3LJxvcclwGSI1Yp21kc_oKoIVga08uzaKXE0,4702
19
+ openscvx/constraints/__init__.py,sha256=J3_UyJMUVYzvhjfyBM_m9WIRDlHQV7Q4CiI-TzRapAs,165
20
+ openscvx/constraints/ctcs.py,sha256=-VJZE8O0xq8n9mzSiDNikax-xo6CpWJtjwMbAPzu1-8,10121
21
+ openscvx/constraints/nodal.py,sha256=qT_U8Go0n0rzv4MupwQYGL8H5P8ShA7ZGATJ7IHnIqU,8185
22
+ openscvx/constraints/violation.py,sha256=curg7R6ER4YtKzdqmd1tgS2kWICGon5ab_Y4YGbeibw,2875
23
+ openscvx-0.2.1.dev0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
24
+ openscvx-0.2.1.dev0.dist-info/METADATA,sha256=d7eEmSOH_jP9tB9uKqD_eGFXeaFDP5pJ5c9Gnnw_B4g,9057
25
+ openscvx-0.2.1.dev0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
+ openscvx-0.2.1.dev0.dist-info/top_level.txt,sha256=nUT4Ybefzh40H8tVXqc1RzKESy_MAowElb-CIvAbd4Q,9
27
+ openscvx-0.2.1.dev0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.4.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,49 +0,0 @@
1
- from dataclasses import dataclass, field
2
- from typing import Union, Sequence
3
- import jax.numpy as jnp
4
-
5
- ALLOWED_TYPES = {"Fix", "Free", "Minimize", "Maximize"}
6
-
7
- @dataclass
8
- class BoundaryConstraint:
9
- value: jnp.ndarray
10
- types: list[str] = field(init=False)
11
-
12
- def __post_init__(self):
13
- self.types = ["Fix"] * len(self.value)
14
-
15
- def __getitem__(self, key):
16
- return self.value[key]
17
-
18
- def __setitem__(self, key, val):
19
- self.value = self.value.at[key].set(val)
20
-
21
- @property
22
- def type(self):
23
- constraint = self
24
- class TypeProxy:
25
- def __getitem__(self, key):
26
- return constraint.types[key]
27
-
28
- def __setitem__(self, key, val: Union[str, Sequence[str]]):
29
- indices = range(*key.indices(len(constraint.types))) if isinstance(key, slice) else [key]
30
- values = [val] * len(indices) if isinstance(val, str) else val
31
-
32
- if len(values) != len(indices):
33
- raise ValueError("Mismatch between indices and values length")
34
-
35
- for idx, v in zip(indices, values):
36
- if v not in ALLOWED_TYPES:
37
- raise ValueError(f"Invalid type: {v}, must be one of {ALLOWED_TYPES}")
38
- constraint.types[idx] = v
39
-
40
- def __len__(self):
41
- return len(constraint.types)
42
-
43
- def __repr__(self):
44
- return repr(constraint.types)
45
-
46
- return TypeProxy()
47
-
48
- def boundary(arr: jnp.ndarray):
49
- return BoundaryConstraint(arr)
@@ -1,27 +0,0 @@
1
- openscvx/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- openscvx/_version.py,sha256=bSmADqydH8nBu-J4lG8UVuR7hnU_zcwhnSav2oQ0W0A,511
3
- openscvx/config.py,sha256=8Cl5O0ekf9MGNDTEeMHsp1C4XvY9NfJQkxd80lvnafM,10296
4
- openscvx/discretization.py,sha256=YF3mEeyYHgyTWQVNQsqpi1Mv72zDLyNfaMJSWqxj34c,4745
5
- openscvx/dynamics.py,sha256=X9sPpxUGGbdsnvQzgyrb_939N9ctBSsWVyI1eXtOKpc,1118
6
- openscvx/integrators.py,sha256=msIS-1Ehj-9TJLHfoCMs3vdyZ8NXz-TM0RII6aqRf4E,3821
7
- openscvx/io.py,sha256=fOvNWQWAegcN1gejeToaNbXenP5H5bAifNU8edJvdk4,4127
8
- openscvx/ocp.py,sha256=L_509EQiMsI6s5gBYlYyxKaHEzzRdpo-XAMjliCU3Rc,7544
9
- openscvx/plotting.py,sha256=fCvWJV4qWMhVyJlh18s12S_5xhj6EviF-_FuP0tWjx4,31207
10
- openscvx/post_processing.py,sha256=TP1gi4TVlDS2HHpdqaIPCqfM5o4w7a7RCMU3Pu3czHw,1024
11
- openscvx/propagation.py,sha256=XNezQnAM-NXb9L7aHUgKQOBn0CNUPeGGDL3_BbGoODU,3758
12
- openscvx/ptr.py,sha256=itDTR6RQUphnU226jaeRaAKuia-6v8U3MqAdw5-BYOk,5268
13
- openscvx/trajoptproblem.py,sha256=3yufy-egU7m0NV834TH8csY1HJqM90Is7VYw0gQe3pk,11996
14
- openscvx/utils.py,sha256=zmkKyto8Jowe_RAdOe8K0w6gzOu4JfxmX1RUL-3OFlY,2408
15
- openscvx/augmentation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- openscvx/augmentation/ctcs.py,sha256=m1jdALXSqHq3WD6lCBAUI7FR0Sfs8aCYr66h0EwE4z4,1707
17
- openscvx/augmentation/dynamics_augmentation.py,sha256=7PL-mMfSmIIfMiXjdbXTolxOgUFSolzKpLu8WAmD384,4271
18
- openscvx/constraints/__init__.py,sha256=OOUcYEVoDWOSY50s2TbjpDjl3dRR3U04gRxmOyjbddY,258
19
- openscvx/constraints/boundary.py,sha256=yEhEnkKJ5f8NUeTksigEJjgBeE_YyuG_PJb_DWxg0L4,1541
20
- openscvx/constraints/ctcs.py,sha256=V763033aV82nAu7y4653KsAs11A7RpUysR_oUcnLfko,2572
21
- openscvx/constraints/nodal.py,sha256=YCS0cwUurA2OTQcHBb1EQqLxNt_w3MX8Nj8FH3GYClo,1726
22
- openscvx/constraints/violation.py,sha256=aIdDhHd-UndT0XB2QeuwLBKSNSAUWVkha_GeHOw9cQg,2362
23
- openscvx-0.1.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
24
- openscvx-0.1.2.dist-info/METADATA,sha256=MDHeKrpE_3FKRiQD5fVKVzNBWerOvcY0vfapGSRTlbk,6911
25
- openscvx-0.1.2.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
26
- openscvx-0.1.2.dist-info/top_level.txt,sha256=nUT4Ybefzh40H8tVXqc1RzKESy_MAowElb-CIvAbd4Q,9
27
- openscvx-0.1.2.dist-info/RECORD,,