exponenta event banner

Слияние для автомобильной безопасности

Этот пример показывает, как сплавлять гусеницы с двух транспортных средств, чтобы обеспечить более полную оценку окружающей среды, которую может видеть каждое транспортное средство. В примере показано использование фузера уровня дорожки и формата данных дорожки объекта. В этом примере используются сценарий вождения и генератор обнаружения видения из Automated Driving Toolbox™, генератор радиолокационных данных из Radar Toolbox™, а также модели слежения и слежения из Sensor Fusion and Tracking Toolbox™.

Мотивация

Применение в области автомобильной безопасности основано на объединении данных от различных сенсорных систем, установленных на транспортном средстве. Отдельные транспортные средства предохраняют датчики, используя либо централизованный трекер, либо более децентрализованный подход и сплавляя дорожки, производимые отдельными датчиками. В дополнение к слиянию данных между транспортными средствами, слияние данных из нескольких транспортных средств дает дополнительные преимущества, которые включают лучшее покрытие, ситуационную осведомленность и безопасность [1]. Этот подход слияния межавтомобильных датчиков использует преимущества множества датчиков и обеспечивает лучшее покрытие для каждого транспортного средства, поскольку он использует данные, обновленные датчиками на других транспортных средствах в этом районе. Правительства и производители транспортных средств давно признали необходимость обмена информацией между транспортными средствами в целях повышения безопасности автомобилей. Например, разрабатываются протоколы V2X и линии сотовой связи.

Хотя слияние датчиков между несколькими транспортными средствами является выгодным, большинство транспортных средств должны отвечать определенным требованиям безопасности, даже если доступны только внутренние датчики. Поэтому транспортное средство, вероятно, будет оснащено трекером, путевым фузером или и тем, и другим. Эти алгоритмы отслеживания обеспечивают ситуационную осведомленность на уровне одного транспортного средства. В результате, допущение, сделанное в этом примере, состоит в том, что транспортные средства совместно информируют о ситуации, транслируя дорожки и выполняя слияние дорожек.

Этот пример демонстрирует преимущества сплавления гусениц с двух транспортных средств для повышения ситуационной осведомленности и безопасности. Этот пример не моделирует системы связи. Вместо этого в примере предполагается, что система связи обеспечивает полосу пропускания, необходимую для передачи дорожек между двумя транспортными средствами.

Архитектура Track-to-Track

На следующей блок-схеме показаны основные функции двух транспортных средств, где:

  • Транспортное средство 1 имеет два датчика, каждый из которых обеспечивает обнаружение местного трекера транспортного средства. Трекер использует детекции от локальных датчиков для отслеживания объектов и выводит эти локальные дорожки на фузер трассы транспортного средства.

  • Транспортное средство 2 имеет один датчик, представляющий собой трекинговый радар. Радар слежения выводит дорожки и служит в качестве локального трекера для транспортного средства 2. Дорожки от радиолокационной станции слежения являются входными сигналами для фюзеляжа пути транспортного средства на транспортном средстве 2.

  • Гусеничный фузер на каждом транспортном средстве сращивает местные пути транспортного средства с путями, полученными от гусеничного фузера другого транспортного средства. После каждого обновления путевой фузер на каждом транспортном средстве передает свои слитые дорожки, которые поступают в следующее обновление путевого фузера на другом транспортном средстве.

В этом примере используется trackerJPDA (Sensor Fusion and Tracking Toolbox) объект для определения трекера транспортного средства 1.

% Create the tracker for vehicle 1
v1Tracker = trackerJPDA('TrackerIndex',1, 'DeletionThreshold', [4 4], 'AssignmentThreshold', [100 inf]); % Vehicle 1 tracker
posSelector = [1 0 0 0 0 0; 0 0 1 0 0 0];

В этой архитектуре слитые дорожки из одного транспортного средства обновляют слитые дорожки на другом транспортном средстве. Эти слитые дорожки затем передаются обратно первому транспортному средству. Чтобы избежать распространения слухов, будьте внимательны, как трассы из другого транспортного средства обновляют путевой фузер.

Рассмотрим следующий пример распространения слухов: на каком-то этапе обновления транспортное средство 1 отслеживает объект с помощью своих внутренних датчиков. Транспортное средство 1 затем сплавляет дорожку объекта и передает ее транспортному средству 2, которое теперь сплавляет дорожку со своими собственными дорожками и получает информацию об объекте. До этого момента именно это и является целью объединения дорожек: повышение ситуационной осведомленности о транспортном средстве 2 с помощью информации от транспортного средства 1. Поскольку транспортное средство 2 теперь знает об объекте, оно также начинает транслировать дорожку, возможно, в интересах другого транспортного средства (не показано в примере).

Однако транспортное средство 1 теперь принимает информацию о дорожке от транспортного средства 2 об объекте, который на самом деле отслеживает только транспортное средство 1. Таким образом, путевой фьюзер на транспортном средстве 1 должен знать, что дорожки этого объекта, который он получает от транспортного средства 2, фактически не содержат никакой новой информации, обновленной независимым источником. Чтобы сделать различие между дорожками, которые содержат новую информацию, и дорожками, которые просто повторяют информацию, необходимо определить транспортное средство 2 как внешний источник для путевого фузера на транспортном средстве 1. Аналогично, транспортное средство 1 должно быть определено как внешний источник для путевого фузера на транспортном средстве 2. Кроме того, необходимо определить только те дорожки, которые обновляются фузером дорожек на основе информации из внутреннего источника в виде самоотчетов. При этом путевой фузер в каждом транспортном средстве игнорирует обновления от дорожек, которые возвращаются назад и вперед между путевыми фузерами без какой-либо новой информации в них.

Локальный трекер каждого транспортного средства отслеживает объекты относительно опорного кадра транспортного средства, называемого эго-кадром. Слияние дорожек выполняется в кадре сценария, который является кадром глобального уровня. Помощник egoToScenario функция преобразует дорожки из эго-кадра в кадр сценария. Аналогично, функция scenarioToEgo преобразует дорожки из кадра сценария в любой из эго-кадров. Оба преобразования основаны на StateParameters имущества objectTrack(Панель инструментов слияния и отслеживания датчиков). Когда trackFuser объект вычисляет расстояние центральной дорожки в кадре сценария до локальной дорожки в любом кадре, использует StateParameters локальной дорожки для выполнения преобразования координат.

Для достижения вышеописанного trackFuser определения, определить следующие источники в качестве fuserSourceConfiguration(Панель инструментов слияния и отслеживания датчиков).

% Define sources for each vehicle
v1TrackerConfiguration = fuserSourceConfiguration('SourceIndex',1,'IsInternalSource',true, ...   % v1Tracker is internal to v1Fuser
    "CentralToLocalTransformFcn", @scenarioToEgo, 'LocalToCentralTransformFcn', @egoToScenario); % Coordinate transformation
v2FuserConfiguration = fuserSourceConfiguration('SourceIndex',4,'IsInternalSource',false);       % v2Fuser is external to v2Fuser
v1Sources = {v1TrackerConfiguration; v2FuserConfiguration};
v2TrackerConfiguration = fuserSourceConfiguration('SourceIndex',2,'IsInternalSource',true, ...   % v2Tracker is internal to v2Fuser
    "CentralToLocalTransformFcn", @scenarioToEgo, 'LocalToCentralTransformFcn', @egoToScenario); % Coordinate transformation
v1FuserConfiguration = fuserSourceConfiguration('SourceIndex',3,'IsInternalSource',false);       % v1Fuser is external to v2Fuser
v2Sources = {v2TrackerConfiguration; v1FuserConfiguration};

Теперь можно определить каждый путевой фузер транспортного средства как trackFuser(Панель инструментов слияния и отслеживания датчиков).

stateParams = struct('Frame','Rectangular','Position',[0 0 0],'Velocity',[0 0 0]);
v1Fuser = trackFuser('FuserIndex',3,...
    'AssignmentThreshold', [100 inf], ...
    'MaxNumSources',2,'SourceConfigurations',v1Sources,...
    'StateFusion','Intersection','DeletionThreshold',[3 3],...
    'StateParameters',stateParams);
v2Fuser = trackFuser('FuserIndex',4,...
    'AssignmentThreshold', [100 inf], ...
    'MaxNumSources',2,'SourceConfigurations',v2Sources,'StateFusion',...
    'Intersection','DeletionThreshold',[3 3],...
    'StateParameters',stateParams);

% Initialize the following variables
fusedTracks1 = objectTrack.empty(0,1);
fusedTracks2 = objectTrack.empty(0,1);
wasFuser1Updated = false;
wasFuser2Updated = false;

Определение сценария

Следующий сценарий показывает, что два автомобиля едут по улице. Транспортное средство 1 является ведущим транспортным средством и оснащено двумя датчиками дальнего обзора: радиолокационным датчиком ближнего радиуса действия и датчиком зрения. Транспортное средство 2, двигающееся в 10 метрах позади транспортного средства 1, оснащено дальним радиолокатором. Правая сторона улицы содержит припаркованные транспортные средства. Между транспортными средствами стоит пешеход. Этот пешеход показан в виде точки на расстоянии приблизительно X = 60 метров.

Благодаря короткому расстоянию между транспортным средством 2 и транспортным средством 1 большая часть зоны действия радиолокационного датчика транспортного средства 2 перекрыта транспортным средством 1. В результате большинство дорожек, которые поддерживает путевой фьюзер на транспортном средстве 2, сначала инициализируются дорожками, транслируемыми из транспортного средства 1.

% Create the drivingScenario object and the two vehicles
[scenario, vehicle1, vehicle2] = createDrivingScenario;

% Create all the sensors
[sensors, numSensors, attachedVehicle] = createSensors(scenario);

% Create display
[f,plotters] = createV2VDisplay(scenario, sensors, attachedVehicle);

Следующий график погони виден с точки зрения второго транспортного средства. Стрелка указывает положение пешехода, которое почти полностью перекрыто припаркованными транспортными средствами и первым транспортным средством.

% Define each vehicle as a combination of an actor, sensors, a tracker, and plotters
v1 = struct('Actor', {vehicle1}, 'Sensors', {sensors(attachedVehicle==1)}, 'Tracker', {v1Tracker}, 'DetPlotter', {plotters.veh1DetPlotter}, 'TrkPlotter', {plotters.veh1TrkPlotter});
v2 = struct('Actor', {vehicle2}, 'Sensors', {sensors(attachedVehicle==2)}, 'Tracker', {{}}, 'DetPlotter', {{}}, 'TrkPlotter', {plotters.veh2TrkPlotter}); % No detections or tracker on Vehicle 2

Запустить моделирование

Следующий код запускает моделирование.

running = true;

% For repeatable results, set the random number seed
s = rng;
rng(2019)
snaptimes = [0.5, 2.8, 4.4, 6.3, inf];
snaps = cell(numel(snaptimes,1));
i = 1;
f.Visible = 'on';
while running && ishghandle(f)
    time  = scenario.SimulationTime;

    % Detect and track at the vehicle level
    [tracks1,wasTracker1Updated] = detectAndTrack(v1,time,posSelector);
    [tracks2,wasTracker2Updated] = detectAndTrack(v2,time,posSelector);

    % Keep the tracks from the previous fuser update
    oldFusedTracks1 = fusedTracks1;
    oldFusedTracks2 = fusedTracks2;

    % Update the fusers
    if wasTracker1Updated || wasFuser2Updated
        tracksToFuse1 = [tracks1;oldFusedTracks2];
        if isLocked(v1Fuser) || ~isempty(tracksToFuse1)
            [fusedTracks1,~,~,info1] = v1Fuser(tracksToFuse1,time);
            wasFuser1Updated = true;
            pos = getTrackPositions(fusedTracks1,posSelector);
            ids = string([fusedTracks1.TrackID]');
            plotTrack(plotters.veh1FusePlotter,pos,ids);
        else
            wasFuser1Updated = false;
            fusedTracks1 = objectTrack.empty(0,1);
        end
    else
        wasFuser1Updated = false;
        fusedTracks1 = objectTrack.empty(0,1);
    end
    if wasTracker2Updated || wasFuser1Updated
        tracksToFuse2 = [tracks2;oldFusedTracks1];
        if isLocked(v2Fuser) || ~isempty(tracksToFuse2)
            [fusedTracks2,~,~,info2] = v2Fuser(tracksToFuse2,time);
            wasFuser2Updated = true;
            pos = getTrackPositions(fusedTracks2,posSelector);
            ids = string([fusedTracks2.TrackID]');
            plotTrack(plotters.veh2FusePlotter,pos,ids);
        else
            wasFuser2Updated = false;
            fusedTracks2 = objectTrack.empty(0,1);
        end
    else
        wasFuser2Updated = false;
        fusedTracks2 = objectTrack.empty(0,1);
    end

    % Update the display
    updateV2VDisplay(plotters, scenario, sensors, attachedVehicle)

    % Advance the scenario one time-step and exit the loop if the scenario is complete
    running = advance(scenario);

    % Snap a shot at required times
    if time >= snaptimes(i)
        snaps{i} = getframe(f);
        i = i + 1;
    end
end

Figure contains 2 axes and other objects of type uipanel. Axes 1 contains 9 objects of type patch, line, text. These objects represent radar, vision, Detections, Local Tracks, Fuser Tracks. Axes 2 contains 7 objects of type patch, line, text. These objects represent radar, Local Tracks, Fuser Tracks.

На рисунке показаны сцена и результаты отслеживания в конце сценария. В последующих разделах этого примера анализируются результаты отслеживания в ключевые моменты времени.

Анализ отслеживания в начале моделирования

Когда начинается моделирование, транспортное средство 1 обнаруживает транспортные средства, припаркованные на правой стороне улицы. Затем трекер транспортного средства 1 подтверждает пути, связанные с припаркованными транспортными средствами и. В это время единственным объектом, обнаруженным и отслеживаемым трекером транспортного средства 2, является транспортное средство 1, которое находится непосредственно перед ним. Как только путевой фузер транспортного средства 1 подтверждает наличие дорожек, он передает их в широковещательном режиме, и путевой фузер транспортного средства 2 сплавляет их. В результате транспортное средство 2 узнает о припаркованных транспортных средствах, прежде чем оно сможет обнаружить их самостоятельно.

showsnap(snaps, 1)

Figure Snap #1 contains an axes. The axes contains an object of type image.

Анализ отслеживания пешеходов на стороне улицы

По мере продолжения моделирования транспортное средство 2 также способно обнаруживать и отслеживать транспортные средства, припаркованные сбоку, и сплавлять их с путями, идущими от транспортного средства 1. Транспортное средство 2 способно обнаруживать и отслеживать пешехода около 4 секунд при моделировании, а транспортное средство 2 сплавляет дорожку, связанную с пешеходом, около 4,4 секунд при моделировании (см. снимок 2). Однако транспортное средство 2 занимает около двух секунд, прежде чем оно сможет обнаружить и отследить пешехода с помощью собственных датчиков (см. снимок 3). Эти две секунды могут оказать огромное влияние на безопасность пешехода, если тот пешеход начал переходить улицу.

showsnap(snaps, 2)

Figure Snap #2 contains an axes. The axes contains an object of type image.

showsnap(snaps, 3)

Figure Snap #3 contains an axes. The axes contains an object of type image.

Как избежать распространения слухов

Когда транспортные средства пропускают объекты и эти объекты выходят из поля их зрения, слитые дорожки, связанные с этими объектами, сбрасываются обоими трекерами (см. снимок 4). Удаление дорожек демонстрирует, что слитые дорожки, транслируемые туда и обратно между двумя транспортными средствами, не используются для распространения слухов.

showsnap(snaps, 4)

Figure Snap #4 contains an axes. The axes contains an object of type image.

% Restart the driving scenario to return the actors to their initial positions.
restart(scenario);

% Release all the sensor objects so they can be used again.
for sensorIndex = 1:numSensors
    release(sensors{sensorIndex});
end

% Return the random seed to its previous value
rng(s)

Резюме

В этом примере показано, как слияние «дорожка-дорожка» может повысить ситуационную осведомленность и повысить безопасность автомобильных приложений. Вы видели, как настроить trackFuser для выполнения слияния дорожек и определения источников как внутренних или внешних с помощью fuserSourceConfiguration объект. Таким образом, вы избегаете распространения слухов и сохраняете только слитые дорожки, которые действительно наблюдаются каждым транспортным средством, подлежащим обслуживанию.

Ссылки

[1] Бхаранидхар Дураисами, Тило Шварц и Кристиан Вулер, «Алгоритмы слияния уровней для приложений автомобильной безопасности», Международная конференция по обработке сигналов, обработке изображений и распознаванию образов, IEEE, 2013.

Вспомогательные функции

createDrivingScenario

Создает сценарий вождения, определенный в приложении Конструктор сценариев вождения.

function [scenario, egoVehicle, secondVehicle] = createDrivingScenario
% Construct a drivingScenario object.
scenario = drivingScenario('SampleTime', 0.1);

% Add all road segments
roadCenters = [50.8 0.5 0; 253.4 1.5 0];
roadWidth = 12;
road(scenario, roadCenters, roadWidth);

roadCenters = [100.7 -100.6 0; 100.7 103.7 0];
road(scenario, roadCenters);

roadCenters = [201.1 -99.2 0; 199.7 99.5 0];
road(scenario, roadCenters);

% Add the ego vehicle
egoVehicle = vehicle(scenario, 'ClassID', 1, 'Position', [65.1 -0.9 0], 'PlotColor', [0 0.7410 0.4470]);
waypoints = [71 -0.5 0; 148.7 -0.5 0];
speed = 12;
trajectory(egoVehicle, waypoints, speed);

% Add the second vehicle
secondVehicle = vehicle(scenario, 'ClassID', 1, 'Position', [55.1 -0.9 0]);
waypoints = [61 -0.5 0; 138.7 -0.5 0];
speed = 12;
trajectory(secondVehicle, waypoints, speed);

% Add the parked cars
vehicle(scenario, 'ClassID', 1, 'Position', [111.0 -3.6 0]);
vehicle(scenario, 'ClassID', 1, 'Position', [140.6 -3.6 0]);
vehicle(scenario, 'ClassID', 1, 'Position', [182.6 -3.6 0]);
vehicle(scenario, 'ClassID', 1, 'Position', [211.3 -4.1 0]);

% Add pedestrian
actor(scenario, 'ClassID', 4, 'Length', 0.5, 'Width', 0.5, ...
    'Height', 1.7, 'Position', [130.3 -2.7 0], 'RCSPattern', [-8 -8;-8 -8]);

% Add parked truck
vehicle(scenario, 'ClassID', 2, 'Length', 8.2, 'Width', 2.5, ...
    'Height', 3.5, 'Position', [117.5 -3.5 0]);
end

createSensors

Создает датчики, используемые в сценарии, и перечисляет их крепления к транспортным средствам.

function [sensors, numSensors, attachedVehicle] = createSensors(scenario)
% createSensors Returns all sensor objects to generate detections
% Units used in createSensors and createDrivingScenario
% Distance/Position - meters
% Speed             - meters/second
% Angles            - degrees
% RCS Pattern       - dBsm

% Assign into each sensor the physical and radar profiles for all actors
profiles = actorProfiles(scenario);

% Vehicle 1 radar reports clustered detections
sensors{1} = radarDataGenerator('No scanning', 'SensorIndex', 1, 'UpdateRate', 10, ...
    'MountingLocation', [3.7 0 0.2], 'RangeLimits', [0 50], 'FieldOfView', [60 5], ...
    'RangeResolution', 2.5, 'AzimuthResolution', 4, ...
    'Profiles', profiles, 'HasOcclusion', true, 'HasFalseAlarms', false, ...
    'TargetReportFormat', 'Clustered detections');

% Vehicle 2 radar reports tracks
sensors{2} = radarDataGenerator('No scanning', 'SensorIndex', 2, 'UpdateRate', 10, ...
    'MountingLocation', [3.7 0 0.2], 'RangeLimits', [0 120], 'FieldOfView', [30 5], ...
    'RangeResolution', 2.5, 'AzimuthResolution', 4, ...
    'Profiles', profiles, 'HasOcclusion', true, 'HasFalseAlarms', false, ...
    'TargetReportFormat', 'Tracks', 'DeletionThreshold', [3 3]);

% Vehicle 1 vision sensor reports detections
sensors{3} = visionDetectionGenerator('SensorIndex', 3, ...
    'MaxRange', 100, 'SensorLocation', [1.9 0], 'DetectorOutput', 'Objects only', ...
    'ActorProfiles', profiles);
attachedVehicle = [1;2;1];
numSensors = numel(sensors);
end

scenarioToEgo

Преобразование координат из сценария в эго-координаты.

trackInScreage имеет параметры StateParameters, определенные для преобразования его из координат сценария в эго-координаты.

В этом состоянии используется модель постоянной скорости [x; vx; y; vy; z; vz].

function trackInEgo = scenarioToEgo(trackInScenario)
egoPosInScenario = trackInScenario.StateParameters.OriginPosition;
egoVelInScenario = trackInScenario.StateParameters.OriginVelocity;
stateInScenario = trackInScenario.State;
stateShift = [egoPosInScenario(1);egoVelInScenario(1);egoPosInScenario(2);egoVelInScenario(2);egoPosInScenario(3);egoVelInScenario(3)];
stateInEgo = stateInScenario - stateShift;
trackInEgo = objectTrack('UpdateTime',trackInScenario.UpdateTime,'State',stateInEgo,'StateCovariance',trackInScenario.StateCovariance,'StateParameters',trackInScenario.StateParameters);
end

egoToScenario

Выполняет преобразование координат из ego в координаты сценария.

trackInEgo имеет параметры StateParameters, определенные для преобразования его из эго-координат в координаты сценария.

В этом состоянии используется модель постоянной скорости [x; vx; y; vy; z; vz].

function trackInScenario = egoToScenario(trackInEgo)
egoPosInScenario = trackInEgo.StateParameters.OriginPosition;
egoVelInScenario = trackInEgo.StateParameters.OriginVelocity;
stateInScenario = trackInEgo.State;
stateShift = [egoPosInScenario(1);egoVelInScenario(1);egoPosInScenario(2);egoVelInScenario(2);egoPosInScenario(3);egoVelInScenario(3)];
stateInEgo = stateInScenario + stateShift;
trackInScenario = objectTrack('UpdateTime',trackInEgo.UpdateTime,'State',stateInEgo,'StateCovariance',trackInEgo.StateCovariance,'StateParameters',trackInEgo.StateParameters);
end

detectAndTrack

Эта функция используется для сбора всех обнаружений от датчиков в одном транспортном средстве и обновления трекера с ними.

Агент представляет собой структуру, которая содержит информацию об акторе и датчики, трекер и необходимый плоттер для построения графиков обнаружения и дорожек транспортных средств.

function [tracks,wasTrackerUpdated] = detectAndTrack(agent,time,posSelector)
% Create detections from the vehicle
poses = targetPoses(agent.Actor);
[detections,isValid] = vehicleDetections(agent.Actor.Position,agent.Sensors,poses,time,agent.DetPlotter);

% Update the tracker to get tracks from sensors that reported detections
if isValid
    agent.Tracker.StateParameters = struct(...
        'Frame','Rectangular', ...
        'OriginPosition', agent.Actor.Position, ...
        'OriginVelocity', agent.Actor.Velocity);
    tracks = agent.Tracker(detections,time);
    tracksInScenario = tracks;
    for i = 1:numel(tracks)
        tracksInScenario(i) = egoToScenario(tracks(i));
    end
    pos = getTrackPositions(tracksInScenario,posSelector);
    plotTrack(agent.TrkPlotter,pos)
    wasTrackerUpdated = true;
else
    tracks = objectTrack.empty(0,1);
    wasTrackerUpdated = false;
end

% Get additional tracks from tracking sensors
[sensorTracks,wasSensorTrackerUpdated] = vehicleTracks(agent.Actor,agent.Sensors,poses,time,agent.TrkPlotter);
tracks = vertcat(tracks,sensorTracks);
wasTrackerUpdated = wasTrackerUpdated || wasSensorTrackerUpdated;
end

vehicleDetections

Собирает обнаруженные сигналы от всех датчиков, прикрепленных к данному транспортному средству, которые возвращают обнаруженные сигналы.

function [objectDetections,isValid] = vehicleDetections(position, sensors, poses, time, plotter)
numSensors = numel(sensors);
objectDetections = {};
isValidTime = false(1, numSensors);

% Generate detections for each sensor
for sensorIndex = 1:numSensors
    sensor = sensors{sensorIndex};
    if isa(sensor, 'visionDetectionGenerator') || ~strcmpi(sensor.TargetReportFormat,'Tracks')
        [objectDets, ~, sensorConfig] = sensor(poses, time);
        if islogical(sensorConfig)
            isValidTime(sensorIndex) = sensorConfig;
        else
            isValidTime(sensorIndex) = sensorConfig.IsValidTime;
        end
        objectDets = cellfun(@(d) setAtt(d), objectDets, 'UniformOutput', false);
        numObjects = numel(objectDets);
        objectDetections = [objectDetections; objectDets(1:numObjects)]; %#ok<AGROW>
    end
end
isValid = any(isValidTime);

% Plot detections
if numel(objectDetections)>0
    detPos = cellfun(@(d)d.Measurement(1:2), objectDetections, 'UniformOutput', false);
    detPos = cell2mat(detPos')' + position(1:2);
    plotDetection(plotter, detPos);
end
end

function d = setAtt(d)
% Set the attributes to be struct
d.ObjectAttributes = struct;
% Keep only the position measurement and remove velocity
if numel(d.Measurement)==6
    d.Measurement = d.Measurement(1:3);
    d.MeasurementNoise = d.MeasurementNoise(1:3,1:3);
    d.MeasurementParameters{1}.HasVelocity = false;
end
end

vehicleTracks

Собирает все дорожки с датчиков, сообщающих о дорожках на транспортном средстве.

function [tracks,wasTrackerUpdated] = vehicleTracks(actor, sensors, poses, time, plotter)
% Create detections from the vehicle
numSensors = numel(sensors);
tracks = objectTrack.empty;
isValidTime = false(1, numSensors);

% Generate detections for each sensor
for sensorIndex = 1:numSensors
    sensor = sensors{sensorIndex};
    if isa(sensor, 'radarDataGenerator') && strcmpi(sensor.TargetReportFormat,'Tracks')
        [sensorTracks, ~, sensorConfig] = sensor(poses, time);
        if islogical(sensorConfig)
            isValidTime(sensorIndex) = sensorConfig;
        else
            isValidTime(sensorIndex) = sensorConfig.IsValidTime;
        end
        numObjects = numel(sensorTracks);
        tracks = [tracks; sensorTracks(1:numObjects)]; %#ok<AGROW>
    end
end
wasTrackerUpdated = any(isValidTime);

if ~wasTrackerUpdated % No vehicle tracking sensor udpated
    return
end

% Add vehicle position and velocity to track state parameters
for i = 1:numel(tracks)
    tracks(i).StateParameters.OriginPosition = tracks(i).StateParameters.OriginPosition + actor.Position';
    tracks(i).StateParameters.OriginVelocity = tracks(i).StateParameters.OriginVelocity + actor.Velocity';
end

% Plot tracks
if numel(tracks)>0
    trPos = arrayfun(@(t)t.State([1,3]), tracks, 'UniformOutput', false);
    trPos = cell2mat(trPos')' + actor.Position(1:2);
    plotTrack(plotter, trPos);
end
end