Этот пример показывает, как сгенерировать виртуальный ведущий сценарий от записанных данных об автомобиле. Сценарий сгенерирован от информации о положении, зарегистрированной от датчика GPS и записанных списков объектов, обработанных от датчика лазерного дальномера.
Виртуальные ведущие сценарии могут использоваться, чтобы воссоздать действительный сценарий от записанных данных об автомобиле. Эти виртуальные сценарии позволяют вам визуализировать и изучить исходный сценарий. Поскольку можно программно изменить виртуальные сценарии, можно также использовать их, чтобы синтезировать изменения сценария при разработке и оценке автономных ведущих систем.
В этом примере вы создаете виртуальный ведущий сценарий путем генерации объекта
drivingScenario
от данных, которые были зарегистрированы от теста (эго) автомобиль и файл OpenDRIVE®. Файл OpenDRIVE описывает дорожную сеть области, где данные были зарегистрированы. Записанные данные об автомобиле включают:
Данные о GPS: Текстовый файл, содержащий координаты широты и долготы автомобиля, оборудованного датчиком в каждой метке времени.
Лоцируйте данные о списке объектов: Текстовый файл, содержащий количество агентов неэго и позиции их центров, относительно автомобиля, оборудованного датчиком, в каждой метке времени.
Видеоданные: файл MP4, зарегистрированный от монокулярной камеры по ходу движения, смонтированной на автомобиле, оборудованном датчиком.
Чтобы сгенерировать и моделировать ведущий сценарий, вы выполняете эти шаги:
Исследуйте зарегистрированные данные об автомобиле.
Импортируйте дорожную сеть OpenDRIVE в ведущий сценарий.
Добавьте данные об автомобиле, оборудованном датчиком от GPS до ведущего сценария.
Добавьте агентов неэго от списка объектов лазерного дальномера до ведущего сценария.
Моделируйте и визуализируйте сгенерированный сценарий.
Следующая схема показывает, как вы используете записанные данные в этом примере. Заметьте, что вы создаете ведущий сценарий из GPS, лоцируете списки объектов и файлы OpenDRIVE. Вы используете данные о камере, чтобы визуализировать исходный сценарий и можете сравнить эти данные со сценарием, который вы генерируете. Вы также визуализируете маршрут сценария на карте с помощью geoplayer
.
Положения автомобиля, оборудованного датчиком были получены с помощью GPS UBlox датчик 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
Хотя зона охвата датчика может быть задана вокруг целого автомобиля, оборудованного датчиком, этот пример показывает только перспективный сценарий.
Данные о дорожной сети для генерации виртуального сценария получены из OpenStreetMap®. Файлы данных OpenStreetMap преобразованы в файлы OpenDRIVE и сохраненные с дополнительным .xodr
. Используйте функцию roadNetwork
, чтобы импортировать эти данные о дорожной сети к ведущему сценарию.
Создайте ведущий сценарий, возражают и импортируют желаемую дорожную сеть OpenDRIVE в сгенерированный сценарий.
scenario = drivingScenario; openDRIVEFile = 'OpenDRIVEUrban.xodr'; roadNetwork(scenario,'OpenDRIVE',openDRIVEFile);
Данные об автомобиле, оборудованном датчиком собраны от датчика GPS и сохранены как текстовый файл. Текстовый файл состоит из трех столбцов, которые хранят широту, долготу и значения метки времени для автомобиля, оборудованного датчиком. Используйте функцию helperGetEgoData
, чтобы импортировать данные об автомобиле, оборудованном датчиком из текстового файла в структуру в рабочей области MATLAB®. Структура содержит три поля, задающие широту, долготу и метки времени.
egoFile = 'EgoUrban.txt';
egoData = helperGetEgoData(egoFile);
Вычислите траекторию waypoints автомобиля, оборудованного датчиком от записанных координат GPS. Используйте функцию geodetic2enu
от Mapping Toolbox™, чтобы преобразовать необработанные координаты GPS на локальный "восточный север" Декартова система. Преобразованные координаты задают траекторию waypoints автомобиля, оборудованного датчиком.
% Specify latitude and longitude at origin of OpenDRIVE file lat0 = 17.425853702697903; lon0 = 78.44939480188313; % Specify latitude and longitude of ego vehicle lat = egoData.lat; lon = egoData.lon; % Compute waypoints of ego vehicle [X,Y,~] = geodetic2enu(lat,lon,0,lat0,lon0,0,wgs84Ellipsoid); 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,'Length',1,'Width',0.6,'Height',0.6);
Создайте траекторию для автомобиля, оборудованного датчиком от вычисленного набора эго waypoints и скорости. Автомобиль, оборудованный датчиком следует за траекторией на заданной скорости.
trajectory(ego,egoWaypoints,egoSpeed);
Данные об агенте неэго собраны от датчика лазерного дальномера и сохранены как текстовый файл. Текстовый файл состоит из пяти столбцов, которые хранят идентификаторы агента, x
- положения, y
- положения, z
- положения и значения метки времени, соответственно. Используйте функцию helperGetNonEgoData
, чтобы импортировать данные об агенте неэго из текстового файла в структуру в рабочей области MATLAB®. Вывод является структурой с тремя полями:
ActorID
- Заданный сценарием идентификатор агента, заданный как положительное целое число.
Положение Position -
агента, заданного как [x y z] вектор действительных чисел. Модули исчисляются в метрах.
Время-
Метка времени записи датчика.
nonEgoFile = 'NonEgoUrban.txt';
nonEgoData = helperGetNonEgoData(nonEgoFile);
Используйте helperComputeNonEgoData
, чтобы вычислить траекторию waypoints и скорость каждого агента неэго в каждой метке времени. Траектория waypoints вычисляется относительно автомобиля, оборудованного датчиком.
actors = unique(nonEgoData.ActorID); [nonEgoSpeed, nonEgoWaypoints] = helperComputeNonEgoData(egoData,egoWaypoints,nonEgoData,egoAngle);
Добавьте агентов неэго в ведущий сценарий. Создайте траектории для агентов неэго от вычисленного набора агента waypoints и скорости.
for i = 1:length(actors) actor = vehicle(scenario,'Length',1,'Width',0.6,'Height',0.6); trajectory(actor,nonEgoWaypoints{i},nonEgoSpeed{i}); end
Визуализируйте автомобиль, оборудованный датчиком и агентов неэго, которых вы импортировали в сгенерированный сценарий. Также визуализируйте соответствующую траекторию waypoints агентов неэго и автомобиля, оборудованного датчиком.
% 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
Эта функция вычисляет скорость и направляющийся угол автомобиля, оборудованного датчиком на основе траектории waypoints и меток времени.
function [egoSpeed, egoAngle] = helperComputeEgoData(egoData,X,Y) egoAngle = zeros; egoSpeed = zeros; for t = 1:size(egoData.Time)-1 currTime = egoData.Time(t+1); prevTime = egoData.Time(t); timeDiff = currTime - prevTime; points = [X(t),Y(t);X(t+1),Y(t+1)]; distance = pdist(points,'euclidean'); egoSpeed(t) = distance/timeDiff; egoAngle(t) = atan((Y(t+1)-Y(t))/(X(t+1)-X(t))); end egoAngle(end+1) = egoAngle(end); egoSpeed(end+1) = egoSpeed(end); end
helperComputeNonEgoData
Эта функция вычисляет скорость и направляющийся угол каждого агента неэго на основе траектории waypoints и меток времени. Скорость и направляющийся угол вычисляются относительно автомобиля, оборудованного датчиком.
function [nonEgoSpeed, nonEgoWaypoints] = helperComputeNonEgoData(egoData,egoWaypoints,nonEgoData,egoAngle) actors = unique(nonEgoData.ActorID); [nonEgoWaypoints] = []; [nonEgoSpeed] = []; for i = 1:length(actors) id = actors(i); idx = find([nonEgoData.ActorID] == id); actorXData = nonEgoData.Position(idx,1); actorYData = nonEgoData.Position(idx,2); actorTime = nonEgoData.Time(idx); clear actorWaypoints actorSpeed; actorWaypoints(:,1) = zeros; actorWaypoints(:,2) = zeros; actorSpeed = zeros; for m = 1:size(actorTime) for n = 1:size(egoData.Time) if(egoData.Time(n) == actorTime(m)) % Compute the trajectory waypoints of non-ego actor tempX = actorXData(m); tempY = actorYData(m); relativeX = -tempX * cos(egoAngle(n)) + tempY * sin(egoAngle(n)); relativeY = -tempX * sin(egoAngle(n)) - tempY * cos(egoAngle(n)); actorWaypoints(m,1) = egoWaypoints(n,1) + relativeX; actorWaypoints(m,2) = egoWaypoints(n,2) + relativeY; % Compute the speed values of non-ego actor if(size(actorWaypoints,1)>=2) currTime = actorTime(m); prevTime = actorTime(m-1); timeDiff = currTime - prevTime; points = [actorWaypoints(m-1,1),actorWaypoints(m-1,2);actorWaypoints(m,1),actorWaypoints(m,2)]; distance = pdist(points,'euclidean'); actorSpeed(m-1) = distance/timeDiff; end break; end end end 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