function mpcobj = design_speed_mpc(scenario)
% parametri di tuning — modifica qui
Ts      = 0.03;
p_hor   = 30;   
m_ctrl  = 4;     
w_v     = 1000;   
w_du    = 1;  
w_u     = 0.0;
alpha_min = -500;
alpha_max =  100;
%dalpha_max = 1.5;
v0      = 5.0;
if isfield(scenario,'sim') && isfield(scenario.sim,'dtcontrol')
    Ts = scenario.sim.dtcontrol;
end
%% ---------- 1. Parametri fisici dal veicolo ---------------------------
v8 = scenario.vehicle8;
m       = v8.m;            % 1300 kg
R0      = v8.R0;           % 0.2 m (plant; era 0.317)
Jw      = v8.Jns;          % 0.8 kg m^2 per ruota
tau     = 10;              % gear_ratio motore->ruota (da motor_map.m)

% Massa efficace: traslante + inerzie rotanti delle 4 ruote
m_eff = m + 4*Jw / R0^2;

% Guadagno dell'acceleratore sulla coppia motore [Nm per %].
% Dalla mappa: T_motor = (alpha/100) * T_env(omega). Vicino al punto di
% lavoro usiamo il plateau di coppia di picco T_peak come pendenza
% rappresentativa (l'MPC è robusto a questo grazie all'azione integrale).
T_peak  = 60;                        % Nm  (4 motori x 15 Nm = 60 totali, da motor_map.m)
k_alpha = T_peak / 100;             % Nm per ogni 1% di pedale
% Guadagno ingresso->forza alla ruota [N per %]
k_v = (tau * k_alpha) / R0;         % N per 1% di acceleratore
%% ---------- 2. Modello di predizione LTI -------------------
% stato:  x = v            [m/s]
% input manipolato (MV):   u = alpha [%]
% input disturbo misurato (MD): d = F_res [N]
% output:  y = v           [m/s]
A = 0;
Bu = k_v / m_eff;          % effetto acceleratore
Bd = -1  / m_eff;         % effetto forza resistente (frena la marcia)
B  = [Bu, Bd];
C  = 1;
D  = [0, 0];
plant = ss(A, B, C, D);
plant = setmpcsignals(plant, 'MV', 1, 'MD', 2);   % col 1 = MV, col 2 = MD
% Discretizzazione al sample time dell'MPC
plant_d = c2d(plant, Ts);

%% ---------- 3. Oggetto MPC --------------------------------------------
mpcobj = mpc(plant_d, Ts, p_hor, m_ctrl);
% --- Vincoli sull'ingresso manipolato (acceleratore) ---
mpcobj.MV(1).Min      = alpha_min;     % freno massimo
mpcobj.MV(1).Max      = alpha_max;     % gas massimo
% mpcobj.MV(1).RateMin  = -o.dalpha_max;   % rate limiter (come nel modello)
% mpcobj.MV(1).RateMax  =  o.dalpha_max;
% --- Pesi della funzione di costo ---
%   J = sum_k [ w_v^2 (v_k - vref)^2 + w_u^2 u_k^2 + w_du^2 (Du_k)^2 ]
mpcobj.Weights.OutputVariables       = w_v;    % Q  (tracking v)
mpcobj.Weights.ManipulatedVariables  = w_u;    % peso su alpha
mpcobj.Weights.ManipulatedVariablesRate = w_du;% R 
% --- Scaling (numerica): porta MV e OV su scala comparabile ---
mpcobj.MV(1).ScaleFactor = alpha_max - alpha_min;
mpcobj.OV(1).ScaleFactor = max(scenario.control.v_max_mps, 1);
mpcobj.OV(1).Max     = 0;              % bound finito (richiesto per ymax variabile)
mpcobj.OV(1).MaxECR  = .001;               % vincolo
% --- Nominal operating point (linearizzazione attorno a v0) ---
mpcobj.Model.Nominal.U = [0; 0];   % alpha=0, F_res=0 al nominale
mpcobj.Model.Nominal.X =  v0;
mpcobj.Model.Nominal.Y =  v0;

%% ---------- Rigetto del mismatch di modello (anti-windup strutturale) ----
% L'errore di velocita' persistente dovuto a EBD/aderenza/dinamica 8-DOF e'
% un DISTURBO D'USCITA dal punto di vista dell'MPC. Modellandolo con un
% integratore ad alto guadagno, l'estimatore ne costruisce rapidamente la
% stima e l'ottimizzatore comanda il freno necessario a cancellarlo:
% azione integrale che elimina il windup SENZA toccare k_v.
setoutdist(mpcobj, 'model', tf(20, [1 0.05]));   % integratore d'uscita, guadagno 20 tune tra 10 e 100
mpcobj.Model.Noise = 0.01;
end
