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

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

Обзор

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

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

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

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

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

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

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

  2. Импорт дорожной сети OpenDRIVE в сценарий вождения.

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

  4. Добавьте актёров, не являющихся эго, из списка объектов лидара в сценарий вождения.

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

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

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

Положения автомобиля , оборудованного датчиком были захвачены с помощью датчика UBlox GPS 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, что обеспечивает доступ к картографическим данным, полученным из толпы, по всему миру. Данные лицензированы под лицензией 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 в сгенерированный сценарий

Данные о автомобиле , оборудованном датчиком собираются с датчика GPS и хранятся в виде текстового файла. Текстовый файл состоит из трех столбцов, в которых хранятся значения широты, долготы и временной метки для автомобиля , оборудованного датчиком. Используйте helperGetEgoData функция для импорта данных ego vehicle из текстового файла в структуру в рабочей области 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

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);

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

trajectory(ego,egoWaypoints,egoSpeed);

Добавьте актёров, не являющихся Ego, из списков объектов лидар в сгенерированный сценарий

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

  1. ActorID - определяемый сценарием идентификатор актёра, заданный как положительное целое число.

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

  3. 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

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

Эта функция вычисляет скорость и угол рыскания автомобиля , оборудованного датчиком на основе точек пути траектории и временных меток.

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

См. также

Приложения

Функции

Объекты

Похожие темы

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