youbot_moveit_teleop.cpp
Go to the documentation of this file.
00001 #include <iostream>
00002 #include <assert.h>
00003 #include "ros/ros.h"
00004 #include <stdio.h>
00005 #include <unistd.h>
00006 #include <termios.h>
00007 #include "std_msgs/String.h"
00008 #include "visualization_msgs/Marker.h"
00009 #include "tf/transform_datatypes.h"
00010 #include "tf/transform_listener.h"
00011 #include "moveit_msgs/CollisionObject.h"
00012 #include "moveit_msgs/PlanningScene.h"
00013 #include <moveit/planning_scene/planning_scene.h>
00014 #include <moveit/collision_detection/world.h>
00015 #include "geometry_msgs/Pose.h"
00016 #include "shape_msgs/SolidPrimitive.h"
00017 #include "control_msgs/FollowJointTrajectoryActionGoal.h"
00018 #include "boost/thread.hpp"
00019 
00020 #include <moveit/move_group_interface/move_group.h>
00021 
00022 volatile bool trajectory_complete = false;
00023 volatile char cancel = '0';
00024 std::string goal_string = "0";
00025 //planning_scene::PlanningScene* current_scene = NULL;
00026 
00027 
00028 using namespace std;
00029 
00030 void trajectory_execution(move_group_interface::MoveGroup *g, move_group_interface::MoveGroup::Plan *plan)
00031 {
00032   trajectory_complete = g->execute(*plan);
00033 }
00034 
00035 void goal_callback(const control_msgs::FollowJointTrajectoryActionGoal::ConstPtr& msg)
00036 {
00037   goal_string = msg->goal_id.id;
00038 }
00039 
00040 /*
00041 void planning_scene_callback(const moveit_msgs::PlanningScene::ConstPtr& msg)
00042 {
00043   current_scene.clone(msg);
00044 }
00045 
00046 
00047 void clear_scene()
00048 {
00049   moveit_msgs::PlanningScene cleared_scene(current_scene);
00050 
00051   
00052   //  I can show you the world 
00053   //  Shining, shimmering, splendid 
00054   //  Tell me, princess, now when did 
00055   //  You last let your heart decide?
00056 
00057   //  I can open your eyes 
00058   //  Take you wonder by wonder 
00059   //  Over, sideways and under 
00060   //  On a magic carpet ride
00061 
00062   cleared_scene = current_scene;
00063 
00064   //A whole new wooooooooooooorld!
00065   collision_detection::World new_world;
00066   
00067   //A new fantastic point of view!
00068   cleared_scene.world = new_world;
00069 }
00070 */
00071 
00072 char getch(void)
00073 {
00074         char ch;
00075         struct termios oldt;
00076         struct termios newt;
00077         tcgetattr(STDIN_FILENO, &oldt); /*store old settings */
00078         newt = oldt; /* copy old settings to new settings */
00079         newt.c_lflag &= ~(ICANON | ECHO); /* make one change to old settings in new settings */
00080         tcsetattr(STDIN_FILENO, TCSANOW, &newt); /*apply the new settings immediately */
00081         ch = getchar(); /* standard getchar call */
00082         tcsetattr(STDIN_FILENO, TCSANOW, &oldt); /*reapply the old settings */
00083         return ch; /*return received char */
00084 }
00085 
00086 void getch_check()
00087 {
00088   cancel = '0';
00089   while(cancel != 'c')
00090   {
00091     boost::this_thread::interruption_point();
00092     cancel = getch();
00093   }
00094 }
00095 
00096 int main(int argc, char **argv)
00097 {
00098   ros::init(argc, argv, "youbot_moveit_teleop", ros::init_options::AnonymousName);
00099   // start a ROS spinning thread
00100   ros::AsyncSpinner spinner(1);
00101   ros::Rate r(10);
00102 
00103   ros::NodeHandle n;
00104 
00105   ros::Publisher marker_publisher = n.advertise<visualization_msgs::Marker>("goal_marker", 1);
00106   //ros::Publisher clear_publisher = n.advertise<moveit_msgs::CollisionObject>("/planning_scene", 1);
00107   ros::Publisher cancel_publisher = n.advertise<actionlib_msgs::GoalID>("/arm_1/arm_controller/follow_joint_trajectory/cancel", 1);
00108   ros::Subscriber goal_listener = n.subscribe("/arm_1/arm_controller/follow_joint_trajectory/goal",1,goal_callback);
00109   //ros::Subscriber planning_scene_listener = n.subscribe("/planning_scene",1,planning_scene_callback);
00110 
00111   tf::TransformListener tf_listener;
00112 
00113   cout << "\nStarting youbot_moveit_teleop..." << endl;
00114   spinner.start();
00115 
00116   cout << "Connecting to move_group node for youbot arm..." << endl;
00117   // this connecs to a running instance of the move_group node
00118   move_group_interface::MoveGroup group("arm");
00119 
00120   //group.setEndEffector("gripper_eef");
00121   //group.setEndEffectorLink("arm_link_5");
00122 
00123   std::string eef_link = group.getEndEffectorLink();
00124   std::string eef = group.getEndEffector();
00125 
00126   vector<string> states;
00127 
00128   robot_model::RobotModel temp = *(*group.getCurrentState()).getRobotModel();
00129 
00130   (*temp.getJointModelGroup("arm")).getKnownDefaultStates(states);
00131 
00132   //temp.robot_model::RobotModel::~RobotModel();
00133 
00134   cout << "\nEnd Effector Link for this group is: " << eef_link << endl;
00135   cout << "\nEnd Effector for this group is: " << eef << endl;
00136 
00137   double tolerance = .05;
00138   double orientationtolerance = 3.141592654;
00139   double positiontolerance = 0.05;
00140 
00141   //cout << "Setting goal tolerance";
00142   group.setGoalTolerance(tolerance);
00143   //group.setGoalOrientationTolerance(orientationtolerance);
00144   //group.setGoalPositionTolerance(positiontolerance);
00145 
00146   while(ros::ok())
00147   {
00148 
00149     visualization_msgs::Marker goalmarker;
00150     goalmarker.header.frame_id = "/odom";
00151     goalmarker.id = 0;
00152     goalmarker.type = goalmarker.MESH_RESOURCE;
00153     goalmarker.action = goalmarker.ADD;
00154     goalmarker.scale.x = 1;
00155     goalmarker.scale.y = 1;
00156     goalmarker.scale.z = 1;
00157     goalmarker.pose.position.x = 0;
00158     goalmarker.pose.position.y = 0;
00159     goalmarker.pose.position.z = 0;
00160     goalmarker.color.r = 0;
00161     goalmarker.color.g = 1;
00162     goalmarker.color.b = 0;
00163     goalmarker.color.a = 1;
00164     goalmarker.mesh_resource = "package://youbot_description/meshes/youbot_gripper/palm.dae";
00165 
00166 
00167     cout << "\nSetting starting position to current position..." << endl;
00168     group.setStartStateToCurrentState();  //Sets the starting state for the move_group to be the current state of the robot
00169     
00170     cout << "Select mode of control:\n\t1)\tTarget specific point\n\t2)\tControlled Marker Teleop\n\t3)\tJoint Poses\n\t4)\tExit" << endl;
00171     
00172     int choose = 0;
00173 
00174     cin >> choose;
00175 
00176     double xposition = 0;
00177     double yposition = 0;
00178     double zposition = 0;
00179 
00180     double roll = 0;
00181     double pitch = 0;
00182     double yaw = 0;
00183 
00184     geometry_msgs::Pose new_pose;
00185 
00186     if(choose == 1)
00187     {
00188       cout << "\n---------------------------------------------------------------------" << endl;
00189 
00190       cout << "Is your target frame relative to the arm or to the global frame (/odom)?\n\t1)\tarm\n\t2)\todom" << endl;
00191 
00192       int frame = 0;
00193 
00194       cin >> frame;
00195 
00196       cout << "\nPlease provide an x,y, and z position that the arm will move towards." << endl;
00197 
00198       cout << "\nPlease enter an x position for the arm: ";
00199       cin >> xposition; //The user-provided x-position for the end-effector
00200       cout << "Please enter a y position for the arm: ";
00201       cin >> yposition; //The user-provided y-position for the end-effector
00202       cout << "Please enter a z position for the arm: ";
00203       cin >> zposition; //The user-provided z-position for the end-effector
00204       cout << "\n\nYou chose the point (" << xposition << ", " << yposition << ", " << zposition << ") ";
00205 
00206       cout << "\nPlease provide a roll,pitch, and yaw orientation that the arm will move towards." << endl;
00207 
00208       cout << "\nPlease enter a roll for the arm: ";
00209       cin >> roll; //The user-provided x-position for the end-effector
00210       cout << "Please enter a pitch for the arm: ";
00211       cin >> pitch; //The user-provided y-position for the end-effector
00212       cout << "Please enter a yaw for the arm: ";
00213       cin >> yaw; //The user-provided z-position for the end-effector
00214       cout << "\n\nYou chose the point (" << xposition << ", " << yposition << ", " << zposition << ") with orientation (" << roll << ", " << pitch << ", " << yaw << ") ";
00215 
00216       new_pose.position.x = xposition;
00217       new_pose.position.y = yposition;
00218       new_pose.position.z = zposition;
00219 
00220       new_pose.orientation.x = tf::createQuaternionFromRPY(roll, pitch, yaw).getAxis().x();
00221       new_pose.orientation.y = tf::createQuaternionFromRPY(roll, pitch, yaw).getAxis().y();
00222       new_pose.orientation.z = tf::createQuaternionFromRPY(roll, pitch, yaw).getAxis().z();
00223       new_pose.orientation.w = tf::createQuaternionFromRPY(roll, pitch, yaw).getAxis().w();
00224 
00225       if(frame == 1)
00226       {     
00227         cout << "relative to the arm." << endl;
00228         ROS_INFO("Transforming arm coordinate frame to global (odom) coordinate frame.");
00229 
00230         tf::StampedTransform arm_relative_to_odom;
00231 
00232         try
00233         {
00234           tf_listener.lookupTransform("arm_link_0", "/odom",ros::Time(0), arm_relative_to_odom);
00235         }
00236         catch(tf::TransformException ex)
00237         {
00238           ROS_ERROR("%s",ex.what());
00239         }
00240  
00241         tf::Transform point_relative_to_odom;
00242 
00243         tf::Transform point_relative_to_arm;
00244         tf::Vector3 point_tf_origin;
00245       
00246         point_tf_origin.setX(xposition);
00247         point_tf_origin.setY(yposition);
00248         point_tf_origin.setZ(zposition);
00249 
00250         point_relative_to_arm.setOrigin(point_tf_origin);
00251     
00252         point_relative_to_odom = point_relative_to_arm * arm_relative_to_odom;
00253 
00254         xposition = point_relative_to_odom.getOrigin().getX();
00255         yposition = point_relative_to_odom.getOrigin().getY();
00256         zposition = point_relative_to_odom.getOrigin().getZ();
00257       }
00258       if(frame == 2)
00259       {
00260         cout << "relative to the global (odom) coordinate frame." << endl;
00261       }
00262       if((frame != 1)&&(frame != 2))
00263       {
00264         cout << "." << endl;
00265         ROS_WARN("Invalid frame provided.  Defaulting to global (odom) coordinate frame.");
00266       }
00267 
00268       goalmarker.pose.position.x = xposition;
00269       goalmarker.pose.position.y = yposition;
00270       goalmarker.pose.position.z = zposition;
00271 
00272       marker_publisher.publish(goalmarker);
00273 
00274     } //END OF CHOICE 1/////////////////////////////////////////////////
00275 
00276 
00277 
00278 
00279 
00280     if(choose == 2)
00281     {
00282       cout << "Generating initial marker at end effector." << endl;
00283       
00284       tf::StampedTransform tf_odom_gripper;
00285 
00286       try
00287       {
00288         tf_listener.lookupTransform("/odom","gripper_palm_link",ros::Time(0), tf_odom_gripper);
00289       }
00290       catch(tf::TransformException ex)
00291       {
00292         ROS_ERROR("%s",ex.what());
00293       }
00294 
00295       goalmarker.pose.position.x = tf_odom_gripper.getOrigin().getX();
00296       goalmarker.pose.position.y = tf_odom_gripper.getOrigin().getY();
00297       goalmarker.pose.position.z = tf_odom_gripper.getOrigin().getZ();
00298   
00299       //goalmarker.pose = goalmarker.pose * transform;
00300 
00301       cout << "To move the target marker along the x-axis, press a/d.\nTo move the target marker along the y-axis, press w/s.\nTo move the target marker along the z-axis, press t/g.\nTo confirm your target location, press 'o'." << endl;
00302 
00303       char keyboardInput = '0';
00304 
00305       while((keyboardInput != 'o')&&ros::ok())
00306       {
00307         keyboardInput = getch();
00308         
00309         if(keyboardInput == 'a')
00310           goalmarker.pose.position.x += 0.01;
00311         if(keyboardInput == 'd')
00312           goalmarker.pose.position.x -= 0.01;
00313         if(keyboardInput == 'w')
00314           goalmarker.pose.position.y += 0.01;
00315         if(keyboardInput == 's')
00316           goalmarker.pose.position.y -= 0.01;
00317         if(keyboardInput == 't')
00318           goalmarker.pose.position.z += 0.01;
00319         if(keyboardInput == 'g')
00320           goalmarker.pose.position.z -= 0.01;
00321 
00322         marker_publisher.publish(goalmarker);
00323       }
00324 
00325       tf::Transform goal_tf;
00326       tf::Transform tf_arm_goalmarker;
00327 
00328       tf::Vector3 goal_tf_origin;
00329     
00330       goal_tf_origin.setX(goalmarker.pose.position.x);
00331       goal_tf_origin.setY(goalmarker.pose.position.y);
00332       goal_tf_origin.setZ(goalmarker.pose.position.z);
00333 
00334       goal_tf.setOrigin(goal_tf_origin);
00335 
00336       tf::StampedTransform tf_arm_odom;
00337 
00338       try
00339       {
00340         tf_listener.lookupTransform("arm_link_0", "/odom",ros::Time(0), tf_arm_odom);
00341       }
00342       catch(tf::TransformException ex)
00343       {
00344         ROS_ERROR("%s",ex.what());
00345       }
00346 
00347       //arm->goal         //arm->odom       //odom->goal
00348       tf_arm_goalmarker = tf_arm_odom  *  goal_tf;
00349 
00350       double goalXToArmX = tf_arm_goalmarker.getOrigin().getX();
00351       double goalYToArmY = tf_arm_goalmarker.getOrigin().getY();
00352       double goalZToArmZ = tf_arm_goalmarker.getOrigin().getZ();
00353 
00354       cout << "Target selected: (" << goalXToArmX << ", " << goalYToArmY << ", " << goalZToArmZ << ")" << endl;
00355 
00356       xposition = goalmarker.pose.position.x;
00357       yposition = goalmarker.pose.position.y;
00358       zposition = goalmarker.pose.position.z;
00359     } //END OF CHOICE 2/////////////////////////////////////////////////////
00360 
00361 
00362 
00363 
00364     if(choose == 3)
00365     {
00366       /*
00367       
00368       ros::spinOnce();
00369       
00370       clear_scene();
00371 
00372       clear_publisher.publish(cleared_scene);
00373       */      
00374       
00375       /*
00376       moveit_msgs::CollisionObject TheApocalypse;
00377 
00378       TheApocalypse.id = "Barbra Streisand";
00379       TheApocalypse.operation = TheApocalypse.ADD;
00380       TheApocalypse.header.stamp = ros::Time::now();
00381       TheApocalypse.header.frame_id = "/odom";
00382 
00383       shape_msgs::SolidPrimitive boom;
00384 
00385       boom.type = boom.BOX;
00386       boom.dimensions.resize(3);
00387       boom.dimensions[0] = 10000;
00388       boom.dimensions[1] = 10000;
00389       boom.dimensions[2] = 10000;
00390 
00391       TheApocalypse.primitives.push_back(boom);
00392 
00393       geometry_msgs::Pose ground_zero;
00394 
00395       TheApocalypse.primitive_poses.push_back(ground_zero);
00396 
00397       clear_publisher.publish(TheApocalypse);
00398       */
00399 
00400       //group.pick("object_3");
00401 
00402       //continue;
00403 
00404       /*
00405       cout << "All remembered joint states: " << endl;
00406         
00407       for( map< string, vector< double > >::const_iterator ii= group.getRememberedJointValues().begin(); ii!= group.getRememberedJointValues().end(); ++ii)
00408       {
00409         cout << "\t" << (*ii).first << endl;
00410         for(int j = 0; j < (*ii).second.size(); j++)
00411         {
00412           cout << "\t\t\t" << (*ii).second.at(j) << endl;
00413         }
00414       }
00415       
00416       cout << "Current State is: \n" << group.getCurrentState();
00417       
00418       continue;     
00419       */
00420  
00421       cout << "Joint Pose Target Names: " << endl;
00422 
00423       for(vector<string>::iterator i= states.begin(); i!= states.end(); ++i)
00424       {
00425         cout << "\t" << (*i) << endl;
00426       }        
00427 
00428       string target;
00429 
00430       cout << "Specify name of joint pose target to reach: ";
00431       cin >> target;
00432       if(!group.setNamedTarget(target))
00433       {
00434         ROS_ERROR("\nInvalid pose name provided.  Please try again.");
00435         //temp.robot_model::RobotModel::~RobotModel();
00436         continue;
00437       }
00438     }
00439 
00440     if(choose == 4)
00441     {
00442       cout << "Exiting...";
00443       break;
00444     }
00445 
00446     if(choose != 3)
00447     {
00448       cout << "Setting Position target to the provided location: (" << xposition << ", " << yposition << ", " << zposition << ") with orientation: (" << roll << ", " << pitch<< ", " << yaw << ")" << endl;
00449 
00450       //Sets the target position for the move_group to the user-sepcified location
00451       group.setPoseTarget(new_pose);
00452      
00453       cout << "\nPose target is: \n" << group.getPoseTarget(eef).pose << endl;
00454     }
00455     cout << "\n\t\tJoint targets are:\tCurrent joint values are:" << endl;
00456     for(int i = 0; i < group.getJointValueTarget().getJointNames().size(); i++)
00457     {
00458       robot_state::JointState j = *group.getJointValueTarget().getJointStateVector().at(i);
00459 
00460       cout << group.getJointValueTarget().getJointNames()[i] << ":  " << j.getVariableValues().back() << "\t\t\t" << group.getCurrentJointValues().at(i) << endl;
00461      
00462     }
00463 
00464     cout << "\n";
00465 
00466     //Plan a motion path to the user-provided position
00467     move_group_interface::MoveGroup::Plan p;
00468 
00469     //If position is unreachable or a path is not possible, the user will be prompted to put in new information
00470     if(!group.plan(p))
00471     {
00472       ROS_ERROR("Destination is unreachable!");
00473       continue;
00474     }
00475 
00476     goalmarker.pose.position.x = xposition;
00477     goalmarker.pose.position.y = yposition;
00478     goalmarker.pose.position.z = zposition;
00479 
00480     marker_publisher.publish(goalmarker);
00481 
00482     cout << "Please press be sure to monitor the arm during its trajectory.  If you wish to cancel the trajectory during execution, please press 'c' during execution." << endl << "To start the trajectory, please press 's' and then enter: ";
00483 
00484     char enter = 0;
00485 
00486     cin >> enter;
00487 
00488     if(enter == 's')
00489     {
00490       trajectory_complete = false;
00491 
00492       cout << "~~Moving to requested position~~" << endl; 
00493 
00494       goal_string = "0";
00495       //Execute will perform the trajectory.  It is non-blocking.
00496       boost::thread execute_thread(trajectory_execution, &group, &p);
00497 
00498       //cout << "Am I really non-blocking?" << endl;
00499       boost::thread read_cancel(getch_check);
00500 
00501       while(ros::ok())
00502       {
00503         ros::spinOnce();
00504         //Hitting 'c' mid trajectory will cancel the current trajectory
00505         if(cancel == 'c')
00506         {
00507           actionlib_msgs::GoalID g_id;
00508           g_id.id = goal_string;
00509 
00510           cancel_publisher.publish(g_id);
00511           cout << "Canceled the current trajectory!" << endl;
00512           cout << "Setting starting position to current position..." << endl;
00513     group.setStartStateToCurrentState();  //Sets the starting state for the move_group to be the current state of the robot
00514           read_cancel.join();
00515           break;
00516         }
00517         
00518         //ros::spinOnce();
00519 
00520         if(trajectory_complete)
00521         {
00522           ROS_INFO("Trajectory completed.");
00523           execute_thread.join();
00524           read_cancel.interrupt();
00525           break;
00526         }
00527       }
00528     }
00529 
00530     cout << "Hit Control + C to exit." << endl;
00531     r.sleep();
00532   }
00533 }


youbot_teleop
Author(s): Russell Toris , Graylin Trevor Jay
autogenerated on Mon Oct 6 2014 09:08:50