# Source code for do_mpc.model._linearize

```
#
# This file is part of do-mpc
#
# do-mpc: An environment for the easy, modular and efficient implementation of
# robust nonlinear model predictive control
#
# Copyright (c) 2014-2019 Sergio Lucia, Alexandru Tatulea-Codrean
# TU Dortmund. All rights reserved
#
# do-mpc is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3
# of the License, or (at your option) any later version.
#
# do-mpc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with do-mpc. If not, see <http://www.gnu.org/licenses/>.
import numpy as np
import pdb
from ._linearmodel import LinearModel
from . import Model
[docs]
def linearize(model:Model,
xss:np.ndarray = None,
uss:np.ndarray=None,
tvp0:np.ndarray = None,
p0:np.ndarray = None
)->LinearModel:
"""Linearize the non-linear :py:class:`Model` to obtain a :py:class:`LinearModel` .
The linearized model is required, e.g. for the :py:class:`do_mpc.controller.LQR` controller.
This method uses the taylor expansion series to linearize non-linear model to linear model at the specified
set points. Linearized model retains the same variable names for all states, inputs with respect to the original model.
The non-linear model equation this method can solve is as follows:
.. math::
\\dot{x} = f(x,u)
The above model is linearized around steady state set point :math:`x_{ss}` and steady state input :math:`u_{ss}`
.. math::
\\frac{\\partial f}{\\partial x}|_{x_{ss}} = 0 \\\\
\\frac{\\partial f}{\\partial u}|_{u_{ss}} = 0
The linearized model is as follows:
.. math::
\\Delta\\dot{x} = A \\Delta x + B \\Delta u
Similarly, it can be extended to discrete time systems. Since the linearized model has only rate of change input and state. The names are appended with 'del' to differentiate
from the original model. This can be seen in the above model definition. Therefore, the solution of the lqr will be ``u`` and its corresponding ``x``. In order to fetch :math:`\\Delta u`
and :math:`\\Delta x`, setpoints has to be subtracted from the solution of lqr.
Args:
model : dynamic systems model
xss : Steady state state
uss : Steady state input
tvp0 : value for tvp variable
p0 : value for parameter variable
Returns:
Linearized Model
"""
#Check whether model setup is done
assert model.flags['setup'] == True, 'Run this function after original model is setup'
assert model.z.size == 0, 'Linearization around steady state is not supported for DAEs'
A,B,C,D = model.get_linear_system_matrices(xss,uss, tvp=tvp0, p=p0)
# Check if A,B,C,D are constant or expressions
all_constant = np.alltrue(
[isinstance(A, np.ndarray), isinstance(B, np.ndarray), isinstance(C, np.ndarray), isinstance(D, np.ndarray)]
)
if all_constant:
# If all are constant, linear model is initialized
linearizedModel = LinearModel(model.model_type,model.symvar_type)
else:
# If not, LTV model is initialized
raise NotImplementedError('LTV models are not yet implemented.')
# Create new variables for linearized model
model._transfer_variables(model, linearizedModel)
n_x = model.n_x
n_u = model.n_u
# Check for trivial measurement equation
if C.shape == (n_x,n_x) and (C == np.eye(n_x)).all():
C = None
if D.shape == (n_x,n_u) and (D == np.zeros((n_x,n_u))).all():
D = None
# Setup linearized model
linearizedModel.setup(A,B,C,D)
return linearizedModel
```