Ignored/Incorrect MV constraint in nonlinear MPC block with parameter
Show older comments
Hello! I am implementing a nonlinear model predictive controller using MPC Toolbox in Simulink. A constraint of my NMPC appears to be ignored and I believe it is due to an error in my custon inequality constraint function. Here's some context:
I am making a mass follow a reference displacement in a vehicle active suspension system. Currently, my NMPC's manipulated variable is the increment in force for an actuator. My system under control takes a force magnitude as an input rather than an increment in force. Therefore, to constrain the maximum force magnitude allowed in my custom constraint function I need to pass in the previous magnitude as a parameter to add to the manipulated variable. This allows me to compare the sum of the increment and the previous magnitude to the constraint parameter. Currently, when looking at the produced force in a scope after a simulation, the amount is outside of the bounds of Fc_max and Fc_min (+/- 15N).
I have ensured the scope determines the value of the force magnitude correctly, and I have also ensured my cost function, state function, and equality constraints are configured properly. The bus that passes in params is also configured correctly. The controller exhibits acceptable tracking performance, it just ignores this constraint. Furthermore, the other constraints appear to be observed (but this could just be due to my reference not requiring the controller to apply those constraints). This leads me to believe my cineq function is incorrect somehow. The first block of code is my nlmpc setup, and the second is my cineq function. The picture is the force command produced (that violates the constraint).
%% cost function weights (best perf @ w=95000,w_dot=105,R=2,'E=1')
Ts = 0.01;
Q_n = 1000;
Q_ndot = 0; % fix this
R = 15;
E = 1;
%% physical constraints
% maximum forces (currently +/- 15) (units: N)
Fc_max = 15;
Fc_min = -15;
% maximum rate of change in forces (units: N/Ts) (at Ts = 0.01 this is 10)
delta_Fc_max = 1000*Ts;
delta_Fc_min =-1000*Ts;
% maximum displacement of the spacing (units: m)
n_max = 0.05;
n_min = -0.05;
%% misc params
alpha_o = 1/(ms) + 1/(mu);
eta_ddot = 0;
Fc_last = 0;
Hc = 1;
%% NMPC settings, weights, and constraints
nx = 2;
ny = nx;
nu = 1;
nulmpcobj = nlmpc(nx,ny,nu);
nulmpcobj.Ts = Ts;
nulmpcobj.PredictionHorizon = 20;
nulmpcobj.ControlHorizon = Hc;
% how plant states evolve over time. Model is DT.
nulmpcobj.Model.StateFcn = "stateFunction";
nulmpcobj.Model.IsContinuousTime = false;
nulmpcobj.Model.NumberOfParameters = 15;
nulmpcobj.Model.OutputFcn = "outputFunction";
% set up cost function and constraints
nulmpcobj.Optimization.CustomCostFcn = "costFunction";
Optimization.CustomEqConFcn = "eqConFunction";
Optimization.CustomIneqConFcn = "ineqConFunction";
nulmpcobj.Optimization.ReplaceStandardCost = true;
SolverOptions.Algorithm = 'sqp';
% initial conditions
x0 = [0;0];
u0 = 0;
%% WARNING: EVERY TIME THIS IS EDITED, YOU NEED TO EDIT ALL OTHER FUNCTIONS WITH PARAMS...
parameters = {alpha_o,eta_ddot,Q_n,Q_ndot,R,E,Fc_max,Fc_min,delta_Fc_max,delta_Fc_min,n_max,n_min,Ts,Fc_last,Hc};
% Set up parameter bus for NMPC object (if it isn't already initialized)
if exist('paramBus','var')==0
mdl = 'NULMPC_RAS';
open_system(mdl)
createParameterBus(nulmpcobj,[mdl '/NULMPC'],'paramBus',parameters);
end
%% Now the NLMPC and simulation parameters are ready to go!
%% Run the simulation or optionally validate the NMPC functions here in MATLAB.
% rng(0);
% validateFcns(nulmpcobj,rand(nx,1),rand(nu,1),[],parameters);
sim(mdl);
function cineq = ineqConFunction(X,U,data,alpha_o,eta_ddot,Q_n,Q_ndot,R,E,Fc_max,Fc_min,delta_Fc_max,delta_Fc_min,n_max,n_min,Ts,Fc_last,Hc)
cineq = zeros(6,1);
p = data.PredictionHorizon;
% delta constraint max/min
U1 = U(1:Hc,data.MVIndex(1));
cineq(1) = U1 - delta_Fc_max;
cineq(2) = -U1 + delta_Fc_min;
% magnitude
X1 = X(2:p+1,1);
cineq(3) = X1 - n_max;
cineq(4) = -X1 + n_min;
%% output constraint (THIS IS THE ONE I THINK IS INCORRECT)
cineq(5) = (U1 + Fc_last) - Fc_max;
cineq(6) = -(U1 + Fc_last) + Fc_min;
end
Since my control horizon is 1, the nmpc controller will hold my constrained input constant after the end of Hc. This should mean I do not need to have these constraints run across the whole prediction horizon p for the constraints to apply. Thank you to anyone who responds!

6 Comments
Sam Chak
on 10 Aug 2024
I don't see the settings on the Force:
nulmpcobj.ManipulatedVariables.Min = Fc_min; nulmpcobj.ManipulatedVariables.Max = Fc_max;
Sam Chak
on 10 Aug 2024
Hi @Aidan
I'm also wondering what went wrong. Could it be the reason that the last two constraints are in the lowest order of priority?
%% output constraint (THIS IS THE ONE I THINK IS INCORRECT)
cineq(5) = (U1 + Fc_last) - Fc_max; % Previous_F + ΔF ≤ Fmax
cineq(6) = - (U1 + Fc_last) + Fc_min; % Fmin ≤ Previous_F + ΔF
Aidan
on 10 Aug 2024
Sam Chak
on 10 Aug 2024
Can you possibly check when these two constraints are violated throughout the simulation?
cineq(1) = (U1 + Fc_last) - Fc_max;
cineq(2) = - (U1 + Fc_last) + Fc_min;
Accepted Answer
More Answers (0)
Categories
Find more on Model Predictive Control Toolbox in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!