Этот пример показывает, как сгенерировать виртуальный сценарий вождения из зарегистрированных данных о транспортном средстве. Сценарий генерируется из информации о положении, записанной с датчика GPS, и записанных списков объектов, обработанных с датчика лидара.
Виртуальные сценарии вождения могут использоваться, чтобы воссоздать реальный сценарий из зарегистрированных данных о транспортном средстве. Эти виртуальные сценарии позволяют вам визуализировать и изучить исходный сценарий. Поскольку вы можете программно изменять виртуальные сценарии, можно также использовать их, чтобы синтезировать изменения сценария при разработке и оценке автономных управлений автомобилем.
В этом примере вы создаете виртуальный сценарий вождения путем генерации drivingScenario
объект из данных, которые были записаны с тестового (ego) транспортного средства и файла OpenDRIVE ®. Файл OpenDRIVE описывает дорожную сеть района, где были записаны данные. Зарегистрированные данные о транспортном средстве включают в себя:
GPS-данные: Текстовый файл, содержащий координаты широты и долготы автомобиля , оборудованного датчиком в каждой временной метке.
Лидар объекта списка данных: Текстовый файл, содержащий количество неэговых актёров и положения их центров относителен автомобиль , оборудованный датчиком в каждой временной метке.
Видео данных: MP4 файл, записанный с прямолинейной монокулярной камеры, установленной на автомобиль , оборудованный датчиком.
Чтобы сгенерировать и симулировать сценарий вождения, вы следуете следующим шагам:
Исследуйте зарегистрированные данные о транспортном средстве.
Импорт дорожной сети OpenDRIVE в сценарий вождения.
Добавьте данные о транспортном автомобиле , оборудованном датчиком из GPS в сценарий вождения.
Добавьте актёров, не являющихся эго, из списка объектов лидара в сценарий вождения.
Моделируйте и визуализируйте сгенерированный сценарий.
Следующая схема показывает, как вы используете записанные данные в этом примере. Заметьте, что вы создаете сценарий вождения из файлов GPS, списков объектов лидара и OpenDRIVE. Вы используете данные камеры, чтобы визуализировать исходный сценарий и можете сравнить эти данные со сценарием, который вы генерируете. Вы также визуализируете маршрут сценария на карте, используя geoplayer
.
Положения автомобиля , оборудованного датчиком были захвачены с помощью датчика UBlox GPS NEO M8N. GPS-датчик был размещен на центре крыши автомобиля , оборудованного датчиком. Эти данные сохраняются в текстовом файле EgoUrban.txt
.
Положения неэговых актёров были захвачены с помощью датчика лидара Velodyne ® VLP-16 с областью значений значений 30 метров. Датчик VLP-16 был помещен на крышу автомобиля , оборудованного датчиком в положении и высоте, которые избегают столкновения датчика с корпусом автомобиля , оборудованного датчиком. Облако точек с датчика лидара было обработано на транспортном средстве, чтобы обнаружить объекты и их положения относителен автомобиль , оборудованный датчиком. Эти данные сохраняются в текстовом файле NonEgoUrban.txt
.
Чтобы помочь разобраться в оригинальном сценарии, в качестве ссылки было записано видео с монокулярной камеры. Это видео также может использоваться, чтобы визуально сравнить оригинальные и сгенерированные сценарии. Предварительный просмотр этого записанного видео сохранен в файл видео urbanpreview.mp4
. Вы можете скачать полный файл видео отсюда.
Сгенерируйте предварительный просмотр сценария городского трафика, используемого в этом примере.
vidObj = VideoReader('urbanpreview.mp4'); fig = figure; set(fig,'Position',[0, 0, 800, 600]); movegui(fig,'center'); pnl = uipanel(fig,'Position',[0 0 1 1],'Title','Urban Traffic Scenario'); plt = axes(pnl); while hasFrame(vidObj) vidFrame = readFrame(vidObj); image(vidFrame,'Parent',plt); currAxes.Visible = 'off'; pause(1/vidObj.FrameRate); end
Хотя зона покрытия датчика может быть задана вокруг всего автомобиля , оборудованного датчиком, этот пример показывает только перспективный сценарий.
Файл дорожной сети для генерации виртуального сценария был загружен из https://www.openstreetmap.org, что обеспечивает доступ к картографическим данным, полученным из толпы, по всему миру. Данные лицензированы под лицензией Open Data Commons Open Database License (ODbL), https://opendatacommons.org/licenses/odbl/. Файлы данных OpenStreetMap преобразуются в файлы OpenDRIVE и сохраняются с расширением .xodr
. Используйте roadNetwork
функция для импорта данных об этой дорожной сети в сценарий вождения.
Создайте объект сценария вождения и импортируйте нужную дорожную сеть OpenDRIVE в сгенерированный сценарий.
scenario = drivingScenario; openDRIVEFile = 'OpenDRIVEUrban.xodr'; roadNetwork(scenario,'OpenDRIVE',openDRIVEFile);
Данные о автомобиле , оборудованном датчиком собираются с датчика GPS и хранятся в виде текстового файла. Текстовый файл состоит из трех столбцов, в которых хранятся значения широты, долготы и временной метки для автомобиля , оборудованного датчиком. Используйте helperGetEgoData
функция для импорта данных ego vehicle из текстового файла в структуру в рабочей области MATLAB ®. Структура содержит три поля, задающие широту, долготу и временные метки.
egoFile = 'EgoUrban.txt';
egoData = helperGetEgoData(egoFile);
Вычислите траекторные точки пути автомобиль , оборудованный датчиком из зарегистрированных координат GPS. Используйте latlon2local
функция для преобразования необработанных координат GPS в локальные Декартовы координаты на востоке-севере-вверх. Преобразованные координаты определяют траекторные точки пути автомобиля , оборудованного датчиком.
% Specify latitude and longitude at origin of data from OpenDRIVE file. This point will also define the origin of the local coordinate system. alt = 540.0; % Average altitude in Hyderabad, India origin = [17.425853702697903, 78.44939480188313, alt]; % [lat, lon, altitude] % Specify latitude and longitude of ego vehicle lat = egoData.lat; lon = egoData.lon; % Compute waypoints of ego vehicle [X,Y,~] = latlon2local(lat,lon,alt,origin); egoWaypoints(:,1) = X; egoWaypoints(:,2) = Y;
Визуализируйте GPS- пути автомобиля , оборудованного датчиком с помощью geoplayer
объект.
zoomLevel = 17; player = geoplayer(lat(1),lon(1),zoomLevel); plotRoute(player,lat,lon); for i = 1:length(lat) plotPosition(player,lat(i),lon(i)); end
Использование helperComputeEgoData
для вычисления скорости и значений угла рыскания автомобиля , оборудованного датчиком в каждой временной метке данных датчика.
[egoSpeed,egoAngle] = helperComputeEgoData(egoData,X,Y);
Добавьте автомобиль , оборудованный датчиком в сценарий вождения.
ego = vehicle(scenario,'ClassID',1,'Length',1,'Width',0.6,'Height',0.6);
Создайте траекторию для автомобиля , оборудованного датчиком из вычисленного набора точек пути ego и скорости. Автомобиль , оборудованный датчиком следует по траектории с заданной скоростью.
trajectory(ego,egoWaypoints,egoSpeed);
Данные актёра, не являющегося эго, собираются с датчика лидара и хранятся в виде текстового файла. Текстовый файл состоит из пяти столбцов, в которых хранятся идентификаторы актёра x
-положения, y
-положения, z
- положения и значения временных меток, соответственно. Используйте helperGetNonEgoData
функция для импорта данных актёра, не являющегося эго, из текстового файла в структуру в рабочей области MATLAB ®. Выходы представляют собой структуру с тремя полями:
ActorID
- определяемый сценарием идентификатор актёра, заданный как положительное целое число.
Position -
Положение актёра, заданное как вектор действительных чисел [x y z]. Модули измерения указаны в метрах.
Time
- Временная метка регистрации датчика.
nonEgoFile = 'NonEgoUrban.txt';
nonEgoData = helperGetNonEgoData(nonEgoFile);
Использование helperComputeNonEgoData
вычислить точки пути траектории и скорость каждого актёра, не являющегося эго, в каждой временной метке. Путевые точки траектории вычисляются относительно автомобиля , оборудованного датчиком.
actors = unique(nonEgoData.ActorID); [nonEgoSpeed, nonEgoWaypoints] = helperComputeNonEgoData(egoData,egoWaypoints,nonEgoData,egoAngle);
Добавьте актёров, не являющихся эго, в сценарий вождения. Создайте траектории для актёров, не являющихся эго, из вычисленного набора точек пути актёра и скорости.
for i = 1:length(actors) actor = vehicle(scenario,'ClassID',1,'Length',1,'Width',0.6,'Height',0.6); trajectory(actor,nonEgoWaypoints{i},nonEgoSpeed{i}); end
Визуализируйте актёров автомобиля , оборудованного датчиком и неэго, которые вы импортировали в сгенерированный сценарий. Также визуализируйте соответствующие траекторные точки пути автомобиль , оборудованный датчиком и non-ego актёров.
% Create a custom figure window and define an axes object fig = figure; set(fig,'Position',[0, 0, 800, 600]); movegui(fig,'center'); hViewPnl = uipanel(fig,'Position',[0 0 1 1],'Title','Ego Vehicle and Actors'); hCarPlt = axes(hViewPnl); % Plot the generated driving scenario. plot(scenario,'Parent',hCarPlt); axis([270 320 80 120]); legend('Imported Road Network','Lanes','Ego Vehicle','Actor 1','Actor 2','Actor 3','Actor 4','Actor 5') legend(hCarPlt,'boxoff');
figure, plot(egoWaypoints(:,1),egoWaypoints(:,2),'Color',[0 0.447 0.741],'LineWidth',2) hold on cMValues = [0.85 0.325 0.098;0.929 0.694 0.125;0.494 0.184 0.556;0.466 0.674 0.188;0.301 0.745 0.933]; for i =1:length(actors) plot(nonEgoWaypoints{i}(:,1),nonEgoWaypoints{i}(:,2),'Color',cMValues(i,:),'LineWidth',2) end axis('tight') xlabel('X (m)') ylabel('Y (m)') title('Computed Ego Vehicle and Actor Trajectories') legend('Ego Vehicle', 'Actor 1', 'Actor 2', 'Actor 3','Actor 4','Actor 5','Location','Best') hold off
Постройте график сценария и соответствующий график погони. Запустите симуляцию, чтобы визуализировать сгенерированный сценарий вождения. Актёры автомобиля , оборудованного датчиком и неэго следуют своим соответствующим траекториям.
% Create a custom figure window to show the scenario and chase plot close all; figScene = figure('Name','Driving Scenario','Tag','ScenarioGenerationDemoDisplay'); set(figScene,'Position',[0, 0, 1032, 1032]); movegui(figScene,'center'); % Add the chase plot hCarViewPanel = uipanel(figScene,'Position',[0.5 0 0.5 1],'Title','Chase Camera View'); hCarPlot = axes(hCarViewPanel); chasePlot(ego,'Parent',hCarPlot); % Add the top view of the generated scenario hViewPanel = uipanel(figScene,'Position',[0 0 0.5 1],'Title','Top View'); hCarPlot = axes(hViewPanel); plot(scenario,'Parent',hCarPlot); % Set the axis limits to display only the active area xMin = min(egoWaypoints(:,1)); xMax = max(egoWaypoints(:,1)); yMin = min(egoWaypoints(:,2)); yMax = max(egoWaypoints(:,2)); limits = [xMin xMax yMin yMax]; axis(limits); % Run the simulation while advance(scenario) pause(0.01) end
Этот пример показывает, как автоматически сгенерировать виртуальный сценарий вождения из данных о транспортном средстве, записанных с помощью датчиков GPS и лидара.
helperGetEgoData
Эта функция считывает данные автомобиля , оборудованного датчиком из текстового файла и преобразует в структуру.
function [egoData] = helperGetEgoData(egoFile) %Read the ego vehicle data from text file fileID = fopen(egoFile); content = textscan(fileID,'%f %f %f'); fields = {'lat','lon','Time'}; egoData = cell2struct(content,fields,2); fclose(fileID); end
helperGetNonEgoData
Эта функция считывает обработанные данные лидара из текстового файла и преобразуется в структуру. Обработанные данные лидара содержат информацию об актерах, не являющихся эго.
function [nonEgoData] = helperGetNonEgoData(nonEgoFile) % Read the processed lidar data of non-ego actors from text file. fileID = fopen(nonEgoFile); content = textscan(fileID,'%d %f %f %f %f'); newcontent{1} = content{1}; newcontent{2} = [content{2} content{3} content{4}]; newcontent{3} = content{5}; fields = {'ActorID','Position','Time'}; nonEgoData = cell2struct(newcontent,fields,2); fclose(fileID); end
helperComputeEgoData
Эта функция вычисляет скорость и угол рыскания автомобиля , оборудованного датчиком на основе точек пути траектории и временных меток.
function [egoSpeed, egoAngle] = helperComputeEgoData(egoData, X, Y) egoTime = egoData.Time; timeDiff = diff(egoTime); points = [X Y]; difference = diff(points, 1); distance = sqrt(sum(difference .* difference, 2)); egoSpeed = distance./timeDiff; egoAngle = atan(diff(Y)./diff(X)); egoAngle(end+1) = egoAngle(end); egoSpeed(end+1) = egoSpeed(end); end
helperComputeNonEgoData
Эта функция вычисляет скорость и угол рыскания каждого актёра, не являющегося эго, на основе точек пути траектории и временных меток. Скорость и угол рыскания вычисляются относительно автомобиля , оборудованного датчиком.
function [nonEgoSpeed, nonEgoWaypoints] = helperComputeNonEgoData(egoData, egoWaypoints, nonEgoData, egoAngle) actors = unique(nonEgoData.ActorID); numActors = length(actors); nonEgoWaypoints = cell(numActors, 1); nonEgoSpeed = cell(numActors, 1); for i = 1:numActors id = actors(i); idx = find([nonEgoData.ActorID] == id); actorXData = nonEgoData.Position(idx,1); actorYData = nonEgoData.Position(idx,2); actorTime = nonEgoData.Time(idx); actorWaypoints = [0 0]; % Compute the trajectory waypoints of non-ego actor [sharedTimeStamps,nonEgoIdx,egoIdx] = intersect(actorTime,egoData.Time,'stable'); tempX = actorXData(nonEgoIdx); tempY = actorYData(nonEgoIdx); relativeX = -tempX .* cos(egoAngle(egoIdx)) + tempY .* sin(egoAngle(egoIdx)); relativeY = -tempX .* sin(egoAngle(egoIdx)) - tempY .* cos(egoAngle(egoIdx)); actorWaypoints(nonEgoIdx,1) = egoWaypoints(egoIdx,1) + relativeX; actorWaypoints(nonEgoIdx,2) = egoWaypoints(egoIdx,2) + relativeY; % Compute the speed values of non-ego actor timeDiff = diff(sharedTimeStamps); difference = diff(actorWaypoints, 1); distance = sqrt(sum(difference .* difference, 2)); actorSpeed = distance./timeDiff; actorSpeed(end+1) = actorSpeed(end); % Smooth the trajectory waypoints of non-ego actor actorWaypoints = smoothdata(actorWaypoints,'sgolay'); % Store the values of trajectory waypoints and speed computed of each non-ego actor nonEgoWaypoints(i) = {actorWaypoints}; nonEgoSpeed(i) = {actorSpeed'}; end end