exponenta event banner

Управляйте движениями руки PR2 Используя действия ROS и обратную кинематику

В этом примере показано, как отправлять команды роботизированным манипуляторам в MATLAB ®. Команды совместного положения посылаются через клиент действий АФК по сети АФК. Этот пример также показывает, как вычислить положения соединения для желаемого положения концевого эффектора. Жесткое дерево тела определяет геометрию робота и зависимости соединения, которые используются с обратной кинематикой для получения положений соединения робота. Затем можно отправить эти позиции соединения в виде траектории, чтобы дать команду роботу двигаться.

Запуск моделирования PR2 беседки

Нерестить PR2 в простой среде (только со столом и коксовой баночкой) в Gazebo Simulator. Выполните шаги, описанные в разделе «Начало работы с беседкой и моделируемым TurtleBot (ROS Toolbox)», чтобы запустить Gazebo PR2 Simulator с рабочего стола виртуальной машины Ubuntu ®.

Подключение к сети ROS от MATLAB

®

В экземпляре MATLAB на хост-компьютере выполните следующие команды для инициализации глобального узла ROS в MATLAB и подключения к хозяину ROS в виртуальной машине через его IP-адрес. ipaddress. Замените «192.168.233.133» на IP-адрес виртуальной машины. При необходимости укажите порт.

ipaddress = '192.168.116.161';
rosinit(ipaddress,11311);
Initializing global node /matlab_global_node_03004 with NodeURI http://192.168.116.1:64988/

Создание клиентов действий для роботов и отправка команд

В этой задаче вы отправляете совместные траектории на PR2 руки. Управление рычагами может осуществляться посредством действий АФК. Траектории суставов задаются вручную для каждой руки и отправляются в виде отдельных целевых сообщений через отдельные клиенты действий.

Создайте клиент простого действия ROS для отправки сообщений о целях для перемещения правой руки робота. rosactionclient (ROS Toolbox) возвращается сообщение об объекте и цели. Дождитесь подключения клиента к серверу действий ROS.

[rArm, rGoalMsg] = rosactionclient('r_arm_controller/joint_trajectory_action');
waitForServer(rArm);

Сообщение цели является trajectory_msgs/JointTrajectoryPoint сообщение. В каждой точке траектории должны быть указаны положения и скорости стыков.

disp(rGoalMsg)
  ROS JointTrajectoryGoal message with properties:

    MessageType: 'pr2_controllers_msgs/JointTrajectoryGoal'
     Trajectory: [1×1 JointTrajectory]

  Use showdetails to show the contents of the message
disp(rGoalMsg.Trajectory)
  ROS JointTrajectory message with properties:

    MessageType: 'trajectory_msgs/JointTrajectory'
         Header: [1×1 Header]
         Points: [0×1 JointTrajectoryPoint]
     JointNames: {0×1 cell}

  Use showdetails to show the contents of the message

Задайте имена соединений в соответствии с именами соединений роботов PR2. Обратите внимание, что имеется 7 соединений для управления. Чтобы узнать, какие соединения находятся PR2 правой руке, введите следующую команду в терминале виртуальной машины:

rosparam get /r_arm_controller/joints 
rGoalMsg.Trajectory.JointNames = {'r_shoulder_pan_joint', ...
                                   'r_shoulder_lift_joint', ...
                                   'r_upper_arm_roll_joint', ...
                                   'r_elbow_flex_joint',...
                                   'r_forearm_roll_joint',...
                                   'r_wrist_flex_joint',...
                                   'r_wrist_roll_joint'};

Создание уставок на траектории сустава рычага путем создания АФК trajectory_msgs/JointTrajectoryPoint сообщения и указание положения и скорости всех 7 соединений в виде вектора. Укажите время от начала как объект длительности ROS.

% Point 1
tjPoint1 = rosmessage('trajectory_msgs/JointTrajectoryPoint');
tjPoint1.Positions = zeros(1,7);
tjPoint1.Velocities = zeros(1,7);
tjPoint1.TimeFromStart = rosduration(1.0);

% Point 2
tjPoint2 = rosmessage('trajectory_msgs/JointTrajectoryPoint');
tjPoint2.Positions = [-1.0 0.2 0.1 -1.2 -1.5 -0.3 -0.5];
tjPoint2.Velocities = zeros(1,7);
tjPoint2.TimeFromStart = rosduration(2.0);

Создайте массив объектов с точками на траектории и назначьте его сообщению о цели. Отправить цель с помощью клиента действия. sendGoalAndWait Функция (ROS Toolbox) блокирует выполнение до тех пор, пока PR2 рука не завершит выполнение траектории

rGoalMsg.Trajectory.Points = [tjPoint1,tjPoint2];

sendGoalAndWait(rArm,rGoalMsg);

Создайте другой клиент действия для отправки команд в левую руку. Укажите имена соединений робота- PR2.

[lArm, lGoalMsg] = rosactionclient('l_arm_controller/joint_trajectory_action');
waitForServer(lArm);

lGoalMsg.Trajectory.JointNames = {'l_shoulder_pan_joint', ...
                                   'l_shoulder_lift_joint', ...
                                   'l_upper_arm_roll_joint', ...
                                   'l_elbow_flex_joint',...
                                   'l_forearm_roll_joint',...
                                   'l_wrist_flex_joint',...
                                   'l_wrist_roll_joint'};

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

tjPoint3 = rosmessage('trajectory_msgs/JointTrajectoryPoint');
tjPoint3.Positions = [1.0 0.2 -0.1 -1.2 1.5 -0.3 0.5];
tjPoint3.Velocities = zeros(1,7);
tjPoint3.TimeFromStart = rosduration(2.0);

lGoalMsg.Trajectory.Points = tjPoint3;

sendGoalAndWait(lArm,lGoalMsg);

Расчет обратной кинематики для конечного положения эффектора

В этом разделе рассчитывается траектория для соединений на основе требуемых положений концевого эффектора (PR2 правого захвата). inverseKinematics класс вычисляет все требуемые позиции соединения, которые могут быть отправлены как целевое сообщение траектории через клиент действия. A rigidBodyTree используется для определения параметров робота, формирования конфигураций и визуализации робота в MATLAB ®.

Выполните следующие шаги:

  • Получение текущего состояния PR2 робота из сети ROS и присвоение его rigidBodyTree объект для работы с роботом в MATLAB ®.

  • Определите цель конечного эффектора.

  • Визуализация конфигурации робота с использованием этих положений соединения для обеспечения правильного решения.

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

  • Отправьте траекторию расположения соединений на сервер действий АФК для команды фактического робота PR2.

Создание дерева жесткого тела в MATLAB

®

Загрузка робота- PR2 в качестве rigidBodyTree объект. Этот объект определяет все кинематические параметры (включая пределы соединения) робота.

pr2 = exampleHelperWGPR2Kinect;

Получить текущее состояние робота

Создайте абонента для получения совместных состояний от робота.

jointSub = rossubscriber('joint_states');

Получить текущее сообщение о совместном состоянии.

jntState = receive(jointSub);

Назначьте позиции соединения из сообщения о состоянии соединения полям структуры конфигурации, которая pr2 объект понимает.

jntPos = exampleHelperJointMsgToStruct(pr2,jntState);

Визуализация текущей конфигурации робота

Использовать show визуализация робота с заданным вектором положения соединения. Это должно соответствовать текущему состоянию робота.

show(pr2,jntPos)

ans = 
  Axes (Primary) with properties:

             XLim: [-2 2]
             YLim: [-2 2]
           XScale: 'linear'
           YScale: 'linear'
    GridLineStyle: '-'
         Position: [0.1300 0.1100 0.7750 0.8150]
            Units: 'normalized'

  Show all properties

Создание inverseKinematics объект из pr2 объект робота. Цель обратной кинематики состоит в том, чтобы вычислить углы соединения для PR2 рычага, который помещает захват (то есть концевой эффектор) в нужную позу. Последовательность концевых эффекторных поз в течение периода времени называется траекторией.

В этом примере мы будем управлять только руками робота. Поэтому мы устанавливаем жесткие ограничения на торс-подъемное соединение во время планирования.

torsoJoint = pr2.getBody('torso_lift_link').Joint;
idx = strcmp({jntPos.JointName}, torsoJoint.Name);
torsoJoint.HomePosition = jntPos(idx).JointPosition;
torsoJoint.PositionLimits = jntPos(idx).JointPosition + [-1e-3,1e-3];

Создать inverseKinematics объект.

ik = inverseKinematics('RigidBodyTree', pr2);

Отключите случайный перезапуск для обеспечения согласованности решений IK.

ik.SolverParameters.AllowRandomRestart = false;

Задайте веса для допусков для каждого компонента целевой позы.

weights = [0.25 0.25 0.25 1 1 1];
initialGuess = jntPos; % current jnt pos as initial guess

Укажите конечные эффекторные позы, связанные с задачей. В этом примере PR2 дойдем до банки на столе, возьмите банку, переместите ее в другое место и снова установите ее. Мы будем использовать inverseKinematics Изобретение относится к медицине и может быть использовано для планирования движений, плавно переходящих от одной концевой эффекторной позы к другой.

Укажите имя конечного эффектора.

endEffectorName = 'r_gripper_tool_frame';

Укажите начальную (текущую) позу банки и требуемую конечную позу.

TCanInitial = trvec2tform([0.7, 0.0, 0.55]);
TCanFinal = trvec2tform([0.6, -0.5, 0.55]);

Определите требуемое относительное преобразование между конечным эффектором и баночкой при захвате.

TGraspToCan = trvec2tform([0,0,0.08])*eul2tform([pi/8,0,-pi]);

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

  • Открыть захват

  • Переместить конечный эффектор из текущей позы в T1 чтобы робот чувствовал себя комфортно, чтобы начать захват

  • Переместить конечный эффектор из T1 кому TGrasp (готов к захвату)

  • Закройте захват и захватите банку

  • Переместить конечный эффектор из TGrasp кому T2 (подъемная банка в воздухе)

  • Переместить конечный эффектор из T2 кому T3 (перемещение может выровняться)

  • Переместить конечный эффектор из T3 кому TRelease (нижняя банка к поверхности стола и готова к освобождению)

  • Откройте захват и отпустите банку

  • Переместить конечный эффектор из TRelease кому T4 (уберите руку)

TGrasp = TCanInitial*TGraspToCan; % The desired end-effector pose when grasping the can
T1 = TGrasp*trvec2tform([0.,0,-0.1]);
T2 = TGrasp*trvec2tform([0,0,-0.2]);
T3 = TCanFinal*TGraspToCan*trvec2tform([0,0,-0.2]);
TRelease = TCanFinal*TGraspToCan; % The desired end-effector pose when releasing the can
T4 = TRelease*trvec2tform([-0.1,0.05,0]);

Фактическое движение будет определено numWaypoints последовательно соединяют позиции и передают роботу через клиент простого действия АФК. Эти конфигурации будут выбраны с помощью inverseKinematics объект таким образом, что концевая эффекторная поза интерполируется из начальной позы в конечную позу.

Выполнение движения

Укажите последовательность движений.

motionTask = {'Release', T1, TGrasp, 'Grasp', T2, T3, TRelease, 'Release', T4};

Выполнить каждую задачу, указанную в motionTask один за другим. Отправка команд с использованием указанных вспомогательных функций.

for i = 1: length(motionTask)
    
    if strcmp(motionTask{i}, 'Grasp')
        exampleHelperSendPR2GripperCommand('right',0.0,1000,false); 
        continue
    end
    
    if strcmp(motionTask{i}, 'Release')
        exampleHelperSendPR2GripperCommand('right',0.1,-1,true);
        continue
    end  
    
    Tf = motionTask{i};
    % Get current joint state
    jntState = receive(jointSub);
    jntPos = exampleHelperJointMsgToStruct(pr2, jntState);
    
    T0 = getTransform(pr2, jntPos, endEffectorName);  
    
    % Interpolating between key waypoints
    numWaypoints = 10;
    [s, sd, sdd, tvec] = trapveltraj([0 1], numWaypoints, 'AccelTime', 0.4); % Relatively slow ramp-up to top speed
    TWaypoints = transformtraj(T0, Tf, [0 1], tvec, 'TimeScaling', [s; sd; sdd]); % end-effector pose waypoints
    jntPosWaypoints = repmat(initialGuess, numWaypoints, 1); % joint position waypoints
    
    rArmJointNames = rGoalMsg.Trajectory.JointNames;
    rArmJntPosWaypoints = zeros(numWaypoints, numel(rArmJointNames));
    
    % Calculate joint position for each end-effector pose waypoint using IK
    for k = 1:numWaypoints
        jntPos = ik(endEffectorName, TWaypoints(:,:,k), weights, initialGuess);
        jntPosWaypoints(k, :) = jntPos;
        initialGuess = jntPos;
        
        % Extract right arm joint positions from jntPos
        rArmJointPos = zeros(size(rArmJointNames));
        for n = 1:length(rArmJointNames)
            rn = rArmJointNames{n};
            idx = strcmp({jntPos.JointName}, rn);
            rArmJointPos(n) = jntPos(idx).JointPosition;
        end  
        rArmJntPosWaypoints(k,:) = rArmJointPos'; 
    end
    
    % Time points corresponding to each waypoint
    timePoints = linspace(0,3,numWaypoints);
        
    % Estimate joint velocity trajectory numerically
    h = diff(timePoints); h = h(1);
    jntTrajectoryPoints = arrayfun(@(~) rosmessage('trajectory_msgs/JointTrajectoryPoint'), zeros(1,numWaypoints)); 
    [~, rArmJntVelWaypoints] = gradient(rArmJntPosWaypoints, h);
    for m = 1:numWaypoints
        jntTrajectoryPoints(m).Positions = rArmJntPosWaypoints(m,:);
        jntTrajectoryPoints(m).Velocities = rArmJntVelWaypoints(m,:);
        jntTrajectoryPoints(m).TimeFromStart = rosduration(timePoints(m));
    end
    
    % Visualize robot motion and end-effector trajectory in MATLAB(R)
    hold on
    for j = 1:numWaypoints
        show(pr2, jntPosWaypoints(j,:),'PreservePlot', false);
        exampleHelperShowEndEffectorPos(TWaypoints(:,:,j));
        drawnow;
        pause(0.1);
    end
    
    % Send the right arm trajectory to the robot
    rGoalMsg.Trajectory.Points = jntTrajectoryPoints;
    sendGoalAndWait(rArm, rGoalMsg);

end

Завершить

Переместите руку назад в исходное положение.

exampleHelperSendPR2GripperCommand('r',0.0,-1)
rGoalMsg.Trajectory.Points = tjPoint2;
sendGoal(rArm, rGoalMsg);

Звонить rosshutdown для отключения сети АФК и отключения от робота.

rosshutdown
Shutting down global node /matlab_global_node_03004 with NodeURI http://192.168.116.1:64988/