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

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

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

Импортируйте дорожную сеть 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

Используйте 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,
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);
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

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

Приложения

Функции

Объекты

Похожие темы

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