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
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
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 char getch(void)
00073 {
00074 char ch;
00075 struct termios oldt;
00076 struct termios newt;
00077 tcgetattr(STDIN_FILENO, &oldt);
00078 newt = oldt;
00079 newt.c_lflag &= ~(ICANON | ECHO);
00080 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
00081 ch = getchar();
00082 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
00083 return ch;
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
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
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
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
00118 move_group_interface::MoveGroup group("arm");
00119
00120
00121
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
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
00142 group.setGoalTolerance(tolerance);
00143
00144
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();
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;
00200 cout << "Please enter a y position for the arm: ";
00201 cin >> yposition;
00202 cout << "Please enter a z position for the arm: ";
00203 cin >> zposition;
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;
00210 cout << "Please enter a pitch for the arm: ";
00211 cin >> pitch;
00212 cout << "Please enter a yaw for the arm: ";
00213 cin >> yaw;
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 }
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
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
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 }
00360
00361
00362
00363
00364 if(choose == 3)
00365 {
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
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
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
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
00467 move_group_interface::MoveGroup::Plan p;
00468
00469
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
00496 boost::thread execute_thread(trajectory_execution, &group, &p);
00497
00498
00499 boost::thread read_cancel(getch_check);
00500
00501 while(ros::ok())
00502 {
00503 ros::spinOnce();
00504
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();
00514 read_cancel.join();
00515 break;
00516 }
00517
00518
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 }