Source code for direct_data_driven_mpc.utilities.controller.controller_creation

"""
Functions for creating data-driven MPC controllers.

This module provides functions to create data-driven MPC controllers for both
LTI and nonlinear systems using controller configurations and initial
input-output measurement data.
"""

import numpy as np

from direct_data_driven_mpc.lti_data_driven_mpc_controller import (
    LTIDataDrivenMPCController,
)
from direct_data_driven_mpc.nonlinear_data_driven_mpc_controller import (
    NonlinearDataDrivenMPCController,
)
from direct_data_driven_mpc.utilities.controller.controller_params import (
    LTIDataDrivenMPCParams,
    NonlinearDataDrivenMPCParams,
)


[docs] def create_lti_data_driven_mpc_controller( controller_config: LTIDataDrivenMPCParams, u_d: np.ndarray, y_d: np.ndarray, use_terminal_constraints: bool = True, ) -> LTIDataDrivenMPCController: """ Create an `LTIDataDrivenMPCController` instance using a specified Data-Driven MPC controller configuration and initial input-output trajectory data measured from a system. Args: controller_config (LTIDataDrivenMPCParams): A dictionary containing configuration parameters for a Data-Driven MPC controller designed for Linear Time-Invariant (LTI) systems. u_d (np.ndarray): An array of shape `(N, m)` representing a persistently exciting input sequence used to generate output data from the system. `N` is the trajectory length and `m` is the number of control inputs. y_d (np.ndarray): An array of shape `(N, p)` representing the system's output response to `u_d`. `N` is the trajectory length and `p` is the number of system outputs. use_terminal_constraints (bool): If `True`, include terminal equality constraints in the Data-Driven MPC formulation. If `False`, the controller will not enforce these constraints. Defaults to `True`. Returns: LTIDataDrivenMPCController: An `LTIDataDrivenMPCController` instance, which represents a Data-Driven MPC controller designed for Linear Time-Invariant (LTI) systems, based on the specified configuration. """ # Get model parameters from input-output trajectory data m = u_d.shape[1] # Number of inputs p = y_d.shape[1] # Number of outputs # Retrieve Data-Driven MPC controller parameters n = controller_config["n"] # Estimated system order L = controller_config["L"] # Prediction horizon Q = controller_config["Q"] # Output weighting matrix R = controller_config["R"] # Input weighting matrix u_s = controller_config["u_s"] # Control input setpoint y_s = controller_config["y_s"] # System output setpoint # Estimated upper bound of the system measurement noise eps_max = controller_config["eps_max"] # Ridge regularization base weight for `alpha` (scaled by `eps_max`) lamb_alpha = controller_config["lamb_alpha"] # Ridge regularization weight for sigma lamb_sigma = controller_config["lamb_sigma"] U = controller_config["U"] # Bounds for the predicted input # Convex slack variable constraint constant c = controller_config["c"] # Slack variable constraint type slack_var_constraint_type = controller_config["slack_var_constraint_type"] # Data-Driven MPC controller type controller_type = controller_config["controller_type"] # n-Step Data-Driven MPC Scheme parameters # Number of consecutive applications of the optimal input n_mpc_step = controller_config["n_mpc_step"] # Create Data-Driven MPC controller lti_data_driven_mpc_controller = LTIDataDrivenMPCController( n=n, m=m, p=p, u_d=u_d, y_d=y_d, L=L, Q=Q, R=R, u_s=u_s, y_s=y_s, eps_max=eps_max, lamb_alpha=lamb_alpha, lamb_sigma=lamb_sigma, U=U, c=c, slack_var_constraint_type=slack_var_constraint_type, controller_type=controller_type, n_mpc_step=n_mpc_step, use_terminal_constraints=use_terminal_constraints, ) return lti_data_driven_mpc_controller
[docs] def create_nonlinear_data_driven_mpc_controller( controller_config: NonlinearDataDrivenMPCParams, u: np.ndarray, y: np.ndarray, ) -> NonlinearDataDrivenMPCController: """ Create a `NonlinearDataDrivenMPCController` instance using a specified Data-Driven MPC controller configuration and initial input-output trajectory data measured from a system. Args: controller_config (NonlinearDataDrivenMPCParams): A dictionary containing configuration parameters for a Data-Driven MPC controller designed for nonlinear systems. u (np.ndarray): An array of shape `(N, m)` representing a persistently exciting input sequence used to generate output data from the system. `N` is the trajectory length and `m` is the number of control inputs. y (np.ndarray): An array of shape `(N, p)` representing the system's output response to `u`. `N` is the trajectory length and `p` is the number of system outputs. Returns: NonlinearDataDrivenMPCController: A `NonlinearDataDrivenMPCController` instance, which represents a Data-Driven MPC controller designed for nonlinear systems, based on the specified configuration. """ # Get model parameters from input-output trajectory data m = u.shape[1] # Number of inputs p = y.shape[1] # Number of outputs # Retrieve Data-Driven MPC controller parameters n = controller_config["n"] # Estimated system order L = controller_config["L"] # Prediction horizon Q = controller_config["Q"] # Output weighting matrix R = controller_config["R"] # Input weighting matrix S = controller_config["S"] # Output setpoint weighting matrix # Ridge regularization weight for alpha lamb_alpha = controller_config["lamb_alpha"] # Ridge regularization weight for sigma lamb_sigma = controller_config["lamb_sigma"] # Bounds for the predicted input U = controller_config["U"] # Bounds for the predicted input setpoint Us = controller_config["Us"] # Alpha regularization type alpha_reg_type = controller_config["alpha_reg_type"] # Nonlinear MPC parameters for alpha_reg_type = 0 (Approximated) # Ridge regularization weight for alpha_s lamb_alpha_s = controller_config["lamb_alpha_s"] # Ridge regularization weight for sigma_s lamb_sigma_s = controller_config["lamb_sigma_s"] # System Output setpoint y_r = controller_config["y_r"] # Extended Output Representation and Incremental Input ext_out_incr_in = controller_config["ext_out_incr_in"] # Tracking cost value threshold update_cost_threshold = controller_config["update_cost_threshold"] # n-Step Data-Driven MPC Scheme parameters # Number of consecutive applications of the optimal input n_mpc_step = controller_config["n_mpc_step"] # Create Data-Driven MPC controller nonlinear_data_driven_mpc_controller = NonlinearDataDrivenMPCController( n=n, m=m, p=p, u=u, y=y, L=L, Q=Q, R=R, S=S, y_r=y_r, lamb_alpha=lamb_alpha, lamb_sigma=lamb_sigma, U=U, Us=Us, lamb_alpha_s=lamb_alpha_s, lamb_sigma_s=lamb_sigma_s, alpha_reg_type=alpha_reg_type, ext_out_incr_in=ext_out_incr_in, update_cost_threshold=update_cost_threshold, n_mpc_step=n_mpc_step, ) return nonlinear_data_driven_mpc_controller