scocp: Sequential Convexified Optimal Control Problem solver in Python
scocp is a pythononic framework for solving general optimal control problems (OCPs) of the form:
\begin{align}
\min_{u(t), t_f, y} \quad& \phi(x(t_f),u(t_f),t_f,y) + \int_{t_0}^{t_f} \mathcal{L}(x(t),u(t),t) \mathrm{d}t
\\ \mathrm{s.t.} \quad& \dot{x}(t) = f(x(t),u(t),t)
\\& g(x(t),u(t),t,y) = 0
\\& h(x(t),u(t),t,y) \leq 0
\\& x(t_0) \in \mathcal{X}(t_0) ,\,\, x(t_f) \in \mathcal{X}(t_f)
\\& x(t) \in \mathcal{X}(t),\,\, u(t) \in \mathcal{U}(t)
\end{align}
with either fixed or free $t_f$ via sequential convex programming (SCP).
Installing is as easy as
pip install scocp
and to uninstall
pip uninstall scocp
Read the full documentation here!
Overview
with either fixed or free $t_f$ via sequential convex programming (SCP).
The SCP is solved with the SCvx* algorithm, an augmented Lagrangian framework to handle non-convex constraints [1].
The dynamics in the OCP are handled by defining an integrator class, which requires a solve(tspan, x0, u=None,stm=False) method.
scocp provides wrappers to be used with either scipy's solve_ivp() method or heyoka, but a user-defined integrator class can be used instead as well.
A custom integrator class should look like:
class MyIntegrator:
def __init__(self, nx, nu, impulsive: bool, nv, *args):
self.nx = nx # dimension of states
self.nu = nu # dimension of controls
self.impulsive = impulsive # whether to consider impulsive or continuous control
self.nv = nv # dimension of control magnitudes to be augmented in the linearized map
# (whatever other stuff you want to do with the integrator)
def solve(self, tspan, x0, u=None, stm=False):
"""Solve IVP
If `u` is provided, solve IVP with control
If `stm = True`, also propagate sensitivities
"""
# (solve initial value problem)
return t_eval, states
To solve an OCP, the user needs to define a problem class, for example:
class MyOptimalControlProblem(scocp.ContinuousControlSCOCP):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs):
return
def evaluate_objective(self, xs, us, gs, ys):
"""Evaluate the objective function"""
# (compute objective)
return objective
def solve_convex_problem(self, xbar, ubar, vbar, ybar):
N,nx = xbar.shape
xs = cp.Variable((N, nx), name='state')
us = cp.Variable((N, nu), name='control')
gs = cp.Variable((N, 1), name='Gamma')
ts = cp.Variable((N, 1), name='ys')
xis_dyn = cp.Variable((N-1,nx), name='xi_dyn') # slacks for dynamics constraints
xis = cp.Variable(self.ng, name='xi') # slacks for non-dynamics equality constraints
zetas = cp.Variable(self.nh, name='xi') # slacks for inequality constraints
# (formulate & solve OCP)
return xs.value, us.value, gs.value, ys.value, xis.value, xis.value, zetas.value
def evaluate_nonlinear_constraints(self, xs, us, gs, ys=None):
g_eval = ... # array of nonlinear equality constraints evaluated along `xs`, `us`, `gs`
h_eval = ... # array of nonlinear inequality constraints evaluated along `xs`, `us`, `gs`
return g_eval, h_eval
In addition, we provide problem classes that can be readily used for typical OCPs in astrodynamics:
- Fixed final time continuous rendezvous's:
FixedTimeContinuousRdv,FixedTimeContinuousRdvLogMass - Fixed final time impulsive rendezvous's:
FixedTimeImpulsiveRdv - Free final time continuous rendezvous's:
FreeTimeContinuousRdv,FreeTimeContinuousRdvLogMass
References
[1] K. Oguri, “Successive Convexification with Feasibility Guarantee via Augmented Lagrangian for Non-Convex Optimal Control Problems,” in 2023 62nd IEEE Conference on Decision and Control (CDC), IEEE, Dec. 2023, pp. 3296–3302. doi: 10.1109/CDC49753.2023.10383462.
Setup
-
git clonethis repository -
Setup virtual environment (requirements:
python 3.11,cvxpy,heyoka,numba,numpy,matplotlib,scipy) -
Run test from the root of the repository (requires
pytest)
[!NOTE]
Additional methods compatible with thepykepinfrastructure are provided inscocp_pykep.
pytest tests
Or, to also get coverage report
coverage run -m pytest -v -s tests
coverage report -m
Examples
See example notebooks in ./examples.
Quadratic objective, unconstrained
Fuel-optimal objective, unconstrained
Astrodynamics examples
Continuous Control
FixedTimeContinuousRdv:Fixed TOF Continuous control rendez-vous
- State: Cartesian position, velocity
- Controls: acceleration
- Fixed TOF
- Fixed boundary conditions
FixedTimeContinuousRdvLogMass: Fixed TOF Continuous control rendez-vous with mass dynamics
- State: Cartesian position, velocity + log(mass)
- Controls: acceleration
- Fixed TOF
- Fixed boundary conditions
FreeTimeContinuousRdvLogMass: Free TOF Continuous control rendez-vous with mass dynamics
- State: Cartesian position, velocity + log(mass) + dilated time
- Controls: acceleration + time dilation factor
- Free TOF
- Fixed boundary conditions
FreeTimeContinuousMovingTargetRdvLogMass: Free TOF Continuous rendez-vous with mass dynamics & moving target
- State: Cartesian position, velocity + log(mass) + dilated time
- Controls: acceleration + time dilation factor
- Free TOF
- Fixed initial conditions, moving terminal conditions
FreeTimeContinuousMovingTargetRdvMass: Free TOF Continuous rendez-vous with mass dynamics & moving target
- State: Cartesian position, velocity + mass + dilated time
- Controls: acceleration + time dilation factor
- Free TOF
- Fixed initial conditions, moving terminal conditions
Impulsive Control
FixedTimeImpulsiveRdv:Fixed TOF impulsive control rendez-vous
- State: Cartesian position, velocity
- Controls: impulsive delta-V's
- Fixed TOF
- Fixed boundary conditions
SCP Miso
Modeling tips
Trust-region constraint
- We want to relax the trust-region as much as possible (for faster convergence) without exising the region approximated by linearization/convexification
- If the control is not upper-bounded (e.g. impulsive), set trust-region on both state and control; if continuous, consider using trust-region only on the state, or use different trust-region radii
Tuning algorithm hyperparameters
Before delving into the rabbit hole of hyperparameters, make sure you're 100% sure model is correct & scaled somewhat appropriately (i.e. no large order of magnitude difference in your state & control variables, etc).
TODO
Commmon issues
My progress is too slow
Is your trust-region upper-bound uncecessarily too small? Is your trust-region collapsing? Below are some things you could do - note that effectiveness is case-dependent!
- Using a lower
rho2will re-increase the step-size more frequently (default:rho2 = 0.7) - Using a larger weight update factor
betawill decrease the feasibility faster (default:beta = 2.0)
Metadata
Release files for scocp 0.1.7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| scocp-0.1.7.tar.gz | 34.7 kB | Without provenance | Details for scocp-0.1.7.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| scocp-0.1.7-py3-none-any.whl | Python 3 | none | any | Details for scocp-0.1.7-py3-none-any.whl |
Total release size: 71.6 kB
Release files / scocp-0.1.7.tar.gz
| Download URL | scocp-0.1.7.tar.gz |
|---|---|
| Size | 34.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
16dda7166a30d7b9c0e0ac1b4c52d16a25604ce403560478a0028966f046b61a
|
|
BLAKE2b-256 checksum How to use checksums |
5e9793c459fd9a3cfb5a1a75dd5a7fa243328144bc6ccdc48074fad8b543a84e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.11.12
|
Release files / scocp-0.1.7-py3-none-any.whl
| Download URL | scocp-0.1.7-py3-none-any.whl |
|---|---|
| Size | 36.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0279030b7d6102e09162e76b9d39a69dfecba9adee834aaa23b15de6aff971e0
|
|
BLAKE2b-256 checksum How to use checksums |
9d0a718a0bd565fc14e3790445e3bcfd496de17040b3e397f4c8c7bc317b41f8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.11.12
|
Security for scocp 0.1.7
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.