LinearModel#

class LinearModel(model_type=None, symvar_type='SX')[source]#

Bases: Model

The do-mpc LinearModel class. This class is inherited from do-mpc model class. This class holds the full model description and is at the core of do_mpc.simulator.Simulator, do_mpc.controller.MPC, do_mpc.controller.LQR and do_mpc.estimator.Estimator. This class can be used to define the linear time invariant models in both continuous and discrete time. The LinearModel class is created with setting the model_type (continuous or discrete).

A continous linear model consists of an underlying ordinary differential equation (ODE)

\[\begin{split}\dot{x}(t) &= Ax(t)+Bu(t),\\ y &= Cx(t)+Du(t)\end{split}\]

whereas a discrete linear model consists of a difference equation.

\[\begin{split} x_{k+1} &= Ax_k+Bu_k,\\ y_k &= Cx_k+Du_k\end{split}\]

The do-mpc linear model can be initiated with SX variable type.

Note

The option symvar_type will be inherited to all derived classes (e.g. do_mpc.simulator.Simulator, do_mpc.controller.MPC and do_mpc.estimator.Estimator). All symbolic variables in these classes will be chosen respectively.

Configuration and setup: Configuring and setting up the LinearModel involves the following steps:

Model can be setup in two different ways. The first method is as follows:

  1. Use set_variable() to introduce new variables to the linear model.

  2. Optionally introduce “auxiliary” expressions as functions of the previously defined variables with set_expression(). The expressions can be used for monitoring or be reused as constraints, the cost function etc.

  3. Optionally introduce measurement equations with set_meas(). The syntax is identical to set_expression(). By default state-feedback is assumed.

  4. Define the right-hand-side of the discrete or continuous model as a function of the previously defined variables with set_rhs(). This method must be called once for each introduced state.

  5. Call setup() to finalize the LinearModel. No further changes are possible afterwards.

The second method is as follows:

  1. Use set_variable() to introduce new variables to the linear model.

  2. Optionally introduce “auxiliary” expressions as functions of the previously defined variables with set_expression(). The expressions can be used for monitoring or be reused as constraints, the cost function etc.

  3. Call setup() and pass the system dynamics matrices as arguments instead of setting up the right hand side equations and measurement equations to finalize the LinearModel. No further changes are possible afterwards.

Note

All introduced model variables are accessible as Attributes of the Model. Use these attributes to query to variables, e.g. to form the cost function in a seperate file for the MPC configuration.

Parameters:
  • model_type (str) – Set if the model is discrete or continuous.

  • symvar_type (str) – Set if the model is configured with CasADi SX variables (default).

Raises:
  • assertion – model_type must be string

  • assertion – model_type must be either discrete or continuous

__getitem__(ind)#

The Model class supports the __getitem__ method, which can be used to retrieve the model variables (see attribute list).

# Query the states like this:
x = model.x
# or like this:
x = model['x']

This also allows to retrieve multiple variables simultaneously:

x, u, z = model['x','u','z']

Methods#

discretize#

discretize(self, t_step=0, conv_method='zoh')#

Converts continuous time to discrete time system.

This method utilizes the exisiting function in scipy library called cont2discrete to convert continuous time to discrete time system.This method allows the user to specify the type of discretization. For more details about the function click here .

where \(A_{\text{discrete}}\) and \(B_{\text{discrete}}\) are the discrete state matrix and input matrix repectively and \(t_{\text{sample}}\) is the sampling time.

Warning

sampling time is zero when not specified or not required

Parameters:
  • t_step (Union[float, int]) – Sampling time (default - 0)

  • conv_method (str) – Method of discretization - Five different methods can be applied. (default -‘zoh’)

Returns:

LinearModel – Discretized linear model

get_linear_system_matrices#

get_linear_system_matrices(self, xss=None, uss=None, z=None, tvp=None, p=None)#

Returns the matrix quadrupel \((A,B,C,D)\) of the linearized system around the operating point (xss,uss,z,tvp,p,w,v). All arguments are optional in which case the matrices might still be symbolic. If the matrices are not symbolic, they are returned as numpy arrays.

Parameters:
  • xss (ndarray) – Steady state state

  • uss (ndarray) – Steady state input

  • z (ndarray) – Steady state algebraic states

  • tvp (ndarray) – time varying parameters set point

  • p (ndarray) – parameters set point

Returns:

Union[Tuple[SX, SX, SX, SX], Tuple[ndarray, ndarray, ndarray, ndarray]] – State matrix, Input matrix, Output matrix, Feedforward matrix

get_steady_state#

get_steady_state(self, xss=None, uss=None)#

Calculates steady states for the given input or states.

This method calculates steady states of a discrete system for the given steady state input and vice versa. The mathematical formulation can be described as:

\[x_{ss} = (I-A)^{-1}Bu_{ss}\]

or

\[u_{ss} = B^{-1}(I-A)x_{ss}\]
Parameters:
  • xss (ndarray) – Steady state State values

  • uss (ndarray) – Steady state Input values

Returns:

ndarray – Steady state state or Steady state input

set_alg#

set_alg(self, expr_name, expr, *args, **kwargs)#

Warning

This method is not supported for linear models.

set_expression#

set_expression(self, expr_name, expr)#

Introduce new expression to the model class. Expressions are not required but can be used to extract further information from the model. Expressions must be formulated with respect to _x, _u, _z, _tvp, _p.

Example:

Maybe you are interested in monitoring the product of two states?

Introduce two scalar states:
x_1 = model.set_variable('_x', 'x_1')
x_2 = model.set_variable('_x', 'x_2')

# Introduce expression:
model.set_expression('x1x2', x_1*x_2)

This new expression x1x2 is then available in all do-mpc modules utilizing this model instance. It can be set, e.g. as the cost function in do_mpc.controller.MPC or simply used in a graphical representation of the simulated / controlled system.

Parameters:
  • expr_name (str) – Arbitrary name for the given expression. Names are used for key word indexing.

  • expr (Union[SX, MX]) – CasADi SX or MX function depending on _x, _u, _z, _tvp, _p.

Raises:
  • assertion – expr_name must be str

  • assertion – expr must be a casadi SX or MX type

  • assertion – Cannot call after setup().

Returns:

Union[SX, MX] – Returns the newly created expression. Expression can be used e.g. for the RHS.

set_meas#

set_meas(self, name, meas)#

Checks if the measurement function is linear and calls Model.set_meas().

Parameters:
  • name (str) – Arbitrary name for the given expression. Names are used for key word indexing.

  • meas (SX) – CasADi SX function depending on _x, _u, _tvp, _p.

Return type:

None

set_rhs#

set_rhs(self, name, rhs)#

Checks if the right-hand-side function is linear and calls Model.set_rhs().

Parameters:
  • name (str) – Reference to previously introduced state names (with LinearModel.set_variable())

  • rhs (SX) – CasADi SX function depending on _x, _u, _tvp, _p.

Return type:

None

set_variable#

set_variable(self, var_type, var_name, shape=(1, 1))#

Introduce new variables to the model class. Define variable type, name and shape (optional).

Example:

# States struct (optimization variables):
C_a = model.set_variable(var_type='_x', var_name='C_a', shape=(1,1))
T_K = model.set_variable(var_type='_x', var_name='T_K', shape=(1,1))

# Input struct (optimization variables):
Q_dot = model.set_variable(var_type='_u', var_name='Q_dot')

# Fixed parameters:
alpha = model.set_variable(var_type='_p', var_name='alpha')

Note

var_type allows a shorthand notation e.g. _x which is equivalent to states.

Parameters:
  • var_type (str) – Declare the type of the variable.

  • var_name (str) – Set a user-defined name for the parameter. The names are reused throughout do_mpc.

  • shape (Union[int, Tuple]) – Shape of the current variable (optional), defaults to 1.

The following types of var_type are valid (long or short name is possible):

Long name

short name

Remark

states

_x

Required

inputs

_u

optional

algebraic

_z

Optional

parameter

_p

Optional

timevarying_parameter

_tvp

Optional

Raises:
  • assertionvar_type must be string

  • assertionvar_name must be string

  • assertionshape must be tuple or int

  • assertion – Cannot call after setup().

Returns:

Union[SX, MX] – Returns the newly created symbolic variable.

setup#

setup(self, A=None, B=None, C=None, D=None)#

Setup method must be called to finalize the modelling process. All required model variables must be declared. The right hand side expression for _x can be set with set_rhs() or can be set by passing the state matrix and input matrix in setup().

Sets default measurement function (state feedback) if set_meas() was not called or output matrix, feedforward matrix are not passed in setup().

Warning

After calling setup(), the model is locked and no further variables, expressions etc. can be set.

Raises:

assertion – Definition of right hand side (rhs) is incomplete

Parameters:
  • A (ndarray) – State matrix (optional)

  • B (ndarray) – Input matrix (optional)

  • C (ndarray) – Output matrix (optional)

  • D (ndarray) – Feedforward matrix (optional)

Return type:

None

Attributes#

aux#

LinearModel.aux#

Auxiliary expressions. CasADi symbolic structure, can be indexed with user-defined variable names.

Note

Expressions are introduced with Model.set_expression() Use this property only to query variables.

Example:

model = do_mpc.model.Model('continuous')
model.set_variable('_x','temperature', 4) # 4 states
dt = model.x['temperature',0]- model.x['temperature', 1]
model.set_expression('dtemp', dt)
# Query:
model.aux['dtemp', 0] # 0th element of variable
model.aux['dtemp']    # all elements of variable

Useful CasADi symbolic structure methods:

  • .shape

  • .keys()

  • .labels()

Raises:

assertion – Cannot set aux directly Use set_expression instead.

p#

LinearModel.p#

Static parameters. CasADi symbolic structure, can be indexed with user-defined variable names.

Note

Variables are introduced with Model.set_variable() Use this property only to query variables.

Example:

model = do_mpc.model.Model('continuous')
model.set_variable('_p','temperature', shape=(4,1))
# Query:
model.p['temperature', 0] # 0th element of variable
model.p['temperature']    # all elements of variable
model.p['temperature', 0:2]    # 0th and 1st element

Useful CasADi symbolic structure methods:

  • .shape

  • .keys()

  • .labels()

Raises:

assertion – Cannot set model variables directly Use set_variable instead.

sys_A#

LinearModel.sys_A#

State matrix. This property provides the state matrix in the numerical array format. Accessible only after model is setup.

sys_B#

LinearModel.sys_B#

Input matrix. This property provides the input matrix in the numerical array format. Accessible only after model is setup.

sys_C#

LinearModel.sys_C#

Output matrix. This property provides the output matrix in the numerical array format. Accessible only after model is setup.

sys_D#

LinearModel.sys_D#

Feedforward matrix. This property provides the feedforward matrix in the numerical array format. Accessible only after model is setup.

tvp#

LinearModel.tvp#

Time-varying parameters. CasADi symbolic structure, can be indexed with user-defined variable names.

Note

Variables are introduced with Model.set_variable() Use this property only to query variables.

Example:

model = do_mpc.model.Model('continuous')
model.set_variable('_tvp','temperature', shape=(4,1))
# Query:
model.tvp['temperature', 0] # 0th element of variable
model.tvp['temperature']    # all elements of variable
model.tvp['temperature', 0:2]    # 0th and 1st element

Useful CasADi symbolic structure methods:

  • .shape

  • .keys()

  • .labels()

Raises:

assertion – Cannot set model variables directly Use set_variable instead.

u#

LinearModel.u#

Inputs. CasADi symbolic structure, can be indexed with user-defined variable names.

Note

Variables are introduced with Model.set_variable() Use this property only to query variables.

Example:

model = do_mpc.model.Model('continuous')
model.set_variable('_u','heating', shape=(4,1))
# Query:
model.u['heating', 0] # 0th element of variable
model.u['heating']    # all elements of variable
model.u['heating', 0:2]    # 0th and 1st element

Useful CasADi symbolic structure methods:

  • .shape

  • .keys()

  • .labels()

Raises:

assertion – Cannot set model variables directly Use set_variable instead.

v#

LinearModel.v#

Measurement noise. CasADi symbolic structure, can be indexed with user-defined variable names.

The measurement noise structure is created automatically, whenever the Model.set_meas() method is called with the argument meas_noise = True.

Note

The measurement noise is used for the do_mpc.estimator.MHE and can be used to simulate a disturbed system in the do_mpc.simulator.Simulator.

Useful CasADi symbolic structure methods:

  • .shape

  • .keys()

  • .labels()

Raises:

assertion – Cannot set v directly

w#

LinearModel.w#

Process noise. CasADi symbolic structure, can be indexed with user-defined variable names.

The process noise structure is created automatically, whenever the Model.set_rhs() method is called with the argument process_noise = True.

Note

The process noise is used for the do_mpc.estimator.MHE and can be used to simulate a disturbed system in the do_mpc.simulator.Simulator.

Useful CasADi symbolic structure methods:

  • .shape

  • .keys()

  • .labels()

Raises:

assertion – Cannot set w directly

x#

LinearModel.x#

Dynamic states. CasADi symbolic structure, can be indexed with user-defined variable names.

Note

Variables are introduced with Model.set_variable() Use this property only to query variables.

Example:

model = do_mpc.model.Model('continuous')
model.set_variable('_x','temperature', shape=(4,1))
# Query:
model.x['temperature', 0] # 0th element of variable
model.x['temperature']    # all elements of variable
model.x['temperature', 0:2]    # 0th and 1st element

Useful CasADi symbolic structure methods:

  • .shape

  • .keys()

  • .labels()

Raises:

assertion – Cannot set model variables directly Use set_variable instead.

y#

LinearModel.y#

Measurements. CasADi symbolic structure, can be indexed with user-defined variable names.

Note

Measured variables are introduced with Model.set_meas() Use this property only to query variables.

Example:

model = do_mpc.model.Model('continuous')
model.set_variable('_x','temperature', 4) # 4 states
model.set_meas('temperature', model.x['temperature',:2]) # first 2 measured
# Query:
model.y['temperature', 0] # 0th element of variable
model.y['temperature']    # all elements of variable

Useful CasADi symbolic structure methods:

  • .shape

  • .keys()

  • .labels()

Raises:

assertion – Cannot set model variables directly Use set_meas instead.

z#

LinearModel.z#

Algebraic states. CasADi symbolic structure, can be indexed with user-defined variable names.

Note

Variables are introduced with Model.set_variable() Use this property only to query variables.

Example:

model = do_mpc.model.Model('continuous')
model.set_variable('_z','temperature', shape=(4,1))
# Query:
model.z['temperature', 0] # 0th element of variable
model.z['temperature']    # all elements of variable
model.z['temperature', 0:2]    # 0th and 1st element

Useful CasADi symbolic structure methods:

  • .shape

  • .keys()

  • .labels()

Raises:

assertion – Cannot set model variables directly Use set_variable instead.