В этом примере показано, как отправлять команды роботизированным манипуляторам в MATLAB ®. Команды совместного положения посылаются через клиент действий АФК по сети АФК. Этот пример также показывает, как вычислить положения соединения для желаемого положения концевого эффектора. Жесткое дерево тела определяет геометрию робота и зависимости соединения, которые используются с обратной кинематикой для получения положений соединения робота. Затем можно отправить эти позиции соединения в виде траектории, чтобы дать команду роботу двигаться.
Нерестить PR2 в простой среде (только со столом и коксовой баночкой) в Gazebo Simulator. Выполните шаги, описанные в разделе «Начало работы с беседкой и моделируемым TurtleBot (ROS Toolbox)», чтобы запустить Gazebo PR2 Simulator с рабочего стола виртуальной машины Ubuntu ®.

В экземпляре 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.
Загрузка робота- 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/