function [rpm,v_min,next_v_min,v_max,next_v_max,rpm_min,next_rpm_min,rpm_max,next_rpm_max]=calculate_rpm(speed,gear,next_gear,rpm_vector,vel_vector,wheel_radius,gear_ratios,differential_ratio)
%SPEEDER Função que calcula a velocidade do carro quando o motor está a
%        realizar trabalho. Fornece também os limites da mudança actual.
%
%##########################################################################
% A função aceita como valores de input os valores das rpm actuais (que são
% controladas a partir do acelerador) e o valor da mudança. Com base nessa
% informação, a função devolve a velocidade actual do veículo, e os limites
% máximo e mínimo de velocidades, para uma determinada mudança.
% O ponto morto devolve apenas o valor das rpm durante o mesmo, quer no
% valor de RPM, quer no valor de rpm_min e rpm_max, e devolve 0 nas
% velocidades por poder suportar toda a gama de velocidades do veículo.
%
% INPUTS:
% speed -> Valor de velocidade actual do veículo [km/h];
% gear -> Mudança actual do veículo;
% next_gear -> Mudança seguinte;
% rpm_vector -> Vector com os valores minimos e máximos de RPM admissiveis para cada mudança;
% vel_vector -> Vector com os valores minimos e máximos de velocidade admissiveis para cada mudança;
%
% OUTPUTS:
% rpm -> RPM para uma determinada velocidade e para uma determinada
%        mudança;
% v_min -> Velocidade mínima admissível para uma determinada mudança
%          [km/h];
% v_max -> Velocidade máxima admissível para uma determinada mudança
%          [km/h];
% rpm_min -> RPM mínima admissível para uma determinada mudança;
% rpm_max -> RPM máxima admissivel para uma determinada mudança.
%##########################################################################
% Geração da matriz original:
M=zeros(7,4);
%##### Parâmetros alteraveis: ##############
% RPM's:                                   #
rpm_n=rpm_vector(1);%        [RPM]         #
rpm_min_r=rpm_vector(2);%    [RPM]         #
rpm_max_r=rpm_vector(3);%    [RPM]         #
rpm_min_1=rpm_vector(4);%    [RPM]         #
rpm_max_1=rpm_vector(5);%    [RPM]         #
rpm_min_2=rpm_vector(6);%    [RPM]         #
rpm_max_2=rpm_vector(7);%    [RPM]         #
rpm_min_3=rpm_vector(8);%    [RPM]         #
rpm_max_3=rpm_vector(9);%    [RPM]         #
rpm_min_4=rpm_vector(10);%   [RPM]         #
rpm_max_4=rpm_vector(11);%   [RPM]         #
rpm_min_5=rpm_vector(12);%   [RPM]         #
rpm_max_5=rpm_vector(13);%   [RPM]         #
% Velocidades:                             #
vel_min_r=vel_vector(1);%     [Km/h]       #
vel_max_r=vel_vector(2);%     [Km/h]       #
vel_min_n=vel_vector(3);%     [Km/h]       # (valor infinito)
vel_max_n=vel_vector(4);%     [Km/h]       # (valor infinito)
vel_min_1=vel_vector(5);%     [Km/h]       #
vel_max_1=vel_vector(6);%     [Km/h]       #
vel_min_2=vel_vector(7);%     [Km/h]       #
vel_max_2=vel_vector(8);%     [Km/h]       #
vel_min_3=vel_vector(9);%     [Km/h]       #
vel_max_3=vel_vector(10);%    [Km/h]       #
vel_min_4=vel_vector(11);%    [Km/h]       #
vel_max_4=vel_vector(12);%    [Km/h]       #
vel_min_5=vel_vector(13);%    [Km/h]       #
vel_max_5=vel_vector(14);%    [Km/h]       #
%###########################################
% Preenchimento da Matriz:
% Primeira mudança:
M(3,:)=[rpm_min_1,rpm_max_1,vel_min_1,vel_max_1];
% Segunda mudança:
M(4,:)=[rpm_min_2,rpm_max_2,vel_min_2,vel_max_2];
% Terceira mudança:
M(5,:)=[rpm_min_3,rpm_max_3,vel_min_3,vel_max_3];
% Quarta mudança:
M(6,:)=[rpm_min_4,rpm_max_4,vel_min_4,vel_max_4];
% Quinta mudança:
M(7,:)=[rpm_min_5,rpm_max_5,vel_min_5,vel_max_5];
% Marcha atrás:
M(1,:)=[rpm_min_r,rpm_max_r,vel_max_r,vel_min_r];
% Ponto morto:
M(2,:)=[rpm_n,rpm_n,vel_max_n,vel_min_n];
% Normalização das mudanças actuais nos indices da matriz:
INDEX=gear+2;
% Verifica se a mudança é a marcha-atrás:
if(gear==6)
    % Cálculo da velocidade:
    rpm=(convert_kmhr_to_ms(speed)*gear_ratios(1)*differential_ratio*60)/(2*pi*wheel_radius);
    % Valor mínimo da velocidade:
    v_min=M(1,3);
    % Valor máximo da velocidade:
    v_max=M(1,4);
    % Valor mínimo das RPM:
    rpm_min=M(1,1);
    % Valor máximo das RPM:
    rpm_max=M(1,2);
% Verifica de a mudança é o ponto morto:
elseif(gear==0)
    rpm=rpm_n;
    % Valor mínimo da velocidade:
    v_min=M(INDEX,3);
    % Valor máximo da velocidade:
    v_max=M(INDEX,4);
    % Valor mínimo das RPM:
    rpm_min=M(INDEX,1);
    % Valor máximo das RPM:
    rpm_max=M(INDEX,2);
% Verifica se a mudança é a primeira:
elseif(gear==1)
    % Cálculo da velocidade:
    rpm=(convert_kmhr_to_ms(speed)*gear_ratios(INDEX)*differential_ratio*60)/(2*pi*wheel_radius);
    % Valor mínimo da velocidade:
    v_min=M(INDEX,3);
    % Valor máximo da velocidade:
    v_max=M(INDEX,4);
    % Valor mínimo das RPM:
    rpm_min=M(INDEX,1);
    % Valor máximo das RPM:
    rpm_max=M(INDEX,2);
% Verifica se a mudança é a segunda:
elseif(gear==2)
    % Cálculo da velocidade:
    rpm=(convert_kmhr_to_ms(speed)*gear_ratios(INDEX)*differential_ratio*60)/(2*pi*wheel_radius);
    % Valor mínimo da velocidade:
    v_min=M(INDEX,3);
    % Valor máximo da velocidade:
    v_max=M(INDEX,4);
    % Valor mínimo das RPM:
    rpm_min=M(INDEX,1);
    % Valor máximo das RPM:
    rpm_max=M(INDEX,2);
% Verifica se a mudança é a terceira:
elseif(gear==3)
    % Cálculo da velocidade:
    rpm=(convert_kmhr_to_ms(speed)*gear_ratios(INDEX)*differential_ratio*60)/(2*pi*wheel_radius);
    % Valor mínimo da velocidade:
    v_min=M(INDEX,3);
    % Valor máximo da velocidade:
    v_max=M(INDEX,4);
    % Valor mínimo das RPM:
    rpm_min=M(INDEX,1);
    % Valor máximo das RPM:
    rpm_max=M(INDEX,2);
% Verifica se a mudança é a quarta:
elseif(gear==4)
    % Cálculo da velocidade:
    rpm=(convert_kmhr_to_ms(speed)*gear_ratios(INDEX)*differential_ratio*60)/(2*pi*wheel_radius);
    % Valor mínimo da velocidade:
    v_min=M(INDEX,3);
    % Valor máximo da velocidade:
    v_max=M(INDEX,4);
    % Valor mínimo das RPM:
    rpm_min=M(INDEX,1);
    % Valor máximo das RPM:
    rpm_max=M(INDEX,2);
% Verifica se a mudança é a quinta:
elseif(gear==5)
    % Cálculo da velocidade:
    rpm=(convert_kmhr_to_ms(speed)*gear_ratios(INDEX)*differential_ratio*60)/(2*pi*wheel_radius);
    % Valor mínimo da velocidade:
    v_min=M(INDEX,3);
    % Valor máximo da velocidade:
    v_max=M(INDEX,4);
    % Valor mínimo das RPM:
    rpm_min=M(INDEX,1);
    % Valor máximo das RPM:
    rpm_max=M(INDEX,2);
end
% Em caso de AUMENTO:
if(next_gear>gear)
    % No caso de se pedir um valor que superior ao maior indice da matriz:
    if(INDEX==7)
        % Os valores de actual e proximo são iguais:
        INDEX=6;
    end
    % Valor mínimo da velocidade para a mudança seguinte:
    next_v_min=M(INDEX+1,3);
    % Valor máximo da velocidade para a mudança seguinte:
    next_v_max=M(INDEX+1,4);
    % Valor mínimo das RPM para a mudança seguinte:
    next_rpm_min=M(INDEX+1,1);
    % Valor máximo das RPM para a mudança seguinte:
    next_rpm_max=M(INDEX+1,2);
% Em caso de REDUÇÃO:
elseif(next_gear<gear)
    % No caso de se pedir um valor que superior ao maior indice da matriz:
    if(INDEX==-1)
        % Os valores de actual e proximo são iguais:
        INDEX=0;
    end
    % Valor mínimo da velocidade para a mudança seguinte:
    next_v_min=M(INDEX-1,3);
    % Valor máximo da velocidade para a mudança seguinte:
    next_v_max=M(INDEX-1,4);
    % Valor mínimo das RPM para a mudança seguinte:
    next_rpm_min=M(INDEX-1,1);
    % Valor máximo das RPM para a mudança seguinte:
    next_rpm_max=M(INDEX-1,2);
% Em caso de IGUALDADE:
elseif(next_gear==gear)
    % Valor mínimo da velocidade para a mudança seguinte:
    next_v_min=v_min;
    % Valor máximo da velocidade para a mudança seguinte:
    next_v_max=v_max;
    % Valor mínimo das RPM para a mudança seguinte:
    next_rpm_min=rpm_min;
    % Valor máximo das RPM para a mudança seguinte:
    next_rpm_max=rpm_max;
end
end