В этом примере показано, как считать и визуализировать строения маршрута для зарегистрированного маршрута движения от службы HERE HD Live Map (HERE HDLM). Эта визуализация может использоваться, чтобы проверить строения маршрута, обнаруженные системой восприятия бортового датчика, такого как монокулярная камера.
В этом примере вы узнаете, как получить доступ к слоям с мозаикой из службы HDLM и идентифицировать соответствующую топологию уровня дороги и уровня полосы движения, геометрию и атрибуты.
Чтобы считать данные, вы используете
объект. Для использования службы HERE HD Live Map требуются действительные учетные данные HERE HDLM. Вам необходимо заключить отдельное соглашение с HERE в порядок получения доступа к сервисам HDLM и получения необходимых учетных данных (access_key_id и access_key_secret) для использования сервиса HERE.hereHDLMReader
Карты высокой четкости (HD) относятся к отображению сервисам, разработанным специально для беспилотных аппаратов. Точная геометрия этих карт (с разрешением до 1 см около экватора) делает их подходящими для беспилотных рабочих процессов, выходящих за рамки планирования маршрутов традиционных дорожных карт. Такие рабочие процессы включают верификацию на уровне маршрута, локализацию и планирование пути. В этом примере показано, как проверить эффективность системы обнаружения маршрута с помощью информации уровня маршрута от данных отображения HD.
Точность данных отображения HD позволяет использовать его в качестве источника достоверных данных для верификации бортовых систем восприятия датчиков. Эта высокая точность позволяет быстрее и точнее верифицировать существующие развернутые алгоритмы.
HERE HD Live Map (HERE HDLM) - облачный сервис HD-карты, разработанный HERE Technologies для поддержки высокоавтоматического вождения. Данные состоят из мозаичных слоев отображения, которые обеспечивают доступ к точной геометрии и устойчивым атрибутам дорожной сети. Слои сгруппированы в следующие модели:
Модель осевой линии дороги: Обеспечивает топологию дороги (заданную как узлы и ссылки в графике), геометрию формы и другие атрибуты уровня дороги.
HD Модель маршрута: Обеспечивает топологию маршрута (как группы маршрутов и соединители группы маршрутов), высокоточную геометрию и атрибуты уровня маршрута.
Модель локализации HD: Обеспечивает функции для поддержки стратегий локализации транспортного средства.
Обзор слоев HERE HDLM см. в HERE HD Live Map Layers.
Камеры используются в автоматизированном вождении, чтобы собрать семантическую информацию о дорожной топологии вокруг транспортного средства. Обнаружение контуров маршрута, классификация типа маршрута и алгоритмы обнаружения дорожных знаков формируют ядро такого трубопровода обработки фотоаппарата. Вы можете использовать сервис HERE HDLM, наряду с высокоточным GPS, установленным на транспортном средстве, чтобы оценить точность таких алгоритмов и проверить их эффективность.
В этом примере вы узнаете, как:
Считывайте информацию о дороге и маршруте из службы HERE HDLM для зарегистрированной последовательности GPS.
Примените эвристический подход соответствия маршрутов к записанным данным GPS. Поскольку данные GPS часто неточны, необходимо решить проблему согласования зарегистрированных географических координат с представлением дорожной сети.
Идентифицируйте экологические атрибуты, относящиеся к транспортному средству. Если транспортное средство успешно расположено в контексте карты, можно использовать атрибуты дороги и маршрута, относящиеся к транспортному средству, для проверки данных, записанных датчиком бортовой камеры транспортного средства.
Начните, загрузив данные с записанного диска. Записанные данные в этом примере получены из набора данных для вождения, собранного командой Udacity ® Self-Driving Car. Эти данные включают видео, захваченное фронтальной монокулярной камерой и положениями транспортного средства и скоростями, регистрируемыми GPS.
Загрузите centerCamera.avi
видео- данные камеры и соответствующие временные метки видео.
recordedData = fullfile(toolboxdir('driving'), 'drivingdata', ... 'udacity', 'drive_segment_09_29_16'); [videoReader, videoTime] = helperLoadCameraData(fullfile(recordedData)); % Show the first frame of the camera data imageFrame = readFrame(videoReader); imshow(imageFrame, 'Border', 'tight');
Загрузите данные GPS из gpsSequence.mat
MAT-файл.
data = load(fullfile(recordedData, 'gpsSequence.mat')); gpsData = data.gpsTT; % Plot the full route and the first position recorded from the GPS gpsPlayer = geoplayer(gpsData.Latitude(1), gpsData.Longitude(1), 18); plotRoute(gpsPlayer, gpsData.Latitude, gpsData.Longitude); plotPosition(gpsPlayer, gpsData.Latitude(1), gpsData.Longitude(1));
Создайте читатель для чтения плитки HERE HD Live Map, которая охватывает все записанные местоположения GPS в накопителе. Если вы ранее не настраивали HDLM-учетные данные HERE, то появится диалоговое окно с приглашением ввести их. Введите идентификатор ключа доступа и секрет ключа доступа, полученные от HERE Technologies, и нажмите OK.
reader = hereHDLMReader(gpsData.Latitude, gpsData.Longitude);
Чтение и построение графика данных топологии дорог из TopologyGeometry
слой. Этот слой представляет строение дорожной сети. Узлы сети соответствуют пересечениям и тупикам. Ссылки между узлами представляют форму соединяющихся улиц как полилинии. Связность и геометрия для этих функций содержатся в LinksStartingInTile
и NodesInTile
поля.
topologyLayer = read(reader, 'TopologyGeometry') figure('Name', 'TopologyGeometry'); topologyAxes = plot(topologyLayer); hold(topologyAxes, 'on'); geoplot(topologyAxes, gpsData.Latitude, gpsData.Longitude, ... 'bo-', 'DisplayName', 'Route');
topologyLayer = TopologyGeometry with properties: Data: HereTileId: 309106790 IntersectingLinkRefs: [44×1 struct] LinksStartingInTile: [895×1 struct] NodesInTile: [651×1 struct] TileCenterHere2dCoordinate: [37.3865 -122.1130] Metadata: Catalog: 'hrn:here:data::olp-here-had:here-hdlm-protobuf-na-2' CatalogVersion: 4601 Use plot to visualize TopologyGeometry data.
Функциональность графического изображения обеспечивается в helperPlotLayer
функция, которая визуализирует доступные данные из слоя HD Live Map с записанным приводом на тех же географических осях. Эта функция, заданная в конце примера, будет использоваться для построения графиков последующих слоев.
Учитывая местоположение GPS, записанное вдоль привода, можно использовать алгоритм соответствия маршрута, чтобы определить, какой дороге в сети соответствует записанное положение. Этот пример использует эвристический алгоритм соответствия маршрутов, который рассматривает ближайшие ссылки пространственно к записанной географической точке. Алгоритм применяет направление движения транспортного средства, чтобы определить наиболее вероятнейшая ссылка. Этот подход соответствия маршрута не учитывает связь дорог, доступ к транспортному средству или данные GPS с высокой позиционной ошибкой. Поэтому этот подход может применяться не ко всем сценариям.
The helperGetGeometry
функция извлекает информацию о геометрии из данного слоя топологии и возвращает эту информацию в таблицу с соответствующими ссылками.
topologyTable = helperGetGeometry(topologyLayer.LinksStartingInTile, ... {'LinkId', 'Geometry.Here2dCoordinateDiffs'}); topologyTable.Properties.VariableNames = {'LinkId', 'Geometry'};
The HelperLinkMatcher
класс создает блок соответствия ссылки, который содержит геометрию формы для каждой ссылки в требуемой плитке карты. Этот класс использует базовый пространственный анализ, чтобы соответствовать записанному положению координатам формы дорожных ссылок.
linkMatcher = HelperLinkMatcher(topologyTable); % Match first point of the recorded route to the most probable link [linkId, linkLat, linkLon] = match(linkMatcher, gpsData.Latitude(1), ... gpsData.Longitude(1), gpsData.Velocity(1,1:2)); % Plot the shape geometry of the link geoplot(gpsPlayer.Axes, linkLat, linkLon, 'r.-');
Характеристики, общие для всех полос вдоль данной дороги, присваиваются элементу link, который описывает эту дорогу. Один из таких атрибутов, предел скорости, описывает максимальную легальную скорость для транспортных средств, путешествующих по ссылке. Если заданная географическая координата совпадает со ссылкой, можно определить предел скорости вдоль этой ссылки. Поскольку такие функции, как пределы скорости, часто изменяются по длине ссылки, эти атрибуты идентифицируются для определенных областей значений ссылки.
The SpeedAttributes
слой содержит информацию об ожидаемой скорости транспортного средства по ссылке, включая указанный предел скорости.
speedLayer = read(reader, 'SpeedAttributes');
The helperGetSpeedLimits
функция извлекает данные пределы скорости для соответствующей длины и направления ссылки. Как и при извлечении геометрической информации для ссылки, конкретный захват данных о пределе скорости требует специализированного кода.
speedTable = helperGetSpeedLimits(speedLayer);
% Find the speed limit entry for the matched link
speed = speedTable(speedTable.LinkId == linkId, :);
Модель HD Lane Model содержит геометрию маршрута и атрибуты дороги, обеспечивая детализацию, необходимую для поддержки беспилотных аппаратов. Подобно модели осевой линии дороги, модель маршрута HD также соответствует шаблону использования топологии для описания дорожной сети на уровне маршрута. Тогда к элементам этой топологии приписываются функции групп маршрутов. В модели HD-маршрута основным топологическим элементом является группа маршрутов.
Чтение и построение графика данных топологии маршрута из LaneTopology
слой. Этот слой представляет топологию маршрута как группы маршрутов и соединители группы маршрутов. Группы маршрутов представляют группу полос в пределах ссылки (сегмента дороги). Соединители группы маршрутов соединяют отдельные группы маршрутов друг с другом. Связность и геометрия для этих функций содержатся в LaneGroupsStartingInTile
и LaneGroupConnectorsInTile
поля для групп маршрутов и соединителей групп маршрутов, соответственно.
laneTopologyLayer = read(reader, 'LaneTopology') laneAxes = helperPlotLayer(laneTopologyLayer, ... gpsData.Latitude, gpsData.Longitude); geolimits(laneAxes, [37.3823, 37.3838], [-122.1151, -122.1128]);
laneTopologyLayer = LaneTopology with properties: Data: HereTileId: 309106790 IntersectingLaneGroupRefs: [56×1 struct] LaneGroupConnectorsInTile: [1174×1 struct] LaneGroupsStartingInTile: [1783×1 struct] TileCenterHere2dCoordinate: [37.3865 -122.1130] Metadata: Catalog: 'hrn:here:data::olp-here-had:here-hdlm-protobuf-na-2' CatalogVersion: 4601 Use plot to visualize LaneTopology data.
Группа маршрутов представляет несколько маршрутов. Поэтому геометрия этого элемента задается полигональной формой, которую принимает группа, что выражается левыми и правыми контурами группы маршрутов. Получите эту геометрию маршрута от контуров маршрута при помощи helperGetGeometry
функция.
laneGroupFields = {'LaneGroupId', ... 'BoundaryGeometry.LeftBoundary.Here2dCoordinateDiffs', ... 'BoundaryGeometry.RightBoundary.Here2dCoordinateDiffs'}; laneTopologyTable = helperGetGeometry(laneTopologyLayer.LaneGroupsStartingInTile, ... laneGroupFields); laneTopologyTable.Properties.VariableNames = {'LaneGroupId', ... 'LeftGeometry', 'RightGeometry'};
Как и в случае разработки совпадающего алгоритма для идентификации наиболее вероятной транспортной ссылки, сопоставление данных GPS с наиболее вероятной группой маршрутов может следовать нескольким подходам. Описанный здесь подход использует два слоя: LaneRoadReferences
и LaneTopology
.
The LaneRoadReferences
слой позволяет перемещать положение на модели осевой линии дороги (заданное ссылкой) в соответствующее положение на модели маршрута HD (заданное группой маршрута). Поскольку ссылка была ранее идентифицирована, можно фильтровать кандидатов на соответствие группы маршрутов меньшему подмножеству всех групп маршрутов, доступных в плитке.
The LaneTopology
слой дает данные геометрии, которые могут использоваться, чтобы учитывать данные, которые пространственно существуют в контурах каждой потенциальной группы маршрута. Как и в случае пространственно совпадающих данных GPS с ссылками, такой подход подвержен ошибке и зависит от точности записанных данных GPS. В дополнение к соответствию группы маршрутов необходимо также соответствовать вектору направления транспортного средства относительно ориентации группы маршрутов. Этот шаг необходим, потому что атрибуты маршрутов заданы относительно топологической ориентации.
Используйте helperGetReferences
функция для генерации таблицы всех групп маршрутов, которые существуют по меньшей мере в течение некоторой длины ссылки.
referenceLayer = read(reader, 'LaneRoadReferences');
referenceTable = helperGetReferences(referenceLayer);
Создайте блок соответствия группы маршрутов, содержащий геометрию границ для каждой группы маршрутов в требуемой плитке карты. The HelperLaneGroupMatcher
класс создает блок соответствия группы маршрутов, который содержит геометрию краевой формы для каждой группы маршрутов в требуемой плитке карты. Она также содержит справочную таблицу ссылок на группы маршрутов. Как и в случае с HelperLinkMatcher
класс, этот класс использует простой подход пространственного анализа, чтобы определить, существует ли заданная зарегистрированная координата в контурах группы маршрутов.
laneGroupMatcher = HelperLaneGroupMatcher(referenceTable, laneTopologyTable); % Match the lane group and relative direction [laneGroupId, isForward, boundGeometry] = match(laneGroupMatcher, linkId, ... gpsData.Latitude(1), gpsData.Longitude(1), gpsData.Velocity(1,1:2)); % Plot the boundary geometry of the lane group geoplot(gpsPlayer.Axes, boundGeometry(:,1), boundGeometry(:,2), 'm.-');
Как и с атрибутами скорости, которые сопоставлены со ссылками идентификатором, атрибуты маршрута также присваивают функции группам маршрутов с помощью идентификатора группы маршрутов. The LaneAttributes
слой содержит информацию о группах маршрутов, включая типы каждой маршрута в группе и характеристики контуров маршрута.
Используйте helperGetLaneAttributes
функция для извлечения различных типов маршрутов и разметки контуров маршрутов для каждой группы маршрутов в плитке.
laneAttributesLayer = read(reader, 'LaneAttributes'); laneAttributesTable = helperGetLaneAttributes(laneAttributesLayer); % Find the lane attribute entry for the matched lane group laneAttribute = laneAttributesTable.LaneGroupId == laneGroupId;
Соответствующие алгоритмы и таблицы, сгенерированные для идентификации свойств дороги и маршрута, могут быть расширены до последовательности зарегистрированных координат GPS. Для каждого временного шага положение транспортного средства согласовывается с группой ссылок и маршрутов на дороге. В сложение предела скорости и строений маршрута отображаются вместе с соответствующими изображениями камеры.
The HelperHDLMUI
Класс создает инструмент для потоковой передачи видео и данных GPS с записанного диска и отображения соответствующей информации от выбранных слоев HERE HD Live Map в каждом записанном транспортным средством положении.
hdlmUI = HelperHDLMUI(gpsData.Latitude(1), gpsData.Longitude(1)); % Synchronize the camera and GPS data into a common timetable synchronizedData = synchronize(videoTime, gpsData); videoReader.CurrentTime = 0; maxDisplayRate = videoReader.FrameRate * 5; % Initialize some variables to maintain history prevLinkId = 0; prevLaneGroupId = 0; for idx = 1 : height(synchronizedData) timeStamp = synchronizedData.Time(idx); % Check if the current timestamp has GPS data hasGPSFrame = ~(ismissing(synchronizedData.Latitude(idx)) || ... ismissing(synchronizedData.Longitude(idx))); if hasGPSFrame latitude = synchronizedData.Latitude(idx); longitude = synchronizedData.Longitude(idx); velocity = synchronizedData.Velocity(idx, 1:2); % Match GPS position to link [linkId, linkLat, linkLon] = match(linkMatcher, ... latitude, longitude, velocity); if linkId ~= prevLinkId % Update link updateLink(hdlmUI, linkLat, linkLon); prevLinkId = linkId; % Update speed limit speed = speedTable(speedTable.LinkId == linkId, :); updateSpeed(hdlmUI, speed.Value); end % Match GPS position to lane group [laneGroupId, isForward, boundGeometry] = match(laneGroupMatcher, linkId, ... latitude, longitude, velocity); if laneGroupId ~= prevLaneGroupId % Update lane group updateLaneGroup(hdlmUI, boundGeometry); prevLaneGroupId = laneGroupId; % Update lane types and boundary markings laneAttribute = laneAttributesTable.LaneGroupId == laneGroupId; plotLanes(hdlmUI, laneAttributesTable.Lanes{laneAttribute}, ... laneAttributesTable.LaneBoundaries{laneAttribute}, isForward); end updatePosition(hdlmUI, latitude, longitude); else % Read frame of the video imageFrame = readFrame(videoReader); end updateImage(hdlmUI, imageFrame); updateTime(hdlmUI, timeStamp); pause(1/maxDisplayRate); end
В этом примере вы исследовали, как:
Доступ к HD- отображения данным для заданной последовательности GPS из сервиса HERE HD Live Map и импорт этих данных в MATLAB.
Сопоставьте зарегистрированные данные GPS с данными импортированной дорожной сети, чтобы найти соответствующую группу ссылок и маршрутов для каждой географической координаты.
Атрибуты запроса совпадающих ссылки и группы маршрутов, такие как пределы скорости и типы маршрутов, чтобы разработать инструмент для визуальной проверки функций дороги на основе зарегистрированных данных камеры.
Методы, обсуждаемые в этом примере, могут быть дополнительно расширены для поддержки автоматизированной верификации алгоритмов восприятия.
helperPlotLayer
строит графики данных слоя и маршрута на географическом графике.
function gx = helperPlotLayer(layer, latitude, longitude) %helperPlotLayer Create geographic plot with layer data and route % gx = helperPlotLayer(layer, latitude, longitude) creates a geographic % axes plot with the plottable HDLM layer and the route given by latitude % and longitude on a new figure. figure; % Plot layer gx = plot(layer); % Enable adding data to the plot hold(gx, 'on'); % Plot latitude, longitude data geoplot(gx, latitude, longitude, 'bo-', 'DisplayName', 'Route'); hold(gx, 'off'); end
helperGetGeometry
извлекает геометрию для элементов топологии из слоя в виде таблицы.
function geometryTable = helperGetGeometry(layer, fields) %helperGetGeometry Create a table with geometry for topology elements % geometryTable = helperGetGeometry(layer, fields) returns a table % formatted with the specified geometry fields of the TopologyGeometry % and LaneTopology layers. % Pre-allocate struct S = repmat(struct, size(layer)); for field = fields C = strsplit(field{:}, '.'); for idx = 1:numel(layer) fieldname = strjoin(C, ''); S(idx).(fieldname) = getfield(layer, {idx}, C{:}); end end geometryTable = struct2table(S); end
helperGetSpeedLimits
извлекает данные ограничения скорости из слоя в виде таблицы.
function speedTable = helperGetSpeedLimits(layer) %helperGetSpeedLimits Create a data table with speed limits % speedTable = helperGetSpeedLimits(layer) returns a table formatted with % the speed limit start, end, direction, and value along a specified link % as given by the SpeedAttributes layer object specified by layer. speed = struct(... 'LinkId', {}, ... 'Start', {}, ... 'End', {}, ... 'Direction', {}, ... 'Value', {}); for idx = 1 : numel(layer.LinkAttribution) % Assign the link ID link = layer.LinkAttribution(idx); attributions = link.ParametricAttribution; % Examine each attribute assigned to the link for attrIndex = 1 : numel(attributions) linkAttr = vertcat(attributions.LinkParametricAttribution); % For each attribute, check if the speed limit information is % listed. If speed limit is provided, make an entry. for linkAttrIndex = 1 : numel(linkAttr) if ~isempty(linkAttr(linkAttrIndex).SpeedLimit) % Assign speed limit to specified link speedLimit = struct; speedLimit.LinkId = link.LinkLocalRef; speedLimit.Start = attributions(attrIndex).AppliesToRange.RangeOffsetFromStart; speedLimit.End = attributions(attrIndex).AppliesToRange.RangeOffsetFromEnd; speedLimit.Direction = attributions(attrIndex).AppliesToDirection; speedLimit.Value = linkAttr(linkAttrIndex).SpeedLimit.Value; % Convert KPH to MPH if strcmpi(linkAttr(linkAttrIndex).SpeedLimit.Unit, 'KILOMETERS_PER_HOUR') speedLimit.Value = speedLimit.Value / 1.609; end if strcmpi(speedLimit.Direction, 'BOTH') speed = [speed; speedLimit]; %#ok<AGROW> end end end end end speedTable = struct2table(speed); end
helperGetReferences
извлекает ссылки на дороги маршрута из объекта слоя в форме таблицы.
function laneRoadReferenceTable = helperGetReferences(layer) %helperGetReferences Create a data table with lane road references % laneRoadReferenceTable = helperGetReferences(layer) returns a table % formatted with a list of all lane groups existing on a specified link % as given by the LaneRoadReferences layer object specified by layer. numLinks = numel(layer.LinkLaneGroupReferences); reference = repmat(struct('LinkId', {}, 'LaneGroupId', {}), numLinks, 1); % Get references from links to lane groups for idx = 1 : numLinks link = layer.LinkLaneGroupReferences(idx); laneGroups = vertcat(link.LaneGroupReferences.LaneGroupRef); reference(idx).LinkId = link.LinkLocalRef; reference(idx).LaneGroupId = [laneGroups(:).LaneGroupId]'; end laneRoadReferenceTable = struct2table(reference); end
helperGetLaneAttributes
извлекает атрибуты маршрута из объекта слоя в форме таблицы.
function laneAttributesTable = helperGetLaneAttributes(layer) %helperGetLaneAttributes Create a table with lane and boundary types % laneAttributesTable = helperGetLaneAttributes(layer) returns a table % formatted with the lane types and the lane boundary markings for each % lane group in the LaneAttributes layer object specified by layer. for laneGroupAttrIndex = 1 : numel(layer.LaneGroupAttribution) laneGroup = layer.LaneGroupAttribution(laneGroupAttrIndex); attributes(laneGroupAttrIndex).LaneGroupId = laneGroup.LaneGroupRef; %#ok % Get lane types for each lane group for laneAttrIndex = 1 : numel(laneGroup.LaneAttribution) lane = laneGroup.LaneAttribution(laneAttrIndex); laneAttr = vertcat(lane.ParametricAttribution); laneAttr = vertcat(laneAttr.LaneParametricAttribution); for idx = 1 : numel(laneAttr) if ~isempty(laneAttr(idx).LaneType) attributes(laneGroupAttrIndex).Lanes{lane.LaneNumber} = ... laneAttr(idx).LaneType; end end end % Get lane boundaries for each lane group for laneBoundaryIndex = 1 : numel(laneGroup.LaneBoundaryAttribution) laneBoundary = laneGroup.LaneBoundaryAttribution(laneBoundaryIndex); boundaries = vertcat(laneBoundary.ParametricAttribution.LaneBoundaryParametricAttribution); attributes(laneGroupAttrIndex).LaneBoundaries{laneBoundary.LaneBoundaryNumber} = ... boundaries.LaneBoundaryMarking; end end laneAttributesTable = struct2table(attributes); end
helperLoadCameraData
загружает средство чтения видео и временные метки из папки.
function [videoReader, videoTime] = helperLoadCameraData(dirName) %helperLoadCameraData Load camera images from folder in a timetable % [videoReader, videoTime] = helperLoadCameraData(dirName) loads a video % from the folder dirName. Timestamps for the video are read from a % MAT-file in the folder named timeStamps.mat. if ~isfolder(dirName) error('Expected dirName to be a path to a folder.') end matFileName = fullfile(dirName, 'centerCameraTime.mat'); if exist(matFileName, 'file') ~= 2 error('Expected dirName to have a MAT-file named centerCameraTime.mat containing timestamps.') end % Load the MAT-file with timestamps ts = load(matFileName); fieldNames = fields(ts); Time = ts.(fieldNames{1}); videoFileName = fullfile(dirName, 'centerCamera.avi'); if exist(matFileName, 'file') ~= 2 error('Expected dirName to have a video file named centerCamera.avi.') end % Load the video file videoTime = timetable(Time); videoReader = VideoReader(videoFileName); end
hereHDLMReader
| plot
| read