В этом примере показано, как использовать радарное управление ресурсами, чтобы эффективно отследить несколько маневрирующих целей. Отслеживание маневрирующих целей требует, чтобы радар пересматривал цели более часто, чем отслеживание неманеврирующих целей. Фильтр Взаимодействующей многоуровневой модели (IMM) оценивает, когда цель маневрирует. Эта оценка помогает справиться, радар пересматривают время, и поэтому улучшает отслеживание. Этот пример использует Radar Toolbox™ для радарной модели и Sensor Fusion and Tracking Toolbox™ для отслеживания.
Многофункциональные радары могут искать цели, подтвердить новые треки и пересмотреть дорожки, чтобы обновить состояние. Чтобы выполнить эти функции, многофункциональный радар часто управляем менеджером ресурсов, который создает радарные задачи для поиска, подтверждения и отслеживания. Эти задачи планируются согласно приоритету и время так, чтобы на каждом временном шаге многофункциональный радар мог указать свой луч в желаемом направлении. Планирование Поиска и Дорожки для Многофункционального Радарного примера Фазированной решетки показывает многофункциональный радар фазированной решетки, управляемый с менеджером ресурсов.
В этом примере мы расширяем Адаптивное Отслеживание Маневрирования Целей с Управляемым Радарным примером к случаю нескольких маневрирующих целей. Существует два конфликтных требования для радара, используемого, чтобы отследить маневрирующие цели:
Количество целей и их начального местоположения не обычно известно заранее. Поэтому радар должен постоянно искать сферу интересов, чтобы найти цели. Кроме того, радар должен обнаружить и установить дорожку на каждой цели, как только это вводит радарную зону охвата.
Период времени целевого маневрирования неизвестен заранее. Если известно, что цели не маневрируют, радар может нечасто пересматривать цели. Однако, поскольку времена начала и конца маневра неизвестны, радар должен пересмотреть каждую дорожку достаточно часто, чтобы смочь распознать когда начала и концы маневра.
Радар должен балансироваться между обеспечением достаточного количества лучей, сосредоточенных на отслеженных целях и отъездом достаточного количества времени, чтобы искать новые цели. Один подход должен просто задать пересмотреть уровень на каждой отслеженной цели независимо от ее состояния маневрирования и оставить остающееся время для нового целевого поиска. Эта радарная схема управления иногда упоминается как Активное Отслеживание [1]. Когда больше целей становится отслеженным, радар может или выполнить меньше поисковых задач, или он может отслеживать каждую цель менее часто. Безусловно, если количество целей является большим, радар может быть разбит.
Активное отслеживание обрабатывает все дорожки таким же образом, который делает его основанным на режиме алгоритмом управления ресурсами. Более сложный способ управлять радаром основан на свойствах каждой дорожки. Например, используйте свойства дорожки, такие как размер ковариации неопределенности состояния, маневрирует ли дорожка, и как быстро это двигает актив, который защищает радарный сайт. Когда такие свойства используются, радарное управление ресурсами упоминается как Адаптивное Отслеживание [1].
В этом примере вы сравниваете результаты Активного Отслеживания и Адаптивного Отслеживания, когда радар адаптируется на основе предполагаемого маневра дорожки.
Вы задаете сценарий и радар с частотой обновления 20 Гц, что означает, что радар имеет 20 лучей, в секунду выделенных или для поиска, подтверждения или для отслеживания. Вы загружаете траектории сравнительного теста, используемые в Траекториях Сравнительного теста для Мультиобъекта, Отслеживающего (Sensor Fusion and Tracking Toolbox) пример. Существует шесть траекторий сравнительного теста, и вы задаете траекторию для каждого. От фигуры ниже, эти шесть платформ следуют за неманеврирующими участками, вкрапленными маневрирующими участками. Можно просмотреть траектории на рисунке ниже.
% 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
Системный объект. 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
это инициализирует фильтр Взаимодействующей многоуровневой модели (IMM). initMPARIMM
функционируйте использует две модели движения: модель постоянной скорости и модель постоянной угловой скорости вращения. trackingIMM
Фильтр (Sensor Fusion and Tracking Toolbox) ответственен за оценку вероятности каждой модели, к которой можно получить доступ от ее 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];
Этот раздел только кратко обрисовывает в общих чертах радарное управление ресурсами, для получения дополнительной информации, смотрите, что Адаптивное Отслеживает Маневрирования Целей с Управляемым Радарным примером.
Поисковые задачи
Поисковые задачи присвоены детерминировано в этом примере. Развертка растра используется, чтобы покрыть желаемое воздушное пространство. Если никакие другие задачи не существуют, радиолокационные обзоры пробел одна угловая ячейка за один раз. Размер угловой ячейки определяется радаром 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;
Отследите задачи
В отличие от поисковых задач, задачи дорожки не могут быть запланированы заранее. Вместо этого менеджер ресурсов создает задачи подтверждения и отслеживания на основе изменяющегося сценария. Основное различие в этом примере от Адаптивного Отслеживания Маневрирования Целей с Управляемым Радарным примером то, что 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;
Планирование задач
В этом примере, для простоты, многофункциональный радар выполняет только один тип задания в маленьком периоде времени, часто называемом тем, чтобы жить, но может переключиться, задачи в начале каждого живут. Поскольку каждый живет, радар смотрит на все задачи, которые подлежат выполнению, и выбирает подтверждение или задачу дорожки, если их время, чтобы запуститься настало. В противном случае радар выбирает поисковую задачу. Чтобы управлять временем, чтобы запустить задачи, вы устанавливаете managerPreferences
struct, заданный ниже. Самые высокие пересматривают уровень, который равен радарной частоте обновления, дан confirm
задача гарантировать, что луч подтверждения следует за каждой новой предварительной дорожкой, которая существует. Точно так же можно управлять пересмотреть уровнем для неманеврирования и маневрирования целей. В этом случае вы выбираете значения 1 Гц и 4 Гц для неманеврирования и маневрирования целей, соответственно. Поскольку существует шесть целей, в то время как радарная частота обновления равняется 20, если цели не маневрируют, радар должен потратить приблизительно 70% времени в режиме поиска и 30% времени в режиме отслеживания. Когда новые треки инициализируются и когда средство отслеживания полагает, что цели маневрируют, менеджер ресурсов выделяет больше лучей отслеживания за счет поисковых лучей.
Раздел Analyze Results показывает результаты других опций.
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
Теперь вы хотите выдержать сравнение, результат выше результатом Активного Отслеживания в дорожке на 1 Гц пересматривают уровень. Следующие рисунки показывают результаты отслеживания и радарный график выделения для Активного случая Отслеживания. Результаты отслеживания показывают, что некоторые следы были потеряны и повреждены, но радарный график распределения ресурсов показывает подобный 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);
Безусловно, более высокое отслеживание пересматривает уровень, необходим для Активного Отслеживания. Эти два графика ниже показа, что увеличение дорожки пересматривает уровень к 2 Гц, улучшают отслеживание маневрирования целей. Однако стоимость - то, что радар выделяет больше чем 50% своего времени к отслеживанию задач, даже когда дорожки не маневрируют. Если бы количество целей было больше, радар стал бы разбитым.
Предыдущие результаты показывают, что достаточно пересмотреть маневрирующие цели на уровне 2 Гц. Однако Адаптивное Отслеживание может использоваться, чтобы уменьшать пересмотреть уровень неманеврирования целей к 0.5 Гц? Графики ниже показа, что отслеживание все еще хорошо. С этой установкой радарное выделение допускает 80%-90% времени в режиме поиска, оставляя радар с возможностью искать и отследить еще больше целей.
В этом примере показано, как использовать комбинацию отслеживания и радарного управления ресурсами, чтобы адаптировать пересмотреть уровень к маневрированию дорожек. Адаптивное отслеживание позволяет, вы, чтобы выбрать пересматриваете уровень, который подходит для каждого целевого типа и маневрирующего состояния. В результате радар становится более эффективным и может отследить большее число маневрирования целей.
Ссылки
[1] Александр Чарлиш, Фолкер Хоффман, Кристоф Деген и Изабель Шлэнджен, "Разработка от Адаптивного до Познавательного Радарного управления ресурсами", в Космосе IEEE и Журнале Электронных систем, издании 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