Адаптивное отслеживание маневрирования целей с управляемым радаром

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

Введение

Многофункциональные радары могут искать цели, подтвердить новые треки и пересмотреть дорожки, чтобы обновить состояние. Чтобы выполнить эти функции, многофункциональный радар часто управляем менеджером ресурсов, который создает радарные задачи для поиска, подтверждения и отслеживания. Эти задачи планируются согласно приоритету и время так, чтобы на каждом временном шаге многофункциональный радар мог указать свой луч в желаемом направлении. Планирование Поиска и Дорожки для Многофункционального Радарного примера Фазированной решетки показывает многофункциональный радар фазированной решетки, управляемый с менеджером ресурсов.

В этом примере мы расширяем Адаптивное Отслеживание Маневрирования Целей с Управляемым Радарным примером к случаю нескольких маневрирующих целей. Существует два конфликтных требования для радара, используемого, чтобы отследить маневрирующие цели:

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

  2. Период времени целевого маневрирования неизвестен заранее. Если известно, что цели не маневрируют, радар может нечасто пересматривать цели. Однако, поскольку времена начала и конца маневра неизвестны, радар должен пересмотреть каждую дорожку достаточно часто, чтобы смочь распознать когда начала и концы маневра.

Радар должен балансироваться между обеспечением достаточного количества лучей, сосредоточенных на отслеженных целях и отъездом достаточного количества времени, чтобы искать новые цели. Один подход должен просто задать пересмотреть уровень на каждой отслеженной цели независимо от ее состояния маневрирования и оставить остающееся время для нового целевого поиска. Эта радарная схема управления иногда упоминается как Активное Отслеживание [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
Для просмотра документации необходимо авторизоваться на сайте