exponenta event banner

roadNetwork

Добавить дорожную сеть к сценарию вождения

Описание

OpenDRIVE

пример

roadNetwork(scenario,'OpenDRIVE',filename) импортирует дороги из файла сети дорог OpenDRIVE ® в сценарий вождения. Эта функция поддерживает спецификацию формата OpenDRIVE версии 1.4H [1 ].

пример

roadNetwork(scenario,'OpenDRIVE','ShowLaneTypes',showLaneTypes) использует пару имя-значение 'ShowLaneTypes' для импорта информации о типе полосы движения из файла и ее отображения в сценарии вождения.

ЗДЕСЬ карта HD Live

пример

roadNetwork(scenario,'HEREHDLiveMap',lat,lon) импортирует дороги из дорожной сети HERE HD Live Map [1] (HERE HDLM) в сценарий вождения. Функция импортирует дороги, ближайшие к координатам широты и долготы, указанным вlat и lonсоответственно.

пример

roadNetwork(scenario,'HEREHDLiveMap',minLat,minLon,maxLat,maxLon) импортирует HERE HDLM дороги, которые по крайней мере частично в пределах географической ограничивающей рамки, указанной minLat, minLon, maxLat, и maxLon.

OpenStreetMap

пример

roadNetwork(scenario,'OpenStreetMap',filename) импортирует дороги из файла дорожной сети OpenStreetMap ® в сценарий вождения.

Zenrin Japan Map API 3.0 (Itsumo NAVI API 3.0)

пример

roadNetwork(scenario,'ZenrinJapanMap',lat,lon) импортирует дороги из дорожной сети Zenrin Japan Map API 3.0 (Itsumo NAVI API 3.0) [2] в сценарий вождения. Функция импортирует дороги, ближайшие к координатам широты и долготы, указанным вlat и lonсоответственно.

Для импорта дорог из Zenrin Japan Map API 3.0 (Itsumo NAVI API 3.0) требуется пакет поддержки Automated Driving Toolbox™ Importer для Zenrin Japan Map API 3.0 (Itsumo NAVI API 3.0) Service. Сведения об установке пакетов поддержки см. в разделе Получение надстроек и управление ими.

пример

roadNetwork(scenario,'ZenrinJapanMap',minLat,minLon,maxLat,maxLon) импортирует Zenrin Japan Map API 3.0 (Itsumo NAVI API 3.0) дороги, которые по крайней мере частично находятся в пределах географической ограничивающей рамки, указанной minLat, minLon, maxLat, и maxLon.

Примеры

свернуть все

Создайте пустой сценарий управления.

scenario = drivingScenario;

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

filePath = 'intersection.xodr';  
roadNetwork(scenario,'OpenDRIVE',filePath);

Постройте график сценария и увеличьте изображение дорожной сети, установив границы осей.

plot(scenario)
xlim([350 800])
ylim([1400 2000])
zlim([0.00 10.00])

Figure contains an axes. The axes contains 2 objects of type patch.

Создайте пустой сценарий управления.

scenario = drivingScenario;

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

filePath = 'parking.xodr';  
roadNetwork(scenario,'OpenDRIVE',filePath);

Постройте график сценария.

plot(scenario)
zoom(2)
legend('Driving lane','Parking lane')

Figure contains an axes. The axes contains 3 objects of type patch. These objects represent Driving lane, Parking lane.

Импортируйте дорогу OpenDRIVE в сценарий. Установите 'ShowLaneTypes' значение для false для подавления нескольких типов полос движения. Функция игнорирует информацию о типе полосы движения и импортирует все полосы движения в качестве ведущих полос движения.

scenario = drivingScenario;
roadNetwork(scenario,'OpenDRIVE',filePath,'ShowLaneTypes',false);
plot(scenario)
zoom(2)

Figure contains an axes. The axes contains 2 objects of type patch.

Импорт данных дорожной сети HERE HDLM, ближайших к координатам указанного маршрута движения, в сценарий движения. Постройте график транспортного средства, идущего по этому маршруту, в сценарии вождения.

Загрузите последовательность географических координат, соответствующих маршруту движения.

data = load('geoSequence.mat');
lat = data.latitude;
lon = data.longitude;

Отображение маршрута путем потоковой передачи координат на географическом проигрывателе. Установите уровень масштабирования 14 и настройте проигрыватель для отображения всех точек в его истории. Чтобы ускорить потоковую передачу, постройте график только для каждой десятой координаты в маршруте.

zoomLevel = 14;
player = geoplayer(lat(1),lon(1),zoomLevel,'HistoryDepth',Inf);
timestep = 10;

for i = 1:timestep:length(lat)
    plotPosition(player,lat(i),lon(i));
end

Создайте сценарий управления. Импортируйте в сценарий данные дороги HERE HDLM, ближайшие к ведущему маршруту.

scenario = drivingScenario;
roadNetwork(scenario,'HEREHDLiveMap',lat,lon);

Используйте latlon2local функция преобразования маршрута движения из географических координат в локальные декартовы координаты восток-север вверх (RUS), используемые в сценарии движения. Для начала координат системы RUS используйте начало координат географической сети дорог, хранящееся в GeoReference свойство сценария. Начало координат - это первая координата, указанная в маршруте движения. Поскольку маршрут движения содержит только широтные и продольные данные, установите высоту на 0.

alt = 0;
origin = scenario.GeoReference;
[xEast,yNorth,zUp] = latlon2local(lat,lon,alt,origin);

Добавить транспортное средство к сценарию вождения. Укажите преобразованный маршрут движения в качестве траектории транспортного средства. Установите скорость транспортного средства 30 метров в секунду.

v = vehicle(scenario,'ClassID',1);
speed = 30;
smoothTrajectory(v,[xEast,yNorth,zUp],speed);

Постройте график сценария и сделайте паузу каждые 0,01 секунды, чтобы замедлить моделирование. Для сохранения той же трассы с отображениями географических координат ось X находится внизу, а ось Y - слева. В сценариях управления, не импортированных с карт, ось X находится слева, а ось Y - внизу. Это выравнивание согласуется с мировой системой координат Automated Driving Toolbox™.

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

plot(scenario)
while advance(scenario)
    pause(0.01)
end

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

Определите координаты широты и долготы, соответствующие круговому перекрестку.

latCenter = 42.302324;
lonCenter = -71.384970; 

Укажите минимальные и максимальные широтные и продольные координаты для прямоугольной области вокруг кругового перекрестка. Отображение ограничивающей рамки, соответствующей этой области, на географическом графике.

offset = 5e-4;
minLat = latCenter - offset;
minLon = lonCenter - offset;
maxLat = latCenter + offset;
maxLon = lonCenter + offset;

gx = geoaxes;
LineSpec = '.-k';
geoplot(gx, ... 
        [minLat maxLat],[minLon minLon],LineSpec, ...
        [maxLat maxLat],[minLon maxLon],LineSpec, ...
        [maxLat minLat],[maxLon maxLon],LineSpec, ...
        [minLat minLat],[maxLon minLon],LineSpec)

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

scenario = drivingScenario;
roadNetwork(scenario,'HEREHDLiveMap',minLat,minLon,maxLat,maxLon);

Постройте график сценария. Для сохранения той же трассы с отображениями географических координат ось X находится внизу, а ось Y - слева. В сценариях управления, не импортированных с карт, ось X находится слева, а ось Y - внизу. Это выравнивание согласуется с мировой системой координат Automated Driving Toolbox™.

plot(scenario) 

Импортируйте дороги из веб-сервиса OpenStreetMap ® в сценарий вождения. Затем постройте график транспортного средства, идущего по маршруту в импортированной дорожной сети.

Импортируйте дорожную сеть кампуса MathWorks ® Apple Hill в пустой сценарий вождения. Файл был загружен из https://www.openstreetmap.org, который обеспечивает доступ к данным карты, полученным из толпы по всему миру. Данные лицензированы по лицензии Open Data Commons Open Database License (ODbL), https://opendatacommons.org/licenses/odbl/.

Постройте график импортированной дорожной сети. Для сохранения той же трассы с отображениями географических координат ось X находится внизу, а ось Y - слева. В сценариях управления, не импортированных с карт, ось X находится слева, а ось Y - внизу. Это выравнивание согласуется с мировой системой координат Automated Driving Toolbox™.

scenario = drivingScenario;
roadNetwork(scenario,'OpenStreetMap','applehill.osm');
plot(scenario)

Загрузите координаты широты и долготы для маршрута движения в этой дорожной сети.

data = load('geoRouteAH.mat');
lat = data.latitude;
lon = data.longitude;

Используйте latlon2local функция преобразования маршрута движения из географических координат в локальные декартовы координаты восток-север вверх (RUS), используемые в сценарии движения. Для начала координат системы RUS используйте начало координат географической сети дорог, хранящееся в GeoReference свойство сценария. Начало координат - это первая координата, указанная в маршруте движения. Поскольку маршрут движения содержит только широтные и продольные данные, установите высоту на 0.

alt = 0;
origin = scenario.GeoReference;
[xEast,yNorth,zUp] = latlon2local(lat,lon,alt,origin);

Добавить транспортное средство к сценарию вождения. Укажите преобразованный маршрут движения в качестве траектории транспортного средства. Установите скорость транспортного средства 30 метров в секунду. Постройте график траектории транспортного средства и сделайте паузу каждые 0,01 секунды, чтобы замедлить моделирование.

v = vehicle(scenario,'ClassID',1);
speed = 30;
smoothTrajectory(v,[xEast,yNorth,zUp],speed);

while advance(scenario)
    pause(0.01)
end

Импорт данных дорожной сети Zenrin Japan Map 3.0 (Itsumo NAVI API 3.0), ближайших к координатам указанного маршрута движения, в сценарий движения. Постройте график транспортного средства, идущего по этому маршруту, в сценарии вождения.

Загрузите последовательность географических координат, соответствующих маршруту движения.

data = load('tokyoSequence.mat');
lat = data.latitude;
lon = data.longitude;

Отображение маршрута путем потоковой передачи координат на географическом проигрывателе. Установите уровень масштабирования 17 и настройте проигрыватель для отображения всех точек в его истории. Чтобы ускорить потоковую передачу, постройте график только для каждой десятой координаты в маршруте.

zoomLevel = 17;
player = geoplayer(lat(1),lon(1),zoomLevel,'HistoryDepth',Inf);
timestep = 10;

for i = 1:timestep:length(lat)
    plotPosition(player,lat(i),lon(i));
end

Создайте сценарий управления. Импортируйте в сценарий дорожные данные Zenrin Japan Map 3.0 (Itsumo NAVI API 3.0), ближайшие к маршруту движения.

scenario = drivingScenario;
roadNetwork(scenario,'ZenrinJapanMap',lat,lon)

Используйте latlon2local функция преобразования маршрута движения из географических координат в локальные декартовы координаты восток-север вверх (RUS), используемые в сценарии движения. Для начала координат системы RUS используйте начало координат географической сети дорог, хранящееся в GeoReference свойство сценария. Начало координат - это первая координата, указанная в маршруте движения.

alt = 0;
origin = scenario.GeoReference;
[xEast,yNorth,zUp] = latlon2local(lat,lon,alt,origin);

Добавить транспортное средство к сценарию вождения. Укажите преобразованный маршрут движения в качестве траектории транспортного средства. Установите скорость транспортного средства 30 метров в секунду.

v = vehicle(scenario,'ClassID',1);
speed = 30;
smoothTrajectory(v,[xEast,yNorth,zUp],speed);

Постройте график сценария и сделайте паузу каждые 0,01 секунды, чтобы замедлить моделирование. Для сохранения той же трассы с отображениями географических координат ось X находится внизу, а ось Y - слева. В сценариях управления, не импортированных с карт, ось X находится слева, а ось Y - внизу. Это выравнивание согласуется с мировой системой координат Automated Driving Toolbox™.

figure 
plot(scenario)
while advance(scenario)
    pause(0.01)
end

Импорт данных дорожной сети Zenrin Japan Map 3.0 (Itsumo NAVI API 3.0) в сценарий вождения. Выберите эти данные из области, центрированной вокруг указанной географической координаты.

Определите координаты широты и долготы, соответствующие парку.

latCenter = 35.6889;
lonCenter = 139.8458;

Укажите минимальные и максимальные координаты широты и долготы для прямоугольной области вокруг парка. Отображение ограничивающей рамки, соответствующей этой области, на географическом графике.

offset = 0.0013;
minLat = latCenter - offset;
minLon = lonCenter - offset;
maxLat = latCenter + offset;
maxLon = lonCenter + offset;

figure
gx = geoaxes;
LineSpec = '.-k';
geoplot(gx, ... 
        [minLat maxLat],[minLon minLon],LineSpec, ...
        [maxLat maxLat],[minLon maxLon],LineSpec, ...
        [maxLat minLat],[maxLon maxLon],LineSpec, ...
        [minLat minLat],[maxLon minLon],LineSpec)

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

scenario = drivingScenario;
roadNetwork(scenario,'ZenrinJapanMap',minLat,minLon,maxLat,maxLon) 

Постройте график сценария. Для сохранения той же трассы с отображениями географических координат ось X находится внизу, а ось Y - слева. В сценариях управления, не импортированных с карт, ось X находится слева, а ось Y - внизу. Это выравнивание согласуется с мировой системой координат Automated Driving Toolbox™.

figure
plot(scenario)

Входные аргументы

свернуть все

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

Имя файла дорожной сети, определяемое как вектор символа или скаляр строки.

filename необходимо указать файл в текущей папке, файл в пути поиска MATLAB ® или полный или относительный путь к файлу.

filename должен заканчиваться расширением файла, действительным для источника дорожной сети.

Источник дорожной сетиДопустимые расширения файловПример синтаксиса
OpenDRIVE

.xodr

.xml

roadNetwork(scenario, ...
    'OpenDRIVE','C:\Desktop\roads.xodr'
OpenStreetMap

.osm

.xml

roadNetwork(scenario, ...
    'OpenStreetMap','C:\Desktop\map.osm'

Импорт информации о типе полосы движения из файла сети дорог OpenDRIVE и отображение ее в сценарии вождения, указанном как пара, разделенная запятыми, состоящая из 'ShowLaneTypes' и одно из этих значений:

  • true или 1 - импорт информации о типах полос и рендеринг типов полос.

  • false или 0 - игнорировать информацию о типе полосы движения и импортировать все полосы движения как полосы движения в сценарии движения.

В таблице суммированы поддерживаемые типы полос движения и их внешний вид по умолчанию после их импорта в сценарий вождения.

Поддерживаемые типы полос движенияОписаниеВнешний вид по умолчанию
Полосы движенияПолосы движения

Пограничные полосыПолосы движения на границах дорог

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

Плечевые полосыПолосы движения, зарезервированные для аварийной остановки

Парковочные полосыПолосы движения вдоль полос движения, предназначенные для стоянки транспортных средств

Все другие неподдерживаемые типы полос тонируются как пограничные полосы.

Пример: 'ShowLaneTypes',false

Координаты широты, заданные как вектор элементов в диапазоне [-90, 90]. lat должен быть того же размера, что и lon. Единицы измерения в градусах.

Координаты долготы, заданные как вектор элементов в диапазоне [-180, 180]. lon должен быть того же размера, что и lat. Единицы измерения в градусах.

Минимальная координата широты ограничивающей рамки, заданная как скаляр в диапазоне [-90, 90]. minLat должно быть меньше, чем maxLat. Единицы измерения в градусах.

roadNetwork функция импортирует любые дороги, которые по крайней мере частично находятся в пределах ограничивающей рамки, заданной входными данными minLat, minLon, maxLat, и maxLon. На этой схеме показана взаимосвязь между этими координатами.

Минимальная координата долготы ограничивающей рамки, заданная как скаляр в диапазоне [-180, 180]. minLon должно быть меньше, чем maxLon. Единицы измерения в градусах.

roadNetwork функция импортирует любые дороги, которые по крайней мере частично находятся в пределах ограничивающей рамки, заданной входными данными minLat, minLon, maxLat, и maxLon. На этой схеме показана взаимосвязь между этими координатами.

Максимальная координата широты ограничивающей рамки, заданная как скаляр в диапазоне [-90, 90]. maxLat должно быть больше, чем minLat. Единицы измерения в градусах.

roadNetwork функция импортирует любые дороги, которые по крайней мере частично находятся в пределах ограничивающей рамки, заданной входными данными minLat, minLon, maxLat, и maxLon. На этой схеме показана взаимосвязь между этими координатами.

Максимальная координата долготы ограничивающей рамки, заданная как скаляр в диапазоне [-180, 180]. maxLon должно быть больше, чем minLon. Единицы измерения в градусах.

roadNetwork функция импортирует любые дороги, которые по крайней мере частично находятся в пределах ограничивающей рамки, заданной входными данными minLat, minLon, maxLat, и maxLon. На этой схеме показана взаимосвязь между этими координатами.

Ограничения

Ограничения импорта OpenDRIVE

  • Можно импортировать только полосы движения, информацию о типах полос и дороги. Импорт дорожных объектов и сигналов дорожного движения не поддерживается.

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

  • Полосы с переменной шириной не поддерживаются. Для ширины задается наибольшая ширина в пределах этой полосы. Например, если ширина полосы изменяется от 2 метров до 4 метров, функция устанавливает ширину полосы в 4 метра на всем протяжении.

  • Дороги с информацией о типе полосы движения, указанной как driving, border, restricted, shoulder, и parking поддерживаются. Полосы движения с любой другой информацией о типах полос движения импортируются как пограничные полосы.

  • Дороги с несколькими стилями разметки полос не поддерживаются. Функция применяет первый найденный стиль разметки ко всем полосам дороги. Например, если дорога имеет Dashed и Solid разметка полосы движения, применяется функция Dashed разметка полос на всем протяжении.

  • Стили разметки полос движения Bott Dots, Curbs, и Grass не поддерживаются. Полосы с этими стилями разметки импортируются как немаркированные.

Ограничения импорта HD Live Map здесь

  • Импорт HERE HDLM дорог с полосами различной ширины не поддерживается. В создаваемой дорожной сети для каждой полосы устанавливается максимальная ширина по всей ее длине. Рассмотрим полосу HERE HDLM шириной от 2 до 4 метров вдоль ее длины. В сформированной дорожной сети ширина полосы составляет 4 метра по всей её длине. Это изменение дорожных сетей иногда может привести к перекрытию дорог в сценарии вождения.

  • Если выдается предупреждение о невозможности вычисления геометрии дороги, кривизна дороги слишком резка, чтобы ее можно было правильно визуализировать, и она не импортируется.

  • Некоторые проблемы с импортируемыми дорогами могут быть связаны с отсутствием или неточностью данных карты в службе HERE HDLM. Например, можно увидеть черные линии, где встречаются дороги и перекрестки. Чтобы проверить, откуда возникает проблема в данных карты, используйте HERE HD Live Map Viewer для просмотра геометрии дорожной сети HERE HDLM. Для просмотра требуется действительная лицензия HERE. Дополнительные сведения см. на сайте HERE Technologies.

Ограничения импорта OpenStreetMap

При импорте данных OpenStreetMap функции дорог и полос движения имеют следующие ограничения:

  • Информация на уровне полос не импортируется с дорог OpenStreetMap. Спецификации полосы движения основаны только на направлении движения, указанном в дорожной сети OpenStreetMap, где:

    • Односторонние дороги импортируются как однополосные дороги со спецификациями полос по умолчанию. Эти полосы программно эквивалентны lanespec(1).

    • Двухсторонние дороги импортируются как двухполосные дороги с двусторонним движением и спецификациями полос по умолчанию. Эти полосы программно эквивалентны lanespec([1 1]).

    В таблице показаны эти различия в дорожной сети OpenStreetMap и дорожной сети в импортированном сценарии вождения.

    Дорожная сеть OpenStreetMapИмпортированный сценарий управления

    Two one-way roads gradually taper into one lane

    Two single-lane roads, with no direction of travel indicated, abruptly transition into a two-lane road with bidirectional travel

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

  • Базовая карта, используемая в приложении, может иметь небольшие отличия от карты, используемой в сервисе OpenStreetMap. Некоторые импортированные дорожные проблемы также могут быть связаны с отсутствующими или неточными данными карты в сервисе OpenStreetMap. Чтобы проверить отсутствие или неточность данных из-за службы карты, рассмотрите возможность просмотра данных карты во внешнем средстве просмотра карт.

  • Если выдается предупреждение о невозможности вычисления геометрии дороги, кривизна дороги слишком резка, чтобы ее можно было правильно визуализировать, и она не импортируется.

Zenrin Japan Map API 3.0 (Itsumo NAVI API 3.0) Ограничения импорта

При импорте данных Zenrin Japan Map API 3.0 (Itsumo NAVI API 3.0) создаваемая дорожная сеть имеет эти ограничения. В результате этих ограничений создаваемая сеть может содержать неточности, а дороги могут перекрываться.

  • Создаваемая дорожная сеть использует данные об отметке дороги, когда ее предоставляет Zenrin Japan Map API 3.0 (Itsumo NAVI API 3.0). В противном случае создаваемая сеть использует данные об отметке рельефа местности, предоставляемые службой.

  • Когда служба Zenrin Japan Map API 3.0 (Itsumo NAVI API 3.0) предоставляет информацию с использованием диапазона, например, путем указания дороги с двумя-тремя полосами или дороги шириной от 3 до 5,5 метров, генерируемая дорожная сеть использует вместо этого скалярные значения. Рассмотрим дорогу Zenrin Japan Map API 3.0 (Itsumo NAVI API 3.0), которая имеет от двух до трех полос. Сформированная дорожная сеть имеет две полосы движения.

  • Полосы движения в пределах дорог в создаваемой сети имеют одинаковую ширину. Рассмотрим дорогу шириной 4,25 метра с двумя полосами. В сформированной дорожной сети ширина каждой полосы составляет 2,125 метра.

  • Если выдается предупреждение о невозможности вычисления геометрии дороги, кривизна дороги слишком резка, чтобы ее можно было правильно визуализировать, и она не импортируется.

  • По возможности в создаваемой дорожной сети используются названия дорог, предоставляемые службой Zenrin Japan Map API 3.0 (Itsumo NAVI API 3.0). В противном случае в создаваемой дорожной сети используются имена по умолчанию, например Road1 и Road2.

Совет

  • Если импортируемые дороги выглядят не так, как ожидалось, попробуйте импортировать их с помощью приложения «Конструктор сценариев управления». Приложение может упростить процесс устранения неполадок и исправления дорог, чем попытки их устранения и исправления с помощью roadNetwork функция.

Ссылки

[1] Dupuis, Marius и др. Спецификация формата OpenDRIVE. Редакция 1.4, Выпуск Н, No документа VI2014.106. Бад Айблинг, Германия: VIRES Simulationstechnologie GmbH, 4 ноября 2015 г.

Представлен в R2018b

[1] Необходимо заключить отдельное соглашение с HERE, чтобы получить доступ к услугам HDLM и получить необходимые учетные данные (access_key_id и access_key_secret) для использования услуги HERE.

[2] Чтобы получить доступ к службе Zenrin Japan Map API 3.0 (Itsumo NAVI API 3.0) и получить необходимые учетные данные (идентификатор клиента и секретный ключ), необходимо заключить отдельное соглашение с ZENRIN DataCom CO., LTD.