mpc-control 0.1.0__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zhen NI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,212 @@
1
+ Metadata-Version: 2.4
2
+ Name: mpc-control
3
+ Version: 0.1.0
4
+ Summary: A Python library for Model Predictive Control (MPC)
5
+ Author-email: Zhen Ni <z.ni@hotmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Zhen-Ni/mpc-control
8
+ Project-URL: Issues, https://github.com/Zhen-Ni/mpc-control/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Topic :: Scientific/Engineering
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: numpy>=2.0
20
+ Requires-Dist: osqp>=1.0.0
21
+ Requires-Dist: scipy>=1.0.0
22
+ Dynamic: license-file
23
+
24
+ # A Python library for model predictive control.
25
+
26
+ A Python library for Model Predictive Control (MPC), integrating system modeling, state estimation, parameter identification, and Quadratic Programming (QP) based MPC solvers.
27
+
28
+ ## Requirements
29
+
30
+ - Python 3.9+ (Tested with Python 3.12)
31
+ - NumPy
32
+ - SciPy
33
+ - OSQP
34
+
35
+ ## Model predictive control
36
+
37
+ ### System Prediction Model
38
+
39
+ For discrete time-invariant systems:
40
+
41
+ $$
42
+ \begin{aligned}
43
+ x[n+1] &= A x[n] + B u[n] + w \\
44
+ y[n] &= C x[n] + v
45
+ \end{aligned}
46
+ $$
47
+
48
+ Prediction over horizon $N$:
49
+
50
+ $$
51
+ \begin{aligned}
52
+ X &= [x_1^T, x_2^T, \dots, x_N^T]^T \\
53
+ U &= [u_0^T, u_1^T, \dots, u_{N-1}^T]^T \\
54
+ Y &= [y_1^T, y_2^T, \dots, y_N^T]^T
55
+ \end{aligned}
56
+ $$
57
+
58
+ The predicted state and output sequences can be expressed as:
59
+
60
+ $$
61
+ \begin{aligned}
62
+ X &= M_x x_0 + M_u U + M_w w \\
63
+ Y &= \bar{C} X + V = \bar{C} M_x x_0 + \bar{C} M_u U + \bar{C} M_w w + V
64
+ \end{aligned}
65
+ $$
66
+
67
+ where $M_x$, $M_u$, and $M_w$ are block matrices defined as:
68
+
69
+ $$
70
+ M_x = \begin{bmatrix} A \\ A^2 \\ \cdots \\ A^N \end{bmatrix}
71
+ $$
72
+ $$
73
+ M_u = \begin{bmatrix}
74
+ B & 0 & \dots & 0 \\
75
+ AB & B & \dots & 0 \\
76
+ \vdots & \vdots & \ddots & \vdots \\
77
+ A^{N-1}B & A^{N-2}B & \dots & B
78
+ \end{bmatrix}
79
+ $$
80
+ $$
81
+ M_w = \begin{bmatrix}
82
+ I & 0 & \dots & 0 \\
83
+ A+I & I & \dots & 0 \\
84
+ \vdots & \vdots & \ddots & \vdots \\
85
+ \sum_{i=0}^{N-1} A^i & \sum_{i=0}^{N-2} A^i & \dots & I
86
+ \end{bmatrix}
87
+ $$
88
+
89
+ and $\bar{C}$ and $V$ are defined as:
90
+
91
+ $$
92
+ \bar{C} = \text{diag}(C, C, \dots, C), \quad
93
+ V = [v^T, v^T, \dots, v^T]^T
94
+ $$
95
+
96
+ ### Cost Function
97
+
98
+ The optimization objective is to minimize the cost function:
99
+
100
+ $$
101
+ J = (Y - Y_{ref})^T \bar{Q} (Y - Y_{ref}) + U^T \bar{R} U + \Delta U^T \bar{R}_{\Delta} \Delta U
102
+ $$
103
+
104
+ where $\bar{Q}$, $\bar{R}$, and $\bar{R}_{\Delta}$ are block-diagonal weighting matrices for output, control, and control delta respectively. The control delta is defined as:
105
+
106
+ $$
107
+ \Delta U = \bar{D} U - U_{last}
108
+ $$
109
+
110
+ where $U_{last} = [u_{-1}^T, 0, \dots, 0]^T$ ($u_{-1}$ is the previous control input), and $\bar{D}$ is the control delta matrix defined as:
111
+
112
+ $$
113
+ \bar{D} = \begin{bmatrix}
114
+ I & 0 & \dots & 0 \\
115
+ -I & I & \dots & 0 \\
116
+ 0 & -I & \dots & 0 \\
117
+ \vdots & \vdots & \ddots & \vdots \\
118
+ 0 & 0 & \dots & I
119
+ \end{bmatrix}
120
+ $$
121
+
122
+ ### QP Formulation
123
+
124
+ Let $E_y = \bar{C} M_x x_0 + \bar{C} M_w w + V - Y_{ref}$. Expanding the cost function and ignoring constant terms, we obtain:
125
+
126
+ $$
127
+ J = \frac{1}{2} U^T (2 M_u^T \bar{C}^T \bar{Q} \bar{C} M_u + 2 \bar{R} + 2 \bar{D}^T \bar{R}_{\Delta} \bar{D}) U + (2 M_u^T \bar{C}^T \bar{Q} E_y - 2 \bar{D}^T \bar{R}_{\Delta} U_{last})^T U
128
+ $$
129
+
130
+ This can be mapped to the standard OSQP form ($\min \frac{1}{2} U^T P U + q^T U$). The actual $P$ and $q$ computed in the code are (without the factor of 2):
131
+
132
+ $$
133
+ \begin{aligned}
134
+ P &= M_u^T \bar{C}^T \bar{Q} \bar{C} M_u + \bar{R} + \bar{D}^T \bar{R}_{\Delta} \bar{D} \\
135
+ q &= M_u^T \bar{C}^T \bar{Q} E_y - \bar{D}^T \bar{R}_{\Delta} U_{last}
136
+ \end{aligned}
137
+ $$
138
+
139
+ ### Constraints
140
+
141
+ The problem is subject to the following constraints:
142
+ - **Output constraints**: $l_{y} \leq \bar{C} M_u U + \bar{C} M_x x_0 + \bar{C} M_w w + V \leq u_{y}$
143
+ - **Control constraints**: $l_{u} \leq U \leq u_{u}$
144
+ - **Control rate constraints**: $l_{\Delta u} \leq \bar{D} U - U_{last} \leq u_{\Delta u}$
145
+
146
+ These linear constraints are compiled into the standard form $l \leq A_c U \leq u$ for the OSQP solver.
147
+
148
+ ### Nonlinear Systems
149
+
150
+ For nonlinear systems, the controller linearizes the system dynamics along a given reference trajectory. At each time step $i$ within the prediction horizon, the system is linearized around the reference state $x_{ref, i}$ and control $u_{ref, i}$ to obtain a linear time-varying (LTV) model:
151
+
152
+ $$
153
+ \begin{aligned}
154
+ x[i+1] &\approx A_i x[i] + B_i u[i] + w_i \\
155
+ y[i] &\approx C_i x[i] + v_i
156
+ \end{aligned}
157
+ $$
158
+
159
+ The QP problem is then formulated using these LTV matrices. The prediction matrices $M_x, M_u, M_w$ and the output mapping $\bar{C}$ become time-varying and are constructed iteratively over the horizon to reflect the changing linearization points. The reference trajectory for linearization can be provided to the solver via the `state_ref` and `control_ref` arguments.
160
+
161
+ ## Features
162
+
163
+ - **System Models (`mpc.discrete`)**: Supports discrete-time system modeling, including Linear Time-Invariant (LTI), Affine Time-Invariant (ATI), Nonlinear, and Homogeneous systems.
164
+ - **Model Predictive Control (`mpc.mpc`)**: Formulates and solves QP problems using the OSQP solver. Supports output, control, and control delta weighting, as well as constraints on output, control, and control rate.
165
+ - **State Estimation (`mpc.kalman`)**: Implements Extended Kalman Filter (EKF) and Unscented Kalman Filter (UKF) for state estimation of nonlinear systems.
166
+ - **Parameter Identification (`mpc.rls`)**: Provides Recursive Least Squares (RLS) algorithms for online system parameter identification.
167
+
168
+ ## Usage
169
+
170
+ Here is a basic example of how to define a system and solve an MPC problem:
171
+
172
+ ```python
173
+ import numpy as np
174
+ immport mpc_control as mpc
175
+
176
+ # 1. Define a discrete LTI system
177
+ # x[n+1] = A x[n] + B u[n]
178
+ # y[n] = C x[n]
179
+ system = mpc.LtiSystem(
180
+ transition_matrix=np.array([[1.0, 1.0],
181
+ [0.0, 1.0]]),
182
+ control_matrix=np.array([[0.0],
183
+ [1.0]]),
184
+ output_matrix=np.array([[1.0, 0.0]])
185
+ )
186
+
187
+ # 2. Initialize the MPC controller
188
+ horizon = 10
189
+ n_output = system.n_output
190
+ n_control = system.n_control
191
+
192
+ Q = np.stack([np.eye(n_output)] * horizon) # Output weighting
193
+ R = np.stack([np.eye(n_control) * 0.1] * horizon) # Control weighting
194
+
195
+ controller = mpc.Mpc(
196
+ system=system,
197
+ horizon=horizon,
198
+ output_weighting=Q,
199
+ control_weighting=R
200
+ )
201
+
202
+ # 3. Set up the problem and solve
203
+ target_output = np.zeros([horizon, n_output])
204
+ initial_state = np.array([1.0, 0.0])
205
+
206
+ u_optimal = controller.solve(
207
+ target_output=target_output,
208
+ initial_state=initial_state
209
+ )
210
+
211
+ print("Optimal control sequence:\n", u_optimal)
212
+ ```
@@ -0,0 +1,189 @@
1
+ # A Python library for model predictive control.
2
+
3
+ A Python library for Model Predictive Control (MPC), integrating system modeling, state estimation, parameter identification, and Quadratic Programming (QP) based MPC solvers.
4
+
5
+ ## Requirements
6
+
7
+ - Python 3.9+ (Tested with Python 3.12)
8
+ - NumPy
9
+ - SciPy
10
+ - OSQP
11
+
12
+ ## Model predictive control
13
+
14
+ ### System Prediction Model
15
+
16
+ For discrete time-invariant systems:
17
+
18
+ $$
19
+ \begin{aligned}
20
+ x[n+1] &= A x[n] + B u[n] + w \\
21
+ y[n] &= C x[n] + v
22
+ \end{aligned}
23
+ $$
24
+
25
+ Prediction over horizon $N$:
26
+
27
+ $$
28
+ \begin{aligned}
29
+ X &= [x_1^T, x_2^T, \dots, x_N^T]^T \\
30
+ U &= [u_0^T, u_1^T, \dots, u_{N-1}^T]^T \\
31
+ Y &= [y_1^T, y_2^T, \dots, y_N^T]^T
32
+ \end{aligned}
33
+ $$
34
+
35
+ The predicted state and output sequences can be expressed as:
36
+
37
+ $$
38
+ \begin{aligned}
39
+ X &= M_x x_0 + M_u U + M_w w \\
40
+ Y &= \bar{C} X + V = \bar{C} M_x x_0 + \bar{C} M_u U + \bar{C} M_w w + V
41
+ \end{aligned}
42
+ $$
43
+
44
+ where $M_x$, $M_u$, and $M_w$ are block matrices defined as:
45
+
46
+ $$
47
+ M_x = \begin{bmatrix} A \\ A^2 \\ \cdots \\ A^N \end{bmatrix}
48
+ $$
49
+ $$
50
+ M_u = \begin{bmatrix}
51
+ B & 0 & \dots & 0 \\
52
+ AB & B & \dots & 0 \\
53
+ \vdots & \vdots & \ddots & \vdots \\
54
+ A^{N-1}B & A^{N-2}B & \dots & B
55
+ \end{bmatrix}
56
+ $$
57
+ $$
58
+ M_w = \begin{bmatrix}
59
+ I & 0 & \dots & 0 \\
60
+ A+I & I & \dots & 0 \\
61
+ \vdots & \vdots & \ddots & \vdots \\
62
+ \sum_{i=0}^{N-1} A^i & \sum_{i=0}^{N-2} A^i & \dots & I
63
+ \end{bmatrix}
64
+ $$
65
+
66
+ and $\bar{C}$ and $V$ are defined as:
67
+
68
+ $$
69
+ \bar{C} = \text{diag}(C, C, \dots, C), \quad
70
+ V = [v^T, v^T, \dots, v^T]^T
71
+ $$
72
+
73
+ ### Cost Function
74
+
75
+ The optimization objective is to minimize the cost function:
76
+
77
+ $$
78
+ J = (Y - Y_{ref})^T \bar{Q} (Y - Y_{ref}) + U^T \bar{R} U + \Delta U^T \bar{R}_{\Delta} \Delta U
79
+ $$
80
+
81
+ where $\bar{Q}$, $\bar{R}$, and $\bar{R}_{\Delta}$ are block-diagonal weighting matrices for output, control, and control delta respectively. The control delta is defined as:
82
+
83
+ $$
84
+ \Delta U = \bar{D} U - U_{last}
85
+ $$
86
+
87
+ where $U_{last} = [u_{-1}^T, 0, \dots, 0]^T$ ($u_{-1}$ is the previous control input), and $\bar{D}$ is the control delta matrix defined as:
88
+
89
+ $$
90
+ \bar{D} = \begin{bmatrix}
91
+ I & 0 & \dots & 0 \\
92
+ -I & I & \dots & 0 \\
93
+ 0 & -I & \dots & 0 \\
94
+ \vdots & \vdots & \ddots & \vdots \\
95
+ 0 & 0 & \dots & I
96
+ \end{bmatrix}
97
+ $$
98
+
99
+ ### QP Formulation
100
+
101
+ Let $E_y = \bar{C} M_x x_0 + \bar{C} M_w w + V - Y_{ref}$. Expanding the cost function and ignoring constant terms, we obtain:
102
+
103
+ $$
104
+ J = \frac{1}{2} U^T (2 M_u^T \bar{C}^T \bar{Q} \bar{C} M_u + 2 \bar{R} + 2 \bar{D}^T \bar{R}_{\Delta} \bar{D}) U + (2 M_u^T \bar{C}^T \bar{Q} E_y - 2 \bar{D}^T \bar{R}_{\Delta} U_{last})^T U
105
+ $$
106
+
107
+ This can be mapped to the standard OSQP form ($\min \frac{1}{2} U^T P U + q^T U$). The actual $P$ and $q$ computed in the code are (without the factor of 2):
108
+
109
+ $$
110
+ \begin{aligned}
111
+ P &= M_u^T \bar{C}^T \bar{Q} \bar{C} M_u + \bar{R} + \bar{D}^T \bar{R}_{\Delta} \bar{D} \\
112
+ q &= M_u^T \bar{C}^T \bar{Q} E_y - \bar{D}^T \bar{R}_{\Delta} U_{last}
113
+ \end{aligned}
114
+ $$
115
+
116
+ ### Constraints
117
+
118
+ The problem is subject to the following constraints:
119
+ - **Output constraints**: $l_{y} \leq \bar{C} M_u U + \bar{C} M_x x_0 + \bar{C} M_w w + V \leq u_{y}$
120
+ - **Control constraints**: $l_{u} \leq U \leq u_{u}$
121
+ - **Control rate constraints**: $l_{\Delta u} \leq \bar{D} U - U_{last} \leq u_{\Delta u}$
122
+
123
+ These linear constraints are compiled into the standard form $l \leq A_c U \leq u$ for the OSQP solver.
124
+
125
+ ### Nonlinear Systems
126
+
127
+ For nonlinear systems, the controller linearizes the system dynamics along a given reference trajectory. At each time step $i$ within the prediction horizon, the system is linearized around the reference state $x_{ref, i}$ and control $u_{ref, i}$ to obtain a linear time-varying (LTV) model:
128
+
129
+ $$
130
+ \begin{aligned}
131
+ x[i+1] &\approx A_i x[i] + B_i u[i] + w_i \\
132
+ y[i] &\approx C_i x[i] + v_i
133
+ \end{aligned}
134
+ $$
135
+
136
+ The QP problem is then formulated using these LTV matrices. The prediction matrices $M_x, M_u, M_w$ and the output mapping $\bar{C}$ become time-varying and are constructed iteratively over the horizon to reflect the changing linearization points. The reference trajectory for linearization can be provided to the solver via the `state_ref` and `control_ref` arguments.
137
+
138
+ ## Features
139
+
140
+ - **System Models (`mpc.discrete`)**: Supports discrete-time system modeling, including Linear Time-Invariant (LTI), Affine Time-Invariant (ATI), Nonlinear, and Homogeneous systems.
141
+ - **Model Predictive Control (`mpc.mpc`)**: Formulates and solves QP problems using the OSQP solver. Supports output, control, and control delta weighting, as well as constraints on output, control, and control rate.
142
+ - **State Estimation (`mpc.kalman`)**: Implements Extended Kalman Filter (EKF) and Unscented Kalman Filter (UKF) for state estimation of nonlinear systems.
143
+ - **Parameter Identification (`mpc.rls`)**: Provides Recursive Least Squares (RLS) algorithms for online system parameter identification.
144
+
145
+ ## Usage
146
+
147
+ Here is a basic example of how to define a system and solve an MPC problem:
148
+
149
+ ```python
150
+ import numpy as np
151
+ immport mpc_control as mpc
152
+
153
+ # 1. Define a discrete LTI system
154
+ # x[n+1] = A x[n] + B u[n]
155
+ # y[n] = C x[n]
156
+ system = mpc.LtiSystem(
157
+ transition_matrix=np.array([[1.0, 1.0],
158
+ [0.0, 1.0]]),
159
+ control_matrix=np.array([[0.0],
160
+ [1.0]]),
161
+ output_matrix=np.array([[1.0, 0.0]])
162
+ )
163
+
164
+ # 2. Initialize the MPC controller
165
+ horizon = 10
166
+ n_output = system.n_output
167
+ n_control = system.n_control
168
+
169
+ Q = np.stack([np.eye(n_output)] * horizon) # Output weighting
170
+ R = np.stack([np.eye(n_control) * 0.1] * horizon) # Control weighting
171
+
172
+ controller = mpc.Mpc(
173
+ system=system,
174
+ horizon=horizon,
175
+ output_weighting=Q,
176
+ control_weighting=R
177
+ )
178
+
179
+ # 3. Set up the problem and solve
180
+ target_output = np.zeros([horizon, n_output])
181
+ initial_state = np.array([1.0, 0.0])
182
+
183
+ u_optimal = controller.solve(
184
+ target_output=target_output,
185
+ initial_state=initial_state
186
+ )
187
+
188
+ print("Optimal control sequence:\n", u_optimal)
189
+ ```
@@ -0,0 +1,21 @@
1
+ from .plant import Plant, LoggedPlant
2
+ from .kalman import Ekf, Ukf
3
+ from .rls import Rls
4
+ from .discrete import LtiSystem, AtiSystem, HomogeneousSystem, NonlinearSystem
5
+ from .mpc import Mpc
6
+
7
+
8
+ def _get_version() -> str:
9
+ """Try to get the installed package version.
10
+
11
+ If the package is not installed (e.g., running from source in
12
+ development mode), fall back to "dev".
13
+ """
14
+ from importlib.metadata import version, PackageNotFoundError
15
+ try:
16
+ return version("mpc-control")
17
+ except PackageNotFoundError:
18
+ return "dev"
19
+
20
+
21
+ __version__ = _get_version()