Этот пример показывает, как создать карту среды с помощью показаний датчика области значений, если положение робота известно во время чтения датчика. Этот пример также показывает, как использовать функции преобразования (такие как quat2eul
) от Robotics System Toolbox™.
Этот пример создает карту из показаний датчика области значений и известных положений робота. В целях этого примера вы будете использовать основанное на MATLAB® средство моделирования, чтобы управлять роботом, наблюдать показания датчика области значений и положения робота. Можно заменить средство моделирования или на действительного робота или на моделируемого робота в средстве моделирования Gazebo, в этом случае вам будут нужны некоторые средние значения, чтобы получить истинное положение робота во время чтения датчика.
Предпосылки: Следование траектории для Робота с дифференциальным приводом, доступ к tf Дереву Преобразования в ROS, обменивается Данными с Издателями ROS и Подписчиками
Запустите ведущее устройство ROS в MATLAB.
rosinit
Initializing ROS master on http://bat6230glnxa64:33643/. Initializing global node /matlab_global_node_62984 with NodeURI http://bat6230glnxa64:44831/
Инициализируйте средство моделирования робота и присвойте начальное положение. Моделируемый робот является двухколесным роботом с дифференциальным приводом с лазерным датчиком области значений.
sim = ExampleHelperRobotSimulator('simpleMap');
setRobotPose(sim,[2 3 -pi/2]);
Включите интерфейс ROS для средства моделирования. Средство моделирования создает издателей и подписчиков, чтобы отправить и получить данные по ROS.
enableROSInterface(sim,true);
Увеличьте лазерное разрешение датчика в средстве моделирования, чтобы упростить создание карты.
sim.LaserSensor.NumReadings = 50;
Создайте издателей ROS и подписчиков, чтобы связаться со средством моделирования. Создайте rossubscriber
для получения лазерных данных о датчике из средства моделирования.
scanSub = rossubscriber('scan');
Для создания карты робот будет управлять вокруг карты и собирать данные о датчике. Создайте rospublisher
, чтобы отправить скоростные команды в робота.
[velPub, velMsg] = rospublisher('/mobile_base/commands/velocity');
Средство моделирования MATLAB публикует положение робота относительно источника карты как преобразование по теме /tf
, который используется в качестве источника для наземного положения робота истины в этом примере. Средство моделирования использует map
и robot_base
как имена кадра в этом преобразовании.
Создайте объект дерева преобразования ROS с помощью rostf
функцию. Для создания карты важно, чтобы положение робота и лазерное чтение датчика соответствовали тому же времени. Дерево преобразования позволяет вам находить положение робота в то время, когда лазерное чтение датчика наблюдалось.
tftree = rostf;
Сделайте паузу в течение секунды для объекта дерева преобразования закончить инициализацию.
pause(1)
Интерфейс ROS связывается со средством моделирования робота, и состояние моделируемого робота отображено в фигуре.
Робот должен будет управлять вокруг целой карты, чтобы собрать лазерные данные о датчике и создать полную карту. Присвойте путь с waypoints, которые покрывают целую карту.
path = [2 3; 3.25 6.25; 2 11; 6 7; 11 11; 8 6; 10 5; 7 3; 11 1.5];
Визуализируйте путь в средстве моделирования робота
plot(path(:,1),path(:,2),'k--d');
На основе пути, заданного выше и модель движения робота, вам нужен контроллер следования траектории, чтобы управлять роботом вдоль пути. Создайте контроллер следования траектории, использующий объект
robotics.PurePursuit
.
controller = robotics.PurePursuit('Waypoints',path);
controller.DesiredLinearVelocity = 0.4;
Установите уровень контроллера достигать 10 Гц.
controlRate = robotics.Rate(10);
Задайте целевую точку и целевой радиус, чтобы остановить робота в конце пути.
goalRadius = 0.1; robotCurrentLocation = path(1,:); robotGoal = path(end,:); distanceToGoal = norm(robotCurrentLocation - robotGoal);
Задайте карту с высоким разрешением с помощью robotics.OccupancyGrid
, чтобы получить показания датчика. Это создает карту с 14 м X 13 м размером и разрешением 20 ячеек на метр.
map = robotics.OccupancyGrid(14,13,20);
Визуализируйте карту в окне рисунка.
figureHandle = figure('Name', 'Map'); axesHandle = axes('Parent', figureHandle); mapHandle = show(map, 'Parent', axesHandle); title(axesHandle, 'OccupancyGrid: Update 0');
Следующий цикл с условием продолжения создаст карту среды при управлении роботом. Следующие шаги выполняются:
Во-первых, вы получаете лазерные данные сканирования с помощью подписчика scanSub
. Используйте функцию
getTransform
с меткой времени на сообщении scan
, чтобы получить преобразование между map
и кадрами robot_base
во время чтения датчика.
Получите положение робота и ориентацию от преобразования. Ориентация робота является вращением Отклонения от курса вокруг оси Z робота. Можно получить вращение Отклонения от курса путем преобразования кватерниона в углы Эйлера с помощью quat2eul
.
Предварительно обработайте лазерные данные сканирования. Средство моделирования возвращает области значений NaN для лазерных лучей, которые не поражают препятствия в максимальной области значений. Замените области значений NaN максимальным значением области значений.
Вставьте лазерное наблюдение сканирования с помощью insertRay
метода на сетке заполнения map
.
Вычислите линейные и угловые скоростные команды с помощью объекта controller
управлять роботом.
(Необязательно), Чтобы визуализировать карту после каждых 50 обновлений, не прокомментируйте раздел в цикле с условием продолжения.
updateCounter = 1; while( distanceToGoal > goalRadius ) % Receive a new laser sensor reading. scanMsg = receive(scanSub); % Get robot pose at the time of sensor reading. pose = getTransform(tftree, 'map', 'robot_base', scanMsg.Header.Stamp, 'Timeout', 2); % Convert robot pose to 1x3 vector [x y yaw]. position = [pose.Transform.Translation.X, pose.Transform.Translation.Y]; orientation = quat2eul([pose.Transform.Rotation.W, pose.Transform.Rotation.X, ... pose.Transform.Rotation.Y, pose.Transform.Rotation.Z], 'ZYX'); robotPose = [position, orientation(1)]; % Extract the laser scan. scan = lidarScan(scanMsg); ranges = scan.Ranges; ranges(isnan(ranges)) = sim.LaserSensor.MaxRange; modScan = lidarScan(ranges, scan.Angles); % Insert the laser range observation in the map. insertRay(map, robotPose, modScan, sim.LaserSensor.MaxRange); % Compute the linear and angular velocity of the robot and publish it % to drive the robot. [v, w] = controller(robotPose); velMsg.Linear.X = v; velMsg.Angular.Z = w; send(velPub, velMsg); % Visualize the map after every 50th update. % if ~mod(updateCounter,50) % mapHandle.CData = occupancyMatrix(map); % title(axesHandle, ['OccupancyGrid: Update ' num2str(updateCounter)]); % end % Update the counter and distance to goal. updateCounter = updateCounter+1; distanceToGoal = norm(robotPose(1:2) - robotGoal); % Wait for control rate to ensure 10 Hz rate. waitfor(controlRate); end
Отобразите итоговую карту, которая включила все показания датчика.
show(map, 'Parent', axesHandle); title(axesHandle, 'OccupancyGrid: Final Map');
Закройте ведущее устройство ROS и удалите глобальный узел.
rosshutdown
Shutting down global node /matlab_global_node_62984 with NodeURI http://bat6230glnxa64:44831/ Shutting down ROS master on http://bat6230glnxa64:33643/.