Skip to content

Commit 2456f36

Browse files
committed
slight code refactoring + docstrings + initial doc/obc.rst
1 parent 0d14642 commit 2456f36

9 files changed

Lines changed: 634 additions & 108 deletions

File tree

control/obc.py

Lines changed: 473 additions & 94 deletions
Large diffs are not rendered by default.

control/tests/obc_test.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from control.tests.conftest import slycotonly
1414

1515

16-
def test_finite_horizon_mpc_simple():
16+
def test_finite_horizon_simple():
1717
# Define a linear system with constraints
1818
# Source: https://www.mpt3.org/UI/RegulationProblem
1919

@@ -30,18 +30,13 @@ def test_finite_horizon_mpc_simple():
3030
R = [[1]]
3131
cost = obc.quadratic_cost(sys, Q, R)
3232

33-
# Create a model predictive controller system
33+
# Set up the optimal control problem
3434
time = np.arange(0, 5, 1)
35-
optctrl = obc.OptimalControlProblem(sys, time, cost, constraints)
36-
mpc = optctrl.mpc
37-
38-
# Optimal control input for a given value of the initial state
3935
x0 = [4, 0]
40-
u = mpc(x0)
41-
np.testing.assert_almost_equal(u, -1)
4236

4337
# Retrieve the full open-loop predictions
44-
t, u_openloop = optctrl.compute_trajectory(x0, squeeze=True)
38+
t, u_openloop = obc.compute_optimal_input(
39+
sys, time, x0, cost, constraints, squeeze=True)
4540
np.testing.assert_almost_equal(
4641
u_openloop, [-1, -1, 0.1393, 0.3361, -5.204e-16], decimal=4)
4742

@@ -54,7 +49,7 @@ def test_finite_horizon_mpc_simple():
5449

5550

5651
@slycotonly
57-
def test_finite_horizon_mpc_oscillator():
52+
def test_class_interface():
5853
# oscillator model defined in 2D
5954
# Source: https://www.mpt3.org/UI/RegulationProblem
6055
A = [[0.5403, -0.8415], [0.8415, 0.5403]]
@@ -124,11 +119,10 @@ def test_mpc_iosystem():
124119
cost = obc.quadratic_cost(model, Q, R, x0=xd, u0=ud)
125120

126121
# online MPC controller object is constructed with a horizon 6
127-
optctrl = obc.OptimalControlProblem(
122+
ctrl = obc.create_mpc_iosystem(
128123
model, np.arange(0, 6) * 0.2, cost, constraints)
129124

130125
# Define an I/O system implementing model predictive control
131-
ctrl = optctrl.create_mpc_iosystem()
132126
loop = ct.feedback(sys, ctrl, 1)
133127

134128
# Choose a nearby initial condition to speed up computation

doc/classes.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,14 @@ that allow for linear, nonlinear, and interconnected elements:
3030
LinearICSystem
3131
LinearIOSystem
3232
NonlinearIOSystem
33+
34+
Additional classes
35+
==================
36+
.. autosummary::
37+
38+
flatsys.BasisFamily
39+
flatsys.FlatSystem
40+
flatsys.LinearFlatSystem
41+
flatsys.PolyFamily
42+
flatsys.SystemTrajectory
43+
obc.OptimalControlProblem

doc/examples.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,6 @@ using running examples in FBS2e.
4343

4444
cruise
4545
describing_functions
46+
mpc_aircraft
4647
steering
4748
pvtol-lqr-nested

doc/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ implements basic operations for analysis and design of feedback control systems.
3030
flatsys
3131
iosys
3232
descfcn
33+
obc
3334
examples
3435

3536
* :ref:`genindex`

doc/mpc-overview.png

172 KB
Loading

doc/mpc_aircraft.ipynb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../examples/mpc_aircraft.ipynb

doc/obc.rst

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
.. _obc-module:
2+
3+
**************************
4+
Optimization-based control
5+
**************************
6+
7+
.. automodule:: control.obc
8+
:no-members:
9+
:no-inherited-members:
10+
11+
Optimal control problem setup
12+
=============================
13+
14+
Consider now the *optimal control problem*:
15+
16+
.. math::
17+
18+
\min_{u(\cdot)}
19+
\int_0^T L(x,u)\, dt + V \bigl( x(T) \bigr)
20+
21+
subject to the constraint
22+
23+
.. math::
24+
25+
\dot x = f(x, u), \qquad x\in\mathbb{R}^n,\, u\in\mathbb{R}^m.
26+
27+
Abstractly, this is a constrained optimization problem where we seek a
28+
*feasible trajectory* :math:`(x(t), u(t))` that minimizes the cost function
29+
30+
.. math::
31+
32+
J(x, u) = \int_0^T L(x,u)\, dt + V \bigl( x(T) \bigr).
33+
34+
More formally, this problem is equivalent to the "standard" problem of
35+
minimizing a cost function :math:`J(x, u)` where :math:`(x, u) \in L_2[0,T]`
36+
(the set of square integrable functions) and :math:`h(z) = \dot x(t) -
37+
f(x(t), u(t)) = 0` models the dynamics. The term :math:`L(x, u)` is
38+
referred to as the integral (or trajectory) cost and :math:`V(x(T))` is the
39+
final (or terminal) cost.
40+
41+
It is often convenient to ask that the final value of the trajectory,
42+
denoted :math:`x_\text{f}`, be specified. We can do this by requiring that
43+
:math:`x(T) = x_\text{f}` or by using a more general form of constraint:
44+
45+
.. math::
46+
47+
\psi_i(x(T)) = 0, \qquad i = 1, \dots, q.
48+
49+
The fully constrained case is obtained by setting :math:`q = n` and defining
50+
:math:`\psi_i(x(T)) = x_i(T) - x_{i,\text{f}}`. For a control problem with
51+
a full set of terminal constraints, :math:`V(x(T))` can be omitted (since
52+
its value is fixed).
53+
54+
Finally, we may wish to consider optimizations in which either the state or
55+
the inputs are constrained by a set of nonlinear functions of the form
56+
57+
.. math::
58+
59+
\text{lb}_i \leq g_i(x, u) \leq \text{ub}_i, \qquad i = 1, \dots, k.
60+
61+
where :math:`\text{lb}_i` and :math:`\text{ub}_i` represent lower and upper
62+
bounds on the constraint function :math:`g_i`. Note that these constraints
63+
can be on the input, the state, or combinations of input and state,
64+
depending on the form of :math:`g_i`. Furthermore, these constraints are
65+
intended to hold at all instants in time along the trajectory.
66+
67+
A common use of optimization-based control techniques is the implementation
68+
of model predictive control (also called receding horizon control). In
69+
model predict control, a finite horizon optimal control problem is solved,
70+
generating open-loop state and control trajectories. The resulting control
71+
trajectory is applied to the system for a fraction of the horizon
72+
length. This process is then repeated, resulting in a sampled data feedback
73+
law. This approach is illustrated in the following figure:
74+
75+
.. image:: mpc-overview.png
76+
77+
Every :math:`\Delta T` seconds, an optimal control problem is solved over a
78+
:math:`T` second horizon, starting from the current state. The first
79+
:math:`\Delta T` seconds of the optimal control :math:`u_T^{\*}(\cdot;
80+
x(t))` is then applied to the system. If we let :math:`x_T^{\*}(\cdot;
81+
x(t))` represent the optimal trajectory starting from :math:`x(t)`$ then the
82+
system state evolves from :math:`x(t)` at current time :math:`t` to
83+
:math:`x_T^{*}(\delta T, x(t))` at the next sample time :math:`t + \Delta
84+
T`, assuming no model uncertainty.
85+
86+
In reality, the system will not follow the predicted path exactly, so that
87+
the red (computed) and blue (actual) trajectories will diverge. We thus
88+
recompute the optimal path from the new state at time :math:`t + \Delta T`,
89+
extending our horizon by an additional :math:`\Delta T` units of time. This
90+
approach can be shown to generate stabilizing control laws under suitable
91+
conditions (see, for example, the FBS2e supplement on `Optimization-Based
92+
Control <https://fbswiki.org/wiki/index.php/OBC>`_.
93+
94+
Module usage
95+
============
96+
97+
The `obc` module provides a means of computing optimal trajectories for
98+
nonlinear systems and implementing optimization-based controllers, including
99+
model predictive control. It follows the basic problem setup described
100+
above, but carries out all computations in *discrete time* (so that
101+
integrals become sums) and over a *finite horizon*.
102+
103+
To describe an optimal control problem we need an input/output system, a
104+
time horizon, a cost function, and (optionally) a set of constraints on the
105+
state and/or input, either along the trajectory and at the terminal time.
106+
The `obc` module operates by converting the optimal control problem into a
107+
standard optimization problem that can be solved by
108+
:func:`scipy.optimize.minimize`. The optimal control problem can be solved
109+
by using the `~control.obc.compute_optimal_input` function:
110+
111+
import control.obc as obc
112+
inputs = obc.compute_optimal_inputs(sys, horizon, X0, cost, constraints)
113+
114+
The `sys` parameter should be a :class:`~control.InputOutputSystem` and the
115+
`horizon` parameter should represent a time vector that gives the list of
116+
times at which the `cost` and `constraints` should be evaluated. By default,
117+
`constraints` are taken to be trajectory constraints holding at all points
118+
on the trajectory. The `terminal_constraint` parameter can be used to
119+
specify a constraint that only holds at the final point of the trajectory
120+
and the `terminal_cost` paramter can be used to specify a terminal cost
121+
function.
122+
123+
124+
Example
125+
=======
126+
127+
Module classes and functions
128+
============================
129+
.. autosummary::
130+
:toctree: generated/
131+
132+
~control.obc.OptimalControlProblem
133+
~control.obc.compute_optimal_input
134+
~control.obc.create_mpc_iosystem
135+
~control.obc.input_poly_constraint
136+
~control.obc.input_range_constraint
137+
~control.obc.output_poly_constraint
138+
~control.obc.output_range_constraint
139+
~control.obc.state_poly_constraint
140+
~control.obc.state_range_constraint

examples/mpc_aircraft.ipynb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
"cost = obc.quadratic_cost(model, Q, R, x0=xd, u0=ud)\n",
7979
"\n",
8080
"# online MPC controller object is constructed with a horizon 6\n",
81-
"optctrl = obc.OptimalControlProblem(model, np.arange(0, 6) * 0.2, cost, constraints)"
81+
"ctrl = obc.create_mpc_iosystem(model, np.arange(0, 6) * 0.2, cost, constraints)"
8282
]
8383
},
8484
{
@@ -99,7 +99,6 @@
9999
],
100100
"source": [
101101
"# Define an I/O system implementing model predictive control\n",
102-
"ctrl = optctrl.create_mpc_iosystem()\n",
103102
"loop = ct.feedback(sys, ctrl, 1)\n",
104103
"print(loop)"
105104
]

0 commit comments

Comments
 (0)