gusucode.com > Beam Alignment and Tracking for Autonomous Vehicular Communication using IEEE 802.11ad-based Radar > mmWave-V2I-Radar-master/v2i_collision_correction.m

    function [xInt,vInt,tInt] = v2i_collision_correction(cInitTime,cVel,cLoc,NCARS,DEBUG)
    % Contains the intervals at which each car needs to adjust its speed
    % due to collision
    xInt  = num2cell(cLoc);            % Spatial velocity updates (collisions)
	vInt  = num2cell(cVel);            % Vector with velocities (collisions)
    tInt  = num2cell(zeros(NCARS,1));  % Time intervals at which speed is updated
    cPass = cell(NCARS,1);             % Stores the cars each cID has reached
    tCol = 0;  % Initial value forcing the system to enter in the loop
    while ~prod(isinf(tCol))  % Iterate until all collision times are Inf
        [~ , idx] = sort(cInitTime);
        tCol = Inf(NCARS,1);  % Contains the earliest collision time for all cID
        cIDCol = cell(NCARS); % Contains the ID of the car cID collides first
        xIntUpdate = num2cell(Inf(1)); % Contains the space intervals (meters)
        vIntUpdate = num2cell(Inf(1)); % Contains the speeds belonging to 
                                       % the space intervals
        % Check collisions for each car on the road
        for id = 1:NCARS
            cID = idx(id);  % Real Car ID
            temp1 = repmat(cLoc(cID),NCARS,1);  % Location of the current cID
            temp2 = cLoc(idx);                  % Location of the rest
            idxTempCol = find(temp1 <= temp2);  % In the sorted list, cars that
                                                % car with real ID "index" has
                                                % passed
            idxTempCol(idxTempCol<=id) = [];
            idxCol{id} = [idxTempCol];                                 %#ok
            % Contains the ID list that the cID is passing during the
            % simulations
            cIDColList = idx(idxCol{id});
            % For each car that cID has collided, calculate the location
            % and time. Return the earliest collision, the only feasible one.
            if ~isempty(cIDColList)
                [tCol(cID) , xIntUpdate{cID} , vIntUpdate{cID}, cIDCol{cID}] ...
                        = detect_collision(cID,cIDColList,xInt,vInt,cPass{cID});
            end
        end
        % Stop execution if no more collisions are detected
        if prod(isinf(tCol))
            if DEBUG; fprintf('END OF EXECUTION - No more collisions were detected\n'); end
            break;
        end
        % We detect the first collision and we correct the speed
        [~,cID] = min(tCol);  % Earliest collision between any pair of cars
        vInt{cID}  = [vInt{cID} vIntUpdate{cID}];  % Update speed vector
        xInt{cID}  = [xInt{cID} xIntUpdate{cID}];  % Update locations
        tInt{cID}  = [tInt{cID} tCol(cID)];        % Update times
        cPass{cID} = [cPass{cID} cIDCol{cID}];     % Update the car cID has passed
        if DEBUG
            fprintf('car %d reaches car %d at time %.2f at location %.2f\n', ...
                    cID,cIDCol{cID},tCol(cID),xIntUpdate{cID}(1));
        end
        % Update total time to simTarget. The total time is the product
        % within the intervals xInt and the velocity at each interval (like
        % an Integral). we add 0 as to simulate the end of the simulation.
        cInitTime(cID) = sum(diff([xInt{cID} 0])./vInt{cID});
        % Update the status of the cars behind the car that just collided
        [xInt,vInt,cPass,cInitTime] = update_tail_cars_velocities ...
                                (cID,xInt,vInt,tInt,cPass,cInitTime,NCARS,DEBUG);
    end
end

function [tCol , xIntUpdate, vIntUpdate, cIDCol] = detect_collision(cID,cIDColList,xInt,vInt,cPass)
    tColList = Inf(length(cIDColList),1);  % Final Collision time for each car in cIDColList
    xColList = Inf(length(cIDColList),1);  % Final Collision location for each car in cIDColList
    % Iterate over each cIDCol that collided with cID
    for idxIDCol = 1:length(cIDColList)
        cIDCol1 = cIDColList(idxIDCol);
        % Calculate intervals in terms of time (xInt -> tInt)
        vIDList = vInt{cID};
        xIDList = xInt{cID};
        vIntColList = vInt{cIDCol1};
        xIntColList = xInt{cIDCol1};
        tIntID  = cumsum(diff([xIDList 0]) ./ vIDList);
        tIntCol = cumsum(diff([xIntColList 0]) ./ vIntColList);
        % Append time intervals and use it as timestamps (ts)
        tsList = [tIntID tIntCol];
        tsList = sort(tsList);
        % Check at each timestamp if cID has surpassed cIDCol
        mID  = xIDList(1);   % Initial Location of cID
        mCol = xIntColList(1);  % Initial Location of cIDCol
        tsPast = 0;          % Previous timeStamp
        for t = 1:length(tsList)
            % Select speeds for each time stamp
            index = find(tIntID >= tsList(t), 1, 'first');
            vID = vIDList(index);
            index = find(tIntCol >= tsList(t), 1, 'first');
            vCol = vIntColList(index);
            % Calculate where they are in space
            mID1 = mID; mCol1 = mCol;  % Backup in case they collide
            mID = mID + vID * (tsList(t) - tsPast);
            mCol = mCol + vCol * (tsList(t) - tsPast);
            % Calculate if they colided in the time stamp interval
            if mID > mCol  % They have collided in the ts interval
                tColInterval = (mID1 - mCol1)./(vCol - vID);  % Time within time interval
                tColList(idxIDCol) = tsPast + tColInterval;
                xColList(idxIDCol) = mID1 + vID*tColInterval;
%                 fprintf('\t\t%d collides with %d at time %.2f at location %.2f\n', ...
%                     cID, cIDCol1, tColList(idxIDCol), xColList(idxIDCol));
                break;
            end
            tsPast = tsList(t);
        end
    end
    notFound = true;
    while(notFound)
        % We take the minimum since the first collision is the one
        % that causes the speed correction. We return the instant, the location
        % and the car ID
        [tCol , indxCol] = min(tColList);
        if ~ismember(cIDColList(indxCol),cPass) || isinf(tCol)
            notFound = false;
        else
            tColList(indxCol) = Inf(1);  % cID has already passed cIDPass
        end
    end
    % The collision happens out of range, we do not care
    if xColList(indxCol) > 0 ; tCol = Inf(1); end
    % The new space intervals need to contain the updated location vector
    % of cIDCol.
    delta = 0.5;  % Car correction in meters. It represents the car length. 
                  % The car needs to break before reaching the next car
                  % (Physics 101)
    xIntUpdate = xColList(indxCol) - delta;
    % Update the latest velocity of the car that we just crashed. If cIDCol
    % has crashed with someone earlier, it is not reflected in the new
    % speed.
    vIntUpdate = vInt{cIDColList(indxCol)}(end);
    % ID of the car first car that collides with cID
    cIDCol = cIDColList(indxCol);
end

function [xInt,vInt,cPass,cInitTime] = update_tail_cars_velocities(cID,xInt,vInt,tInt,cPass,cInitTime,NCARS,DEBUG)
    someoneToUpdate = true;
    cIDUpdate = [];
    delta = 0.5;  % Car length to be corrected in the collision location
    while someoneToUpdate
        for id = 1:NCARS
            if ismember(cID,cPass{id})
                cIDUpdate = id;  % cIDUpdate is the car that is driving 
                                 % right behind the car updated in the 
                                 % previous iteration
                break;
            else
                cIDUpdate = [];
            end
        end
        if ~isempty(cIDUpdate)  % Check if there is any car to be updated
            % Update Basic parameters for cIDUpdate
            xCol = xInt{cID}(end) - delta;
            xInt{cIDUpdate}  = [xInt{cIDUpdate} xCol];
            vInt{cIDUpdate}  = [vInt{cIDUpdate} vInt{cID}(end)];
            tInt{cIDUpdate}  = [tInt{cIDUpdate} tInt{cID}(end)];
            cPass{cIDUpdate} = [cPass{cIDUpdate} cPass{cID}(end)];
            % Update times
            cInitTime(cIDUpdate) = sum(diff([xInt{cIDUpdate} 0])./vInt{cIDUpdate});
            if DEBUG
                fprintf('\tcar %d updated by car %d at time %.2f at location %.2f\n', ...
                        cIDUpdate,cID,tInt{cIDUpdate}(end),xInt{cIDUpdate}(end));
            end
            % The updated car needs to update its followers
            cID = cIDUpdate;
        else
            someoneToUpdate = false;
        end
    end
end