Here is the model of the underlying equations:
1. State of charge: \dot{z}(t) = -\eta(t)i(t)/Q
2. Current i_{R_1}: \dot{i_{R_1}}(t)= -\frac{1}{R_1C_1}i_{R_1}(t) + \frac{1}{R_1C_1}i(t)
3. terminal voltage: v(t) = \mathrm{OCV}(z(t)) - R_1i_{R_1}(t)- R_0i(t)
4. Battery power: P(t) = v(t) \cdot i(t)
I want to add a power tracking contraint, meaning that the battery power is equal to the demanded power, which is a parameter p.
For this I used the following nonlinear equality contraint:
% this is the mapping from SoC to open circuit voltage
Uocv = interpolant('UocvFcn','linear', {Bat.V_ocv2.SoCBrkPts}, round(Bat.V_ocv2.UocvVals, 2));
% terminal voltage equation, where model.x(1) is SoC, model.x(4) is iR1 and model.u(1) is ibat
Vbat = Uocv(model.x(1)) - Bat.R1 * model.x(4) - Bat.R0 * model.u(1);
% battery power
Pbat = (Vbat * model.u(1)) / Bat.kW2W;
% This is the constraint
ocp.model.con_h_expr = Pbat - model.p(1);
ocp.constraints.lh = 0;
ocp.constraints.uh = 0;
For some reason the power tracking does not work, when I simulate the MPC with plant model in Simulink. Only tracking states x works, but when I add the input u to the nonlinear equality constrainz, the tracking is no longer working.
Is this the correct way of adding a nonlinear equality constraint? Is there another way of adding a constraint on the model ouput y?
regarding your implemetation: you do not need to introduce the extra parameter. You can simply set the lower and upper bounds lh and uh. It is also possible to update these values stagewise after solver creation using the setter: constraints_set, see Python Interface — acados documentation
In general, additional equalities might be challenging. I would recommend to slack this constraint.
Do you get status 0, i.e. is the solve successful? If not could you provide the output of print_statictics?
Ist the constraint satisfied for those problems for which you get status 0? If not, you need to tune the slack weights a bit. Do you set a linear or a quadratic penalty term, or both?