В этом примере показано, как сгенерировать виртуальный ведущий сценарий из записанных данных о транспортном средстве. Сценарий сгенерирован от информации о положении, зарегистрированной от датчика 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] вектор действительных чисел. Модули исчисляются в метрах.
Time
- Метка времени записи датчика.
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) 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
Эта функция вычисляет скорость и направляющийся угол каждого агента неэго на основе траектории waypoints и меток времени. Скорость и направляющийся угол вычисляются относительно автомобиля, оборудованного датчиком.
function [nonEgoSpeed, nonEgoWaypoints] = helperComputeNonEgoData(egoData, egoWaypoints, nonEgoData, egoAngle) actors = unique(nonEgoData.ActorID); nonEgoWaypoints = cell(length(actors), 1); nonEgoSpeed = cell(length(actors), 1); 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) = 0; actorWaypoints(:,2) = 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