function new_flows = controller_alinea(densities, flows, celldata, ts, idx)
% CONTROLLER_ALINEA - implementation of ALINEA controller.
%
% Call: new_flows = controller_alinea(densities, flows, celldata, ts, idx)
%
% Parameters:
% densities - vector of densities;
% flows - vector of on-ramp flows, same size as 'densities';
% celldata - array of freeway cell structures, whose length
% must be the same as size of 'densities';
% ts - sampling period;
% idx - index of the cell with our on-ramp.
%
% Returns: new_flows - updated vector of on-ramp flows.
%
% Last modified: 10/14/2006.
%
% Alex Kurzhanskiy <akurzhan@eecs.berkeley.edu>
%
L = size(densities, 1);
M = size(flows, 1);
N = size(celldata, 2);
if L ~= N
error('CONTROLLER_ALINEA: number of densities does not match number of cells.');
end
if M ~= N
error('CONTROLLER_ALINEA: number of flows does not match number of cells.');
end
if (idx < 1) | (idx > N)
error('CONTROLLER_ALINEA: invalid cell index.');
end
% initialize flow vector with current values
new_flows = flows;
if (celldata(idx).ORmlcontroller.upstream > 0) & (idx > 1)
i = idx - 1;
else
i = idx;
end
o_d = celldata(i).FDrhocrit;% / celldata(i).FDrhojam; % desired occupancy
o_a = densities(i, 1);% / celldata(i).FDrhojam; % actual occupancy
K = celldata(idx).ORmlcontroller.K; % control gain
f = flows(idx, 1) + K * (o_d - o_a) / ts; % on-ramp flow that we can allow
f = min([f celldata(idx).ORmlcontroller.Cmax]);
f = max([f celldata(idx).ORmlcontroller.Cmin 0]);
% update flow vector
new_flows(idx, 1) = f;
return;