algorithms
Successive convexification algorithms for trajectory optimization.
This module provides implementations of SCvx (Successive Convexification) algorithms for solving non-convex trajectory optimization problems through iterative convex approximation.
Current Implementations
PTR (Penalized Trust Region): The default SCvx algorithm using trust region methods with penalty-based constraint handling. Includes adaptive parameter tuning and virtual control relaxation.
Planned Architecture (ABC-based):
A base class will be introduced to enable pluggable algorithm implementations. This will enable users to implement custom SCvx variants or research algorithms. Future algorithms will implement the SCvxAlgorithm interface:
# algorithms/base.py (planned):
class SCvxAlgorithm(ABC):
@abstractmethod
def initialize(self, lowered: LoweredProblem) -> SolverState:
'''Initialize solver state from a lowered problem.'''
...
@abstractmethod
def step(self, state: SolverState, solver: ConvexSolver) -> SolverState:
'''Execute one iteration of the algorithm.'''
...
OptimizationResults
dataclass
¶
Structured container for optimization results from the Successive Convexification (SCP) solver.
This class provides a type-safe and organized way to store and access optimization results, replacing the previous dictionary-based approach. It includes core optimization data, iteration history for convergence analysis, post-processing results, and flexible storage for plotting and application-specific data.
Attributes:
| Name | Type | Description |
|---|---|---|
converged |
bool
|
Whether the optimization successfully converged |
t_final |
float
|
Final time of the optimized trajectory |
x_guess |
ndarray
|
Optimized state trajectory at discretization nodes, shape (N, n_states) |
u_guess |
ndarray
|
Optimized control trajectory at discretization nodes, shape (N, n_controls) |
nodes |
dict[str, ndarray]
|
Dictionary mapping state/control names to arrays at optimization nodes. Includes both user-defined and augmented variables. |
trajectory |
dict[str, ndarray]
|
Dictionary mapping state/control names to arrays along the propagated trajectory. Added by post_process(). |
x_history |
list[ndarray]
|
State trajectories from each SCP iteration |
u_history |
list[ndarray]
|
Control trajectories from each SCP iteration |
discretization_history |
list[ndarray]
|
Time discretization from each iteration |
J_tr_history |
list[ndarray]
|
Trust region cost history |
J_vb_history |
list[ndarray]
|
Virtual buffer cost history |
J_vc_history |
list[ndarray]
|
Virtual control cost history |
t_full |
Optional[ndarray]
|
Full time grid for interpolated trajectory |
x_full |
Optional[ndarray]
|
Interpolated state trajectory on full time grid |
u_full |
Optional[ndarray]
|
Interpolated control trajectory on full time grid |
cost |
Optional[float]
|
Total cost of the optimized trajectory |
ctcs_violation |
Optional[ndarray]
|
Continuous-time constraint violations |
plotting_data |
dict[str, Any]
|
Flexible storage for plotting and application data |
Source code in openscvx/algorithms/optimization_results.py
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | |
u: np.ndarray
property
¶
Optimal control trajectory at discretization nodes.
Returns the final converged solution from the SCP iteration history.
Returns:
| Type | Description |
|---|---|
ndarray
|
Control trajectory array, shape (N, n_controls) |
x: np.ndarray
property
¶
Optimal state trajectory at discretization nodes.
Returns the final converged solution from the SCP iteration history.
Returns:
| Type | Description |
|---|---|
ndarray
|
State trajectory array, shape (N, n_states) |
get(key: str, default: Any = None) -> Any
¶
Get a value from the results, similar to dict.get().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
The key to look up |
required |
default
|
Any
|
Default value if key is not found |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
The value associated with the key, or default if not found |
Source code in openscvx/algorithms/optimization_results.py
to_dict() -> dict[str, Any]
¶
Convert the results to a dictionary for backward compatibility.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary representation of the results |
Source code in openscvx/algorithms/optimization_results.py
update(other: dict[str, Any])
¶
Update the results with additional data from a dictionary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
dict[str, Any]
|
Dictionary containing additional data |
required |
Source code in openscvx/algorithms/optimization_results.py
update_plotting_data(**kwargs)
¶
Update the plotting data with additional information.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**kwargs
|
Key-value pairs to add to plotting_data |
{}
|
SolverState
dataclass
¶
Mutable state for SCP iterations.
This dataclass holds all state that changes during the solve process. It stores only the evolving trajectory arrays, not the full State/Control objects which contain immutable configuration metadata.
Trajectory arrays are stored in history lists, with the current guess accessed via properties that return the latest entry.
A fresh instance is created for each solve, enabling easy reset functionality.
Attributes:
| Name | Type | Description |
|---|---|---|
k |
int
|
Current iteration number (starts at 1) |
J_tr |
float
|
Current trust region cost |
J_vb |
float
|
Current virtual buffer cost |
J_vc |
float
|
Current virtual control cost |
w_tr |
float
|
Current trust region weight (may adapt during solve) |
lam_cost |
float
|
Current cost weight (may relax during solve) |
lam_vc |
Union[float, ndarray]
|
Current virtual control penalty weight |
lam_vb |
float
|
Current virtual buffer penalty weight |
n_x |
int
|
Number of states (for unpacking V vectors) |
n_u |
int
|
Number of controls (for unpacking V vectors) |
N |
int
|
Number of trajectory nodes (for unpacking V vectors) |
X |
List[ndarray]
|
List of state trajectory iterates |
U |
List[ndarray]
|
List of control trajectory iterates |
V_history |
List[ndarray]
|
List of discretization history |
Source code in openscvx/algorithms/solver_state.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | |
A_d: np.ndarray
property
¶
Extract discretized state transition matrix from latest V.
Returns:
| Type | Description |
|---|---|
ndarray
|
Discretized state Jacobian A_d with shape (N-1, n_x, n_x), or None if no V_history |
Example
After running an iteration, access linearization matrices::
problem.step()
A_d = problem.state.A_d # Shape (N-1, n_x, n_x)
B_d: np.ndarray
property
¶
Extract discretized control influence matrix (current node) from latest V.
Returns:
| Type | Description |
|---|---|
ndarray
|
Discretized control Jacobian B_d with shape (N-1, n_x, n_u), or None if no V_history |
Example
After running an iteration, access linearization matrices::
problem.step()
B_d = problem.state.B_d # Shape (N-1, n_x, n_u)
C_d: np.ndarray
property
¶
Extract discretized control influence matrix (next node) from latest V.
Returns:
| Type | Description |
|---|---|
ndarray
|
Discretized control Jacobian C_d with shape (N-1, n_x, n_u), or None if no V_history |
Example
After running an iteration, access linearization matrices::
problem.step()
C_d = problem.state.C_d # Shape (N-1, n_x, n_u)
u: np.ndarray
property
¶
Get current control trajectory array.
Returns:
| Type | Description |
|---|---|
ndarray
|
Current control trajectory guess (latest entry in history), shape (N, n_controls) |
x: np.ndarray
property
¶
Get current state trajectory array.
Returns:
| Type | Description |
|---|---|
ndarray
|
Current state trajectory guess (latest entry in history), shape (N, n_states) |
x_prop: np.ndarray
property
¶
Extract propagated state trajectory from latest V.
Returns:
| Type | Description |
|---|---|
ndarray
|
Propagated state trajectory x_prop with shape (N-1, n_x), or None if no V_history |
Example
After running an iteration, access the propagated states::
problem.step()
x_prop = problem.state.x_prop # Shape (N-1, n_x)
from_settings(settings: Config) -> SolverState
classmethod
¶
Create initial solver state from configuration.
Copies only the trajectory arrays from settings, leaving all metadata (bounds, boundary conditions, etc.) in the original settings object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
settings
|
Config
|
Configuration object containing initial guesses and SCP parameters |
required |
Returns:
| Type | Description |
|---|---|
SolverState
|
Fresh SolverState initialized from settings with copied arrays |
Source code in openscvx/algorithms/solver_state.py
PTR_step(params, settings: Config, state: SolverState, prob: cp.Problem, discretization_solver: callable, cpg_solve, emitter_function, jax_constraints: LoweredJaxConstraints) -> bool
¶
Performs a single SCP iteration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
Problem parameters |
required | |
settings
|
Config
|
Configuration object |
required |
state
|
SolverState
|
Solver state (mutated in place) |
required |
prob
|
Problem
|
CVXPy problem |
required |
discretization_solver
|
callable
|
Discretization solver function |
required |
cpg_solve
|
CVXPyGen solver (if enabled) |
required | |
emitter_function
|
Function to emit iteration data |
required | |
jax_constraints
|
LoweredJaxConstraints
|
JAX-lowered non-convex constraints |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if converged, False otherwise |
Source code in openscvx/algorithms/ptr.py
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | |
format_result(problem, state: SolverState, converged: bool) -> OptimizationResults
¶
Formats the solver state as an OptimizationResults object.
Directly passes trajectory arrays from solver state to results - no object construction needed. Results store pure arrays, settings store metadata.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
problem
|
The Problem instance (for symbolic metadata and settings). |
required | |
state
|
SolverState
|
The SolverState to extract results from. |
required |
converged
|
bool
|
Whether the optimization converged. |
required |
Returns:
| Type | Description |
|---|---|
OptimizationResults
|
OptimizationResults containing the solution data. |