EKF#
- class EKF(model)[source]#
Bases:
EstimatorExtended Kalman Filter. Setup this class and use
EKF.make_step()during runtime to obtain the currently estimated states given the measurementsy0.Warning
Work in progress. The current implementation is not working with DAE systems.
- Parameters:
model (
Union[Model,LinearModel])
Methods#
get_p_template#
- get_p_template(self)#
Obtain output template for
set_p_fun(). Use this method in conjunction withset_p_fun()to define the function for retrieving the parameters at each sampling time.See
set_p_fun()for more details.- Returns:
Union[SXStruct,MXStruct] – numerical CasADi structure
get_tvp_template#
- get_tvp_template(self)#
Obtain the output template for
set_tvp_fun(). Use this method in conjunction withset_tvp_fun()to define the function for retrieving the time-varying parameters at each sampling time.- Returns:
Union[SXStruct,MXStruct] – numerical CasADi structure
make_step#
- make_step(self, y_next, u_next, Q_k, R_k)#
Main method of the EKF class during control runtime. This method is called at each timestep and computes the next state estimates
x0. The method returns the resulting states.The initial state
x0is stored as a class attribute. Use this attributex0to change the initial state, by callingset_initial_guess().- Parameters:
y_next – Current measurement of system.
u_next – Current input to the system.
Q_k – Current process noise covariance.
R_k – Current mesusrement noise covariance.
- Returns:
x0
- Raises:
AssertionError – If the EKF was not setup yet or if the initial guess was not set.
AssertionError – If the dimensions of Q_k and R_k are not correct.
reset_history#
- reset_history(self)#
Reset the history of the estimator
- Return type:
None
set_initial_guess#
- set_initial_guess(self)#
Initial guess for DAE variables. Use the current class attribute
z0to create the initial guess for the DAE algebraic equations.The simulator uses “warmstarting” to solve the continous/discrete DAE system by using the previously computed algebraic states as an initial guess. Thus, this method is typically only invoked once.
set_p_fun#
- set_p_fun(self, p_fun)#
Method to set the function which gives the values of the parameters. This function must return a CasADi structure which can be obtained with
get_p_template().Example:
In the
do_mpc.model.Modelwe have defined the following parameters:Theta_1 = model.set_variable('parameter', 'Theta_1') Theta_2 = model.set_variable('parameter', 'Theta_2') Theta_3 = model.set_variable('parameter', 'Theta_3')
To integrate the ODE or evaluate the discrete dynamics, the simulator needs to obtain the numerical values of these parameters at each timestep. In the most general case, these values can change, which is why a function must be supplied that can be evaluted at each timestep to obtain the current values.
do-mpc requires this function to have a specific return structure which we obtain first by calling:
p_template = simulator.get_p_template()
The parameter function can look something like this:
p_template['Theta_1'] = 2.25e-4 p_template['Theta_2'] = 2.25e-4 p_template['Theta_3'] = 2.25e-4 def p_fun(t_now): return p_template simulator.set_p_fun(p_fun)
which results in constant parameters.
A more “interesting” variant could be this random-walk:
p_template['Theta_1'] = 2.25e-4 p_template['Theta_2'] = 2.25e-4 p_template['Theta_3'] = 2.25e-4 def p_fun(t_now): p_template['Theta_1'] += 1e-6*np.random.randn() p_template['Theta_2'] += 1e-6*np.random.randn() p_template['Theta_3'] += 1e-6*np.random.randn() return p_template
- Parameters:
p_fun (
Callable[[float],Union[SXStruct,MXStruct]]) – A function which gives the values of the parameters- Raises:
assert – p must have the right structure
- Return type:
None
set_tvp_fun#
- set_tvp_fun(self, tvp_fun)#
Method to set the function which returns the values of the time-varying parameters. This function must return a CasADi structure which can be obtained with
get_tvp_template().In the
do_mpc.model.Modelwe have defined the following parameters:a = model.set_variable('_tvp', 'a')
The integrate the ODE or evaluate the discrete dynamics, the simulator needs to obtain the numerical values of these parameters at each timestep. In the most general case, these values can change, which is why a function must be supplied that can be evaluted at each timestep to obtain the current values.
do-mpc requires this function to have a specific return structure which we obtain first by calling:
tvp_template = simulator.get_tvp_template()
The time-varying parameter function can look something like this:
def tvp_fun(t_now): tvp_template['a'] = 3 return tvp_template simulator.set_tvp_fun(tvp_fun)
which results in constant parameters.
Note
From the perspective of the simulator there is no difference between time-varying parameters and regular parameters. The difference is important only for the MPC controller and MHE estimator. These methods consider a finite sequence of future / past information, e.g. the weather, which can change over time. Parameters, on the other hand, are constant over the entire horizon.
- Parameters:
tvp_fun (
Callable[[float],Union[SXStruct,MXStruct]]) – Function which gives the values of the time-varying parameters- Raises:
assertion – tvp_fun has incorrect return type.
assertion – Incorrect output of tvp_fun. Use get_tvp_template to obtain the required structure.
- Return type:
None
setup#
- setup(self)#
Sets up the EKF and finalizes the EKF configuration. Only after the setup, the
make_step()method becomes available.- Raises:
assertion – number of algebraic equations must be zero
Attributes#
P0#
- EKF.P0#
Initial error covariance matrix for the Extended Kalman Filter.
This matrix represents the initial uncertainty in the state estimates. It must be a positive semi-definite matrix of shape (n_x, n_x).
The default initialization is an identity matrix.
t0#
- EKF.t0#
Current time marker of the class. Use this property to set of query the time.
Set with
int,float,numpy.ndarrayorcasadi.DMtype.
u0#
- EKF.u0#
Initial input and current iterate. This is the numerical structure holding the information about the current input in the class. The property can be indexed according to the model definition.
Example:
model = do_mpc.model.Model('continuous') model.set_variable('_u','heating', shape=(4,1)) ... mhe = do_mpc.estimator.MHE(model) # or mpc = do_mpc.estimator.MPC(model) # Get or set current value of variable: mpc.u0['heating', 0] # 0th element of variable mpc.u0['heating'] # all elements of variable mpc.u0['heating', 0:2] # 0th and 1st element
Useful CasADi symbolic structure methods:
.shape.keys().labels()
x0#
- EKF.x0#
Initial state and current iterate. This is the numerical structure holding the information about the current states in the class. The property can be indexed according to the model definition.
Example:
model = do_mpc.model.Model('continuous') model.set_variable('_x','temperature', shape=(4,1)) ... mhe = do_mpc.estimator.MHE(model) # or mpc = do_mpc.estimator.MPC(model) # Get or set current value of variable: mpc.x0['temperature', 0] # 0th element of variable mpc.x0['temperature'] # all elements of variable mpc.x0['temperature', 0:2] # 0th and 1st element
Useful CasADi symbolic structure methods:
.shape.keys().labels()
z0#
- EKF.z0#
Initial algebraic state and current iterate. This is the numerical structure holding the information about the current algebraic states in the class. The property can be indexed according to the model definition.
Example:
model = do_mpc.model.Model('continuous') model.set_variable('_z','temperature', shape=(4,1)) ... mhe = do_mpc.estimator.MHE(model) # or mpc = do_mpc.estimator.MPC(model) # Get or set current value of variable: mpc.z0['temperature', 0] # 0th element of variable mpc.z0['temperature'] # all elements of variable mpc.z0['temperature', 0:2] # 0th and 1st element
Useful CasADi symbolic structure methods:
.shape.keys().labels()