В этом примере показано, как отправить команды в автоматизированные манипуляторы в MATLAB®. Объединенные команды положения отправляются через клиент действия ROS по сети ROS. Этот пример также показывает, как вычислить объединенные положения для желаемого положения исполнительного элемента конца. Дерево твердого тела задает геометрию робота и объединенные ограничения, который используется с инверсной кинематикой, чтобы получить положения соединения робота. Можно затем отправить эти объединенные позиции траектории, чтобы управлять, чтобы робот переместился.
Породите PR2 в простой среде (только с таблицей, и кокс может) в Средстве моделирования Gazebo. Выполните шаги в Начало работы с Gazebo и Симулированным TurtleBot (ROS Toolbox), чтобы запустить Gazebo PR2 Simulator
с рабочего стола виртуальной машины Ubuntu®.
В вашем экземпляре MATLAB на хосте - компьютере запустите следующие команды, чтобы инициализировать глобальный узел ROS в MATLAB и соединить с ведущим устройством ROS в виртуальной машине через ее IP-адрес ipaddress
. Замените '192.168.233.133' на IP-адрес своей виртуальной машины. Задайте порт в случае необходимости.
ipaddress = '192.168.233.133';
rosinit(ipaddress,11311);
Initializing global node /matlab_global_node_59258 with NodeURI http://192.168.233.1:57169/
В этой задаче вы отправляете объединенные траектории в руки 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] JointNames: {0×1 cell} Points: [0×1 JointTrajectoryPoint] 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) положения. 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, которая помещает механизм захвата (i.e. исполнительный элемент конца) в желаемом положении. Последовательность положений исполнительного элемента конца в течение времени называется траекторией.
В этом примере мы будем только управлять руками робота. Поэтому мы устанавливаем трудные границы соединения лифта туловища во время планирования.
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]);
Задайте ключ waypoints желаемой Декартовой траектории. Банка должна пройти эта траектория. Траектория может быть разбита можно следующим образом:
Откройте механизм захвата
Переместите исполнительный элемент конца от текущего положения до T1
так, чтобы робот чувствовал себя комфортно, чтобы инициировать схватывание
Переместите исполнительный элемент конца от T1
к TGrasp
(готовый схватить)
Закройте механизм захвата и захватите банку
Переместите исполнительный элемент конца от TGrasp
к T2
(лифт может в воздухе),
Переместите исполнительный элемент конца от T2
к T3
(перемещение может levelly),
Переместите исполнительный элемент конца от 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 = T3*trvec2tform([-0.1,0,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,true); 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; TWaypoints = exampleHelperSE3Trajectory(T0, Tf, numWaypoints); % 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_59258 with NodeURI http://192.168.233.1:57169/