exponenta event banner

Сопоставление с известными позициями

В этом примере показано, как создать карту среды с использованием показаний датчика дальности и позиций робота для робота с дифференциальным приводом. Вы создаете карту из показаний датчиков диапазона, которые моделируются с помощью rangeSensor объект. differentialDriveKinematics модель движения моделирует перемещение робота по комнате на основе команд скорости. rangeSensor выдает показания дальности в зависимости от позы робота при следовании по пути.

Эталонная карта и рисунки

Загрузить набор примеров двоичных сеток занятости из exampleMaps, в том числе simpleMap, который используется в этом примере.

load exampleMaps.mat

Создание эталонной двоичной карты занятости с помощью simpleMap с разрешением 1. Показать рисунок и сохранить маркер перемещения рисунка.

refMap = binaryOccupancyMap(simpleMap,1);
refFigure = figure('Name','SimpleMap');
show(refMap);

Создайте пустую карту с теми же размерами, что и выбранная карта с разрешением 10. Показать рисунок и сохранить маркер перемещения рисунка. Зафиксируйте оси по размеру карты.

[mapdimx,mapdimy] = size(simpleMap);
map = binaryOccupancyMap(mapdimy,mapdimx,10);
mapFigure = figure('Name','Unknown Map');
show(map);

Инициализация модели движения и контроллера

Создайте модель кинематического движения дифференциального привода. Модель движения представляет движение моделируемого робота с дифференциальным приводом. Эта модель использует скорости левого и правого колес или линейные и угловые скорости для курса робота. В этом примере используйте скорость и курс транспортного средства для VehicleInputs.

diffDrive = differentialDriveKinematics("VehicleInputs","VehicleSpeedHeadingRate");

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

controller = controllerPurePursuit('DesiredLinearVelocity',2,'MaxAngularVelocity',3);

Настройка датчика дальности

Создайте датчик с максимальным диапазоном 10 метров. Этот датчик моделирует показания диапазона на основе заданной позы и карты. Эталонная карта используется с этим датчиком диапазона для моделирования сбора показаний датчика в неизвестной среде.

sensor = rangeSensor;
sensor.Range = [0,10];

Создание запланированного пути

Создайте путь для перемещения по карте для сбора показаний датчика дальности.

path = [4 6; 6.5 12.5; 4 22; 12 14; 22 22; 16 12; 20 10; 14 6; 22 3];

Постройте график траектории на рисунке ссылочной карты.

figure(refFigure);
hold on
plot(path(:,1),path(:,2), 'o-');
hold off

Задайте путь в качестве ППМ контроллера чистого преследования.

controller.Waypoints = path;

Следовать пути и среде карты

Задайте начальную позу и конечное местоположение цели на основе пути. Создание глобальных переменных для хранения текущей позы и индекса для отслеживания итераций.

initPose = [path(1,1) path(1,2), pi/2];
goal = [path(end,1) path(end,2)]';
poses(:,1) = initPose';

Используйте предоставленную функцию помощника exampleHelperDiffDriveControl. Вспомогательная функция содержит основной цикл навигации по пути, получения показаний диапазона и отображения среды.

exampleHelperDiffDriveControl имеет следующий рабочий процесс:

  • Просканируйте эталонную карту с помощью датчика дальности и текущей позы. При этом моделируются обычные показания диапазона для вождения в неизвестной среде.

  • Обновите карту с помощью показаний диапазона.

  • Получите управляющие команды от чистого контроллера слежения, чтобы перейти к следующему ППМ.

  • Расчет производной движения робота на основе команд управления.

  • Приращение позы робота на основе производной.

Вы должны видеть, как робот передвигается по пустой карте и заполняет стены, когда датчик дальности обнаруживает их.

exampleHelperDiffDriveCtrl(diffDrive,controller,initPose,goal,refMap,map,refFigure,mapFigure,sensor)

Goal position reached

Функция управления дифференциальным приводом

exampleHelperDiffDriveControl имеет следующий рабочий процесс:

  • Просканируйте эталонную карту с помощью датчика дальности и текущей позы. При этом моделируются обычные показания диапазона для вождения в неизвестной среде.

  • Обновите карту с помощью показаний диапазона.

  • Получите управляющие команды от чистого контроллера слежения, чтобы перейти к следующему ППМ.

  • Расчет производной движения робота на основе команд управления.

  • Приращение позы робота на основе производной.

function exampleHelperDiffDriveControl(diffDrive,ppControl,initPose,goal,map1,map2,fig1,fig2,lidar)
sampleTime = 0.05;             % Sample time [s]
t = 0:sampleTime:100;         % Time array
poses = zeros(3,numel(t));    % Pose matrix
poses(:,1) = initPose';

% Set iteration rate
r = rateControl(1/sampleTime);

% Get the axes from the figures
ax1 = fig1.CurrentAxes;
ax2 = fig2.CurrentAxes;

    for idx = 1:numel(t)
        position = poses(:,idx)';
        currPose = position(1:2);
        
        % End if pathfollowing is vehicle has reached goal position within tolerance of 0.2m
        dist = norm(goal'-currPose);
        if (dist < .2)
            disp("Goal position reached")
            break;
        end
        
        % Update map by taking sensor measurements
        figure(2)
        [ranges, angles] = lidar(position, map1);
        scan = lidarScan(ranges,angles);
        validScan = removeInvalidData(scan,'RangeLimits',[0,lidar.Range(2)]);
        insertRay(map2,position,validScan,lidar.Range(2));
        show(map2);
        
        % Run the Pure Pursuit controller and convert output to wheel speeds
        [vRef,wRef] = ppControl(poses(:,idx));
    
        % Perform forward discrete integration step
        vel = derivative(diffDrive, poses(:,idx), [vRef wRef]);
        poses(:,idx+1) = poses(:,idx) + vel*sampleTime; 
    
    
        % Update visualization
        plotTrvec = [poses(1:2, idx+1); 0];
        plotRot = axang2quat([0 0 1 poses(3, idx+1)]);
        
        % Delete image of the last robot to prevent displaying multiple robots
        if idx > 1
           items = get(ax1, 'Children');
           delete(items(1)); 
        end
    
        %plot robot onto known map
        plotTransforms(plotTrvec', plotRot, 'MeshFilePath', 'groundvehicle.stl', 'View', '2D', 'FrameSize', 1, 'Parent', ax1);
        %plot robot on new map
        plotTransforms(plotTrvec', plotRot, 'MeshFilePath', 'groundvehicle.stl', 'View', '2D', 'FrameSize', 1, 'Parent', ax2);
    
        % waiting to iterate at the proper rate
        waitfor(r);
    end
end