Введение в Использование глобального самого близкого соседнего средства отслеживания

В этом примере показано, как сконфигурировать и использовать средство отслеживания глобального самого близкого соседа (GNN).

Мотивация

trackerGNN глобальный самый близкий сосед (GNN), средство отслеживания одно гипотезы. trackerGNN позволяет вам:

  1. Выберите алгоритм присвоения, чтобы сопоставить обнаружения с дорожками.

  2. Используйте или основанную на истории или основанную на счете логику дорожки для подтверждения и удаления дорожек.

  3. Используйте любой вид отслеживания фильтра, включая взаимодействующий фильтр многоуровневой модели.

  4. Соедините средство отслеживания со сканированием и управляемые датчики, которые обновляют только подмножество дорожек, управляемых средством отслеживания.

  5. Предскажите дорожки в будущее, не изменяя их внутреннее состояние. Это позволяет вам отображать предсказанное состояние дорожек или предоставлять предсказания дорожки менеджеру ресурсов датчика.

Создайте и используйте trackerGNN

Можно создать trackerGNN и выберите один из алгоритмов присвоения. По умолчанию, trackerGNN использует 'Munkres' алгоритм, который гарантирует оптимальное присвоение, но может занять больше времени, чтобы вычислить. Можно использовать 'Auction' или 'Jonker-Volgenant' или обеспечьте 'Custom' собственная функция. В этом примере вы выбираете 'Auction' алгоритм.

tracker = trackerGNN('Assignment','Auction')
tracker = 

  trackerGNN with properties:

                  TrackerIndex: 0
       FilterInitializationFcn: 'initcvekf'
                    Assignment: 'Auction'
           AssignmentThreshold: [30 Inf]
                  MaxNumTracks: 100
              MaxNumDetections: Inf
                 MaxNumSensors: 20

                  OOSMHandling: 'Terminate'

                    TrackLogic: 'History'
         ConfirmationThreshold: [2 3]
             DeletionThreshold: [5 5]

            HasCostMatrixInput: false
    HasDetectableTrackIDsInput: false
               StateParameters: [1x1 struct]

                     NumTracks: 0
            NumConfirmedTracks: 0

Основной способ использовать trackerGNN путем вызова его с новыми обнаружениями в каждом шаге симуляции. Обнаружением является objectDetection введите или struct с подобными полями. Необходимо задать время обнаружения и его измерения. Другие свойства имеют значения по умолчанию. Например:

detections = {objectDetection(0,[1;2;3]); % Using default values on the detection ...
    objectDetection(0, [10;0;0], 'ObjectClassID', 2)}; % Using a non-default object class
disp(detections{1})
  objectDetection with properties:

                     Time: 0
              Measurement: [3x1 double]
         MeasurementNoise: [3x3 double]
              SensorIndex: 1
            ObjectClassID: 0
    MeasurementParameters: {}
         ObjectAttributes: {}

time = 0;
[confirmedTracks, tentativeTracks] = tracker(detections, time);
disp(confirmedTracks)
disp(tentativeTracks)
  objectTrack with properties:

             TrackID: 2
            BranchID: 0
         SourceIndex: 0
          UpdateTime: 0
                 Age: 1
               State: [6x1 double]
     StateCovariance: [6x6 double]
     StateParameters: [1x1 struct]
       ObjectClassID: 2
          TrackLogic: 'History'
     TrackLogicState: [1 0 0 0 0]
         IsConfirmed: 1
           IsCoasted: 0
      IsSelfReported: 1
    ObjectAttributes: [1x1 struct]

  objectTrack with properties:

             TrackID: 1
            BranchID: 0
         SourceIndex: 0
          UpdateTime: 0
                 Age: 1
               State: [6x1 double]
     StateCovariance: [6x6 double]
     StateParameters: [1x1 struct]
       ObjectClassID: 0
          TrackLogic: 'History'
     TrackLogicState: [1 0 0 0 0]
         IsConfirmed: 0
           IsCoasted: 0
      IsSelfReported: 1
    ObjectAttributes: [1x1 struct]

Создаются два типа дорожек: подтвержденный и предварительный. Подтвержденная дорожка является дорожкой, которая считается оценкой действительной цели, в то время как предварительная дорожка может все еще быть ложной целью. IsConfirmed флаг различает два. Дорожка, созданная вторым обнаружением, имеет ненулевой ObjectClassID поле и сразу подтверждено, потому что датчик, который сообщил о нем, смог классифицировать его, и таким образом это рассматривается действительной целью. В качестве альтернативы дорожка может быть подтверждена, если существует достаточно доказательства ее существования. В основанной на истории логике подтверждения, используемой здесь, если дорожка была присвоена 2 обнаружения из 3, она будет подтверждена. Этим управляет ConfirmationThreshold свойство. Например, следующее обнаружение присвоено предварительной дорожке и подтверждает его:

detections = {objectDetection(1,[1.1;2.2;3.3])};
time = time + 1; % Time must increase from one update of the tracker to the next
confirmedTracks = tracker(detections,time);
confirmedTracks(1)
ans = 

  objectTrack with properties:

             TrackID: 1
            BranchID: 0
         SourceIndex: 0
          UpdateTime: 1
                 Age: 2
               State: [6x1 double]
     StateCovariance: [6x6 double]
     StateParameters: [1x1 struct]
       ObjectClassID: 0
          TrackLogic: 'History'
     TrackLogicState: [1 1 0 0 0]
         IsConfirmed: 1
           IsCoasted: 0
      IsSelfReported: 1
    ObjectAttributes: [1x1 struct]

Используйте основанную на счете логику подтверждения и удаления

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

Чтобы преобразовать средство отслеживания в основанную на счете логику подтверждения и удаления, сначала выпустите средство отслеживания и затем установите TrackLogic средства отслеживания к 'Score':

release(tracker)
tracker.TrackLogic = 'Score'
tracker = 

  trackerGNN with properties:

                  TrackerIndex: 0
       FilterInitializationFcn: 'initcvekf'
                    Assignment: 'Auction'
           AssignmentThreshold: [30 Inf]
                  MaxNumTracks: 100
              MaxNumDetections: Inf
                 MaxNumSensors: 20

                  OOSMHandling: 'Terminate'

                    TrackLogic: 'Score'
         ConfirmationThreshold: 20
             DeletionThreshold: -7
          DetectionProbability: 0.9000
                FalseAlarmRate: 1.0000e-06
                        Volume: 1
                          Beta: 1

            HasCostMatrixInput: false
    HasDetectableTrackIDsInput: false
               StateParameters: [1x1 struct]

                     NumTracks: 0
            NumConfirmedTracks: 0

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

Теперь обновите средство отслеживания, чтобы видеть подтверждение дорожек.

detections = {objectDetection(0,[1;2;3]); % Using default values on the detection ...
    objectDetection(0, [10;0;0], 'ObjectClassID', 2)}; % Using a non-default object class
time = 0;
tracker(detections, time); % Same as the first step above
detections = {objectDetection(1,[1.1;2.2;3.3])};
time = time + 1; % Time must increase from one update of the tracker to the next
[confirmedTracks, tentativeTracks] = tracker(detections,time);
confirmedTracks
confirmedTracks = 

  objectTrack with properties:

             TrackID: 2
            BranchID: 0
         SourceIndex: 0
          UpdateTime: 1
                 Age: 2
               State: [6x1 double]
     StateCovariance: [6x6 double]
     StateParameters: [1x1 struct]
       ObjectClassID: 2
          TrackLogic: 'Score'
     TrackLogicState: [11.4076 13.7102]
         IsConfirmed: 1
           IsCoasted: 1
      IsSelfReported: 1
    ObjectAttributes: [1x1 struct]

Поскольку подтвержденная дорожка не была присвоена никакому обнаружению в этом обновлении, его уменьшенный счет. Вы видите это путем рассмотрения TrackLogicState поле и видя, что первый элемент, текущий счет, ниже, чем второй элемент, максимальный счет. Если дорожка продолжает уменьшаться относительно максимального счета, больше, чем DeletionThreshold значение, дорожка удалена.

tentativeTracks
tentativeTracks = 

  objectTrack with properties:

             TrackID: 1
            BranchID: 0
         SourceIndex: 0
          UpdateTime: 1
                 Age: 2
               State: [6x1 double]
     StateCovariance: [6x6 double]
     StateParameters: [1x1 struct]
       ObjectClassID: 0
          TrackLogic: 'Score'
     TrackLogicState: [17.7217 17.7217]
         IsConfirmed: 0
           IsCoasted: 0
      IsSelfReported: 1
    ObjectAttributes: [1x1 struct]

Если дорожки не будут присвоены никаким обнаружениям, они будут сначала курсироваться и после нескольких 'промахов', они будут удалены. Чтобы видеть что, вызовите средство отслеживания без обнаружений:

for i = 1:3
    time = time + 1;
    [~,~,allTracks] = tracker({},time)
end
allTracks = 

  2x1 objectTrack array with properties:

    TrackID
    BranchID
    SourceIndex
    UpdateTime
    Age
    State
    StateCovariance
    StateParameters
    ObjectClassID
    TrackLogic
    TrackLogicState
    IsConfirmed
    IsCoasted
    IsSelfReported
    ObjectAttributes


allTracks = 

  2x1 objectTrack array with properties:

    TrackID
    BranchID
    SourceIndex
    UpdateTime
    Age
    State
    StateCovariance
    StateParameters
    ObjectClassID
    TrackLogic
    TrackLogicState
    IsConfirmed
    IsCoasted
    IsSelfReported
    ObjectAttributes


allTracks = 

  objectTrack with properties:

             TrackID: 1
            BranchID: 0
         SourceIndex: 0
          UpdateTime: 4
                 Age: 5
               State: [6x1 double]
     StateCovariance: [6x6 double]
     StateParameters: [1x1 struct]
       ObjectClassID: 0
          TrackLogic: 'Score'
     TrackLogicState: [10.8139 17.7217]
         IsConfirmed: 0
           IsCoasted: 1
      IsSelfReported: 1
    ObjectAttributes: [1x1 struct]

Вторая дорожка была удалена, потому что она не была присвоена никакие обнаружения в 4 обновлениях. Это заставило его счет падать на больше чем 7, значение DeletionThreshold. Первая дорожка все еще не удалена, но ее счет теперь ниже и близко к порогу удаления.

Используйте любой фильтр отслеживания

trackerGNN поддерживает любой фильтр отслеживания, который реализует интерфейс фильтра отслеживания. Выбор функции инициализации фильтра задан с помощью FilterInitializationFcn свойство trackerGNN. Это обеспечивает следующую гибкость:

  1. Можно использовать любую функцию инициализации фильтра, доступную в продукте. Некоторые примеры включают initcvekf (значение по умолчанию), initcvkf , initcvukf , initcvckf , initcaekf , и т.д.

  2. Можно записать, что собственная инициализация фильтра функционирует и использует любой фильтр отслеживания. Они включают trackingABF , trackingEKF , trackingKF , trackingUKF , trackingCKF , trackingPF , trackingMSCEKF , trackingGSF , и trackingIMM .

  3. Можно записать фильтр отслеживания, который наследовал и реализует интерфейс, заданный абстрактным matlabshared.tracking.internal.AbstractTrackingFilter класс.

Следующий пример показывает, как использовать фильтр взаимодействующей модели движения (IMM), который имеет 3 типа моделей движения: постоянная скорость, постоянное ускорение и постоянная угловая скорость вращения.

Измените средство отслеживания, чтобы использовать фильтр IMM

release(tracker) % Release the tracker
tracker.FilterInitializationFcn = 'initekfimm'
tracker = 

  trackerGNN with properties:

                  TrackerIndex: 0
       FilterInitializationFcn: 'initekfimm'
                    Assignment: 'Auction'
           AssignmentThreshold: [30 Inf]
                  MaxNumTracks: 100
              MaxNumDetections: Inf
                 MaxNumSensors: 20

                  OOSMHandling: 'Terminate'

                    TrackLogic: 'Score'
         ConfirmationThreshold: 20
             DeletionThreshold: -7
          DetectionProbability: 0.9000
                FalseAlarmRate: 1.0000e-06
                        Volume: 1
                          Beta: 1

            HasCostMatrixInput: false
    HasDetectableTrackIDsInput: false
               StateParameters: [1x1 struct]

                     NumTracks: 0
            NumConfirmedTracks: 0

Затем обновите средство отслеживания с обнаружением и наблюдайте три модели движения, которые включают его. Вы видите, какая модель используется путем рассмотрения StateTransitionFcn из каждого фильтра.

% Update the tracker with a single detection to get a single track
detection = {objectDetection(0, [1;2;3], 'ObjectClassID', 2)};
time = 0;
tracker(detection, time);

Используйте getTrackFilterProperties метод, чтобы просмотреть TrackingFilters свойство. Это возвращает массив ячеек, который содержит TrackingFilters свойство: {filter1;filter2;filter3}

filters = getTrackFilterProperties(tracker,1,'TrackingFilters');
for i = 1:numel(filters{1})
    disp(filters{1}{i})
end
  trackingEKF with properties:

                          State: [6x1 double]
                StateCovariance: [6x6 double]

             StateTransitionFcn: @constvel
     StateTransitionJacobianFcn: @constveljac
                   ProcessNoise: [3x3 double]
        HasAdditiveProcessNoise: 0

                 MeasurementFcn: @cvmeas
         MeasurementJacobianFcn: @cvmeasjac
               MeasurementNoise: [3x3 double]
    HasAdditiveMeasurementNoise: 1

                MaxNumOOSMSteps: 0

                EnableSmoothing: 0

  trackingEKF with properties:

                          State: [9x1 double]
                StateCovariance: [9x9 double]

             StateTransitionFcn: @constacc
     StateTransitionJacobianFcn: @constaccjac
                   ProcessNoise: [3x3 double]
        HasAdditiveProcessNoise: 0

                 MeasurementFcn: @cameas
         MeasurementJacobianFcn: @cameasjac
               MeasurementNoise: [3x3 double]
    HasAdditiveMeasurementNoise: 1

                MaxNumOOSMSteps: 0

                EnableSmoothing: 0

  trackingEKF with properties:

                          State: [7x1 double]
                StateCovariance: [7x7 double]

             StateTransitionFcn: @constturn
     StateTransitionJacobianFcn: @constturnjac
                   ProcessNoise: [4x4 double]
        HasAdditiveProcessNoise: 0

                 MeasurementFcn: @ctmeas
         MeasurementJacobianFcn: @ctmeasjac
               MeasurementNoise: [3x3 double]
    HasAdditiveMeasurementNoise: 1

                MaxNumOOSMSteps: 0

                EnableSmoothing: 0

Интерфейс со сканированием и управляемыми датчиками

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

Следующий пример показывает, как датчики показывают, что дорожка не будет обнаружена, и как дорожка не удалена.

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

release(tracker) % Release the tracker
tracker.FilterInitializationFcn = 'initcvekf';
tracker.HasDetectableTrackIDsInput = true % Allows the tracker to get input about the track detectability by the sensors
% Update the tracker with a single detection to get a single track
detection = {objectDetection(0, [1;2;3], 'ObjectClassID', 2)};
time = 0;
trackIDs = []; % Initially, there are no tracks, so trackIDs has zero rows
track = tracker(detection, time, trackIDs)
% Update the tracker 2 more times without any detections. Let the tracker
% know that the track was not detectable by any sensor. Note how the
% TrackLogicState, shown as [currentScore, maxScore], does not change even
% though the track is not detected.
for i=1:2
    time = time + 1;
    trackIDs = [1, 0]; % Zero probability of detection means the track score should not decrease
    track = tracker({}, time, trackIDs) % No detections
end
tracker = 

  trackerGNN with properties:

                  TrackerIndex: 0
       FilterInitializationFcn: 'initcvekf'
                    Assignment: 'Auction'
           AssignmentThreshold: [30 Inf]
                  MaxNumTracks: 100
              MaxNumDetections: Inf
                 MaxNumSensors: 20

                  OOSMHandling: 'Terminate'

                    TrackLogic: 'Score'
         ConfirmationThreshold: 20
             DeletionThreshold: -7
          DetectionProbability: 0.9000
                FalseAlarmRate: 1.0000e-06
                        Volume: 1
                          Beta: 1

            HasCostMatrixInput: false
    HasDetectableTrackIDsInput: true
               StateParameters: [1x1 struct]

                     NumTracks: 0
            NumConfirmedTracks: 0


track = 

  objectTrack with properties:

             TrackID: 1
            BranchID: 0
         SourceIndex: 0
          UpdateTime: 0
                 Age: 1
               State: [6x1 double]
     StateCovariance: [6x6 double]
     StateParameters: [1x1 struct]
       ObjectClassID: 2
          TrackLogic: 'Score'
     TrackLogicState: [13.7102 13.7102]
         IsConfirmed: 1
           IsCoasted: 0
      IsSelfReported: 1
    ObjectAttributes: [1x1 struct]


track = 

  objectTrack with properties:

             TrackID: 1
            BranchID: 0
         SourceIndex: 0
          UpdateTime: 1
                 Age: 2
               State: [6x1 double]
     StateCovariance: [6x6 double]
     StateParameters: [1x1 struct]
       ObjectClassID: 2
          TrackLogic: 'Score'
     TrackLogicState: [13.7102 13.7102]
         IsConfirmed: 1
           IsCoasted: 1
      IsSelfReported: 1
    ObjectAttributes: [1x1 struct]


track = 

  objectTrack with properties:

             TrackID: 1
            BranchID: 0
         SourceIndex: 0
          UpdateTime: 2
                 Age: 3
               State: [6x1 double]
     StateCovariance: [6x6 double]
     StateParameters: [1x1 struct]
       ObjectClassID: 2
          TrackLogic: 'Score'
     TrackLogicState: [13.7102 13.7102]
         IsConfirmed: 1
           IsCoasted: 1
      IsSelfReported: 1
    ObjectAttributes: [1x1 struct]

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

Предскажите дорожки к определенному времени

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

  1. Отображение предсказанных дорожек на отображении.

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

Вы используете predictTracksToTime метод, чтобы получить предсказанные дорожки.

Обновите средство отслеживания с большим количеством обнаружений

time = time + 1;
detections = {objectDetection(time, [4,2,3]); ...
    objectDetection(time, [10;0;0])};
track = tracker(detections, time, trackIDs);
disp('State of track #1 at time 3:')
disp(track.State)

% Predict tracks to different time steps:
predictedTrack1 = predictTracksToTime(tracker,1, time+0.5); % Predict track number 1 half a second to the future
disp('State of track #1 at time 3.5:')
predictedTrack1.State
% Predict all the confirmed tracks 2 seconds to the future
predictedConfirmedTracks = predictTracksToTime(tracker, 'Confirmed', time+2);
disp('State of track #1 at time 5:')
predictedConfirmedTracks.State

% Predict all the tracks 0.3 seconds to the future
disp('State of all the tracks at time 3.3:')
predictedTracks = predictTracksToTime(tracker, 'all', time+0.3);
predictedTracks.State
State of track #1 at time 3:
    3.9967
    1.0030
    2.0000
         0
    3.0000
         0

State of track #1 at time 3.5:

ans =

    4.4982
    1.0030
    2.0000
         0
    3.0000
         0

State of track #1 at time 5:

ans =

    6.0027
    1.0030
    2.0000
         0
    3.0000
         0

State of all the tracks at time 3.3:

ans =

    4.2976
    1.0030
    2.0000
         0
    3.0000
         0


ans =

    10
     0
     0
     0
     0
     0

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

% First, use a |theaterPlot| and a |trackPlotter| to plot the tracks.
thPlot = theaterPlot('XLimits',[-20 20], 'Ylimits', [-20 20]);
trPlotter = trackPlotter(thPlot, 'DisplayName', 'Predicted Track');
posSelector = [1 0 0 0 0 0; 0 0 1 0 0 0; 0 0 0 0 1 0];
velSelector = [0 1 0 0 0 0; 0 0 0 1 0 0; 0 0 0 0 0 1];

% Then, plot the predicted tracks every 0.1 seconds
for t = time+(0.1:0.1:5)
    predictedTracks = predictTracksToTime(tracker, 'Confirmed', t);
    [pos,cov] = getTrackPositions(predictedTracks,posSelector);
    vel = getTrackVelocities(predictedTracks,velSelector);
    plotTrack(trPlotter,pos,vel,cov);
    drawnow
end

Сводные данные

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