В этом примере показано, как плавить дорожки от двух транспортных средств, чтобы обеспечить более всестороннюю оценку среды, чем видны каждому транспортному средству. Пример демонстрирует использование термофиксатора уровня дорожки и объектного формата данных дорожки. В этом примере вы используете ведущий сценарий и генератор обнаружения видения от Automated Driving Toolbox™, радарный генератор данных от Radar Toolbox™ и отслеживание и отслеживаете модели сплава от Sensor Fusion and Tracking Toolbox™.
Автомобильные приложения безопасности используют сплав данных из различных систем датчика, смонтированных на транспортном средстве. Отдельные транспортные средства плавят обнаружения датчика или при помощи централизованного средства отслеживания или путем проявления более децентрализованного подхода и плавления дорожек, произведенных отдельными датчиками. В дополнение к сплаву данных о внутритранспортном средстве сплав данных из нескольких транспортных средств предоставляет дополнительные преимущества, которые включают лучшее покрытие, ситуативную осведомленность и безопасность [1]. Этот подход cочетания датчиков межтранспортного средства использует в своих интересах множество датчиков и предоставляет лучше страховую защиту к каждому транспортному средству, потому что это использует данные, обновленные датчиками на других транспортных средствах в области. Правительства и производители транспортного средства долго распознавали потребность поделиться информацией между транспортными средствами для того, чтобы увеличить автомобильную безопасность. Например, протоколы V2X и ссылки сотовой связи разрабатываются.
В то время как cочетание датчиков через несколько транспортных средств выгодно, большинство транспортных средств требуется, чтобы выполнять определенным требованиям техники безопасности, даже если только внутренние датчики доступны. Поэтому транспортное средство, вероятно, будет оборудовано средством отслеживания, термофиксатором дорожки или обоими. Эти алгоритмы отслеживания обеспечивают ситуативную осведомленность на одном уровне транспортного средства. В результате предположение, сделанное в этом примере, - то, что транспортные средства совместно используют ситуативную осведомленность путем широковещательной передачи дорожек и выполнения сплава от дорожки к дорожке.
Этот пример демонстрирует преимущество плавления дорожек от двух транспортных средств, чтобы улучшить ситуативную осведомленность и безопасность. Этот пример не симулирует системы связи. Вместо этого пример принимает, что система связи обеспечивает полосу пропускания, требуемую передать дорожки между этими двумя транспортными средствами.
Следующая блок-схема изображает основные функции в этих двух транспортных средствах, где:
Транспортное средство 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
(Sensor Fusion and Tracking Toolbox) объекты. Когда trackFuser
объект вычисляет расстояние центральной дорожки в системе координат сценария к локальной дорожке в любой системе координат, это использует StateParameters
из локальной дорожки, чтобы выполнить координатное преобразование.
Достигнуть ранее описанного trackFuser
определения, задайте следующие источники как fuserSourceConfiguration
Объект (Sensor Fusion and Tracking Toolbox).
% 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
Объект (Sensor Fusion and Tracking Toolbox).
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); % Capture an image of the frame at specified times if time >= snaptimes(i) snaps{i} = takesnap(f); i = i + 1; end end
Рисунок показывает сцену и отслеживающие результаты в конце сценария. Последующие разделы этого примера анализируют результаты отслеживания в ключевые времена.
Когда симуляция начинается, транспортное средство 1 обнаруживает транспортные средства, припаркованные на правой стороне улицы. Затем транспортное средство 1 средство отслеживания подтверждает дорожки, сопоставленные с припаркованными транспортными средствами. В это время единственный объект обнаружил и прослеженный транспортным средством, 2 средства отслеживания являются транспортным средством 1, который сразу является перед ним. Однажды транспортное средство 1 термофиксатор дорожки подтверждает дорожки, это широковещательно передает их и транспортное средство, 2 термофиксатора дорожки плавят их. В результате транспортное средство 2 узнает припаркованные транспортные средства, прежде чем оно сможет обнаружить их самостоятельно.
showsnap(snaps,1)
В то время как симуляция продолжается, транспортное средство 2 может обнаружить и отследить транспортные средства, припаркованные в стороне также, и плавит их с дорожками, прибывающими из транспортного средства 1. Транспортное средство 2 может обнаружить и отследить пешехода приблизительно 4 секунды в симуляцию и транспортное средство 2 предохранителя дорожка, сопоставленная с пешеходом приблизительно 4,4 секунды в симуляцию (см. снимок состояния 2). Однако это садится в транспортное средство 2 приблизительно за две секунды до того, как это сможет обнаружить и отследить пешехода своими собственными датчиками (см. снимок состояния 3). Обнаружение пешехода на улице двумя секундами ранее может заметно повысить уровень безопасности.
showsnap(snaps,2)
showsnap(snaps,3)
Когда эти два транспортных средства передают дорожки друг другу, существует риск, что они продолжат передавать информацию об объектах, которые они не обнаруживают больше только путем повторения что другое переданное транспортное средство. Эта ситуация называется распространением слуха.
Когда транспортные средства передают объекты, и эти объекты выходят из своего поля зрения, сплавленные дорожки, сопоставленные с этими объектами, пропущены обоими средствами отслеживания (см. снимок состояния 4). Отбрасывание дорожек демонстрирует, что сплавленная широковещательная передача дорожек назад и вперед между этими двумя транспортными средствами не используется, чтобы распространить слухи.
showsnap(snaps,4)
% 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] Duraisamy, B., Т. Шварц и К. Уохлер. “Отследите Алгоритмы Fusion Уровня для Автомобильных Приложений Безопасности”. На 2 013 Международных конференциях по вопросам Signal Processing, Image Processing & Pattern Recognition, 179–84, 2013. https://doi.org/10.1109/ICSIPR.2013.6497983.
createDrivingScenario
Создайте ведущий сценарий, заданный в приложении Driving Scenario Designer.
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
Выполните координатное преобразование от сценария до координат эго.
trackInScenario
имеет StateParameters
заданный, чтобы преобразовать его из сценария координирует к координатам эго.
Состояние использует постоянную скоростную модель [x; vx; y;; z;].
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
Выполните координатное преобразование от эго до координат сценария.
trackInEgo
имеет StateParameters
заданный, чтобы преобразовать его от эго координирует к координатам сценария.
Состояние использует постоянную скоростную модель [x; vx; y;; z;].
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 a structure 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