exponenta event banner

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

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

Обзор

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

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

  • Данные GPS: Текстовый файл, содержащий координаты широты и долготы эго-транспортного средства в каждой временной метке.

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

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

Для создания и моделирования сценария движения выполните следующие шаги:

  1. Изучите записанные данные о транспортных средствах.

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

  3. Добавление данных о транспортных средствах ego из GPS в сценарий вождения.

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

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

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

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

Добавление данных Ego Vehicle из GPS в сгенерированный сценарий

Данные эго-транспортного средства собираются с 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

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

Создайте траекторию для эго-транспортного средства из вычисленного набора эго-ППМ и скорости. Эго-транспортное средство следует по траектории с заданной скоростью.

trajectory(ego,egoWaypoints,egoSpeed);

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

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

Визуализируйте 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 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

См. также

Приложения

Функции

Объекты

Связанные темы

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