Управление примером по сценарию

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

В этом примере вы генерируете ведущий сценарий из командной строки 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 Датчика Используя Синтетические Данные о Радаре и Видении.

Смотрите также

Приложения

Объекты

Функции

Похожие темы