В этом примере показано, как создать сценарий виртуального вождения на основе записанных данных транспортного средства. Сценарий формируется на основе информации о положении, записанной от GPS-датчика, и записанных списков объектов, обработанных от лидарного датчика.
Сценарии виртуального вождения могут использоваться для воссоздания реального сценария на основе записанных данных транспортного средства. Эти виртуальные сценарии позволяют визуализировать и изучить исходный сценарий. Поскольку можно программно изменять виртуальные сценарии, их также можно использовать для синтеза вариантов сценариев при проектировании и оценке автономных систем вождения.
В этом примере создается сценарий виртуального управления путем создания drivingScenario объект из данных, записанных из тестового (ego) транспортного средства и файла OpenDRIVE ®. Файл OpenDRIVE описывает дорожную сеть области, в которой были записаны данные. Записанные данные транспортного средства включают в себя:
Данные GPS: Текстовый файл, содержащий координаты широты и долготы эго-транспортного средства в каждой временной метке.
Данные списка объектов Lidar: Текстовый файл, содержащий количество субъектов, не являющихся эго, и положения их центров относительно транспортного средства эго на каждой временной метке.
Видеоданные: MP4 файл записан с обращенной вперед монокулярной камеры, установленной на эго-транспортном средстве.
Для создания и моделирования сценария движения выполните следующие шаги:
Изучите записанные данные о транспортных средствах.
Импорт дорожной сети OpenDRIVE в сценарий управления.
Добавление данных о транспортных средствах ego из GPS в сценарий вождения.
Добавление субъектов, не являющихся эго, из списка объектов lidar в сценарий управления.
Моделирование и визуализация сгенерированного сценария.
На следующей диаграмме показано использование записанных данных в этом примере. Обратите внимание, что сценарий управления создается из списков объектов GPS, lidar и файлов OpenDRIVE. Данные камеры используются для визуализации исходного сценария и могут быть сопоставлены с создаваемым сценарием. Также можно визуализировать маршрут сценария на карте с помощью geoplayer.

Положения эго-транспортного средства были зафиксированы с помощью датчика UBlox GPS NEO M8N. GPS-датчик был размещен в центре крыши эго-транспортного средства. Эти данные сохраняются в текстовом файле EgoUrban.txt.
Позиции не-эго актеров были захвачены с помощью датчика Velodine ® VLP-16 lidar с дальностью действия 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-датчика и сохраняются в виде текстового файла. Текстовый файл состоит из трех столбцов, в которых хранятся значения широты, долготы и временных меток для транспортного средства ego. Используйте helperGetEgoData для импорта данных эго-транспортного средства из текстового файла в структуру в рабочем пространстве 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);
Создайте траекторию для эго-транспортного средства из вычисленного набора эго-ППМ и скорости. Эго-транспортное средство следует по траектории с заданной скоростью.
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
Визуализируйте ego-транспортное средство и не-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