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

В этом примере показано, как настроить и запустить трекер для отслеживания нескольких объектов в сцене. Пример объясняет и демонстрирует важность ключевых свойств трекеров в 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 Probabilistic 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 - задает фильтр, используемый для инициализации новой дорожки с неназначенным обнаружением.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Эта функция запускает сценарий с заданным трекером и объектом метрики track 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