Author: Alessandro Di Fava < alessandro.difava@pal-robotics.com >

Maintainer: Jordi Pages < jordi.pages@pal-robotics.com >

Support: tiago-support@pal-robotics.com

Source: https://github.com/pal-robotics/tiago_dual_tutorials.git

(!) Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags.

Planning in cartesian space

Description: UseMoveIt! to plan a joint trajectory in order to reach a given pose in cartesian space

Keywords: Motion planning, cartesian space, inverse kinematics

Tutorial Level: INTERMEDIATE

Next Tutorial: Planning with Octomap

plan_cartesian_title.jpg

Purpose

This tutorial shows how to use MoveIt! in order to move the end-effectors frame of TIAGo++ to a desired pose in cartesian space. An example is given in C++.

Pre-requisites

First make sure that the tutorials are properly installed along with the TIAGo++ simulation, as shown in the Tutorials Installation Section.

Execution

First open two consoles and source the public simulation workspace as follows:

  • cd ~/tiago_dual_public_ws
    source ./devel/setup.bash

Launching the simulation

In the first console launch the following simulation

  • roslaunch tiago_dual_gazebo tiago_dual_gazebo.launch public_sim:=true end_effector_left:=pal-gripper end_effector_right:=pal-gripper

Gazebo will show up with TIAGo++ with a 6-axis force/torque sensor in each wrist and the parallel gripper.

tiago++_gazebo_grippers.jpg

Wait until TIAGo++ has tucked its arm. Then you may proceed with the next steps.

Launching the nodes

Now we are going to run an example that will bring TIAGo++'s left end-effector frame, i.e. arm_left_tool_link, to the following cartesian space configuration with respect to /base_footprint:

  • x: 0.4
    y: 0.3
    z: 0.28
    Roll: -0.011
    Pitch: 1.57
    Yaw: 0.037

And an example that will bring TIAGo++'s right end-effector frame, i.e. arm_right_tool_link, to the following cartesian space configuration with respect to /base_footprint:

  • x: 0.4
    y: -0.3
    z: 0.28
    Roll: -0.011
    Pitch: 1.57
    Yaw: 0.037

which corresponds to the following pose as shown in rviz:

plan_cartesian_rviz.jpg

In order to safely reach such a cartesian goal the node plan_dual_arm_torso_ik included in tiago_dual_moveit_tutorial package and has to be called as follows for the left arm

  • rosrun tiago_dual_moveit_tutorial plan_dual_arm_torso_ik left 0.4 0.3 0.28 -0.011 1.57 0.037

After going to the home position:

rosrun play_motion run_motion home

Can also be run as follows for the right arm

  • rosrun tiago_dual_moveit_tutorial plan_dual_arm_torso_ik right 0.4 -0.3 0.28 -0.011 1.57 0.037

An example of plan executed by the node for the left arm is depicted in the following sequence of images:

plan_cart_2.jpg

plan_cart_3.jpg

plan_cart_4.jpg

Note that the final pose of /arm_left_tool_link is the desired one:

plan_cartesian_rviz_final.jpg

Here, instead, an example of plan executed by the node for the right arm is shown in the following sequence of images:

plan_cart_5.jpg

plan_cart_6.jpg

plan_cart_7.jpg

Inspecting the code

The code to implement such a node able to plan in cartesian space is shown below. Note that the key parts of the code are:

  • Choose a group of joints
  • Choose a planner and define the reference frame, i.e. /base_footprint in this case
  • Set desired pose of /arm_[left/right]_tool_link encoded in a geometry_msgs::PoseStamped

  • Give time to find a plan
  • Execute the plan if found
       1 // ROS headers
       2 #include <ros/ros.h>
       3 
       4 // MoveIt! headers
       5 #include <moveit/move_group_interface/move_group_interface.h>
       6 #include <tf/transform_broadcaster.h>
       7 
       8 // Std C++ headers
       9 #include <string>
      10 #include <vector>
      11 #include <map>
      12 
      13 int main(int argc, char** argv)
      14 {
      15   ros::init(argc, argv, "plan_dual_arm_torso_ik");
      16 
      17   if ( argc < 8 )
      18   {
      19     ROS_INFO(" ");
      20     ROS_INFO("\tUsage:");
      21     ROS_INFO(" ");
      22     ROS_INFO("\trosrun tiago_moveit_tutorial plan_dual_arm_torso_ik [left|right] x y z  r p y");
      23     ROS_INFO(" ");
      24     ROS_INFO("\twhere the list of arguments specify the target pose of /arm_[left|right]_tool_link expressed in /base_footprint");
      25     ROS_INFO(" ");
      26     return EXIT_FAILURE;
      27   }
      28 
      29   std::string arm_name = argv[1];
      30   geometry_msgs::PoseStamped goal_pose;
      31   goal_pose.header.frame_id = "base_footprint";
      32   goal_pose.pose.position.x = atof(argv[2]);
      33   goal_pose.pose.position.y = atof(argv[3]);
      34   goal_pose.pose.position.z = atof(argv[4]);
      35   goal_pose.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(atof(argv[5]), atof(argv[6]), atof(argv[7]));
      36 
      37   ros::NodeHandle nh;
      38   ros::AsyncSpinner spinner(1);
      39   spinner.start();
      40 
      41   std::vector<std::string> torso_arm_joint_names;
      42   //select group of joints
      43   std::string moveit_group = "arm_" + arm_name + "_torso";
      44   moveit::planning_interface::MoveGroupInterface group_arm_torso(moveit_group);
      45   //choose your preferred planner
      46   group_arm_torso.setPlannerId("SBLkConfigDefault");
      47   group_arm_torso.setPoseReferenceFrame("base_footprint");
      48   group_arm_torso.setPoseTarget(goal_pose);
      49 
      50   ROS_INFO_STREAM("Planning to move " <<
      51                   group_arm_torso.getEndEffectorLink() << " to a target pose expressed in " <<
      52                   group_arm_torso.getPlanningFrame());
      53 
      54   group_arm_torso.setStartStateToCurrentState();
      55   group_arm_torso.setMaxVelocityScalingFactor(1.0);
      56 
      57 
      58   moveit::planning_interface::MoveGroupInterface::Plan my_plan;
      59   //set maximum time to find a plan
      60   group_arm_torso.setPlanningTime(5.0);
      61   bool success = bool(group_arm_torso.plan(my_plan));
      62 
      63   if ( !success )
      64     throw std::runtime_error("No plan found");
      65 
      66   ROS_INFO_STREAM("Plan found in " << my_plan.planning_time_ << " seconds");
      67 
      68   // Execute the plan
      69   ros::Time start = ros::Time::now();
      70 
      71 
      72   moveit::planning_interface::MoveItErrorCode e = group_arm_torso.move();
      73   if (!bool(e))
      74     throw std::runtime_error("Error executing plan");
      75 
      76   ROS_INFO_STREAM("Motion duration: " << (ros::Time::now() - start).toSec());
      77 
      78   spinner.stop();
      79 
      80   return EXIT_SUCCESS;
      81 }
    

Note that when a plan is found and is executed with the following line of code

  72   moveit::planning_interface::MoveItErrorCode e = group_arm_torso.move();

The required control commands are sent to the arm and torso controllers through their Action interfaces:

  • /arm_left_controller/follow_joint_trajectory/goal
    /arm_right_controller/follow_joint_trajectory/goal
    /torso_controller/follow_joint_trajectory/goal

Note also the following line of code

  43   std::string moveit_group = "arm_" + arm_name + "_torso";

Here we are selecting the group of arm and torso related to the correspondent left or right arm torso group. There is also the possibility to select the both_arms_torso group where you can control arm_right, arm_left and torso contemporaneously.

Wiki: Robots/TIAGo++/Tutorials/MoveIt/Planning_cartesian_space (last edited 2023-03-06 15:17:00 by thomaspeyrucain)