Генерация сценария из записанных данных о транспортном средстве

В этом примере показано, как сгенерировать виртуальный ведущий сценарий из записанных данных о транспортном средстве. Сценарий сгенерирован от информации о положении, зарегистрированной от датчика GPS и записанных списков объектов, обработанных от датчика лидара.

Обзор

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

В этом примере вы создаете виртуальный ведущий сценарий путем генерации drivingScenario объект из данных, которые были зарегистрированы от теста (эго) транспортное средство и файл OpenDRIVE®. Файл OpenDRIVE описывает дорожную сеть области, где данные были зарегистрированы. Записанные данные о транспортном средстве включают:

  • Данные о GPS: Текстовый файл, содержащий координаты широты и долготы автомобиля, оборудованного датчиком в каждой метке времени.

  • Лоцируйте данные о списке объектов: Текстовый файл, содержащий количество агентов неэго и позиции их центров, относительно автомобиля, оборудованного датчиком, в каждой метке времени.

  • Видеоданные: файл MP4, зарегистрированный от монокулярной камеры по ходу движения, смонтированной на автомобиле, оборудованном датчиком.

Чтобы сгенерировать и симулировать ведущий сценарий, вы выполняете эти шаги:

  1. Исследуйте зарегистрированные данные о транспортном средстве.

  2. Импортируйте дорожную сеть OpenDRIVE в ведущий сценарий.

  3. Добавьте данные об автомобиле, оборудованном датчиком от GPS до ведущего сценария.

  4. Добавьте агентов неэго от списка объектов лидара до ведущего сценария.

  5. Симулируйте и визуализируйте сгенерированный сценарий.

Следующая схема показывает, как вы используете записанные данные в этом примере. Заметьте, что вы создаете ведущий сценарий из 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

Figure contains an axes and an object of type uipanel. The axes contains an object of type image.

Figure contains an axes and an object of type uipanel. The axes contains an object of type image.

Хотя зона охвата датчика может быть задана вокруг целого автомобиля, оборудованного датчиком, этот пример показывает только перспективный сценарий.

Импортируйте дорожную сеть OpenDRIVE в управление сценарием

Файл дорожной сети для генерации виртуального сценария был загружен с https://www.openstreetmap.org, который обеспечивает доступ к полученным толпой данным о карте во всем мире. Данные лицензируются под Открытыми Данными палата общин Открытая Лицензия Базы данных (ODbL), https://opendatacommons.org/licenses/odbl/. Файлы данных OpenStreetMap преобразованы в файлы OpenDRIVE и сохраненные с дополнительным .xodr. Используйте roadNetwork функция, чтобы импортировать эти данные о дорожной сети к ведущему сценарию.

Создайте ведущий сценарий, возражают и импортируют желаемую дорожную сеть OpenDRIVE в сгенерированный сценарий.

scenario = drivingScenario;
openDRIVEFile = 'OpenDRIVEUrban.xodr';
roadNetwork(scenario,'OpenDRIVE',openDRIVEFile);

Добавьте данные об автомобиле, оборудованном датчиком от GPS до сгенерированного сценария

Данные об автомобиле, оборудованном датчиком собраны от датчика GPS и сохранены как текстовый файл. Текстовый файл состоит из трех столбцов, которые хранят широту, долготу и значения метки времени для автомобиля, оборудованного датчиком. Используйте helperGetEgoData функция, чтобы импортировать данные об автомобиле, оборудованном датчиком из текстового файла в структуру в рабочей области MATLAB®. Структура содержит три поля, задающие широту, долготу и метки времени.

egoFile = 'EgoUrban.txt';
egoData = helperGetEgoData(egoFile);

Вычислите траекторию waypoints автомобиля, оборудованного датчиком от записанных координат GPS. Используйте latlon2local функционируйте, чтобы преобразовать необработанные координаты GPS в локальные Декартовы координаты "восточный север". Преобразованные координаты задают траекторию waypoints автомобиля, оборудованного датчиком.

% 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

Figure Geographic Player contains an axes. The axes contains 4 objects of type line, scatter, text.

Используйте helperComputeEgoData вычислить скорость и значения угла рыскания автомобиля, оборудованного датчиком в каждой метке времени данных о датчике.

[egoSpeed,egoAngle] = helperComputeEgoData(egoData,X,Y);

Добавьте автомобиль, оборудованный датчиком в ведущий сценарий.

ego = vehicle(scenario,'ClassID',1,'Length',1,'Width',0.6,'Height',0.6);

Создайте траекторию для автомобиля, оборудованного датчиком от вычисленного набора эго waypoints и скорости. Автомобиль, оборудованный датчиком следует за траекторией на заданной скорости.

trajectory(ego,egoWaypoints,egoSpeed);

Добавьте агентов неэго от списков объектов лидара до сгенерированного сценария

Данные об агенте неэго собраны от датчика лидара и сохранены как текстовый файл. Текстовый файл состоит из пяти столбцов, которые хранят идентификаторы агента, x- положения, y- положения, z- положения и значения метки времени, соответственно. Используйте helperGetNonEgoData функция, чтобы импортировать данные об агенте неэго из текстового файла в структуру в рабочей области MATLAB®. Выход является структурой с тремя полями:

  1. ActorID - Заданный сценарием идентификатор агента в виде положительного целого числа.

  2. Position - Положение агента в виде [x y z] вектор действительных чисел. Модули исчисляются в метрах.

  3. 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,'ClassID',1,'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 contains an axes and an object of type uipanel. The axes contains 9 objects of type patch. These objects represent Imported Road Network, Lanes, Ego Vehicle, Actor 1, Actor 2, Actor 3, Actor 4, Actor 5.

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

Figure contains an axes. The axes with title Computed Ego Vehicle and Actor Trajectories contains 6 objects of type line. These objects represent Ego Vehicle, Actor 1, Actor 2, Actor 3, Actor 4, Actor 5.

Симулируйте и визуализируйте сгенерированный сценарий

Постройте сценарий и соответствующий график преследования. Запустите симуляцию, чтобы визуализировать сгенерированный ведущий сценарий. Автомобиль, оборудованный датчиком и агенты неэго следуют за их соответствующими траекториями.

% 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

Figure Driving Scenario contains an axes and other objects of type uipanel. The axes contains 9 objects of type patch.

Сводные данные

В этом примере показано, как автоматически сгенерировать виртуальный ведущий сценарий из данных о транспортном средстве, зарегистрированных с помощью датчиков лидара и 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);
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

Смотрите также

Приложения

Функции

Объекты

Похожие темы

Внешние веб-сайты