Этот пример показывает, как сгенерировать наземную истину для синтетических данных о датчике и алгоритмов отслеживания. Это также показывает, как обновить положения агента в разомкнутом цикле и симуляциях с обратной связью. Наконец, это показывает, как использовать ведущий сценарий, чтобы выполнить координатное преобразование и включить их в видимый с большого расстояния график.
В этом примере вы генерируете ведущий сценарий из командной строки MATLAB®. Также можно сгенерировать сценарии в интерактивном режиме при помощи приложения Driving Scenario Designer. Для примера смотрите Сборку Ведущий Сценарий и Сгенерируйте Синтетические Обнаружения.
Одна из целей ведущего сценария состоит в том, чтобы сгенерировать "наземные тесты" истины для использования с алгоритмами обнаружения и отслеживания датчика, используемыми на определенном автомобиле.
Эта наземная истина обычно задается в глобальной системе координат; но, потому что датчики обычно монтируются на движущемся автомобиле, эти данные должны быть преобразованы в ссылочный кадр, который перемещается наряду с автомобилем. Ведущий сценарий упрощает это преобразование автоматически, позволяя вам задать дороги и траектории объектов в глобальных координатах и обеспечивает инструменты, чтобы преобразовать и визуализировать эту информацию в ссылочном кадре любого агента в сценарии.
drivingScenario
состоит из модели дорог и подвижных объектов, названных агентами. Можно использовать агентов для образцовых пешеходов, парковочные часы, пожарные гидранты и другие объекты в рамках сценария. Агенты состоят из кубоидов с длиной, шириной, высотой и радарным поперечным сечением (RCS). Агент расположен и ориентирован об одной точке в центре ее нижней поверхности.
Специальный вид агента, который перемещается в колеса, является автомобилем, который расположен и ориентирован на землю непосредственно ниже центра задней оси, которая является более естественным центром вращения.
Все агенты (включая автомобили) могут быть помещены куда угодно в рамках сценария путем определения их соответствующего Position
, Roll
, Pitch
, Yaw
, Velocity
и свойств AngularVelocity
.
Вот пример сценария, состоящего из двух автомобилей на расстоянии в 10 метров и управляющего к источнику со скоростью 3 и 4 метров в секунду, соответственно:
s = drivingScenario; v1 = vehicle(s,'Position',[ 6 0 0],'Velocity',[-3 0 0],'Yaw', 180)
v1 = Vehicle with properties: ActorID: 1 ClassID: 0 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 RCSPattern: [2x2 double] RCSAzimuthAngles: [-180 180] RCSElevationAngles: [-90 90] FrontOverhang: 0.9000 RearOverhang: 1 Wheelbase: 2.8000
v2 = vehicle(s,'Position',[ 0 10 0],'Velocity',[ 0 -4 0],'Yaw',-90)
v2 = Vehicle with properties: ActorID: 2 ClassID: 0 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 RCSPattern: [2x2 double] RCSAzimuthAngles: [-180 180] RCSElevationAngles: [-90 90] FrontOverhang: 0.9000 RearOverhang: 1 Wheelbase: 2.8000
Чтобы визуализировать сценарий, вызовите его метод plot
:
plot(s); set(gcf,'Name','Scenario Plot') xlim([-20 20]); ylim([-20 20]);
Если все агенты в сценарии были созданы, можно осмотреть информацию о положении всех агентов в координатах сценария путем осмотра Position
, Roll
, Pitch
, Yaw
, Velocity
и свойств AngularVelocity
каждого агента, или можно получить всех их в удобной структуре путем вызова метода actorPoses
сценария:
ap = actorPoses(s)
ap = 2x1 struct array with fields: ActorID Position Velocity Roll Pitch Yaw AngularVelocity
Чтобы получить информацию о положении всех других объектов (или цели) замеченный определенным агентом в его собственном ссылочном кадре, можно вызвать метод targetPoses
на самом агенте:
v2TargetPoses = targetPoses(v2)
v2TargetPoses = struct with fields: ActorID: 1 ClassID: 0 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(s);
Ведущий сценарий может также использоваться, чтобы получить контуры дорог, заданных в сценарии.
Здесь мы используем простую овальную дорожку, описанную в Размещениях Дефайн-Роуд, который покрывает область примерно 200 метров длиной и 100 метров шириной и чьи кривые имеют угол банка девяти градусов:
s = 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(s, roadCenters, bankAngles, 'lanes', lanespec(2)); plot(s);
Чтобы получить строки, которые задают границы дороги, используйте метод roadBoundaries
из ведущего сценария. Это возвращает массив ячеек, который содержит дорожные границы (показанный в графике сценария выше как чистые черные строки).
rb = roadBoundaries(s)
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(s,'Position',[80 -40 .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}
Можно расположить и построить любого определенного агента вдоль предопределенного 3D пути.
Вот пример для двух автомобилей, которые следуют за трассой на уровне 30 м/с и 50 м/с соответственно, каждым в ее собственном соответствующем маршруте. Мы смещаем автомобили от центра дороги путем установки положения смещения наполовину ширина маршрута 2,7 метров, и, для окруженных валом угловых разделов дорожки, половина вертикальной высоты на каждой стороне:
chasePlot(egoCar);
fastCar = vehicle(s);
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,:)];
trajectory(egoCar,rWayPoints(:,:), 30);
trajectory(fastCar,lWayPoints(:,:), 50);
Агенты, которые следуют за траекторией, обновляются путем вызова advance
на ведущем сценарии. Когда advance
будет назван, каждый агент, который следует за траекторией, продвинется, и соответствующие графики будут обновлены. Только агенты, которые задали траектории на самом деле, обновляют. Это так, можно обеспечить собственную логику, в то время как симуляция запускается.
Свойство SampleTime
в сценарии управляет интервалом времени между обновлениями. По умолчанию это - 10 миллисекунд, но можно задать его с произвольным разрешением:
s.SampleTime = 0.02
s = drivingScenario with properties: SampleTime: 0.0200 StopTime: Inf SimulationTime: 0 IsRunning: 1 Actors: [1x2 driving.scenario.Vehicle]
Можно запустить симуляцию путем вызова advance
в условном выражении некоторое время цикла и размещения команд, чтобы осмотреть или изменить сценарий в теле цикла.
Цикл с условием продолжения автоматически остановится, когда траектория для любого автомобиля закончилась, или был достигнут дополнительный StopTime
.
s.StopTime = 4; while advance(s) pause(0.001) end
Как удобство, когда траектории всех агентов известны заранее, можно вызвать метод record
сценария, чтобы возвратить структуру, которая содержит информацию о положении каждого агента в каждый такт.
Например, можно осмотреть информацию о положении каждого агента для первых 100 миллисекунд симуляции и осмотреть пятую записанную выборку:
close all
s.StopTime = 0.100;
poseRecord = record(s)
r = poseRecord(5)
r.ActorPoses(1)
r.ActorPoses(2)
poseRecord = 1x6 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.3501 0] Velocity: [30.0000 -0.0028 0] Roll: 0 Pitch: 0 Yaw: -0.0053 AngularVelocity: [0 0 -0.0589] ans = struct with fields: ActorID: 2 Position: [4.0000 -48.6503 0] Velocity: [50.0000 -0.0075 0] Roll: 0 Pitch: 0 Yaw: -0.0086 AngularVelocity: [0 0 -0.0884]
При отладке симуляции можно хотеть сообщить о "наземных данных о" истины в видимом с большого расстояния графике определенного агента, одновременно просматривая графики, сгенерированные сценарием. Для этого можно сначала создать фигуру с осями, помещенными в пользовательское расположение:
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 a scenario plot and a chase plot in the first two axes plot(s, 'Parent', hAxes1); chasePlot(egoCar, 'Parent', hAxes2); % assign a bird's-eye plot in 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(s) s.StopTime = Inf; while advance(s) 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
Для получения дополнительной информации о том, как задать агентов и дороги, смотрите, Создают Траектории Агента и Автомобиля и Дефайн-Роуд Лайоутс.
Для более всестороннего примера о том, как использовать видимый с большого расстояния график с обнаружениями и дорожками, смотрите, Визуализируют Покрытие Датчика, Обнаружения и Дорожки.
Для примеров, которые используют ведущий сценарий, чтобы помочь в генерации синтетических данных, смотрите Образцовые Радарные Обнаружения Датчика, Образцовые Обнаружения Датчика Видения и Fusion Датчика Используя Синтетические Данные о Радаре и Видении.
actorPoses
| chasePlot
| record
| road
| roadBoundaries
| targetPoses
| updatePlots
| vehicle