1212# Define the regularization types of `alpha`, considering
1313# with respect to what variable it is regularized
1414class AlphaRegType (Enum ):
15- # Alpha regularized w.r.t. an approximation of alpha_Lin^sr(D_t),
16- # based on Remark 1 of [2].
15+ """
16+ Regularization types for the `alpha` variable used in the formulation of
17+ Data-Driven MPC controllers for nonlinear systems.
18+
19+ Attributes:
20+ APPROXIMATED: Regularizes `alpha` with respect to an approximation of
21+ `alpha_Lin^sr(D_t)`. Based on Remark 1 of [2].
22+ PREVIOUS: Regularizes `alpha` with respect to the previous optimal
23+ alpha value to encourage stationary behavior. Refer to Section V of
24+ [2].
25+ ZERO: Regularizes `alpha` with respect to zero.
26+
27+ References:
28+ [2] J. Berberich, J. Köhler, M. A. Müller and F. Allgöwer, "Linear
29+ Tracking MPC for Nonlinear Systems—Part II: The Data-Driven Case," in
30+ IEEE Transactions on Automatic Control, vol. 67, no. 9, pp. 4406-4421,
31+ Sept. 2022, doi: 10.1109/TAC.2022.3166851.
32+ """
33+
1734 APPROXIMATED = 0
18- # Alpha regularized w.r.t. the previous optimal alpha value to
19- # encourage stationary behavior. Refer to Section V of [2].
2035 PREVIOUS = 1
21- # Alpha regularized w.r.t. zero.
2236 ZERO = 2
2337
2438
2539class NonlinearDataDrivenMPCController :
2640 """
2741 A class that implements a Data-Driven Model Predictive Control (MPC)
28- controller for Nonlinear systems. The implementation is based on research
42+ controller for nonlinear systems. The implementation is based on research
2943 by J. Berberich et al., as described in [2].
3044
3145 Attributes:
@@ -60,10 +74,15 @@ class NonlinearDataDrivenMPCController:
6074 lamb_sigma_s (float): The ridge regularization weight for
6175 `sigma_s` for a controller that uses an approximation of
6276 `alpha_Lin^sr(D_t)` for the regularization of `alpha`.
63- ext_out_incr_in (bool): The controller structure (uses an extended
64- output representation and input increments, or operates as a
65- standard controller with direct control inputs and without system
66- state extensions).
77+ ext_out_incr_in (bool): The controller structure:
78+
79+ - If `True`, the controller uses an extended output representation
80+ (y_ext[k] = [y[k], u[k]]) and input increments (u[k] = u[k-1] +
81+ du[k-1]).
82+ - If `False`, the controller operates as a standard controller with
83+ direct control inputs and without system state extensions.
84+
85+ Defaults to `False`.
6786 update_cost_threshold (float): The tracking cost value threshold.
6887 Online input-output data updates are disabled when the tracking
6988 cost value is less than this value.
@@ -137,9 +156,9 @@ class NonlinearDataDrivenMPCController:
137156
138157 References:
139158 [2] J. Berberich, J. Köhler, M. A. Müller and F. Allgöwer, "Linear
140- Tracking MPC for Nonlinear Systems—Part II: The Data-Driven Case,"
141- in IEEE Transactions on Automatic Control, vol. 67, no. 9, pp.
142- 4406-4421, Sept. 2022, doi: 10.1109/TAC.2022.3166851.
159+ Tracking MPC for Nonlinear Systems—Part II: The Data-Driven Case," in
160+ IEEE Transactions on Automatic Control, vol. 67, no. 9, pp. 4406-4421,
161+ Sept. 2022, doi: 10.1109/TAC.2022.3166851.
143162 """
144163
145164 def __init__ (
@@ -202,18 +221,22 @@ def __init__(
202221 single input.
203222 alpha_reg_type (AlphaRegType): The `alpha` regularization type
204223 for the Nonlinear Data-Driven MPC formulation.
205- lamb_alpha_s (float): The ridge regularization weight for
224+ lamb_alpha_s (float | None ): The ridge regularization weight for
206225 `alpha_s` for a controller that uses an approximation of
207226 `alpha_Lin^sr(D_t)` for the regularization of `alpha`.
208- lamb_sigma_s (float): The ridge regularization weight for
227+ lamb_sigma_s (float | None ): The ridge regularization weight for
209228 `sigma_s` for a controller that uses an approximation of
210229 `alpha_Lin^sr(D_t)` for the regularization of `alpha`.
211230 ext_out_incr_in (bool): The controller structure:
212- If `True`, the controller uses an extended output
213- representation (y_ext[k] = [y[k], u[k]]) and input increments
214- (u[k] = u[k-1] + du[k-1]). If `False`, the controller operates
215- as a standard controller with direct control inputs and
216- without system state extensions. Defaults to `False`.
231+
232+ - If `True`, the controller uses an extended output
233+ representation (y_ext[k] = [y[k], u[k]]) and input increments
234+ (u[k] = u[k-1] + du[k-1]).
235+ - If `False`, the controller operates as a standard controller
236+ with direct control inputs and without system state
237+ extensions.
238+
239+ Defaults to `False`.
217240 update_cost_threshold (float | None): The tracking cost value
218241 threshold. Online input-output data updates are disabled when
219242 the tracking cost value is less than this value. If `None`,
@@ -225,9 +248,9 @@ def __init__(
225248
226249 References:
227250 [2] J. Berberich, J. Köhler, M. A. Müller and F. Allgöwer, "Linear
228- Tracking MPC for Nonlinear Systems—Part II: The Data-Driven
229- Case," in IEEE Transactions on Automatic Control, vol. 67, no.
230- 9, pp. 4406-4421, Sept. 2022, doi: 10.1109/TAC.2022.3166851.
251+ Tracking MPC for Nonlinear Systems—Part II: The Data-Driven Case,"
252+ in IEEE Transactions on Automatic Control, vol. 67, no. 9, pp .
253+ 4406-4421, Sept. 2022, doi: 10.1109/TAC.2022.3166851.
231254 """
232255 # Define controller structure:
233256 # - If `True`: The controller uses an extended output representation
@@ -274,9 +297,10 @@ def __init__(
274297 self .Us = Us # Bounds for the predicted input setpoint
275298 # Note: Us must be a subset of U.
276299
277- # Alpha regularization type for Nonlinear MPC
300+ # Alpha regularization type
278301 self .alpha_reg_type = alpha_reg_type
279- # Nonlinear MPC parameters for the approximation of alpha_Lin^sr(D_t).
302+
303+ # Parameters for the approximation of alpha_Lin^sr(D_t).
280304 # Alpha is regularized w.r.t. this parameter, based on Remark 1
281305 # of [2].
282306 if alpha_reg_type == AlphaRegType .APPROXIMATED :
@@ -438,6 +462,7 @@ def initialize_data_driven_mpc(self) -> None:
438462 Initialize the Data-Driven MPC controller.
439463
440464 This method performs the following tasks:
465+
441466 1. Constructs Hankel matrices from the initial input-output trajectory
442467 data (`u`, `y`). These matrices are used for the data-driven
443468 characterization of the unknown system, as defined by the system
@@ -502,6 +527,7 @@ def update_and_solve_data_driven_mpc(
502527 and store the optimal control input.
503528
504529 This method performs the following tasks:
530+
505531 1. Constructs Hankel matrices using the latest measured input-output
506532 data. If the tracking cost value from the previous solution is
507533 small enough (less than `update_cost_threshold`), omits this step
@@ -809,23 +835,23 @@ def define_mpc_constraints(self) -> None:
809835
810836 This method defines the following constraints, as described in the
811837 Nonlinear Data-Driven MPC formulation in [2]:
838+
812839 - **System dynamics**: Ensures input-output predictions are possible
813- trajectories of the system based on a data-driven characterization
814- of all its input-output trajectories. Defined by Equation (22b).
840+ trajectories of the system based on a data-driven characterization of
841+ all its input-output trajectories. Defined by Equation (22b).
815842 - **Internal state**: Ensures predictions align with the internal
816- state of the system's trajectory. This constrains the first `n`
817- input-output predictions to match the past `n` input-output
818- measurements of the system, guaranteeing that the predictions
819- consider the initial state of the system. Defined by Equation
820- (22c).
843+ state of the system's trajectory. This constrains the first `n`
844+ input-output predictions to match the past `n` input-output
845+ measurements of the system, guaranteeing that the predictions
846+ consider the initial state of the system. Defined by Equation (22c).
821847 - **Terminal state**: Aims to stabilize the internal state of the
822- system so it aligns with the steady-state that corresponds to the
823- input-output equilibrium pair (predicted equilibrium setpoints
824- `u_s`, ` y_s`) in any minimal realization (last `n` input-output
825- predictions, as considered in [2]). Defined by Equation (22d).
848+ system so it aligns with the steady-state that corresponds to the
849+ input-output equilibrium pair (predicted equilibrium setpoints `u_s`,
850+ ` y_s`) in any minimal realization (last `n` input-output predictions,
851+ as considered in [2]). Defined by Equation (22d).
826852 - **Input**: Constrains both the equilibrium input (predicted input
827- setpoint `u_s`) and the input trajectory (`ubar`). Defined by
828- Equation (22e).
853+ setpoint `u_s`) and the input trajectory (`ubar`). Defined by
854+ Equation (22e).
829855
830856 Note:
831857 This method initializes the `dynamics_constraints`,
@@ -867,8 +893,8 @@ def define_system_dynamic_constraints(self) -> list[cp.Constraint]:
867893
868894 Returns:
869895 list[cp.Constraint]: A list containing the CVXPY system dynamic
870- constraints for the Data-Driven MPC controller, corresponding
871- to the specified MPC controller type.
896+ constraints for the Data-Driven MPC controller, corresponding to
897+ the specified MPC controller type.
872898
873899 References:
874900 [2]: See class-level docstring for full reference details.
@@ -904,7 +930,7 @@ def define_internal_state_constraints(self) -> list[cp.Constraint]:
904930
905931 Returns:
906932 list[cp.Constraint]: A list containing the CVXPY internal state
907- constraints for the Data-Driven MPC controller.
933+ constraints for the Data-Driven MPC controller.
908934
909935 Note:
910936 It is essential to update the system's input-output measurements,
@@ -941,7 +967,7 @@ def define_terminal_state_constraints(self) -> list[cp.Constraint]:
941967
942968 Returns:
943969 list[cp.Constraint]: A list containing the CVXPY terminal state
944- constraints for the Data-Driven MPC controller.
970+ constraints for the Data-Driven MPC controller.
945971
946972 References:
947973 [2]: See class-level docstring for full reference details.
@@ -968,7 +994,7 @@ def define_input_constraints(self) -> list[cp.Constraint]:
968994
969995 Returns:
970996 list[cp.Constraint]: A list containing the CVXPY input constraints
971- for the Data-Driven MPC controller.
997+ for the Data-Driven MPC controller.
972998 """
973999 # Define input constraints
9741000 if self .ext_out_incr_in :
@@ -1063,8 +1089,8 @@ def solve_mpc_problem(self, warm_start: bool = False) -> str:
10631089
10641090 Returns:
10651091 str: The status of the optimization problem after attempting to
1066- solve it (e.g., "optimal", "optimal_inaccurate", "infeasible",
1067- "unbounded").
1092+ solve it (e.g., "optimal", "optimal_inaccurate", "infeasible",
1093+ "unbounded").
10681094
10691095 Note:
10701096 This method assumes that the MPC problem has already been defined.
@@ -1082,8 +1108,8 @@ def get_problem_solve_status(self) -> str:
10821108
10831109 Returns:
10841110 str: The status of the optimization problem after attempting to
1085- solve it (e.g., "optimal", "optimal_inaccurate", "infeasible",
1086- "unbounded").
1111+ solve it (e.g., "optimal", "optimal_inaccurate", "infeasible",
1112+ "unbounded").
10871113 """
10881114 return self .problem .status
10891115
@@ -1094,7 +1120,7 @@ def get_optimal_cost_value(self) -> float:
10941120
10951121 Returns:
10961122 float: The optimal cost value of the solved MPC optimization
1097- problem.
1123+ problem.
10981124 """
10991125 return self .problem .value
11001126
@@ -1105,9 +1131,9 @@ def get_optimal_control_input(self) -> np.ndarray:
11051131
11061132 Returns:
11071133 np.ndarray: The predicted optimal control input from time step 0
1108- to L. If the controller uses an extended output representation
1109- and input increments, returns the predicted optimal control
1110- input increments instead.
1134+ to L. If the controller uses an extended output representation and
1135+ input increments, returns the predicted optimal control input
1136+ increments instead.
11111137
11121138 Raises:
11131139 ValueError: If the MPC problem solution status was not "optimal"
@@ -1152,7 +1178,7 @@ def get_optimal_control_input_at_step(self, n_step: int = 0) -> np.ndarray:
11521178
11531179 Returns:
11541180 np.ndarray: An array containing the optimal control input for the
1155- specified prediction time step.
1181+ specified prediction time step.
11561182
11571183 Note:
11581184 This method assumes that the optimal control input from the MPC
@@ -1214,9 +1240,9 @@ def get_du_value_at_step(self, n_step: int = 0) -> np.ndarray | None:
12141240
12151241 Returns:
12161242 np.ndarray | None: An array containing the optimal control
1217- input increment for the specified prediction time step if the
1218- controller uses an extended output representation and input
1219- increments. Otherwise, returns `None`.
1243+ input increment for the specified prediction time step if the
1244+ controller uses an extended output representation and input
1245+ increments. Otherwise, returns `None`.
12201246
12211247 Note:
12221248 This method assumes that the `optimal_du` attribute contains the
@@ -1250,9 +1276,9 @@ def store_input_output_measurement(
12501276 time step, expected to match the dimensions of prior outputs.
12511277 This output should correspond to the system's response to
12521278 `u_current`, as both represent a trajectory of the system.
1253- du_current (np.ndarray): The control input increment (du[k] =
1254- u[k+1] - u[k]) for the current time step, expected to match
1255- the dimensions of prior inputs.
1279+ du_current (np.ndarray | None ): The control input increment
1280+ (du[k] = u[k+1] - u[k]) for the current time step, expected to
1281+ match the dimensions of prior inputs.
12561282
12571283 Raises:
12581284 ValueError: If `u_current`, `y_current`, or `du_current` do not
0 commit comments