В этом примере показано, как отслеживать транспортные средства с помощью измерений с помощью лидарного датчика, установленного поверх эго-транспортного средства. Датчики Lidar сообщают об измерениях как облако точек. Пример иллюстрирует рабочий процесс в MATLAB ® для обработки облака точек и отслеживания объектов. Пример версии Simulink ® см. в разделе Отслеживание транспортных средств с использованием данных лидара в Simulink (Sensor Fusion and Tracking Toolbox). Данные лидара, используемые в этом примере, записываются из сценария вождения по шоссе. В этом примере записанные данные используются для отслеживания транспортных средств с помощью совместного трекера вероятностных данных (JPDA) и подхода, основанного на взаимодействии нескольких моделей (IMM).
Благодаря высокой разрешающей способности лидарного датчика каждое сканирование датчика содержит большое количество точек, обычно известных как облако точек. Эти необработанные данные должны быть предварительно обработаны для извлечения объектов, представляющих интерес, таких как автомобили, велосипедисты и пешеходы. В этом примере используется классический алгоритм сегментации с использованием алгоритма кластеризации на основе расстояния. Дополнительные сведения о сегментации данных лидара на такие объекты, как наземная плоскость и препятствия, см. в примере «Наземная плоскость» и «Обнаружение препятствий с помощью лидара». Подробное описание процесса сегментации обучения см. в примере Обнаружение, классификация и отслеживание транспортных средств с помощью Lidar (Lidar Toolbox). В этом примере облака точек, принадлежащие препятствиям, далее классифицируются на кластеры с использованием pcsegdist функция, и каждый кластер преобразуется в обнаружение ограничивающей рамки со следующим форматом:
![$[x\ y\ z\ {\theta}\ l\ w\ h]$](../../examples/shared_driving_fusion_lidar/win64/TrackVehiclesUsingLidarExample_eq14686089282307683830.png)
и
отсылают к позициям x, y и z ограничивающей рамки,
отсылают к ее углу рыскания
и, и
отсылают
к ее длине, ширине и высоте соответственно. pcfitcuboid Функция (Lidar Toolbox) использует алгоритм L-образного фитинга для определения угла рыскания ограничивающей рамки.
Детектор реализован поддерживающим классом HelperBoundingBoxDetector, которая охватывает сегментацию облака точек и функции кластеризации. Объект этого класса принимает pointCloud и возвращает список objectDetection объекты с измерениями ограничивающей рамки.
На диаграмме показаны процессы, задействованные в модели детектора ограничивающей рамки, и функции Лидара Toolbox™, используемые для реализации каждого процесса. Он также показывает свойства поддерживающего класса, которые управляют каждым процессом.

Данные лидара доступны в следующем месте: https://ssd.mathworks.com/supportfiles/lidar/data/TrackVehiclesUsingLidarExampleData.zip
Загрузите файлы данных во временный каталог, местоположение которого определяется MATLAB tempdir функция. Если требуется поместить файлы в другую папку, измените имя каталога в последующих инструкциях.
% Load data if unavailable. The lidar data is stored as a cell array of % pointCloud objects. if ~exist('lidarData','var') dataURL = 'https://ssd.mathworks.com/supportfiles/lidar/data/TrackVehiclesUsingLidarExampleData.zip'; datasetFolder = fullfile(tempdir,'LidarExampleDataset'); if ~exist(datasetFolder,'dir') unzip(dataURL,datasetFolder); end % Specify initial and final time for simulation. initTime = 0; finalTime = 35; [lidarData, imageData] = loadLidarAndImageData(datasetFolder,initTime,finalTime); end % Set random seed to generate reproducible results. S = rng(2018); % A bounding box detector model. detectorModel = HelperBoundingBoxDetector(... 'XLimits',[-50 75],... % min-max 'YLimits',[-5 5],... % min-max 'ZLimits',[-2 5],... % min-max 'SegmentationMinDistance',1.8,... % minimum Euclidian distance 'MinDetectionsPerCluster',1,... % minimum points per cluster 'MeasurementNoise',blkdiag(0.25*eye(3),25,eye(3)),... % measurement noise in detection report 'GroundMaxDistance',0.3); % maximum distance of ground points from ground plane
Первым шагом отслеживания объекта является определение его состояния и моделей, определяющих переход состояния и соответствующее измерение. Эти два набора уравнений в совокупности известны как модель состояния-пространства цели. Для моделирования состояния транспортных средств для отслеживания с помощью лидара в этом примере используется кубовидная модель со следующим соглашением:
![$x = [x_{kin}\ {\theta}\ l\ w\ h]$](../../examples/shared_driving_fusion_lidar/win64/TrackVehiclesUsingLidarExample_eq16573381371266659065.png)
относится к части состояния, которая управляет кинематикой центра движения и
является углом рыскания. Длина, ширина, высота кубоида моделируются как константы, оценки которых эволюционируют во времени во время этапов коррекции фильтра.
В этом примере используются две модели состояния-пространства: кубоидная модель с постоянной скоростью (cv) и кубоидная модель с постоянной скоростью поворота (ct). Эти модели отличаются тем, как они определяют кинематическую часть состояния, как описано ниже:
![$x_{cv} = [x\ {\dot{x}}\ y\ {\dot{y}}\ z\ {\dot{z}}\ {\theta}\ l\ w\ h]$](../../examples/shared_driving_fusion_lidar/win64/TrackVehiclesUsingLidarExample_eq13156135384765122457.png)
![$x_{ct} = [x\ {\dot{x}}\ y\ {\dot{y}}\ {\dot{\theta}}\ z\ {\dot{z}}\ {\theta}\ l\ w\ h]$](../../examples/shared_driving_fusion_lidar/win64/TrackVehiclesUsingLidarExample_eq06720148183353337561.png)
Для получения информации об их переходе к состоянию см. helperConstvelCuboid и helperConstturnCuboid функции, используемые в этом примере.
helperCvmeasCuboid и helperCtmeasCuboid модели измерения описывают, как датчик воспринимает состояния постоянной скорости и постоянной скорости поворота соответственно, и они возвращают измерения ограничивающей рамки. Поскольку состояние содержит информацию о размере цели, модель измерения включает в себя эффект смещения центральной точки и усадки ограничивающей рамки, воспринимаемый датчиком, вследствие таких эффектов, как самоокклюзия [1]. Этот эффект моделируется коэффициентом усадки, который прямо пропорционален расстоянию от гусеничного транспортного средства до датчика.
На рисунке ниже показана модель измерения, работающая в различных выборках состояния и пространства. Обратите внимание на смоделированные эффекты усадки ограничивающей рамки и смещения центральной точки при перемещении объектов вокруг эго-транспортного средства.

На приведенном ниже рисунке показан полный рабочий процесс для получения списка дорожек из входных данных, входящих в «Cloud».
Теперь настройте трекер и визуализацию, используемую в примере.
Совместный вероятностный трекер ассоциации данных (trackerJPDA), соединенный с фильтром IMM (trackingIMM) используется для отслеживания объектов в этом примере. Фильтр IMM использует модель постоянной скорости и постоянной скорости поворота и инициализируется с помощью поддерживающей функции. helperInitIMMFilter, включен в этот пример. Подход IMM помогает трассе переключаться между моделями движения и таким образом достигать хорошей точности оценки во время таких событий, как маневрирование или изменение полосы движения. Анимация ниже показывает эффект смешивания постоянной скорости и модели постоянной скорости поворота во время этапов прогнозирования фильтра IMM.

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

Установите HasDetectableTrackIDsInput свойство трекера как true, что позволяет задать зависящую от состояния вероятность обнаружения. Вероятность обнаружения дорожки вычисляется посредством helperCalcDetectability , перечисленная в конце этого примера.
assignmentGate = [75 1000]; % Assignment threshold; confThreshold = [7 10]; % Confirmation threshold for history logic delThreshold = [8 10]; % Deletion threshold for history logic Kc = 1e-9; % False-alarm rate per unit volume % IMM filter initialization function filterInitFcn = @helperInitIMMFilter; % A joint probabilistic data association tracker with IMM filter tracker = trackerJPDA('FilterInitializationFcn',filterInitFcn,... 'TrackLogic','History',... 'AssignmentThreshold',assignmentGate,... 'ClutterDensity',Kc,... 'ConfirmationThreshold',confThreshold,... 'DeletionThreshold',delThreshold,... 'HasDetectableTrackIDsInput',true,... 'InitializationThreshold',0,... 'HitMissThreshold',0.1);
Визуализация разделена на следующие основные категории:
Предварительная обработка и отслеживание Lidar (Lidar Preprocessing and Tracking) - на этом экране отображается облако исходных точек, сегментированный грунт и препятствия. Он также показывает результирующие обнаружения из модели детектора и дорожек транспортных средств, генерируемых трекером.
Ego Vehicle Display - на этом экране отображается 2-D вид сценария с высоты птичьего полета. Он показывает облако точек препятствий, обнаруженные ограничивающие рамки и дорожки, созданные трекером. Для справки он также отображает изображение, записанное с камеры, установленной на эго-транспортном средстве, и его поле зрения.
Сведения об отслеживании - на этом экране отображается сценарий, увеличенный вокруг транспортного средства ego. Он также показывает более точные детали отслеживания, такие как ковариация ошибок в оцененном положении каждой дорожки и вероятности ее модели движения, обозначенные cv и ct.
% Create display displayObject = HelperLidarExampleDisplay(imageData{1},... 'PositionIndex',[1 3 6],... 'VelocityIndex',[2 4 7],... 'DimensionIndex',[9 10 11],... 'YawIndex',8,... 'MovieName','',... % Specify a movie name to record a movie. 'RecordGIF',false); % Specify true to record new GIFs
Закольцовывайте записанные данные лидара, генерируйте обнаружения из текущего облака точек с помощью модели детектора, а затем обрабатывайте обнаружения с помощью трекера.
time = 0; % Start time dT = 0.1; % Time step % Initiate all tracks. allTracks = struct([]); % Initiate variables for comparing MATLAB and MEX simulation. numTracks = zeros(numel(lidarData),2); % Loop through the data for i = 1:numel(lidarData) % Update time time = time + dT; % Get current lidar scan currentLidar = lidarData{i}; % Generator detections from lidar scan. [detections,obstacleIndices,groundIndices,croppedIndices] = detectorModel(currentLidar,time); % Calculate detectability of each track. detectableTracksInput = helperCalcDetectability(allTracks,[1 3 6]); % Pass detections to track. [confirmedTracks,tentativeTracks,allTracks,info] = tracker(detections,time,detectableTracksInput); numTracks(i,1) = numel(confirmedTracks); % Get model probabilities from IMM filter of each track using % getTrackFilterProperties function of the tracker. modelProbs = zeros(2,numel(confirmedTracks)); for k = 1:numel(confirmedTracks) c1 = getTrackFilterProperties(tracker,confirmedTracks(k).TrackID,'ModelProbabilities'); modelProbs(:,k) = c1{1}; end % Update display if isvalid(displayObject.PointCloudProcessingDisplay.ObstaclePlotter) % Get current image scan for reference image currentImage = imageData{i}; % Update display object displayObject(detections,confirmedTracks,currentLidar,obstacleIndices,... groundIndices,croppedIndices,currentImage,modelProbs); end % Snap a figure at time = 18 if abs(time - 18) < dT/2 snapnow(displayObject); end end % Write movie if requested if ~isempty(displayObject.MovieName) writeMovie(displayObject); end % Write new GIFs if requested. if displayObject.RecordGIF % second input is start frame, third input is end frame and last input % is a character vector specifying the panel to record. writeAnimatedGIF(displayObject,10,170,'trackMaintenance','ego'); writeAnimatedGIF(displayObject,310,330,'jpda','processing'); writeAnimatedGIF(displayObject,120,140,'imm','details'); end

На рисунке выше показаны три дисплея во время = 18 секунд. Дорожки представлены зелеными ограничивающими прямоугольниками. Обнаруженные ограничивающие рамки представлены оранжевыми ограничивающими рамками. Обнаруженные объекты также имеют оранжевые точки внутри, представляющие облако точек, сегментированное как препятствия. Сегментированный грунт показан фиолетовым цветом. Обрезанное или удаленное облако точек отображается синим цветом.
Код C можно сгенерировать из кода MATLAB ® для отслеживания и алгоритма предварительной обработки с помощью Coder™ MATLAB. Генерация кода C позволяет ускорить создание кода MATLAB для моделирования. Для генерации кода C алгоритм должен быть реструктурирован как функция MATLAB, которая может быть скомпилирована в файл MEX или общую библиотеку. С этой целью алгоритм обработки облака точек и алгоритм отслеживания преобразуются в функцию MATLAB ,mexLidarTracker. Некоторые переменные определяются как persistent сохранение их состояния между несколькими вызовами функции (см. persistent). Входы и выходы функции можно наблюдать в описании функции, приведенном в разделе «Вспомогательные файлы» в конце этого примера.
Кодер MATLAB требует указания свойств всех входных аргументов. Простой способ сделать это - определить входные свойства на примере в командной строке с помощью -args вариант. Дополнительные сведения см. в разделе Определение входных свойств по примеру в командной строке (кодер MATLAB). Обратите внимание, что входные аргументы верхнего уровня не могут быть объектами handle класс. Поэтому функция принимает местоположения x, y и z облака точек в качестве входных данных. Из сохраненного облака точек эту информацию можно извлечь с помощью Location имущества pointCloud объект. Эта информация также доступна непосредственно в виде необработанных данных от лидарного датчика.
% Input lists inputExample = {lidarData{1}.Location, 0}; % Create configuration for MEX generation cfg = coder.config('mex'); % Replace cfg with the following to generate static library and perform % software-in-the-loop simulation. This requires Embedded Coder license. % % cfg = coder.config('lib'); % Static library % cfg.VerificationMode = 'SIL'; % Software-in-the-loop % Generate code if file does not exist. if ~exist('mexLidarTracker_mex','file') h = msgbox({'Generating code. This may take a few minutes...';'This message box will close when done.'},'Codegen Message'); % -config allows specifying the codegen configuration % -o allows specifying the name of the output file codegen -config cfg -o mexLidarTracker_mex mexLidarTracker -args inputExample close(h); else clear mexLidarTracker_mex; end
Повторный запуск моделирования с кодом MEX
Повторно запустите моделирование с использованием созданного кода MEX, mexLidarTracker_mex. Время сброса
time = 0; for i = 1:numel(lidarData) time = time + dT; currentLidar = lidarData{i}; [detectionsMex,obstacleIndicesMex,groundIndicesMex,croppedIndicesMex,... confirmedTracksMex, modelProbsMex] = mexLidarTracker_mex(currentLidar.Location,time); % Record data for comparison with MATLAB execution. numTracks(i,2) = numel(confirmedTracksMex); end
Сравнение результатов между MATLAB и выполнением MEX
disp(isequal(numTracks(:,1),numTracks(:,2)));
1
Обратите внимание, что количество подтвержденных дорожек одинаково для выполнения кода MATLAB и MEX. Это гарантирует, что алгоритм предварительной обработки и отслеживания лидара возвращает те же результаты с сгенерированным кодом C, что и с кодом MATLAB.
Теперь проанализируйте различные события в сценарии и поймите, как сочетание модели измерения лидара, совместной вероятностной ассоциации данных и взаимодействующего фильтра нескольких моделей помогает достичь хорошей оценки дорожек транспортного средства.
Техническое обслуживание пути

Анимация выше показывает моделирование между временем = 3 секунды и временем = 16 секунд. Обратите внимание, что такие дорожки, как T10 и T6, сохраняют свои идентификаторы и траекторию в течение периода времени. Однако дорожка T9 теряется, поскольку гусеничное транспортное средство долгое время было пропущено (не обнаружено) датчиком. Кроме того, обратите внимание, что отслеживаемые объекты способны сохранять свою форму и кинематический центр, размещая детекторы на видимых участках транспортных средств. Например, когда Track T7 движется вперед, обнаружения ограничивающей рамки начинают падать на ее видимую заднюю часть, и дорожка сохраняет фактический размер транспортного средства. Это иллюстрирует эффект смещения и усадки, смоделированный в функциях измерения.
Захват маневров

Анимация показывает, что использование фильтра IMM помогает трекеру поддерживать дорожки на маневрирующих транспортных средствах. Обратите внимание, что транспортное средство, отслеживаемое T4, меняет полосы движения позади эго-транспортного средства. Трекер способен поддерживать трассу на транспортном средстве во время этого маневренного события. Также обратите внимание на дисплее, что его вероятность следования модели постоянного поворота, обозначенной ct, увеличивается во время маневра смены полосы.
Совместная ассоциация вероятностных данных

Эта анимация показывает, что использование совместного вероятностного трекера ассоциации данных помогает поддерживать треки во время неоднозначных ситуаций. Здесь транспортные средства, отслеживаемые T43 и T73, имеют низкую вероятность обнаружения из-за их большого расстояния от датчика. Обратите внимание, что трекер может поддерживать дорожки во время событий, когда один из транспортных средств не обнаружен. Во время этого события треки сначала объединяются, что является известным явлением в JPDA, а затем отделяются, как только транспортное средство обнаруживается снова.
В этом примере показано, как использовать JPDA-трекер с IMM-фильтром для отслеживания объектов с помощью лидарного датчика. Вы узнали, как облако исходных точек может быть предварительно обработано для создания обнаружений для обычных трекеров, которые предполагают одно обнаружение на объект на сканирование датчика. Также было показано, как определить кубовидную модель для описания кинематики, размеров и измерений расширенных объектов, отслеживаемых JPDA-трекером. Кроме того, из алгоритма был сгенерирован код C и проверены результаты его выполнения с помощью моделирования MATLAB.
helperLidarModel
Эта функция определяет модель лидара для моделирования усадки измерения ограничивающей рамки и смещения центральной точки. Эта функция используется в helperCvmeasCuboid и helperCtmeasCuboid для получения измерения ограничивающей рамки из состояния.
function meas = helperLidarModel(pos,dim,yaw) % This function returns the expected bounding box measurement given an % object's position, dimension, and yaw angle. % Copyright 2019 The MathWorks, Inc. % Get x,y and z. x = pos(1,:); y = pos(2,:); z = pos(3,:) - 2; % lidar mounted at height = 2 meters. % Get spherical measurement. [az,~,r] = cart2sph(x,y,z); % Shrink rate s = 3/50; % 3 meters radial length at 50 meters. sz = 2/50; % 2 meters height at 50 meters. % Get length, width and height. L = dim(1,:); W = dim(2,:); H = dim(3,:); az = az - deg2rad(yaw); % Shrink length along radial direction. Lshrink = min(L,abs(s*r.*(cos(az)))); Ls = L - Lshrink; % Shrink width along radial direction. Wshrink = min(W,abs(s*r.*(sin(az)))); Ws = W - Wshrink; % Shrink height. Hshrink = min(H,sz*r); Hs = H - Hshrink; % Similar shift is for x and y directions. shiftX = Lshrink.*cosd(yaw) + Wshrink.*sind(yaw); shiftY = Lshrink.*sind(yaw) + Wshrink.*cosd(yaw); shiftZ = Hshrink; % Modeling the affect of box origin offset x = x - sign(x).*shiftX/2; y = y - sign(y).*shiftY/2; z = z + shiftZ/2 + 2; % Measurement format meas = [x;y;z;yaw;Ls;Ws;Hs]; end
helperInverseLidarModel
Эта функция определяет обратную модель лидара для инициирования фильтра слежения с помощью измерения ограничивающей рамки лидара. Эта функция используется в helperInitIMMFilter функция для получения оценок состояния из измерения ограничивающей рамки.
function [pos,posCov,dim,dimCov,yaw,yawCov] = helperInverseLidarModel(meas,measCov) % This function returns the position, dimension, yaw using a bounding % box measurement. % Copyright 2019 The MathWorks, Inc. % Shrink rate. s = 3/50; sz = 2/50; % x,y and z of measurement x = meas(1,:); y = meas(2,:); z = meas(3,:); [az,~,r] = cart2sph(x,y,z); % Shift x and y position. Lshrink = abs(s*r.*(cos(az))); Wshrink = abs(s*r.*(sin(az))); Hshrink = sz*r; shiftX = Lshrink; shiftY = Wshrink; shiftZ = Hshrink; x = x + sign(x).*shiftX/2; y = y + sign(y).*shiftY/2; z = z - shiftZ/2; pos = [x;y;z]; posCov = measCov(1:3,1:3,:); yaw = meas(4,:); yawCov = measCov(4,4,:); % Dimensions are initialized for a standard passenger car with low % uncertainity. dim = [4.7;1.8;1.4]; dimCov = 0.01*eye(3); end
HelperBoundingBoxDetector
Это поддерживающий класс HelperBoundingBoxDetector чтобы принять входные данные облака точек и вернуть список objectDetection
classdef HelperBoundingBoxDetector < matlab.System % HelperBoundingBoxDetector A helper class to segment the point cloud % into bounding box detections. % The step call to the object does the following things: % % 1. Removes point cloud outside the limits. % 2. From the survived point cloud, segments out ground % 3. From the obstacle point cloud, forms clusters and puts bounding % box on each cluster. % Cropping properties properties % XLimits XLimits for the scene XLimits = [-70 70]; % YLimits YLimits for the scene YLimits = [-6 6]; % ZLimits ZLimits fot the scene ZLimits = [-2 10]; end % Ground Segmentation Properties properties % GroundMaxDistance Maximum distance of point to the ground plane GroundMaxDistance = 0.3; % GroundReferenceVector Reference vector of ground plane GroundReferenceVector = [0 0 1]; % GroundMaxAngularDistance Maximum angular distance of point to reference vector GroundMaxAngularDistance = 5; end % Bounding box Segmentation properties properties % SegmentationMinDistance Distance threshold for segmentation SegmentationMinDistance = 1.6; % MinDetectionsPerCluster Minimum number of detections per cluster MinDetectionsPerCluster = 2; % MaxZDistanceCluster Maximum Z-coordinate of cluster MaxZDistanceCluster = 3; % MinZDistanceCluster Minimum Z-coordinate of cluster MinZDistanceCluster = -3; end % Ego vehicle radius to remove ego vehicle point cloud. properties % EgoVehicleRadius Radius of ego vehicle EgoVehicleRadius = 3; end properties % MeasurementNoise Measurement noise for the bounding box detection MeasurementNoise = blkdiag(eye(3),10,eye(3)); end properties (Nontunable) MeasurementParameters = struct.empty(0,1); end methods function obj = HelperBoundingBoxDetector(varargin) setProperties(obj,nargin,varargin{:}) end end methods (Access = protected) function [bboxDets,obstacleIndices,groundIndices,croppedIndices] = stepImpl(obj,currentPointCloud,time) % Crop point cloud [pcSurvived,survivedIndices,croppedIndices] = cropPointCloud(currentPointCloud,obj.XLimits,obj.YLimits,obj.ZLimits,obj.EgoVehicleRadius); % Remove ground plane [pcObstacles,obstacleIndices,groundIndices] = removeGroundPlane(pcSurvived,obj.GroundMaxDistance,obj.GroundReferenceVector,obj.GroundMaxAngularDistance,survivedIndices); % Form clusters and get bounding boxes detBBoxes = getBoundingBoxes(pcObstacles,obj.SegmentationMinDistance,obj.MinDetectionsPerCluster,obj.MaxZDistanceCluster,obj.MinZDistanceCluster); % Assemble detections if isempty(obj.MeasurementParameters) measParams = {}; else measParams = obj.MeasurementParameters; end bboxDets = assembleDetections(detBBoxes,obj.MeasurementNoise,measParams,time); end end end function detections = assembleDetections(bboxes,measNoise,measParams,time) % This method assembles the detections in objectDetection format. numBoxes = size(bboxes,2); detections = cell(numBoxes,1); for i = 1:numBoxes detections{i} = objectDetection(time,cast(bboxes(:,i),'double'),... 'MeasurementNoise',double(measNoise),'ObjectAttributes',struct,... 'MeasurementParameters',measParams); end end function bboxes = getBoundingBoxes(ptCloud,minDistance,minDetsPerCluster,maxZDistance,minZDistance) % This method fits bounding boxes on each cluster with some basic % rules. % Cluster must have at least minDetsPerCluster points. % Its mean z must be between maxZDistance and minZDistance. % length, width and height are calculated using min and max from each % dimension. [labels,numClusters] = pcsegdist(ptCloud,minDistance); pointData = ptCloud.Location; bboxes = nan(7,numClusters,'like',pointData); isValidCluster = false(1,numClusters); for i = 1:numClusters thisPointData = pointData(labels == i,:); meanPoint = mean(thisPointData,1); if size(thisPointData,1) > minDetsPerCluster && ... meanPoint(3) < maxZDistance && meanPoint(3) > minZDistance cuboid = pcfitcuboid(pointCloud(thisPointData)); yaw = cuboid.Orientation(3); L = cuboid.Dimensions(1); W = cuboid.Dimensions(2); H = cuboid.Dimensions(3); if abs(yaw) > 45 possibles = yaw + [-90;90]; [~,toChoose] = min(abs(possibles)); yaw = possibles(toChoose); temp = L; L = W; W = temp; end bboxes(:,i) = [cuboid.Center yaw L W H]'; isValidCluster(i) = L < 20 & W < 20; end end bboxes = bboxes(:,isValidCluster); end function [ptCloudOut,obstacleIndices,groundIndices] = removeGroundPlane(ptCloudIn,maxGroundDist,referenceVector,maxAngularDist,currentIndices) % This method removes the ground plane from point cloud using % pcfitplane. [~,groundIndices,outliers] = pcfitplane(ptCloudIn,maxGroundDist,referenceVector,maxAngularDist); ptCloudOut = select(ptCloudIn,outliers); obstacleIndices = currentIndices(outliers); groundIndices = currentIndices(groundIndices); end function [ptCloudOut,indices,croppedIndices] = cropPointCloud(ptCloudIn,xLim,yLim,zLim,egoVehicleRadius) % This method selects the point cloud within limits and removes the % ego vehicle point cloud using findNeighborsInRadius locations = ptCloudIn.Location; locations = reshape(locations,[],3); insideX = locations(:,1) < xLim(2) & locations(:,1) > xLim(1); insideY = locations(:,2) < yLim(2) & locations(:,2) > yLim(1); insideZ = locations(:,3) < zLim(2) & locations(:,3) > zLim(1); inside = insideX & insideY & insideZ; % Remove ego vehicle nearIndices = findNeighborsInRadius(ptCloudIn,[0 0 0],egoVehicleRadius); nonEgoIndices = true(ptCloudIn.Count,1); nonEgoIndices(nearIndices) = false; validIndices = inside & nonEgoIndices; indices = find(validIndices); croppedIndices = find(~validIndices); ptCloudOut = select(ptCloudIn,indices); end
mexLidarTracker
Эта функция реализует отображение предварительной обработки облака точек и алгоритм отслеживания с использованием функционального интерфейса для генерации кода.
function [detections,obstacleIndices,groundIndices,croppedIndices,... confirmedTracks, modelProbs] = mexLidarTracker(ptCloudLocations,time) persistent detectorModel tracker detectableTracksInput currentNumTracks if isempty(detectorModel) || isempty(tracker) || isempty(detectableTracksInput) || isempty(currentNumTracks) % Use the same starting seed as MATLAB to reproduce results in SIL % simulation. rng(2018); % A bounding box detector model. detectorModel = HelperBoundingBoxDetector(... 'XLimits',[-50 75],... % min-max 'YLimits',[-5 5],... % min-max 'ZLimits',[-2 5],... % min-max 'SegmentationMinDistance',1.8,... % minimum Euclidian distance 'MinDetectionsPerCluster',1,... % minimum points per cluster 'MeasurementNoise',blkdiag(0.25*eye(3),25,eye(3)),... % measurement noise in detection report. 'GroundMaxDistance',0.3); % maximum distance of ground points from ground plane assignmentGate = [75 1000]; % Assignment threshold; confThreshold = [7 10]; % Confirmation threshold for history logic delThreshold = [8 10]; % Deletion threshold for history logic Kc = 1e-9; % False-alarm rate per unit volume filterInitFcn = @helperInitIMMFilter; tracker = trackerJPDA('FilterInitializationFcn',filterInitFcn,... 'TrackLogic','History',... 'AssignmentThreshold',assignmentGate,... 'ClutterDensity',Kc,... 'ConfirmationThreshold',confThreshold,... 'DeletionThreshold',delThreshold,... 'HasDetectableTrackIDsInput',true,... 'InitializationThreshold',0,... 'MaxNumTracks',30,... 'HitMissThreshold',0.1); detectableTracksInput = zeros(tracker.MaxNumTracks,2); currentNumTracks = 0; end ptCloud = pointCloud(ptCloudLocations); % Detector model [detections,obstacleIndices,groundIndices,croppedIndices] = detectorModel(ptCloud,time); % Call tracker [confirmedTracks,~,allTracks] = tracker(detections,time,detectableTracksInput(1:currentNumTracks,:)); % Update the detectability input currentNumTracks = numel(allTracks); detectableTracksInput(1:currentNumTracks,:) = helperCalcDetectability(allTracks,[1 3 6]); % Get model probabilities modelProbs = zeros(2,numel(confirmedTracks)); if isLocked(tracker) for k = 1:numel(confirmedTracks) c1 = getTrackFilterProperties(tracker,confirmedTracks(k).TrackID,'ModelProbabilities'); probs = c1{1}; modelProbs(1,k) = probs(1); modelProbs(2,k) = probs(2); end end end
helperCalcDetectability
Функция вычисляет вероятность обнаружения для каждой дорожки. Эта функция используется для генерации входных данных «DetectiveTalkIds» для trackerJPDA.
function detectableTracksInput = helperCalcDetectability(tracks,posIndices) % This is a helper function to calculate the detection probability of % tracks for the lidar tracking example. It may be removed in a future % release. % Copyright 2019 The MathWorks, Inc. % The bounding box detector has low probability of segmenting point clouds % into bounding boxes are distances greater than 40 meters. This function % models this effect using a state-dependent probability of detection for % each tracker. After a maximum range, the Pd is set to a high value to % enable deletion of track at a faster rate. if isempty(tracks) detectableTracksInput = zeros(0,2); return; end rMax = 75; rAmbig = 40; stateSize = numel(tracks(1).State); posSelector = zeros(3,stateSize); posSelector(1,posIndices(1)) = 1; posSelector(2,posIndices(2)) = 1; posSelector(3,posIndices(3)) = 1; pos = getTrackPositions(tracks,posSelector); if coder.target('MATLAB') trackIDs = [tracks.TrackID]; else trackIDs = zeros(1,numel(tracks),'uint32'); for i = 1:numel(tracks) trackIDs(i) = tracks(i).TrackID; end end [~,~,r] = cart2sph(pos(:,1),pos(:,2),pos(:,3)); probDetection = 0.9*ones(numel(tracks),1); probDetection(r > rAmbig) = 0.4; probDetection(r > rMax) = 0.99; detectableTracksInput = [double(trackIDs(:)) probDetection(:)]; end
loadLidarAndImageData
Сшивает данные Лидара и Камеры для обработки с использованием заданного начального и окончательного времени.
function [lidarData,imageData] = loadLidarAndImageData(datasetFolder,initTime,finalTime) initFrame = max(1,floor(initTime*10)); lastFrame = min(350,ceil(finalTime*10)); load (fullfile(datasetFolder,'imageData_35seconds.mat'),'allImageData'); imageData = allImageData(initFrame:lastFrame); numFrames = lastFrame - initFrame + 1; lidarData = cell(numFrames,1); % Each file contains 70 frames. initFileIndex = floor(initFrame/70) + 1; lastFileIndex = ceil(lastFrame/70); frameIndices = [1:70:numFrames numFrames + 1]; counter = 1; for i = initFileIndex:lastFileIndex startFrame = frameIndices(counter); endFrame = frameIndices(counter + 1) - 1; load(fullfile(datasetFolder,['lidarData_',num2str(i)]),'currentLidarData'); lidarData(startFrame:endFrame) = currentLidarData(1:(endFrame + 1 - startFrame)); counter = counter + 1; end end
[1] Арья Сенна Абдул Рахман, Арья. «3D ЛИДАР много отслеживание объекта для автономного вождения: мультицелевое обнаружение и отслеживающий под Урбан-Роуд Ансертэйнтис». (2017).
pointCloud | trackerJPDA (панель инструментов слияния и отслеживания датчиков) | trackingIMM(Панель инструментов слияния и отслеживания датчиков)