Этот пример показывает, как использовать trackerGNN
, чтобы отследить большие количества целей. Подобные методы могут быть применены к trackerJPDA
и trackerTOMHT
также.
Во многих приложениях средства отслеживания требуются, чтобы отслеживать сотни или тысячи объектов. Увеличение числа дорожек, сохраняемых средством отслеживания, является проблемой, вызванной вычислительной сложностью алгоритма в ядре каждого средства отслеживания. В частности, два общих этапа на шаге обновления средства отслеживания не легко масштабируемы: вычисление стоимости присвоения и выполнение присвоения. Расчет стоимости присвоения характерен для trackerGNN
, trackerJPDA
и trackerTOMHT
, и методы, показанные в этом примере, могут быть применены при использовании любого из этих средств отслеживания. Путем каждое средство отслеживания выполняет присвоение, уникально для каждого средства отслеживания и может потребовать, чтобы специализированные решения улучшали производительность средства отслеживания, которые выходят за рамки этого примера.
Сценарий
В целях этого примера вы задаете сценарий, который содержит 900 платформ, организованных в 15 15 сетка, с каждой ячейкой сетки, содержащей 4 платформы. Цель ячеек сетки состоит в том, чтобы продемонстрировать преимущество крупного расчета стоимости, объясненного позже в примере.
Следующий код располагает 900 объектов в ячейке сетки и создает визуализацию. Слева, целый сценарий показывают. Справа, визуализация увеличивает масштаб 4 ячеек сетки. Обратите внимание, что каждая ячейка содержит 4 платформы.
[platforms,tp,zoomedtp] = createPlatforms;
Этот раздел показывает результаты отслеживания платформ, заданных выше использования trackerGNN
с AssignmentThreshold
по умолчанию. Свойство AssignmentThreshold
содержит два значения: [C1 C2]
, где C1
является порогом, используемым для присвоения и C2
, является порогом для крупного вычисления, объясненного в следующем разделе.
Когда средство отслеживания обновляется с новым набором обнаружений, оно вычисляет стоимость присвоения каждого обнаружения к каждой дорожке. Точный расчет стоимости должен учесть измерение и неуверенность в каждом обнаружении, а также ожидаемое измерение и ожидаемую неуверенность от каждой дорожки, как изображено ниже.
По умолчанию C2
установлен в Inf, который требует, чтобы затраты на все комбинации дорожки и обнаружения были вычислены. Это приводит к более точному присвоению, но более в вычислительном отношении интенсивно. Необходимо начать с настройки по умолчанию убеждаться, что средство отслеживания присваивает обнаружения дорожкам лучшим способом, и затем полагайте, что понижение значения C2
уменьшает время, требуемое для вычисления стоимости присвоения.
Во время расчета стоимости присвоения элементы матрицы стоимости, значения которой выше, чем C1
, заменяются Inf. Выполнение так помогает алгоритму присвоения проигнорировать невозможные присвоения.
Задайте средство отслеживания, которое может отследить до 1 000 дорожек. Средство отслеживания использует расширенный Фильтр Калмана постоянной скорости по умолчанию, и его состояние задано как [x;vx;y;vy;z;vz]
, который используется positionSelector
ниже, чтобы получить компоненты положения.
tracker = trackerGNN('MaxNumTracks',1000, 'AssignmentThreshold', [30 Inf]); positionSelector = [1 0 0 0 0 0; 0 0 1 0 0 0; 0 0 0 0 0 0];
На первом вызове шага средство отслеживания инстанцирует всех дорожек. Изолировать время, требуемое инстанцировать дорожек со времени вычислений, потребовало для первого шага, можно вызвать setup
и reset
прежде, чем продвинуться средство отслеживания. Смотрите функцию поддержки runTracker
в конце этого примера для получения дополнительной информации.
[trkSummary,truSummary,info] = runTracker(platforms,tracker,positionSelector,tp,zoomedtp);
Tracker set up time: 6.2629 Step 1 time: 3.0754 Step 2 time: 13.5342 Step 3 time: 12.2972 Step 4 time: 12.3253 Step 5 time: 12.5448
All steps from now are without detections. Step 6 time: 0.48672 Step 7 time: 0.46594 Step 8 time: 0.50402 Step 9 time: 0.49171 Step 10 time: 0.13955 Scenario done. All tracks are now deleted.
Вы анализируете результаты отслеживания путем исследования метрических значений присвоения дорожки. Для совершенного отслеживания общего количества дорожек должно быть равно количеству платформ и не должно быть никакой лжи, подкачанных, или расходящихся дорожек. Точно так же не должно быть никакой недостающей истины или не прерывает сводные данные истины.
assignmentMetricsSummary(trkSummary,truSummary)
Track assignment metrics summary: TotalNumTracks NumFalseTracks MaxSwapCount MaxDivergenceCount MaxDivergenceLength ______________ ______________ ____________ __________________ ___________________ 900 0 0 0 0 Truth assignment metrics summary: TotalNumTruths NumMissingTruths MaxEstablishmentLength MaxBreakCount ______________ ________________ ______________________ _____________ 900 0 1 0
В предыдущем разделе вы видели, что средство отслеживания может отследить все платформы, но каждый шаг обновления занимает много времени. Наиболее часто был потрачен на вычисление матрицы стоимости присвоения.
Исследуя матрицу стоимости, вы видите, что подавляющим большинством ее элементов является, на самом деле, Inf.
cm = info.CostMatrix; disp("Cost matrix has " + numel(cm) + " elements."); disp("But the number of finite values is " + numel(cm(isfinite(cm))) + newline)
Cost matrix has 810000 elements. But the number of finite values is 2700
Вышеупомянутый результат показывает, что расчет стоимости проводит слишком много времени при вычислении стоимости присвоения всех комбинаций дорожки и обнаружения. Однако большинство этих комбинаций слишком далеко, чтобы быть присвоенным, как фактическое измерение слишком далеко от ожидаемого измерения дорожки на основе характеристик датчика. Чтобы избежать отходов в вычислении всех затрат, можно использовать крупный расчет стоимости.
Крупное вычисление сделано, чтобы проверить, какие комбинации дорожки и обнаружения могут потребовать точного нормированного расчета расстояния. Только комбинации, крупная стоимость присвоения которых ниже, чем C2
, вычисляются точно. Крупный расчет стоимости изображен в изображении ниже. Обнаружение представлено его шумом измерения и измерения. Две дорожки предсказаны ко времени обнаружения и спроектированы к пробелу измерения, изображенному точками и. Обратите внимание на то, что неуверенность дорожки не спроектирована к пробелу измерения, который позволяет нам векторизовать крупное вычисление. Это - грубая оценка, потому что только неуверенность по поводу обнаружения учтена. В изображенном примере первая дорожка падает за пределами крупного логического элемента вычисления, в то время как вторая дорожка падает в нем. Таким образом точный расчет стоимости только сделан для комбинации этого обнаружения и второй дорожки.
Чтобы использовать крупный расчет стоимости, выпустите средство отслеживания и измените его AssignmentThreshold
к значению [30 200]. Затем повторно выполните средство отслеживания.
release(tracker) tracker.AssignmentThreshold = [30 200]; [trkSummary,truSummary] = runTracker(platforms,tracker,positionSelector,tp,zoomedtp);
Tracker set up time: 5.4344 Step 1 time: 2.8964 Step 2 time: 3.1965 Step 3 time: 2.8143 Step 4 time: 2.7336 Step 5 time: 2.602
All steps from now are without detections. Step 6 time: 0.47158 Step 7 time: 0.4913 Step 8 time: 0.46417 Step 9 time: 0.45706 Step 10 time: 0.12533 Scenario done. All tracks are now deleted.
Вы замечаете, что шаги 3-5 теперь требуют, чтобы значительно меньше времени завершилось. Шаг 2 также быстрее, чем он раньше был, но еще медленнее, чем шаги 3-5.
Чтобы понять, почему шаг 2 медленнее, рассмотрите состояния дорожки после первого обновления средства отслеживания. Состояния содержат информацию о положении, но скорость является все еще нулевой. Когда средство отслеживания вычисляет стоимость присвоения, оно предсказывает, что дорожка утверждает ко временам обнаружения, но поскольку дорожки имеют нулевую скорость, они остаются в том же положении. Это приводит к большим расстояниям между измерениями обнаружения и ожидаемыми измерениями от предсказанных состояний дорожки. Эти относительно большие затраты присвоения делают его тяжелее для алгоритма присвоения, чтобы найти лучшее присвоение, которое заставляет шаг 2 занимать больше времени, чем шаги 3-5.
Важно проверить, что присвоение дорожки с крупным расчетом стоимости остается то же самое как без него. Если метрики присвоения дорожки не являются тем же самым, необходимо увеличить размер крупного логического элемента вычисления. Следующее показывает, что отслеживание все еще совершенно, как это было в предыдущем разделе, но каждый шаг обработки занял меньше времени.
assignmentMetricsSummary(trkSummary,truSummary)
Track assignment metrics summary: TotalNumTracks NumFalseTracks MaxSwapCount MaxDivergenceCount MaxDivergenceLength ______________ ______________ ____________ __________________ ___________________ 900 0 0 0 0 Truth assignment metrics summary: TotalNumTruths NumMissingTruths MaxEstablishmentLength MaxBreakCount ______________ ________________ ______________________ _____________ 900 0 1 0
Другим способом управлять временем, которое требуется, чтобы вычислить присвоение стоимости, является при помощи вашего собственного расчета стоимости присвоения вместо значения по умолчанию использование средства отслеживания.
Вычисление внешней стоимости может учесть атрибуты, которые не являются частью состояния дорожки и ожидаемого измерения. Это может также использовать различные метрики расстояния, например, Евклидова норма вместо нормированного расстояния. Выбор которого расчет стоимости применяться зависит от специфических особенностей проблемы, пробела измерения, и как вы задаете состояние и измерение.
Чтобы использовать вычисление внешней стоимости, вы выпускаете средство отслеживания и устанавливаете его свойство HasCostMatrixInput
на истину. Необходимо передать собственную матрицу стоимости как дополнительный вход с каждым обновлением средства отслеживания. Дополнительную информацию см. в функции поддержки runTracker
.
release(tracker); tracker.HasCostMatrixInput = true; [trkSummary,truSummary] = runTracker(platforms,tracker,positionSelector,tp,zoomedtp); assignmentMetricsSummary(trkSummary,truSummary)
Tracker set up time: 5.4425 Step 1 time: 2.7897 Step 2 time: 1.5586 Step 3 time: 1.365 Step 4 time: 1.4195 Step 5 time: 1.3637
All steps from now are without detections. Step 6 time: 0.55515 Step 7 time: 0.55081 Step 8 time: 0.5411 Step 9 time: 0.5556 Step 10 time: 0.19762 Scenario done. All tracks are now deleted. Track assignment metrics summary: TotalNumTracks NumFalseTracks MaxSwapCount MaxDivergenceCount MaxDivergenceLength ______________ ______________ ____________ __________________ ___________________ 900 0 0 0 0 Truth assignment metrics summary: TotalNumTruths NumMissingTruths MaxEstablishmentLength MaxBreakCount ______________ ________________ ______________________ _____________ 900 0 1 0
Как ожидалось время вычислений еще ниже при использовании функции вычисления внешней стоимости.
Другая опция, чтобы попробовать использует различный алгоритм присвоения GNN, который может быть более эффективным в нахождении присвоения путем изменения свойства Assignment
средства отслеживания.
release(tracker)
tracker.Assignment = 'Jonker-Volgenant';
tracker.HasCostMatrixInput = true;
runTracker(platforms,tracker,positionSelector,tp,zoomedtp);
Tracker set up time: 5.4339 Step 1 time: 2.9202 Step 2 time: 1.7385 Step 3 time: 2.9389 Step 4 time: 2.9151 Step 5 time: 2.8985
All steps from now are without detections. Step 6 time: 0.54947 Step 7 time: 0.54664 Step 8 time: 0.53913 Step 9 time: 0.60383 Step 10 time: 0.20843 Scenario done. All tracks are now deleted.
Алгоритм Jonker-Volgenant выполняет присвоение на втором шаге быстрее относительно алгоритма Munkres по умолчанию.
Если вы хотите запустить несколько сценариев, не изменяя настройки средства отслеживания, нет никакой потребности вызвать метод release
. Вместо этого только вызовите метод reset
, чтобы очистить предыдущую информацию о дорожке от средства отслеживания. Таким образом, вы экономите время, требуемое инстанцировать всех дорожек. Обратите внимание, что "Средство отслеживания настроило время" ниже относительно предыдущих выполнений.
reset(tracker) runTracker(platforms,tracker,positionSelector,tp,zoomedtp);
Tracker set up time: 0.084152 Step 1 time: 2.7899 Step 2 time: 1.5324 Step 3 time: 2.9437 Step 4 time: 2.9087 Step 5 time: 2.9117
All steps from now are without detections. Step 6 time: 0.54433 Step 7 time: 0.54118 Step 8 time: 0.54495 Step 9 time: 0.5426 Step 10 time: 0.19652 Scenario done. All tracks are now deleted.
Этот пример показал, как отследить большие количества объектов. При отслеживании многих объектов средство отслеживания тратит большую часть времени вычислений на вычислении присвоения стоимости для каждой комбинации дорожки и обнаружения. Вы видели, как использовать порог расчета стоимости, чтобы улучшить время, проведенное относительно вычисления стоимости присвоения. Кроме того, пример показал, как использовать вычисление внешней стоимости, которое может быть разработано, чтобы быть более в вычислительном отношении эффективным для конкретной проблемы отслеживания, которую вы имеете.
Можно уменьшать порог присвоения стоимости или использовать вычисление внешней стоимости, чтобы улучшить скорость trackerJPDA
и trackerTOMHT
также.
createPlatforms
Эта функция создает платформы в 20x20 сетка с 2x2 платформы на ячейку сетки.
function [platforms,tp,zoomedtp] = createPlatforms % This is a helper function to run the tracker and display the results. It % may be removed in the future. nh = 15; % Number of horizontal grid cells nv = 15; % Number of vertical grid cells nsq = 2; % 2x2 platforms in a grid cell nPl = nh*nv*nsq^2; % Overall number of platforms xgv = sort(-50 + repmat(100 * (1:nh), [1 nsq])); ygv = sort(-50 + repmat(100 * (1:nv), [1 nsq])); [X,Y] = meshgrid(xgv,ygv); npts = nsq/2; xshift = 10*((-npts+1):npts) -5; yshift = xshift; xadd = repmat(xshift, [1 nh]); yadd = repmat(yshift, [1 nv]); [Xx, Yy] = meshgrid(xadd,yadd); X = X + Xx; Y = Y + Yy; pos = [X(:),Y(:),zeros(numel(X),1)]; % The following creates an array of struct for the platforms, which are % used later for track assignment metrics. vel = [3 1 0]; % Platform velocity platforms = repmat(struct('PlatformID', 1, 'Position', [0 0 0], 'Velocity', vel),nPl,1); for i = 1:nPl platforms(i).PlatformID = i; platforms(i).Position(:) = pos(i,:); end % Visualization f = figure('Position',[1 1 1425 700]); movegui center; h1 = uipanel(f,'FontSize',12,'Position',[.01 .01 .48 .98],"Title","Scene View"); a1 = axes(h1,'Position',[0.05 0.05 0.9 0.9]); tp = theaterPlot('Parent', a1, 'XLimits',[0 nh*100], 'YLimits',[0 nv*100]); set(a1,'XTick',0:100:nh*100) set(a1,'YTick',0:100:nv*100) grid on pp = trackPlotter(tp,'Tag','Truth','Marker','^','MarkerEdgeColor','k','MarkerSize',4,'HistoryDepth',10); plotTrack(pp,reshape([platforms.Position],3,[])'); trackPlotter(tp, 'Tag','Tracks','MarkerEdgeColor','b','MarkerSize',6,'HistoryDepth',10); c = get(a1.Parent,'Children'); for i = 1:numel(c) if isa(c(i),'matlab.graphics.illustration.Legend') set(c(i),'Visible','off') end end h2 = uipanel(f,'FontSize',12,'Position',[.51 .01 .48 .98],'Title','Zoomed View'); a2 = axes(h2,'Position',[0.05 0.05 0.9 0.9]); zoomedtp = theaterPlot('Parent', a2, 'XLimits',[400 500], 'YLimits',[400 500]); set(a2,'XTick',400:100:500) set(a2,'YTick',400:100:500) grid on zoomedpp = trackPlotter(zoomedtp,'DisplayName','Truth','Marker','^','MarkerEdgeColor','k','MarkerSize',6,'HistoryDepth',10); plotTrack(zoomedpp,reshape([platforms.Position],3,[])'); trackPlotter(zoomedtp, 'DisplayName','Tracks','MarkerEdgeColor','b','MarkerSize',8,'HistoryDepth',10,'ConnectHistory','on','FontSize',1); end
runTracker
Эта функция запускает средство отслеживания, обновляет плоттеры и собирает метрики присвоения дорожки.
function [trkSummary,truSummary,info] = runTracker(platforms,tracker,positionSelector,tp,zoomedtp) % This is a helper function to run the tracker and display the results. It % may be removed in the future. pp = findPlotter(tp,'Tag','Truth'); trp = findPlotter(tp, 'Tag','Tracks'); zoomedpp = findPlotter(zoomedtp,'DisplayName','Truth'); zoomedtrp = findPlotter(zoomedtp, 'DisplayName','Tracks'); % To save time, pre-allocate all the detections and assign them on the fly. nPl = numel(platforms); det = objectDetection(0,[0;0;0]); dets = repmat({det},[nPl,1]); % Define a track assignment metrics object. tam = trackAssignmentMetrics; % Bring the visualization back. set(tp.Parent.Parent.Parent,'Visible','on') hasExternalCostFunction = tracker.HasCostMatrixInput; % Measure the time it takes to set the tracker up. tic if ~isLocked(tracker) if hasExternalCostFunction setup(tracker,dets,0,0); else setup(tracker,dets,0); end end reset(tracker) disp("Tracker set up time: " + toc); % Run 5 steps with detections for all the platforms. for t = 1:5 for i = 1:nPl dets{i}.Time = t; dets{i}.Measurement = platforms(i).Position(:); end tic if hasExternalCostFunction if isLocked(tracker) % Use predictTracksToTime to get all the predicted tracks. allTracks = predictTracksToTime(tracker,'all',t); else allTracks = []; end costMatrix = predictedEuclidean(allTracks,dets,positionSelector); [tracks,~,~,info] = tracker(dets,t,costMatrix); else [tracks,~,~,info] = tracker(dets,t); end trPos = getTrackPositions(tracks, positionSelector); trIDs = string([tracks.TrackID]'); disp("Step " + t + " time: " + toc) % Update the plot. plotTrack(pp,reshape([platforms.Position],3,[])'); plotTrack(trp,trPos); plotTrack(zoomedpp,reshape([platforms.Position],3,[])'); plotTrack(zoomedtrp,trPos,trIDs); drawnow % Update the track assignment metrics object. if nargout [trkSummary, truSummary] = tam(tracks,platforms); end % Update the platform positions. for i = 1:nPl platforms(i).Position = platforms(i).Position + platforms(i).Velocity; end end snapnow % Run steps with no detections until the tracker deletes all the tracks. disp("All steps from now are without detections.") while ~isempty(tracks) t = t+1; tic if hasExternalCostFunction allTracks = predictTracksToTime(tracker,'all',t); costMatrix = predictedEuclidean(allTracks,{},positionSelector); tracks = tracker({},t,costMatrix); else tracks = tracker({},t); end disp("Step " + t + " time: " + toc) % Update the position of the tracks to plot. trPos = getTrackPositions(tracks,positionSelector); trIDs = string([tracks.TrackID]'); % Update the plot. plotTrack(pp,reshape([platforms.Position],3,[])'); plotTrack(trp,trPos); plotTrack(zoomedpp,reshape([platforms.Position],3,[])'); plotTrack(zoomedtrp,trPos,trIDs); drawnow % Update the platform positions. for i = 1:nPl platforms(i).Position = platforms(i).Position + platforms(i).Velocity; end end disp("Scenario done. All tracks are now deleted." + newline) clearData(pp) clearData(trp) clearData(zoomedpp) clearData(zoomedtrp) set(tp.Parent.Parent.Parent,'Visible','off') % Prevent excessive snapshots drawnow end
predictedEuclidean
Функция вычисляет Евклидово расстояние между измеренными положениями от обнаружений и предсказанными положениями от дорожек.
function euclidDist = predictedEuclidean(tracks,detections,positionSelector) % This is a helper function to run the tracker and display the results. It % may be removed in the future. if isempty(tracks) || isempty(detections) euclidDist = zeros(numel(tracks),numel(detections)); return end predictedStates = [tracks.State]; predictedPositions = positionSelector * predictedStates; dets = [detections{:}]; measuredPositions = [dets.Measurement]; euclidDist = zeros(numel(tracks),numel(detections)); for i = 1:numel(detections) diffs = bsxfun(@minus, predictedPositions',measuredPositions(:,i)'); euclidDist(:,i) = sqrt(sum((diffs .* diffs),2)); end end
assignmentMetricsSummary
Функция отображает метрики назначения клавиш в табличной форме.
function assignmentMetricsSummary(trkSummary,truSummary) trkSummary = rmfield(trkSummary, {'TotalSwapCount','TotalDivergenceCount',... 'TotalDivergenceLength','MaxRedundancyCount','TotalRedundancyCount',... 'MaxRedundancyLength','TotalRedundancyLength'}); truSummary = rmfield(truSummary, {'TotalEstablishmentLength','TotalBreakCount',... 'MaxBreakLength','TotalBreakLength'}); trkTable = struct2table(trkSummary); truTable = struct2table(truSummary); disp("Track assignment metrics summary:") disp(trkTable) disp("Truth assignment metrics summary:") disp(truTable) end