В этом примере показано, как отправить команды роботам-манипуляторам в MATLAB ®. Команды положения соединения передаются через клиент действия ROS через сеть ROS. Этот пример также показывает, как вычислить положения соединений для желаемого положения концевого эффектора. Древо твёрдого тела задает геометрию робота и ограничения в соединениях, которые используются с обратной кинематикой, чтобы получить положения соединений робота. Затем можно отправить эти положения соединений как траекторию, чтобы заставить робота двигаться.
Нерест PR2 в простое окружение (только с таблицей и коксовой банкой) в Gazebo Simulator. Следуйте шагам в запуске с Gazebo и моделируемым 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. Траектории соединений задаются вручную для каждой руки и отправляются как отдельные сообщения о целях через отдельные клиенты действий.
Создайте простой клиент действия 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'};Создайте уставки в траектории соединения рычагов путем создания ROS 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 правого захвата). The inverseKinematics класс вычисляет все необходимые положения соединений, которые могут быть отправлены в качестве сообщения цели траектории через клиент действий. A rigidBodyTree объект используется для определения параметров робота, генерации строений и визуализации робота в MATLAB ®.
Выполните следующие шаги:
Получите текущее состояние робота- PR2 из сети ROS и присвойте его rigidBodyTree объект для работы с роботом в MATLAB ®.
Задайте конечное положение цели эффектора.
Визуализируйте строение робота, используя эти положения соединений, чтобы гарантировать правильное решение.
Используйте обратную кинематику, чтобы вычислить положения соединений из конечных положений цели.
Отправьте траекторию положений соединений на сервер действий ROS, чтобы выполнить команду фактического робота- PR2.
Загрузите PR2 робота как rigidBodyTree объект. Этот объект определяет все кинематические параметры (включая пределы соединений) робота.
pr2 = exampleHelperWGPR2Kinect;
Создайте абонента, чтобы получить совместные состояния от робота.
jointSub = rossubscriber('joint_states');Получите текущее сообщение о совместном состоянии.
jntState = receive(jointSub);
Присвойте положения соединений из сообщения о состояниях соединений полям struct строения, которую 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Задайте положения end-effector, связанные с задачей. В этом примере PR2 доберемся до баллончика на таблице, схватите баллончик, переместите его в другое место и снова установите его вниз. Мы будем использовать inverseKinematics объект для планирования движений, которые плавно переходят от одного концевого эффекторного положения к другому.
Задайте имя конечного эффектора.
endEffectorName = 'r_gripper_tool_frame';Задайте начальное (текущее) положение банки и желаемое окончательное положение.
TCanInitial = trvec2tform([0.7, 0.0, 0.55]); TCanFinal = trvec2tform([0.6, -0.5, 0.55]);
Задайте требуемое относительное преобразование между end-effector и банкой при захвате.
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 положения соединений в последовательности и отправка роботу через клиент простого действия ROS. Эти строения будут выбраны с помощью 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 для завершения работы сети ROS и отсоединения от робота.
rosshutdown
Shutting down global node /matlab_global_node_03004 with NodeURI http://192.168.116.1:64988/