Программно создайте сценарий вождения

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

В этом примере вы программно создаете сценарий вождения из командной строки 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.

См. также

Приложения

Объекты

Функции

Похожие темы