Model#
- class Model(model_type=None, symvar_type='SX')[source]#
Bases:
object
The 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
anddo_mpc.estimator.Estimator
. TheModel
class is created with setting themodel_type
(continuous or discrete). Acontinous
model consists of an underlying ordinary differential equation (ODE) or differential algebraic equation (DAE):\[\begin{split}\dot{x}(t) &= f(x(t),u(t),z(t),p(t),p_{\text{tv}}(t)) + w(t),\\ 0 &= g(x(t),u(t),z(t),p(t),p_{\text{tv}}(t))\\ y &= h(x(t),u(t),z(t),p(t),p_{\text{tv}}(t)) + v(t)\end{split}\]whereas a
discrete
model consists of a difference equation:\[\begin{split}x_{k+1} &= f(x_k,u_k,z_k,p_k,p_{\text{tv},k}) + w_k,\\ 0 &= g(x_k,u_k,z_k,p_k,p_{\text{tv},k})\\ y_k &= h(x_k,u_k,z_k,p_k,p_{\text{tv},k}) + v_k\end{split}\]The do-mpc model can be initiated with either
SX
orMX
variable type. We refer to the CasADi documentation on the difference of these two types.Note
SX
vs.MX
in a nutshell: In general useSX
variables (default). If your model consists of scalar operationsSX
variables will be beneficial. Your implementation will most likely only benefit fromMX
variables if you use large(r)-scale matrix-vector multiplications.Note
The option
symvar_type
will be inherited to all derived classes (e.g.do_mpc.simulator.Simulator
,do_mpc.controller.MPC
anddo_mpc.estimator.Estimator
). All symbolic variables in these classes will be chosen respectively.Configuration and setup:
Configuring and setting up the
Model
involves the following steps:Use
set_variable()
to introduce new variables to the model.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.Optionally introduce measurement equations with
set_meas()
. The syntax is identical toset_expression()
. By default state-feedback is assumed.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.Call
setup()
to finalize theModel
. 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 isdiscrete
orcontinuous
.symvar_type (
str
) – Set if the model is configured with CasADiSX
orMX
variables.
- Raises:
assertion – model_type must be string
assertion – model_type must be either discrete or continuous
- __getitem__(ind)[source]#
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#
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 stateuss (
ndarray
) – Steady state inputz (
ndarray
) – Steady state algebraic statestvp (
ndarray
) – time varying parameters set pointp (
ndarray
) – parameters set point
- Returns:
Union
[Tuple
[SX
,SX
,SX
,SX
],Tuple
[ndarray
,ndarray
,ndarray
,ndarray
]] – State matrix, Input matrix, Output matrix, Feedforward matrix
set_alg#
- set_alg(self, expr_name, expr)#
Introduce new algebraic equation to model.
For the continous time model, the expression must be formulated as
\[0 = g(x(t),u(t),z(t),p(t),p_{\text{tv}}(t))\]or for a
discrete
model:\[0 = g(x_k,u_k,z_k,p_k,p_{\text{tv},k})\]Note
For the introduced algebraic variables \(z \in \mathbb{R}^{n_z}\) it is required to introduce exactly \(n_z\) algebraic equations. Otherwise
setup()
will throw an error message.- Parameters:
expr_name (
str
) – Name of the introduced expressionexpr (
Union
[SX
,MX
]) – CasADi SX or MX function depending on_x
,_u
,_z
,_tvp
,_p
.
- Return type:
None
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 indo_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, meas_name, expr, meas_noise=True)#
Introduce new measurable output to the model class.
\[y = h(x(t),u(t),z(t),p(t),p_{\text{tv}}(t)) + v(t)\]or in case of discrete dynamics:
\[y_k = h(x_k,u_k,z_k,p_k,p_{\text{tv},k}) + v_k\]By default, the model assumes state-feedback (all states are measured outputs). Expressions must be formulated with respect to
_x
,_u
,_z
,_tvp
,_p
.Be default, it is assumed that the measurements experience additive noise \(v_k\). This can be deactivated for individual measured variables by changing the boolean variable
meas_noise
toFalse
. Note that measurement noise is only meaningful for state-estimation and will not affect the controller. Furthermore, it can be set with eachdo_mpc.simulator.Simulator
call to obtain imperfect outputs.Note
For moving horizon estimation it is suggested to declare all inputs (
_u
) and e.g. a subset of states (_x
) as measurable output. Some other MHE formulations treat inputs separately.Note
It is often suggested to deactivate measurement noise for “measured” inputs (
_u
). These can typically seen as certain variables.Example:
# Introduce states: x_meas = model.set_variable('_x', 'x', 3) # 3 measured states (vector) x_est = model.set_variable('_x', 'x', 3) # 3 estimated states (vector) # and inputs: u = model.set_variable('_u', 'u', 2) # 2 inputs (vector) # define measurements: model.set_meas('x_meas', x_meas) model.set_meas('u', u)
- Parameters:
meas_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
.meas_noise (
bool
) – Set if the measurement equation is disturbed by additive noise.
- 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 measurement expression.
set_rhs#
- set_rhs(self, var_name, expr, process_noise=False)#
Formulate the right hand side (rhs) of the ODE:
\[\dot{x}(t) = f(x(t),u(t),z(t),p(t),p_{\text{tv}}(t)) + w(t),\]or the update equation in case of discrete dynamics:
\[x_{k+1} = f(x_k,u_k,z_k,p_k,p_{\text{tv},k}) + w_k,\]Each defined state variable must have a respective equation (of matching dimension) for the rhs. Match the rhs with the state by choosing the corresponding names. rhs must be formulated with respect to
_x
,_u
,_z
,_tvp
,_p
.Example:
tank_level = model.set_variable('states', 'tank_level') tank_temp = model.set_variable('states', 'tank_temp') tank_level_next = 0.5*tank_level tank_temp_next = ... model.set_rhs('tank_level', tank_level_next) model.set_rhs('tank_temp', tank_temp_next)
Optionally, set
process_noise = True
to introduce an additive process noise variable. This is meaningful for thedo_mpc.estimator.MHE
(Seedo_mpc.estimator.MHE.set_default_objective()
for more details). Furthermore, it can be set with eachdo_mpc.simulator.Simulator
call to obtain imperfect (realistic) simulation results.- Parameters:
var_name (
str
) – Reference to previously introduced state names (withModel.set_variable()
)expr (
Union
[SX
,MX
]) – CasADi SX or MX function depending on_x
,_u
,_z
,_tvp
,_p
.process_noise (
bool
) – Make the respective state variable non-deterministic.
- Raises:
assertion – var_name must be str
assertion – expr must be a casadi SX or MX type
assertion – var_name must refer to the previously defined states
assertion – Cannot call after :py:func`setup`.
- 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 tostates
.- 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 to1
.
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:
assertion – var_type must be string
assertion – var_name must be string
assertion – shape must be tuple or int
assertion – Cannot call after
setup()
.
- Returns:
Union
[SX
,MX
] – Returns the newly created symbolic variable.
setup#
- setup(self)#
Setup method must be called to finalize the modelling process. All required model variables must be declared. The right hand side expression for
_x
must have been set withset_rhs()
.Sets default measurement function (state feedback) if
set_meas()
was not called. :rtype:None
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
Attributes#
aux#
- Model.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#
- Model.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.
tvp#
- Model.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#
- Model.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#
- Model.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 argumentmeas_noise = True
.Note
The measurement noise is used for the
do_mpc.estimator.MHE
and can be used to simulate a disturbed system in thedo_mpc.simulator.Simulator
.Useful CasADi symbolic structure methods:
.shape
.keys()
.labels()
- Raises:
assertion – Cannot set v directly
w#
- Model.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 argumentprocess_noise = True
.Note
The process noise is used for the
do_mpc.estimator.MHE
and can be used to simulate a disturbed system in thedo_mpc.simulator.Simulator
.Useful CasADi symbolic structure methods:
.shape
.keys()
.labels()
- Raises:
assertion – Cannot set w directly
x#
- Model.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#
- Model.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#
- Model.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.