Этот пример показывает, как сгенерировать основную истину для синтетических данных датчика и алгоритмов отслеживания. Также показано, как обновить положения актёра в симуляциях без разомкнутого контура и с обратной связью. Наконец, он показывает, как использовать сценарий вождения для выполнения преобразования координат и включения их в график птичьего глаза.
В этом примере вы программно создаете сценарий вождения из командной строки MATLAB ®. Кроме того, можно создать сценарии в интерактивном режиме с помощью приложения Driving Scenario Designer. Для получения примера смотрите Создание сценария вождения в интерактивном режиме и Генерация синтетических данных датчика.
Одна из целей сценария вождения состоит в том, чтобы сгенерировать «основную истину» тестов для использования с алгоритмами обнаружения и отслеживания датчиков, используемыми на конкретном транспортном средстве.
Эта основная истина обычно определяется в глобальной системе координат; но поскольку датчики обычно устанавливаются на движущемся транспортном средстве, эти данные должны быть преобразованы в опорную систему координат, которая перемещается вместе с транспортным средством. Сценарий вождения облегчает это преобразование автоматически, позволяя вам задавать дороги и траектории объектов в глобальных координатах и предоставляет инструменты для преобразования и визуализации этой информации в опорной системе координат любого актёра в сценарии.
A drivingScenario
состоит из модели дорог и подвижных объектов, называемой актёрами. Можно использовать актёров для моделирования пешеходов, паркоматов, пожарных гидрантов и других объектов в рамках сценария. Актёры состоят из кубоидов с длиной, шириной, высотой и радарным сечением (RCS). Актёр расположен и ориентирован вокруг одной точки в центре его нижней грани.
Особым видом актёра, который движется на колесах, является транспортное средство, которая расположена и ориентирована на земле непосредственно под центром задней оси, которая является более естественным центром вращения.
Все субъекты (включая транспортные средства) могут быть размещены в любом месте сценария путем определения их соответствующих Position
, Roll
, Pitch
, Yaw
, Velocity
, и AngularVelocity
свойства.
Вот пример сценария, состоящего из двух транспортных средств на 10 метров друг от друга и движущихся в сторону источника со скоростью 3 и 4 метра в секунду соответственно:
scenario = drivingScenario; v1 = vehicle(scenario,'ClassID',1','Position',[6 0 0],'Velocity',[-3 0 0],'Yaw',180)
v1 = Vehicle with properties: FrontOverhang: 0.9000 RearOverhang: 1 Wheelbase: 2.8000 EntryTime: 0 ExitTime: Inf ActorID: 1 ClassID: 1 Name: "" PlotColor: [0 0.4470 0.7410] Position: [6 0 0] Velocity: [-3 0 0] Yaw: 180 Pitch: 0 Roll: 0 AngularVelocity: [0 0 0] Length: 4.7000 Width: 1.8000 Height: 1.4000 Mesh: [1x1 extendedObjectMesh] RCSPattern: [2x2 double] RCSAzimuthAngles: [-180 180] RCSElevationAngles: [-90 90]
v2 = vehicle(scenario,'ClassID',1,'Position',[0 10 0],'Velocity',[0 -4 0],'Yaw',-90)
v2 = Vehicle with properties: FrontOverhang: 0.9000 RearOverhang: 1 Wheelbase: 2.8000 EntryTime: 0 ExitTime: Inf ActorID: 2 ClassID: 1 Name: "" PlotColor: [0.8500 0.3250 0.0980] Position: [0 10 0] Velocity: [0 -4 0] Yaw: -90 Pitch: 0 Roll: 0 AngularVelocity: [0 0 0] Length: 4.7000 Width: 1.8000 Height: 1.4000 Mesh: [1x1 extendedObjectMesh] RCSPattern: [2x2 double] RCSAzimuthAngles: [-180 180] RCSElevationAngles: [-90 90]
Чтобы визуализировать сценарий, вызовите plot
функция на ней:
plot(scenario); set(gcf,'Name','Scenario Plot') xlim([-20 20]); ylim([-20 20]);
После создания всех актёров в сценарии можно просмотреть информацию о положении всех актёров в координатах сценария путем просмотра Position
, Roll
, Pitch
, Yaw
, Velocity
, и AngularVelocity
свойства каждого актёра, или вы можете получить все их в удобной структуре, позвонив в actorPoses
функция в сценарии:
ap = actorPoses(scenario)
ap = 2x1 struct array with fields: ActorID Position Velocity Roll Pitch Yaw AngularVelocity
Чтобы получить информацию о положении всех других объектов (или целей), замеченных конкретным актером в собственной опорной системе координат, можно вызвать targetPoses
функция на самом актёре:
v2TargetPoses = targetPoses(v2)
v2TargetPoses = struct with fields: ActorID: 1 ClassID: 1 Position: [10 6.0000 0] Velocity: [-4 -3.0000 0] Roll: 0 Pitch: 0 Yaw: -90.0000 AngularVelocity: [0 0 0]
Мы можем качественно подтвердить относительное размещение транспортного средства, добавив график погони для транспортного средства. По умолчанию график погони отображает проективно-перспективный вид с фиксированного расстояния позади транспортного средства.
Здесь мы покажем перспективу, видимую сразу за вторым транспортным средством (красный). Целевые положения, видимые вторым транспортным средством, показывают, что положение другого транспортного средства (синего цвета) составляет 6 м вперед и 10 м налево от второго транспортного средства. Качественно мы это видим на графике погони:
chasePlot(v2) set(gcf,'Name','Chase Plot')
Обычно все графики, связанные со сценарием вождения, обновляются в процессе симуляции при вызове advance
функция. Если вы обновляете свойство положения другого актёра вручную, можно вызвать updatePlots
чтобы увидеть результаты немедленно:
v1.Yaw = 135; updatePlots(scenario);
Сценарий вождения может также использоваться для извлечения контуров дорог, определенных в сценарии.
Здесь мы используем простую овальную дорожку, описанную в Define Road Размещений Programmatic, которая занимает площадь примерно 200 метров в длину и 100 метров в ширину и кривые которой имеют угол крена девяти степеней:
scenario = drivingScenario; roadCenters = ... [ 0 40 49 50 100 50 49 40 -40 -49 -50 -100 -50 -49 -40 0 -50 -50 -50 -50 0 50 50 50 50 50 50 0 -50 -50 -50 -50 0 0 .45 .45 .45 .45 .45 0 0 .45 .45 .45 .45 .45 0 0]'; bankAngles = ... [ 0 0 9 9 9 9 9 0 0 9 9 9 9 9 0 0]; road(scenario, roadCenters, bankAngles, 'lanes', lanespec(2)); plot(scenario);
Чтобы получить линии, которые определяют границы дороги, используйте roadBoundaries
функция на сценарии вождения. Он возвращает массив ячеек, который содержит границы дорог (показан на графике сценария выше как сплошные черные линии).
rb = roadBoundaries(scenario)
rb = 1x2 cell array {258x3 double} {258x3 double}
В приведенном выше примере существуют два контуров дорог (внешние и внутренние контуры). Вы можете построить их самостоятельно следующим образом:
figure outerBoundary = rb{1}; innerBoundary = rb{2}; plot3(innerBoundary(:,1),innerBoundary(:,2),innerBoundary(:,3),'r', ... outerBoundary(:,1),outerBoundary(:,2),outerBoundary(:,3),'g') axis equal
Можно использовать roadBoundaries
функция на актёра, чтобы получить контуры дороги в координатах актёра. Для этого просто передайте актёра как первый аргумент, вместо сценария.
Чтобы увидеть это, добавьте «автомобиль , оборудованный датчиком» и поместите его на трассу:
egoCar = vehicle(scenario,'ClassID',1,'Position',[80 -40 0.45],'Yaw',30);
Далее вызовите roadBoundaries
функция на транспортном средстве и построение графика как и прежде. Он будет отображаться относительно координат транспортного средства:
figure rb = roadBoundaries(egoCar) outerBoundary = rb{1}; innerBoundary = rb{2}; plot3(innerBoundary(:,1),innerBoundary(:,2),innerBoundary(:,3),'r', ... outerBoundary(:,1),outerBoundary(:,2),outerBoundary(:,3),'g') axis equal
rb = 1x2 cell array {258x3 double} {258x3 double}
Вы можете расположить и построить график любого конкретного актёра вдоль предопределенного трехмерного пути.
Вот пример для двух транспортных средств, которые следуют за гоночной трассой со скоростью 30 м/с и 50 м/с соответственно, каждый в своей собственной соответствующей полосе. Мы смещаем автомобили от центра дороги путем установки смещения на половину ширины полосы 2,7 метра, и, для наклоненных углов участков пути, половину вертикальной высоты с каждой стороны:
chasePlot(egoCar); fastCar = vehicle(scenario,'ClassID',1); d = 2.7/2; h = .45/2; roadOffset = [ 0 0 0 0 d 0 0 0 0 0 0 -d 0 0 0 0 -d -d -d -d 0 d d d d d d 0 -d -d -d -d 0 0 h h h h h 0 0 h h h h h 0 0]'; rWayPoints = roadCenters + roadOffset; lWayPoints = roadCenters - roadOffset; % loop around the track four times rWayPoints = [repmat(rWayPoints(1:end-1,:),5,1); rWayPoints(1,:)]; lWayPoints = [repmat(lWayPoints(1:end-1,:),5,1); lWayPoints(1,:)]; smoothTrajectory(egoCar,rWayPoints(:,:), 30); smoothTrajectory(fastCar,lWayPoints(:,:), 50);
Актёры, которые следуют по траектории, обновляются по вызову advance
о сценарии вождения. Когда advance
вызывается, каждый актёр, который следует по траектории, будет двигаться вперед, и соответствующие графики будут обновлены. Только актёры, которые определили траектории, действительно обновляются. Это значит, что вы можете предоставить свою собственную логику во время симуляции.
The SampleTime
свойство в сценарии определяет интервал времени между обновлениями. По умолчанию это 10 миллисекунд, но вы можете задать его с произвольным разрешением:
scenario.SampleTime = 0.02
scenario = drivingScenario with properties: SampleTime: 0.0200 StopTime: Inf SimulationTime: 0 IsRunning: 1 Actors: [1x2 driving.scenario.Vehicle] Barriers: [0x0 driving.scenario.Barrier]
Можно запустить симуляцию, позвонив advance
в условии цикла while и команд размещения для просмотра или изменения сценария в теле цикла.
Цикл while автоматически прерывается, когда завершена траектория для любого транспортного средства или опционально StopTime
достигнуто.
scenario.StopTime = 4; while advance(scenario) pause(0.001) end
Как удобство, когда траектории всех актёров известны заранее, можно вызвать record
функция в сценарии для возврата структуры, которая содержит информацию о положении каждого актёра на каждом временном шаге.
Для примера можно просмотреть информацию о положении каждого актёра за первые 100 миллисекунд симуляции и просмотреть пятую зарегистрированную выборку:
close all
scenario.StopTime = 0.100;
poseRecord = record(scenario)
r = poseRecord(5)
r.ActorPoses(1)
r.ActorPoses(2)
poseRecord = 1x5 struct array with fields: SimulationTime ActorPoses r = struct with fields: SimulationTime: 0.0800 ActorPoses: [2x1 struct] ans = struct with fields: ActorID: 1 Position: [2.4000 -51.3502 0] Velocity: [30.0000 -0.0038 0] Roll: 0 Pitch: 0 Yaw: -0.0073 AngularVelocity: [0 0 -0.0823] ans = struct with fields: ActorID: 2 Position: [4.0000 -48.6504 0] Velocity: [50.0000 -0.0105 0] Roll: 0 Pitch: 0 Yaw: -0.0120 AngularVelocity: [0 0 -0.1235]
При отладке симуляции можно хотеть сообщить «основную истину» данные на графике птичьего глаза конкретного актёра при одновременном просмотре графиков, сгенерированных сценарием. Для этого можно сначала создать рисунок с осями, помещенными в пользовательское расположение:
close all; hFigure = figure; hFigure.Position(3) = 900; hPanel1 = uipanel(hFigure,'Units','Normalized','Position',[0 1/4 1/2 3/4],'Title','Scenario Plot'); hPanel2 = uipanel(hFigure,'Units','Normalized','Position',[0 0 1/2 1/4],'Title','Chase Plot'); hPanel3 = uipanel(hFigure,'Units','Normalized','Position',[1/2 0 1/2 1],'Title','Bird''s-Eye Plot'); hAxes1 = axes('Parent',hPanel1); hAxes2 = axes('Parent',hPanel2); hAxes3 = axes('Parent',hPanel3);
Как только вы определили оси, вы задаете их через Parent
свойство при создании графиков:
% assign scenario plot to first axes and add indicators for ActorIDs 1 and 2 plot(scenario, 'Parent', hAxes1,'ActorIndicators',[1 2]); % assign chase plot to second axes chasePlot(egoCar, 'Parent', hAxes2); % assign bird's-eye plot to third axes egoCarBEP = birdsEyePlot('Parent',hAxes3,'XLimits',[-200 200],'YLimits',[-240 240]); fastTrackPlotter = trackPlotter(egoCarBEP,'MarkerEdgeColor','red','DisplayName','target','VelocityScaling',.5); egoTrackPlotter = trackPlotter(egoCarBEP,'MarkerEdgeColor','blue','DisplayName','ego','VelocityScaling',.5); egoLanePlotter = laneBoundaryPlotter(egoCarBEP); plotTrack(egoTrackPlotter, [0 0]); egoOutlinePlotter = outlinePlotter(egoCarBEP);
Теперь можно перезапустить симуляцию и запустить ее до своего завершения, на этот раз извлечя позиционную информацию целевого автомобиля через targetPoses
и отобразить его на графике птичьего глаза. Точно так же можно вызвать roadBoundaries
и targetOutlines
непосредственно из автомобиля , оборудованного датчиком извлечения границ дорог и контуров актёров. График птичьего глаза способен отображать результаты этих функций непосредственно:
restart(scenario) scenario.StopTime = Inf; while advance(scenario) t = targetPoses(egoCar); plotTrack(fastTrackPlotter, t.Position, t.Velocity); rbs = roadBoundaries(egoCar); plotLaneBoundary(egoLanePlotter, rbs); [position, yaw, length, width, originOffset, color] = targetOutlines(egoCar); plotOutline(egoOutlinePlotter, position, yaw, length, width, 'OriginOffset', originOffset, 'Color', color); end
Этот пример показал, как сгенерировать и визуализировать основную истину для синтетических данных датчика и алгоритмов отслеживания с помощью drivingScenario
объект. Чтобы моделировать, визуализировать или изменить этот сценарий вождения в интерактивном окружении, попробуйте импортировать drivingScenario
объект в приложение Driving Scenario Designer:
drivingScenarioDesigner(scenario)
Для получения дополнительной информации о том, как задать актёров и дороги, смотрите Создание Траекторий Актёра и Транспортного средства Программно и Программно Задайте Размещения Дорог.
Для более глубокого примера использования графика птичьего глаза с обнаружениями и треками, смотрите Визуализация Покрытия Датчика, Обнаружения и Треки.
Для примеров, которые используют сценарий вождения, чтобы помочь в генерации синтетических данных, смотрите Model Radar Sensor Detections, Model Vision Sensor Detections и Sensor Fusion Using Synthetic Radar and Vision Data.
actorPoses
| chasePlot
| record
| road
| roadBoundaries
| targetPoses
| updatePlots
| vehicle