В этом примере показано, как использовать 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: 8.3108 Step 1 time: 3.7554 Step 2 time: 15.3029 Step 3 time: 14.1099 Step 4 time: 14.3506 Step 5 time: 14.3963
All steps from now are without detections. Step 6 time: 0.53103 Step 7 time: 0.52582 Step 8 time: 0.50639 Step 9 time: 0.50909 Step 10 time: 0.16034 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: 6.5846 Step 1 time: 3.5863 Step 2 time: 3.4095 Step 3 time: 2.9347 Step 4 time: 2.8555 Step 5 time: 2.9397
All steps from now are without detections. Step 6 time: 0.51446 Step 7 time: 0.52277 Step 8 time: 0.54865 Step 9 time: 0.50941 Step 10 time: 0.19085 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: 6.559 Step 1 time: 3.4394 Step 2 time: 1.7852 Step 3 time: 1.474 Step 4 time: 1.5312 Step 5 time: 1.5152
All steps from now are without detections. Step 6 time: 0.60809 Step 7 time: 0.61374 Step 8 time: 0.616 Step 9 time: 0.63798 Step 10 time: 0.22762 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: 6.494 Step 1 time: 3.5346 Step 2 time: 1.894 Step 3 time: 3.1192 Step 4 time: 3.1212 Step 5 time: 3.1458
All steps from now are without detections. Step 6 time: 0.61109 Step 7 time: 0.62456 Step 8 time: 0.61849 Step 9 time: 0.60604 Step 10 time: 0.22303 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.097531 Step 1 time: 3.4684 Step 2 time: 1.6592 Step 3 time: 3.1429 Step 4 time: 3.1274 Step 5 time: 3.0994
All steps from now are without detections. Step 6 time: 0.63232 Step 7 time: 0.61857 Step 8 time: 0.61433 Step 9 time: 0.60698 Step 10 time: 0.25301 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