Этот пример показывает, как использовать управление радиолокационными ресурсами для эффективного отслеживания нескольких маневрирующих целей. Отслеживание маневрирующих целей требует, чтобы радар пересматривал цели чаще, чем отслеживание не маневрирующих целей. Фильтр «Взаимодействие нескольких моделей» (IMM) оценивает, когда цель маневрирует. Эта оценка помогает управлять временем пересмотра радара и, следовательно, улучшает отслеживание. Этот пример использует Radar Toolbox™ для модели радара и Sensor Fusion and Tracking Toolbox™ для отслеживания.
Многофункциональные радары могут искать цели, подтверждать новые треки и пересматривать треки, чтобы обновить состояние. Для выполнения этих функций многофункциональным радаром часто управляет менеджер ресурсов, который создает радиолокационные задачи для поиска, подтверждения и отслеживания. Эти задачи планируются в соответствии с приоритетом и временем, так что на каждом временном шаге многофункциональный радар может указывать свой луч в желаемом направлении. В примере Search and Track Scheduling for Multifunction Phased Array Radar (Radar Toolbox) показан многофункциональный радар с фазированной решеткой, управляемый менеджером ресурсов.
В этом примере мы расширяем пример Адаптивного Отслеживания Маневрирующих Целей с Управляемым Радаром (Radar Toolbox) до случая нескольких маневрирующих целей. Существует два противоречивых требования к радару, используемому для отслеживания маневрирующих целей:
Количество целей и их начальное местоположение обычно не известны заранее. Поэтому радар должен постоянно искать интересующую область, чтобы найти цели. Кроме того, радар должен обнаружить и установить дорожку на каждой цели, как только он войдет в зону покрытия радара.
Период времени маневрирования цели неизвестен в усовершенствование. Если известно, что цели не маневрируют, радар может пересматривать цели нечасто. Однако, поскольку начало и конец маневра неизвестно, радар должен пересматривать каждую дорожку достаточно часто, чтобы иметь возможность распознавать, когда маневр начинается и заканчивается.
Радар должен сбалансироваться между обеспечением достаточного количества лучей с центром на сопровождаемых целях и оставлением достаточного времени для поиска новых целей. Один из подходов состоит в том, чтобы просто определить скорость повторного просмотра для каждой отслеживаемой цели независимо от ее статуса маневрирования и оставить оставшееся время для поиска новой цели. Эта схема управления радаром иногда упоминается как Активное Отслеживание [1]. Когда больше целей становится отслеживаемым, радар может или выполнять меньше задач поиска или он может отслеживать каждую цель реже. Очевидно, что если количество целей велико, радар может быть перегружен.
Активное отслеживание обрабатывает все дорожки одинаково, что делает его основанным на режиме алгоритмом управления ресурсами. Более сложный способ управления радаром основан на свойствах каждой дорожки. Например, используйте свойства дорожки, такие как размер ковариации неопределенности состояния, маневрирует ли дорожка и насколько быстро она движется к активу, который защищает сайт радара. Когда такие свойства используются, управление ресурсами радара упоминается как Адаптивное Отслеживание [1].
В этом примере вы сравниваете результаты Active Tracking и Adaptive Tracking, когда радар адаптируется на основе предполагаемого маневра пути.
Вы задаете сценарий и радар со частотой обновления 20 Гц, что означает, что радар имеет 20 лучей в секунду, выделенных для поиска, подтверждения или отслеживания. Вы загружаете траектории бенчмарка, используемые в примере Benchmark Trajectories for Multi-Object Tracking. Существует шесть траекторий бенчмарка, и вы задаете траекторию для каждой. Из рисунка ниже шесть платформ следуют неманеврирующим ногам, перемежающимся маневрирующими ногами. Траектории можно просмотреть на рисунке ниже.
% Create scenario updateRate = 20; scenario = trackingScenario('UpdateRate',updateRate); % Add the benchmark trajectories load('BenchmarkTrajectories.mat','-mat'); platform(scenario,'Trajectory',v1Trajectory); platform(scenario,'Trajectory',v2Trajectory); platform(scenario,'Trajectory',v3Trajectory); platform(scenario,'Trajectory',v4Trajectory); platform(scenario,'Trajectory',v5Trajectory); platform(scenario,'Trajectory',v6Trajectory); % Create visualization f = figure; mp = uipanel('Parent',f,'Title','Theater Plot','FontSize',12,... 'BackgroundColor','white','Position',[.01 .25 .98 .73]); tax = axes(mp,'ZDir','reverse'); % Visualize scenario thp = theaterPlot('Parent',tax,'AxesUnits',["km","km","km"],'XLimits',[0 85000],'YLimits',[-45000 70000],'ZLimits',[-10000 1000]); plp = platformPlotter(thp, 'DisplayName', 'Platforms'); pap = trajectoryPlotter(thp, 'DisplayName', 'Trajectories', 'LineWidth', 1); dtp = detectionPlotter(thp, 'DisplayName', 'Detections'); cvp = coveragePlotter(thp, 'DisplayName', 'Radar Coverage'); trp = trackPlotter(thp, 'DisplayName', 'Tracks', 'ConnectHistory', 'on', 'ColorizeHistory', 'on'); numPlatforms = numel(scenario.Platforms); trajectoryPositions = cell(1,numPlatforms); for i = 1:numPlatforms trajectoryPositions{i} = lookupPose(scenario.Platforms{i}.Trajectory,(0:0.1:185)); end plotTrajectory(pap, trajectoryPositions); view(tax,3)
Вы задаете радар используя helperManagedRadarDataGenerator
объект, который является объектом, унаследованным от radarDataGenerator
Системный объект. The helperManagedRadarDataGenerator
обеспечивает вероятностную радиолокационную модель и позволяет указывать радар на определенное направление. Эта настройка позволяет менеджеру ресурсов радара планировать радар для поиска, подтверждения и сопровождения целей. Радар моделирует электронные лучи, которые имеют пределы сканирования азимута [-90 60] степеней и пределы повышения [-9,9 0] степеней. Отрицательные углы возвышения означают, что радар указывает луч от горизонта вверх. Установите радар на новой платформе в сценарии.
radar = helperManagedRadarDataGenerator(1, ... 'ScanMode', 'Electronic', ... 'UpdateRate', updateRate, ... 'MountingLocation', [0 0 -15], ... 'FieldOfView', [3;10], ... 'AzimuthResolution', 1.5, ... 'ElectronicAzimuthLimits', [-90 60], ... 'ElectronicElevationLimits', [-9.9 0], ... 'HasElevation', true, ... 'DetectionCoordinates', 'Sensor spherical'); platform(scenario,'Position',[0 0 0],'Sensors',radar);
После того, как радар обнаруживает объекты, он подает обнаружения на трекер, который выполняет несколько операций. Трекер поддерживает список треков, которые являются оценками целевых состояний в интересующей области. Если обнаружение не может быть назначено ни одному треку, уже поддерживаемому трекером, трекер инициирует новый трек. В большинстве случаев неясно, представляет ли новая дорожка истинную цель или ложную цель. Сначала создается трек с предварительным статусом. Если получено достаточное количество обнаружений, дорожка становится подтвержденной. Точно так же, если никакие обнаружения не назначены дорожке, дорожка покрывается (прогнозируется без коррекции). Если у трека несколько пропущенных обновлений, трекер удаляет трек.
В этом примере вы используете трекер, который связывает обнаружения с треками с помощью глобального алгоритма ближайшего соседа (GNN). Чтобы отслеживать маневрирующие цели, вы задаете FilterInitializationFcn
который инициализирует фильтр Interacting Multiple Model (IMM). The initMPARIMM
функция использует две модели движения: модель постоянной скорости и модель постоянной скорости поворота. The trackingIMM
фильтр отвечает за оценку вероятности каждой модели, к которой можно получить доступ из ее ModelProbabilities
свойство. В этом примере вы классифицируете цель как маневрирующую, когда вероятность модели скорости постоянного поворота выше 0,6.
tracker = trackerGNN('FilterInitializationFcn',@initMPARIMM,... 'ConfirmationThreshold',[2 3], 'DeletionThreshold',[5 5],... 'HasDetectableTrackIDsInput',true,'AssignmentThreshold',150,... 'MaxNumTracks',10,'MaxNumSensors',1); posSelector = [1 0 0 0 0 0; 0 0 1 0 0 0; 0 0 0 0 1 0];
В этом разделе только кратко описывается управление ресурсами радара. Для получения дополнительной информации смотрите пример Адаптивного Отслеживания Маневрирующих Целей с Управляемым Радаром (Radar Toolbox).
Задачи поиска
Задачи поиска присваиваются определенно в этом примере. Растровый скан используется, чтобы закрыть желаемое воздушное пространство. Если других задач не существует, радар сканирует пространство по одной угловой камере за раз. Размер угловой камеры определяется радаром FieldOfView
свойство и ограничено радаром ElectronicAzimuthLimits
и ElectronicElevatonLimits
свойства.
azscanspan = diff(radar.ElectronicAzimuthLimits); numazscan = floor(azscanspan/radar.FieldOfView(1))+1; azscanangles = linspace(radar.ElectronicAzimuthLimits(1),radar.ElectronicAzimuthLimits(2),numazscan)+radar.MountingAngles(1); elscanspan = diff(radar.ElectronicElevationLimits); numelscan = floor(elscanspan/radar.FieldOfView(2))+1; elscanangles = linspace(radar.ElectronicElevationLimits(1),radar.ElectronicElevationLimits(2),numelscan)+radar.MountingAngles(2); [elscangrid,azscangrid] = meshgrid(elscanangles,azscanangles); scanangles = [azscangrid(:) elscangrid(:)].'; searchq = struct('JobType','Search','BeamDirection',num2cell(scanangles,1),... 'Priority',1000,'WaveformIndex',1); current_search_idx = 1;
Отслеживайте задачи
В отличие от задач поиска, отслеживать задачи нельзя заранее планировать. Вместо этого менеджер ресурсов создает задачи подтверждения и отслеживания на основе изменяющегося сценария. Основным различием этого примера от примера Адаптивного Отслеживания Маневрирующих Целей с Управляемым Радаром (Radar Toolbox) является то, что JobType
для каждой задачи трекинга может быть либо "TrackNonManeuvering"
или "TrackManeuvering"
. Различие между двумя типами задач отслеживания позволяет вам планировать задачи для каждого типа дорожки с различными скоростями повторного просмотра, что делает его адаптивным алгоритмом отслеживания. Подобно задачам поиска, задачи отслеживания также управляются в очереди заданий.
trackq = repmat(struct('JobType',[],'BeamDirection',[],'Priority',3000,'WaveformIndex',[],... 'Time',[],'Range',[],'TrackID',[]), 10, 1); num_trackq_items = 0;
Сгруппируйте очереди поиска и отслеживания вместе в структуре для более легкой ссылки в цикле симуляции.
jobq.SearchQueue = searchq;
jobq.SearchIndex = current_search_idx;
jobq.TrackQueue = trackq;
jobq.NumTrackJobs = num_trackq_items;
jobq.PositionSelector = posSelector;
% Keep a reset state of jobq
resetJobQ = jobq;
Планирование задач
В этом примере для простоты многофункциональный радар выполняет только один тип задания в течение небольшого периода времени, часто называемого dwell, но может переключать задачи в начале каждого dwell. Для каждого dwell радар просматривает все задачи, которые подлежат выполнению, и выбирает подтверждение или отслеживает задачу, если их время для запуска пришло. В противном случае радар выбирает задачу поиска. Чтобы контролировать время выполнения задач, вы устанавливаете managerPreferences
struct, заданная ниже. Самая высокая частота повторного просмотра, которая равна частоте обновления радара, дается confirm
задача, чтобы гарантировать, что пучок подтверждения следует за каждой новой предварительной дорожкой, которая существует. Точно так же можно управлять скоростью пересмотра для неманеврирующих и маневрирующих целей. При этом вы выбираете значения 1Hz и 4 Гц для неманеврирующих и маневрирующих целей соответственно. Поскольку есть шесть целей, в то время как частота обновления радара составляет 20, если цели не маневрируют, радар должен тратить около 70% времени в поисковом режиме и 30% времени в режиме слежения. Когда новые дорожки инициализируются и когда трекер считает, что цели маневрируют, менеджер ресурсов выделяет больше пучков слежения за счет поисковых пучков.
В разделе Анализ результатов показаны результаты других опций.
managerPreferences = struct(... 'Type', {"Search","Confirm","TrackNonManeuvering","TrackManeuvering"}, ... 'RevisitRate', {0, updateRate, 1, 4}, ... 'Priority', {1000, 3000, 1500, 2500});
Во время симуляции радиолокационный луч изображается синим или фиолетовым цветами, представляющими лучи, связанные с поиском и дорожкой, соответственно. Распределение задач между поиском и конкретными треками на последнюю секунду симуляции можно также увидеть с помощью панели «Распределение ресурсов» на панели «Последняя секунда» в нижней части рисунка. На верхнем рисунке можно увидеть историю каждой дорожки и сравнить ее с траекторией.
% Create a radar resource allocation display rp = uipanel('Parent',f,'Title','Resource Allocation in the Last Second','FontSize',12,... 'BackgroundColor','white','Position',[.01 0.01 0.98 0.23]); rax = axes(rp); % Run the scenario allocationType = helperAdaptiveTrackingSim(scenario, thp, rax, tracker, resetJobQ, managerPreferences);
Анализируйте нагрузку радиолокационной задачи и ее деление между заданиями поиска, подтверждения и отслеживания. График ниже показывает, что в течение большей части времени радар выделяет около 70% заданий поиска и 30% заданий отслеживания, что ожидаемо, когда цели не маневрируют. Когда цели маневрируют, менеджер ресурсов адаптируется, чтобы выделить больше заданий отслеживания. Когда одновременно маневрирует больше трасс, появляется больше заданий слежения, что видно, например, около 700-го временного шага. Задания подтверждения занимают очень мало радарного времени, потому что трекер сконфигурирован для подтверждения треков после двух ассоциаций обнаружения в трех попытках. Поэтому подтверждение или отказ от предварительных дорожек является быстрым.
numSteps = numel(allocationType); allocationSummary = zeros(3,numSteps); for i = 1:numSteps for jobType = 1:3 allocationSummary(jobType,i) = sum(allocationType(1,max(1,i-2*updateRate+1):i)==jobType)/min(i-1,2*updateRate); end end figure; plot(1:numSteps,allocationSummary(:,1:numSteps)) title('Radar Allocation vs. Time Step'); xlabel('Time Step'); ylabel('Fraction of step in the last two seconds in each mode'); legend('Search','Confirmation','Tracking'); grid on
Теперь вы хотите сравнить результат выше с результатом активного отслеживания с 1Hz частотой повторного просмотра трека. Следующие рисунки показывают результаты отслеживания и график распределения радаров для случая активного отслеживания. Результаты отслеживания показывают, что некоторые треки были потеряны и сломаны, но график распределения радиолокационных ресурсов показывает 70% задачу поиска и 30% отслеживания деления как в случае Адаптивного Отслеживания. Вы можете получить эти результаты, выполнив выборку кода ниже.
% Modify manager preferences to 1Hz revisit rate for both non-maneuvering and maneuvering targets managerPreferences = struct(... 'Type', {"Search","Confirm","TrackNonManeuvering","TrackManeuvering"}, ... 'RevisitRate', {0, updateRate, 1, 1}, ... 'Priority', {1000, 3000, 1500, 2500}); % Run the scenario allocationType = helperAdaptiveTrackingSim(scenario, thp, rax, tracker, resetJobQ, managerPreferences);
Очевидно, что для активного отслеживания необходима более высокая скорость пересмотра отслеживания. Два графика ниже показывают, что увеличение скорости пересмотра дорожки до 2Hz улучшает отслеживание маневрирующих целей. Однако стоимость в том, что радар посвящает более 50% своего времени отслеживанию задач, даже когда трассы не маневрируют. Если бы количество целей было больше, радар стал бы перегружен.
Предыдущие результаты показывают, что достаточно пересмотреть маневрирующие цели со скоростью 2Hz. Однако может ли Adaptive Tracking использоваться, чтобы уменьшить скорость повторного рассмотрения неманеврирующих целей, чтобы 0.5Hz? Приведенные ниже графики показывают, что отслеживание все еще хорошо. При такой настройке выделение радара позволяет на 80% -90% времени в поисковом режиме, оставляя радар с способностью искать и отслеживать еще больше целей.
В этом примере показано, как использовать комбинацию отслеживания и управления радиолокационными ресурсами для адаптации скорости повторного просмотра для маневрирования треков. Адаптивное отслеживание позволяет вам выбрать скорость повторного просмотра, которая подходит для каждого типа цели и статуса маневрирования. В результате радар становится более эффективным и может отслеживать большее количество маневрирующих целей.
Ссылки
[1] Александр Чарлиш, Фолкер Хоффман, Кристоф Деген и Изабель Шлэнджен, «Развитие от Адаптивного до Познавательного Радарного управления Ресурсом», в Космосе IEEE и журнале Electronic Systems, издании 35, № 6, стр 8-19, 1 июня 2020, doi: 10.1109/MAES.2019.2957847.
getCurrentRadarTask
Возвращает радиолокационную задачу, которая используется для указания радиолокационного луча.
type('getCurrentRadarTask.m')
function [currentjob,jobq] = getCurrentRadarTask(jobq,current_time) searchq = jobq.SearchQueue; trackq = jobq.TrackQueue; searchidx = jobq.SearchIndex; num_trackq_items = jobq.NumTrackJobs; % Update search queue index searchqidx = mod(searchidx-1,numel(searchq))+1; % Find the track job that is due and has the highest priority readyidx = find([trackq(1:num_trackq_items).Time]<=current_time); [~,maxpidx] = max([trackq(readyidx).Priority]); taskqidx = readyidx(maxpidx); % If the track job found has a higher priority, use that as the current job % and increase the next search job priority since it gets postponed. % Otherwise, the next search job due is the current job. if ~isempty(taskqidx) % && trackq(taskqidx).Priority >= searchq(searchqidx).Priority currentjob = trackq(taskqidx); for m = taskqidx+1:num_trackq_items trackq(m-1) = trackq(m); end num_trackq_items = num_trackq_items-1; searchq(searchqidx).Priority = searchq(searchqidx).Priority+100; else currentjob = searchq(searchqidx); searchidx = searchqidx+1; end jobq.SearchQueue = searchq; jobq.SearchIndex = searchidx; jobq.TrackQueue = trackq; jobq.NumTrackJobs = num_trackq_items;
helperAdaptiveRadarSim
Запускает симуляцию
type('helperAdaptiveTrackingSim.m')
function allocationType = helperAdaptiveTrackingSim(scenario, thp, rax, tracker, resetJobQ, managerPreferences) % Initialize variables radar = scenario.Platforms{end}.Sensors{1}; updateRate = radar.UpdateRate; resourceAllocation = nan(1,updateRate); h = histogram(rax,resourceAllocation,'BinMethod','integers'); xlabel(h.Parent,'TrackID') ylabel(h.Parent,'Num beams'); numSteps = updateRate * 185; allocationType = nan(1,numSteps); currentStep = 1; restart(scenario); reset(tracker); % Return to a reset state of jobq jobq = resetJobQ; % Plotters and axes plp = thp.Plotters(1); dtp = thp.Plotters(3); cvp = thp.Plotters(4); trp = thp.Plotters(5); % For repeatable results, set the random seed and revert it when done s = rng(2020); oc = onCleanup(@() rng(s)); % Main loop while advance(scenario) time = scenario.SimulationTime; % Update ground truth display poses = platformPoses(scenario); plotPlatform(plp, reshape([poses.Position],3,[])'); % Point the radar based on the scheduler current job [currentJob,jobq] = getCurrentRadarTask(jobq,time); currentStep = currentStep + 1; if currentStep > updateRate resourceAllocation(1:end-1) = resourceAllocation(2:updateRate); end if strcmpi(currentJob.JobType,'Search') detectableTracks = zeros(0,1,'uint32'); resourceAllocation(min([currentStep,updateRate])) = 0; allocationType(currentStep) = 1; cvp.Color = [0 0 1]; else detectableTracks = currentJob.TrackID; resourceAllocation(min([currentStep,updateRate])) = currentJob.TrackID; cvp.Color = [1 0 1]; if strcmpi(currentJob.JobType,'Confirm') allocationType(currentStep) = 2; else allocationType(currentStep) = 3; end end ra = resourceAllocation(~isnan(resourceAllocation)); h.Data = ra; h.Parent.YLim = [0 updateRate]; h.Parent.XTick = 0:max(ra); point(radar, currentJob.BeamDirection); plotCoverage(cvp, coverageConfig(scenario)); % Collect detections and plot them detections = detect(scenario); if isempty(detections) meas = zeros(0,3); else dets = [detections{:}]; meassph = reshape([dets.Measurement],3,[])'; [x,y,z] = sph2cart(deg2rad(meassph(1)),deg2rad(meassph(2)),meassph(3)); meas = (detections{1}.MeasurementParameters.Orientation*[x;y;z]+detections{1}.MeasurementParameters.OriginPosition)'; end plotDetection(dtp, meas); % Track and plot tracks if isLocked(tracker) || ~isempty(detections) tracks = tracker(detections, time, detectableTracks); pos = getTrackPositions(tracks,jobq.PositionSelector); plotTrack(trp,pos,string([tracks.TrackID])); end % Manage resources for next jobs jobq = manageResource(detections,jobq,tracker,currentJob,time,managerPreferences); end
initMPARIMM
Инициализирует взаимодействующий фильтр нескольких моделей, используемый трекером.
type('initMPARIMM.m')
function imm = initMPARIMM(detection) cvekf = initcvekf(detection); cvekf.StateCovariance(2,2) = 1e6; cvekf.StateCovariance(4,4) = 1e6; cvekf.StateCovariance(6,6) = 1e6; ctekf = initctekf(detection); ctekf.StateCovariance(2,2) = 1e6; ctekf.StateCovariance(4,4) = 1e6; ctekf.StateCovariance(7,7) = 1e6; ctekf.ProcessNoise(3,3) = 1e6; % Large noise for unknown angular acceleration imm = trackingIMM('TrackingFilters', {cvekf;ctekf}, 'TransitionProbabilities', [0.99, 0.99]);
manageResources
Управляет очередью заданий и создает новые задачи на основе результатов отслеживания.
type('manageResource.m')
function jobq = manageResource(detections,jobq,tracker,current_job,current_time,managerPreferences) trackq = jobq.TrackQueue; num_trackq_items = jobq.NumTrackJobs; if ~isempty(detections) detection = detections{1}; else detection = []; end % Execute current job switch current_job.JobType case 'Search' % For search job, if there is a detection, establish tentative % track and schedule a confirmation job if ~isempty(detection) rng_est = detection.Measurement(3); revisit_time = current_time+1; allTracks = predictTracksToTime(tracker, 'all', revisit_time); % A search task can still find a track we already have. Define % a confirmation task only if it's a tentative track. There % could be more than one if there are false alarms. toConfirm = find(~[allTracks.IsConfirmed]); numToConfirm = numel(toConfirm); for i = 1:numToConfirm trackid = allTracks(toConfirm(i)).TrackID; job = revisitTrackJob(tracker, trackid, current_time, managerPreferences, 'Confirm'); num_trackq_items = num_trackq_items+1; trackq(num_trackq_items) = job; end end case 'Confirm' % For confirm job, if the detection is confirmed, establish a track % and create a track job corresponding to the revisit time if ~isempty(detection) trackid = current_job.TrackID; job = revisitTrackJob(tracker, trackid, current_time, managerPreferences, 'TrackNonManeuvering'); if ~isempty(job) num_trackq_items = num_trackq_items+1; trackq(num_trackq_items) = job; end end otherwise % Covers both types of track jobs % For track job, if there is a detection, update the track and % schedule a track job corresponding to the revisit time. If there % is no detection, predict and schedule a track job sooner so the % target is not lost. if ~isempty(detection) trackid = current_job.TrackID; job = revisitTrackJob(tracker, trackid, current_time, managerPreferences, 'TrackNonManeuvering'); if ~isempty(job) num_trackq_items = num_trackq_items+1; trackq(num_trackq_items) = job; end else trackid = current_job.TrackID; job = revisitTrackJob(tracker, trackid, current_time, managerPreferences, 'TrackNonManeuvering'); if ~isempty(job) num_trackq_items = num_trackq_items+1; trackq(num_trackq_items) = job; end end end jobq.TrackQueue = trackq; jobq.NumTrackJobs = num_trackq_items; end function job = revisitTrackJob(tracker, trackID, currentTime, managerPreferences, jobType) types = [managerPreferences.Type]; inTypes = strcmpi(jobType,types); revisitTime = 1/managerPreferences(inTypes).RevisitRate + currentTime; predictedTracks = predictTracksToTime(tracker,'All',revisitTime); % If the track is not dropped, try to revisit it allTrackIDs = [predictedTracks.TrackID]; if any(trackID == allTrackIDs) mdlProbs = getTrackFilterProperties(tracker, trackID, 'ModelProbabilities'); if mdlProbs{1}(2) > 0.6 jobType = 'TrackManeuvering'; inTypes = strcmpi(jobType,types); revisitTime = 1/managerPreferences(inTypes).RevisitRate+currentTime; predictedTracks = predictTracksToTime(tracker,trackID,revisitTime); xpred = predictedTracks.State([1 3 5]); else xpred = predictedTracks(trackID == allTrackIDs).State([1 3 5]); end [phipred,thetapred,rpred] = cart2sph(xpred(1),xpred(2),xpred(3)); job = struct('JobType',jobType,'Priority',3000,... 'BeamDirection',rad2deg([phipred thetapred]),'WaveformIndex',1,'Time',revisitTime,... 'Range',rpred,'TrackID',trackID); else job = []; end end