exponenta event banner

Настройка многообъектного трекера

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

Конфигурация трекера по умолчанию

Для проверки возможности трекера отслеживать несколько объектов необходимо настроить базовый сценарий. В сценарии определяются три объекта, каждый из которых движется по прямой с постоянной скоростью. Первоначально установились скорости объекта 48 м/с, 60 м/с и 72 м/с соответственно.

stopTime = 10;
v = 60;
scenario = trackingScenario;
scenario.StopTime = stopTime;
scenario.UpdateRate = 0;
p1 = platform(scenario);
p1.Trajectory = waypointTrajectory([30 20 0; 30 .8*v*stopTime 0], [0 stopTime]);
p2 = platform(scenario);
p2.Trajectory = waypointTrajectory([0 0 0; 0 v*stopTime 0], [0 stopTime]);
p3 = platform(scenario);
p3.Trajectory = waypointTrajectory([-30 -20 0; -30 1.2*v*stopTime 0], [0 stopTime]);

Кроме того, определяется радар, который смотрит на место происшествия и обновляется 5 раз в секунду. Ее монтируют на платформе, расположенной сбоку от движущихся объектов.

pRadar = platform(scenario);
pRadar.Trajectory = kinematicTrajectory('Position', [-v*stopTime 0.5*v*stopTime 0]);
radar = monostaticRadarSensor(1, 'No scanning', 'UpdateRate', 5, ...
    'MountingAngles', [0 0 0], 'AzimuthResolution', 1, ...
    'FieldOfView', [100 1], 'HasINS', true, 'DetectionCoordinates', 'Scenario', ...
    'MaxUnambiguousRange', 1000);
pRadar.Sensors = radar;

Для отображения сцены создается театральный график.

fig = figure;
ax = axes(fig);
tp = theaterPlot('Parent', ax, 'XLimits', [-11*v 100], 'YLimits', [-50 15*v], 'ZLimits', [-100 100]);
rp = platformPlotter(tp, 'DisplayName', 'Radar', 'Marker', 'd');
pp = platformPlotter(tp, 'DisplayName', 'Platforms');
dp = detectionPlotter(tp, 'DisplayName', 'Detections');
trp = trackPlotter(tp, 'DisplayName', 'Tracks', 'ConnectHistory', 'on', 'ColorizeHistory', 'on');
covp = coveragePlotter(tp, 'DisplayName', 'Radar Coverage', 'Alpha', [0.1 0]);

Наконец, создается значение по умолчанию trackerGNN объект, выполните сценарий и просмотрите результаты. Вы используете trackGOSPAMetric для оценки производительности трекера.

tracker = trackerGNN;
tgm = trackGOSPAMetric("Distance","posabserr");
gospa = zeros(1,51); % number of timesteps is 51
i = 0;

% Define the random number generator seed for repeatable results
s = rng(2019); 
while advance(scenario)
    % Get detections
    dets = detect(scenario);
    
    % Update the tracker
    if isLocked(tracker) || ~isempty(dets)
        [tracks, ~, ~, info] = tracker(dets, scenario.SimulationTime);
    end
    
    % Evaluate GOSPA
    i = i + 1;
    truth = platformPoses(scenario);
    gospa(i) = tgm(tracks, truth);
    
    % Update the display
    updateDisplay(rp, pp, dp, trp, covp, scenario, dets, tracks);
end

Figure contains an axes. The axes contains 9 objects of type line, patch, text. These objects represent Radar, Platforms, Detections, Tracks, (history), Radar Coverage.

rng(s)
figure
plot(gospa)
title('Generalized OSPA vs. Timestep')

Figure contains an axes. The axes with title Generalized OSPA vs. Timestep contains an object of type line.

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

Порог назначения

Вы смотрите на info структура, что трекер выводит и наблюдать, что CostMatrix и Assignments не показывать назначение пар дорожек и объектов, которые ожидаются. Это означает, что AssignmentThreshold слишком мал и должен быть увеличен. Увеличьте порог назначения до 50.

release(tracker);
tracker.AssignmentThreshold = 50;
rerunScenario(scenario, tracker, tgm, tp);

Figure contains an axes. The axes contains 9 objects of type line, patch, text. These objects represent Radar, Platforms, Detections, Tracks, (history), Radar Coverage.

Figure contains an axes. The axes with title Generalized OSPA vs. Timestep contains an object of type line.

Свойство порога назначения также имеет максимальное расстояние от обнаружения, которое можно задать. Это последний элемент в AssignmentThreshold значение. Это значение можно использовать для ускорения отслеживания при обработке большого количества обнаружений и дорожек. Дополнительные сведения см. в примере «Как эффективно отслеживать большое количество объектов». Здесь устанавливается значение 2000 вместо inf, что уменьшит количество комбинаций дорожек и обнаружений, которые используются для расчета стоимости назначения.

release(tracker);
tracker.AssignmentThreshold = [50 2000];
rerunScenario(scenario, tracker, tgm, tp);

Figure contains an axes. The axes contains 9 objects of type line, patch, text. These objects represent Radar, Platforms, Detections, Tracks, (history), Radar Coverage.

Figure contains an axes. The axes with title Generalized OSPA vs. Timestep contains an object of type line.

Функция инициализации фильтра

Результаты выше показывают, что трекер способен поддерживать три дорожки для трех движущихся объектов без создания ложных дорожек. Однако сохранится ли производительность трекера, если объекты будут двигаться с большей скоростью? Для проверки необходимо изменить сценарий и увеличить скорость объекта до 160, 200 и 240 м/с соответственно.

v = 200;
p1.Trajectory = waypointTrajectory([30 0 0; 30 0.8*v*stopTime 0], [0 stopTime]);
p2.Trajectory = waypointTrajectory([0 0 0; 0 v*stopTime 0], [0 stopTime]);
p3.Trajectory = waypointTrajectory([-30 0 0; -30 1.2*v*stopTime 0], [0 stopTime]);
pRadar.Trajectory = kinematicTrajectory('Position', [-v*stopTime 0.5*v*stopTime 0]);
tp.XLimits = [-100-v*stopTime 300];
tp.YLimits = [-100 100+v*1.2*stopTime];
release(radar);
radar.MaxUnambiguousRange = 3000;
rerunScenario(scenario, tracker, tgm, tp);

Figure contains an axes. The axes contains 8 objects of type line, patch, text. These objects represent Radar, Platforms, Detections, Tracks, (history), Radar Coverage.

Figure contains an axes. The axes with title Generalized OSPA vs. Timestep contains an object of type line.

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

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

release(tracker)
tracker.FilterInitializationFcn = @initFastCVEKF;
rerunScenario(scenario, tracker, tgm, tp);

Figure contains an axes. The axes contains 9 objects of type line, patch, text. These objects represent Radar, Platforms, Detections, Tracks, (history), Radar Coverage.

Figure contains an axes. The axes with title Generalized OSPA vs. Timestep contains an object of type line.

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

Пороги подтверждения и удаления

Вы хотите убедиться, что ваш трекер надежен к более высокой частоте ложных аварийных сигналов. Для этого необходимо настроить радар так, чтобы частота ложных аварийных сигналов была в 250 раз выше, чем ранее.

Можно уменьшить масштаб изображения, чтобы увидеть большую часть сцены и увидеть, созданы ли ложные дорожки.

release(radar);
radar.FalseAlarmRate = 2.5e-4;
tp.XLimits = [-2100 300];
tp.YLimits = [-100  3100];
tp.ZLimits = [-1000 1000];
rerunScenario(scenario, tracker, tgm, tp);

Figure contains an axes. The axes contains 10 objects of type line, patch, text. These objects represent Radar, Platforms, Detections, Tracks, (history), Radar Coverage.

Figure contains an axes. The axes with title Generalized OSPA vs. Timestep contains an object of type line.

Создается несколько ложных дорожек (не все из них показаны), и они увеличивают значение GOSPA.

Вы хотите удалить ложные дорожки быстрее, для чего вы используете DeletionThreshold собственность. Значением по умолчанию для порога удаления является [5 5], что требует 5 последовательных промахов перед удалением подтвержденной дорожки. Вы можете ускорить процесс удаления, уменьшив это значение до [3 3] или до 3 из 3 промахов. В качестве альтернативы, поскольку радар DetectionProbability высок, можно даже удалить трассу после промахов 2 из 3, установив:

release(tracker)
tracker.DeletionThreshold = [2 3];
rerunScenario(scenario, tracker, tgm, tp);

Figure contains an axes. The axes contains 9 objects of type line, patch, text. These objects represent Radar, Platforms, Detections, Tracks, (history), Radar Coverage.

Figure contains an axes. The axes with title Generalized OSPA vs. Timestep contains an object of type line.

Как и ожидалось, уменьшение количества шагов, предпринимаемых для удаления дорожек, уменьшает значение GOSPA, поскольку эти ложные дорожки недолговечны. Однако эти ложные следы все еще подтверждаются и ухудшают общее качество отслеживания.

Таким образом, вы хотите сделать подтверждение новых треков более строгим в попытке уменьшить количество ложных треков. Рассмотрим трекер ConfirmationThreshold собственность.

disp(tracker.ConfirmationThreshold);
     2     3

Значение показывает, что трекер подтверждает каждый трек, если ему назначено два обнаружения в первых трех обновлениях. Вы решите затруднить подтверждение дорожки и сбросить значение, чтобы оно было 3 из 4 назначений.

release(tracker)
tracker.ConfirmationThreshold = [3 4];
rerunScenario(scenario, tracker, tgm, tp);

Figure contains an axes. The axes contains 9 objects of type line, patch, text. These objects represent Radar, Platforms, Detections, Tracks, (history), Radar Coverage.

Figure contains an axes. The axes with title Generalized OSPA vs. Timestep contains an object of type line.

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

Максимальное количество дорожек

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

Количество дорожек колеблется в течение срока службы трекера. Однако вы не хотите, чтобы он превышал максимальное количество дорожек, которое может поддерживать трекер, определенное MaxNumTracks, которая по умолчанию равна 100. Если трекер превышает это число, он выдает предупреждение о том, что новая дорожка не может быть добавлена, но выполнение может быть продолжено.

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

release(tracker)
tracker.MaxNumTracks = 200;
tracker.ConfirmationThreshold = [5 6];

release(radar)
radar.FalseAlarmRate = 1e-3;
rerunScenario(scenario, tracker, tgm, tp);

Figure contains an axes. The axes contains 9 objects of type line, patch, text. These objects represent Radar, Platforms, Detections, Tracks, (history), Radar Coverage.

Figure contains an axes. The axes with title Generalized OSPA vs. Timestep contains an object of type line.

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

Попробуйте другой трекер

Вы хотите попробовать использовать другой трекер, в данном случае трекер Joint Probilistic Data Association, trackerJPDA. Многие свойства, определенные для предыдущего трекера, по-прежнему действительны в трекере JPDA. Вы используете helperGNN2JPDA для создания трекера JPDA.

jpda = helperGNN2JPDA(tracker);
jpda.ClutterDensity = 1e-3;
rerunScenario(scenario, tracker, tgm, tp);

Figure contains an axes. The axes contains 9 objects of type line, patch, text. These objects represent Radar, Platforms, Detections, Tracks, (history), Radar Coverage.

Figure contains an axes. The axes with title Generalized OSPA vs. Timestep contains an object of type line.

Резюме

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

При настройке многообъектного трекера рассмотрите возможность изменения следующих свойств:

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

  • Функция определяет модели движения и измерения.

  • Убедитесь, что неопределенности состояния правильно представлены параметром StateCovariance фильтра. Например, большая ковариация начальной скорости позволяет отслеживать быстро движущиеся объекты.

AssignureThreshold - максимальное нормализованное расстояние, используемое при назначении обнаружений дорожкам.

  • Уменьшите это значение, чтобы ускорить назначение, особенно в больших сценах с большим количеством дорожек и избежать ложных дорожек, избыточных дорожек и свопов дорожек. При использовании trackerJPDAуменьшение этого значения уменьшает количество обнаружений, которые считаются назначенными одной дорожке. При использовании trackerTOMHTуменьшение пороговых значений назначения уменьшает количество создаваемых ветвей пути.

  • Увеличьте это значение, чтобы избежать расхождения и разрыва треков даже при наличии новых обнаружений.

MaxNumTracks - максимальное количество дорожек, поддерживаемых трекером.

  • Уменьшите это значение, чтобы минимизировать использование памяти и ускорить инициализацию трекера.

  • Увеличьте это значение, чтобы не допустить инициализации новых дорожек из-за достижения предела.

ConfirmationThreshold - управляет подтверждением новых треков.

  • Уменьшите это значение для подтверждения большего количества дорожек и для более быстрого подтверждения дорожек.

  • Увеличьте это значение, чтобы уменьшить количество ложных дорожек.

ThreadThreshold - управляет накатом и удалением дорожек.

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

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

Для получения дополнительной информации вы можете обратиться к следующим примерам: Как создать код C для трекера, Введение в логику трекинга, Трекинг близко расположенных целей в условиях неоднозначности и Трекинг точечных целей в плотном нагромождении с помощью GM-PHD трекера.

Служебные функции

updateDisplay

Эта функция обновляет отображение на каждом шаге моделирования.

function updateDisplay(rp, pp, dp, trp, covp, scenario, dets, tracks)
    % Plot the platform positions
    poses = platformPoses(scenario);
    pos = reshape([poses(1:3).Position], 3, [])'; % Only the platforms
    plotPlatform(pp, pos);
    radarPos = poses(4).Position; % Only the radar
    plotPlatform(rp, radarPos)
    
    % Plot the detection positions
    if ~isempty(dets)
        ds = [dets{:}];
        dPos = reshape([ds.Measurement], 3, [])';
    else
        dPos = zeros(0,3);
    end
    plotDetection(dp, dPos);
    
    % Plot the tracks
    tPos = getTrackPositions(tracks, [1 0 0 0 0 0; 0 0 1 0 0 0; 0 0 0 0 1 0]);
    tIDs = string([tracks.TrackID]);
    plotTrack(trp, tPos, tIDs);
    
    % Plot the coverage
    covcon = coverageConfig(scenario);
    plotCoverage(covp, covcon);
end

rerunScenario

Эта функция запускает сценарий с заданным трекером и объектом метрики GOSPA дорожки. Для отображения результатов используется объект графика кинотеатра.

function info = rerunScenario(scenario, tracker, tgm, tp)
    % Reset the objects after the previous run
    restart(scenario);
    reset(tracker);
    reset(tgm);
    rp = findPlotter(tp, 'DisplayName', 'Radar');
    pp = findPlotter(tp, 'DisplayName', 'Platforms');
    trp = findPlotter(tp, 'DisplayName', 'Tracks');
    dp = findPlotter(tp, 'DisplayName', 'Detections');
    covp = findPlotter(tp, 'DisplayName', 'Radar Coverage');
    clearPlotterData(tp);
    
    gospa = zeros(1,51); % number of timesteps is 51
    i = 0;
    s = rng(2019); 
    while advance(scenario)
        % Get detections
        dets = detect(scenario);

        % Update the tracker
        if isLocked(tracker) || ~isempty(dets)
            [tracks, ~, ~, info] = tracker(dets, scenario.SimulationTime); 
        end
        
        % Evaluate GOSPA
        i = i + 1;
        truth = platformPoses(scenario);
        gospa(i) = tgm(tracks, truth);

        % Update the display
        updateDisplay(rp, pp, dp, trp, covp, scenario, dets, tracks);
    end
    rng(s)
    figure
    plot(gospa(gospa>0))
    title('Generalized OSPA vs. Timestep')
end

initFastCVEKF

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

function ekf = initFastCVEKF(detection)
    ekf = initcvekf(detection);
    initialCovariance = diag(ekf.StateCovariance);
    initialCovariance([2,4,6]) = 300^2; % Increase the speed covariance
    ekf.StateCovariance = diag(initialCovariance);
end

helperGNN2JPDA

Эта функция обеспечивает трекер JPDA, эквивалентный трекеру GNN, заданному в качестве входного сигнала.

function jpda = helperGNN2JPDA(gnn)
    jpda = trackerJPDA(...
        'MaxNumTracks', gnn.MaxNumTracks, ...
        'AssignmentThreshold', gnn.AssignmentThreshold, ...
        'FilterInitializationFcn', gnn.FilterInitializationFcn, ...
        'MaxNumSensors', gnn.MaxNumSensors, ...
        'ConfirmationThreshold', gnn.ConfirmationThreshold, ...
        'DeletionThreshold', gnn.DeletionThreshold, ...
        'HasCostMatrixInput', gnn.HasCostMatrixInput, ...
        'HasDetectableTrackIDsInput', gnn.HasDetectableTrackIDsInput);

    if strcmpi(gnn.TrackLogic, 'History')
        jpda.TrackLogic = 'History';
    else
        jpda.TrackLogic = 'Integrated';
        jpda.DetectionProbability = gnn.DetectionProbability;
        jpda.ClutterDensity = gnn.FalseAlarmRate / gnn.Volume;
    end
end