В этом примере показано, как сгенерировать основную истину для синтетических данных о датчике и алгоритмов отслеживания. Это также показывает, как обновить положения агента в разомкнутом контуре и симуляциях с обратной связью. Наконец, это показывает, как использовать ведущий сценарий, чтобы выполнить координатное преобразование и включить их в видимый с большого расстояния график.
В этом примере вы программно создаете ведущий сценарий из командной строки MATLAB®. В качестве альтернативы можно создать сценарии в интерактивном режиме при помощи приложения Driving Scenario Designer. Для примера смотрите, Создают Ведущий Сценарий В интерактивном режиме и Генерируют Синтетические Данные о Датчике.
Одна из целей ведущего сценария состоит в том, чтобы сгенерировать тесты "основной истины" для использования с алгоритмами обнаружения и отслеживания датчика, используемыми на определенном транспортном средстве.
Эта основная истина обычно задается в глобальной системе координат; но, потому что датчики обычно монтируются на движущемся транспортном средстве, эти данные должны быть преобразованы в систему координат, которая перемещается наряду с транспортным средством. Ведущий сценарий упрощает это преобразование автоматически, позволяя вам задать дороги и траектории объектов в глобальных координатах и обеспечивает инструменты, чтобы преобразовать и визуализировать эту информацию в системе координат любого агента в сценарии.
drivingScenario
состоит из модели дорог и подвижных объектов, названных агентами. Можно использовать агентов для пешеходов модели, парковочные часы, пожарные гидранты и другие объекты в рамках сценария. Агенты состоят из кубоидов с длиной, шириной, высотой и радарным поперечным сечением (RCS). Агент расположен и ориентирован об одной точке в центре ее нижней поверхности.
Специальный вид агента, который перемещается в колеса, является транспортным средством, которое расположено и ориентировано на землю непосредственно ниже центра задней оси, которая является более естественным центром вращения.
Все агенты (включая транспортные средства) могут быть помещены куда угодно в рамках сценария путем определения их соответствующего Position
Крен
Тангаж
, 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
Крен
Тангаж
, 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);
Ведущий сценарий может также использоваться, чтобы получить контуры дорог, заданных в сценарии.
Здесь мы используем простую овальную дорожку, описанную в Размещениях Дефайн-Роуд Программно, который покрывает область примерно 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}
Можно расположить и построить любого определенного агента вдоль предопределенного 3D пути.
Вот пример для двух транспортных средств, которые следуют за трассой на уровне 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
называется, каждый агент, который следует за траекторией, продвинется, и соответствующие графики будут обновлены. Только агенты, которые задали траектории на самом деле, обновляются. Это так, можно обеспечить собственную логику, в то время как симуляция запускается.
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
в условном выражении некоторое время цикла и помещающих команд, чтобы смотреть или изменить сценарий в теле цикла.
Цикл с условием продолжения автоматически завершит работу, когда траектория для любого транспортного средства закончится или дополнительный 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)
Для получения дополнительной информации о том, как задать агентов и дороги, смотрите, Создают Траектории Агента и Транспортного средства Программно и Размещения Дефайн-Роуд Программно.
Для более всестороннего примера о том, как использовать видимый с большого расстояния график с обнаружениями и дорожками, смотрите, Визуализируют Покрытие Датчика, Обнаружения и Дорожки.
Для примеров, которые используют ведущий сценарий, чтобы помочь в генерации синтетических данных, смотрите Радарные Обнаружения Датчика Модели, Обнаружения Датчика Видения Модели и Fusion Датчика Используя Синтетические Данные о Радаре и Видении.
actorPoses
| chasePlot
| record
| road
| roadBoundaries
| targetPoses
| updatePlots
| vehicle