ik_test.cpp
Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <time.h>
00004 #include <ros/ros.h>
00005 #include <kinematics_msgs/GetKinematicTreeInfo.h>
00006 #include <kinematics_msgs/GetPositionIK.h>
00007 #include <kinematics_msgs/GetPositionFK.h>
00008 #include <vector>
00009 
00010 #define IK_NEAR 1e-4
00011 #define IK_NEAR_TRANSLATE 1e-5
00012 
00013 static const std::string ARM_FK_NAME = "/pr2_ik_right_arm/get_fk";
00014 static const std::string ARM_IK_NAME = "/pr2_ik_right_arm/get_ik";
00015 static const std::string ARM_QUERY_NAME = "/pr2_ik_right_arm/get_kinematic_tree_info";
00016 
00017 
00018 double gen_rand(double min, double max)
00019 {
00020   int rand_num = rand()%100+1;
00021   double result = min + (double)((max-min)*rand_num)/101.0;
00022   return result;
00023 }
00024 
00025 bool NOT_NEAR(const double &v1, const double &v2, const double &NEAR)
00026 {
00027    if(fabs(v1-v2) > NEAR)
00028       return true;
00029    return false;
00030 }
00031 
00032 
00033 class TestIKandFK{
00034 
00035 private:
00036   ros::NodeHandle node;
00037   ros::ServiceClient ik_client;
00038   ros::ServiceClient fk_client;
00039   ros::ServiceClient query_client;
00040 
00041 public:
00042   TestIKandFK(){
00043 
00044     //create a client function for the IK, FK, and joint query services
00045     ik_client = node.serviceClient<kinematics_msgs::GetPositionIK>
00046       (ARM_IK_NAME, true);    
00047     fk_client = node.serviceClient<kinematics_msgs::GetPositionFK>
00048       (ARM_FK_NAME, true);
00049     query_client = node.serviceClient<kinematics_msgs::GetKinematicTreeInfo>
00050       (ARM_QUERY_NAME, true);
00051 
00052     //wait for the various services to be ready
00053     ROS_INFO("Waiting for services to be ready");
00054     ros::service::waitForService(ARM_IK_NAME);
00055     ros::service::waitForService(ARM_FK_NAME);
00056     ros::service::waitForService(ARM_QUERY_NAME);
00057     ROS_INFO("Services ready");
00058   }
00059 
00060   //run inverse kinematics on a PoseStamped (7-dof pose 
00061   //(position + quaternion orientation) + header specifying the 
00062   //frame of the pose)
00063   //tries to stay close to double start_angles[7]
00064   //returns the solution angles in double solution[7] 
00065   bool run_ik(geometry_msgs::PoseStamped pose, double start_angles[7], 
00066               double solution[7], std::string link_name){
00067 
00068     kinematics_msgs::GetPositionIK::Request  ik_request;
00069     kinematics_msgs::GetPositionIK::Response ik_response;  
00070  
00071     ik_request.ik_request.ik_seed_state.joint_state.name.push_back("r_shoulder_pan_joint");
00072     ik_request.ik_request.ik_seed_state.joint_state.name.push_back("r_shoulder_lift_joint");
00073     ik_request.ik_request.ik_seed_state.joint_state.name.push_back("r_upper_arm_roll_joint");
00074     ik_request.ik_request.ik_seed_state.joint_state.name.push_back("r_elbow_flex_joint");
00075     ik_request.ik_request.ik_seed_state.joint_state.name.push_back("r_forearm_roll_joint");
00076     ik_request.ik_request.ik_seed_state.joint_state.name.push_back("r_wrist_flex_joint");
00077     ik_request.ik_request.ik_seed_state.joint_state.name.push_back("r_wrist_roll_joint");
00078 
00079     ik_request.ik_request.ik_link_name = link_name; 
00080 
00081     ik_request.ik_request.pose_stamped = pose;
00082     ik_request.ik_request.ik_seed_state.joint_state.position.resize(7);
00083 
00084     for(int i=0; i<7; i++) ik_request.ik_request.ik_seed_state.joint_state.position[i] = start_angles[i];
00085 
00086     ROS_INFO("request pose: %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f", pose.pose.position.x, pose.pose.position.y, pose.pose.position.z, pose.pose.orientation.x, pose.pose.orientation.y, pose.pose.orientation.z, pose.pose.orientation.w);
00087 
00088     bool ik_service_call = ik_client.call(ik_request,ik_response);
00089     if(!ik_service_call){
00090       ROS_ERROR("IK service call failed!");  
00091       return 0;
00092     }
00093     for(int i=0; i<7; i++){
00094       solution[i] = ik_response.solution.joint_state.position[i];
00095     }
00096     ROS_INFO("solution angles: %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f", 
00097              solution[0],solution[1], solution[2],solution[3],
00098              solution[4],solution[5],solution[6]);
00099     ROS_INFO("IK service call succeeded");
00100     return 1;
00101   }
00102 
00103   //run forward kinematics on a set of 7 joint angles 
00104   bool run_fk(double angles[7], geometry_msgs::PoseStamped &return_pose, std::string link_name){
00105     int i;
00106     kinematics_msgs::GetPositionFK::Request  fk_request;
00107     kinematics_msgs::GetPositionFK::Response fk_response;
00108     fk_request.header.stamp = ros::Time::now();
00109     fk_request.header.frame_id = "base_link";
00110 
00111     fk_request.robot_state.joint_state.name.push_back("r_shoulder_pan_joint");
00112     fk_request.robot_state.joint_state.name.push_back("r_shoulder_lift_joint");
00113     fk_request.robot_state.joint_state.name.push_back("r_upper_arm_roll_joint");
00114     fk_request.robot_state.joint_state.name.push_back("r_elbow_flex_joint");
00115     fk_request.robot_state.joint_state.name.push_back("r_forearm_roll_joint");
00116     fk_request.robot_state.joint_state.name.push_back("r_wrist_flex_joint");
00117     fk_request.robot_state.joint_state.name.push_back("r_wrist_roll_joint");
00118 
00119     fk_request.fk_link_names.push_back(link_name);
00120 
00121     fk_request.robot_state.joint_state.position.resize(7);
00122     for(i=0; i<7; i++){
00123       fk_request.robot_state.joint_state.position[i] = angles[i];
00124     }
00125     bool success = fk_client.call(fk_request, fk_response);
00126     if(!success){
00127       ROS_INFO("FK call failed!");
00128       return 0;
00129     }
00130     return_pose = fk_response.pose_stamped[0];
00131     return 1;
00132   }
00133 
00134   //test the ik and fk functions
00135   bool run_test(){
00136     srand ( time(NULL) ); // initialize random seed
00137 
00138     // use IKQuery to get the min and max joint angles
00139     kinematics_msgs::GetKinematicTreeInfo::Request request;
00140     kinematics_msgs::GetKinematicTreeInfo::Response response;
00141     query_client.call(request, response);
00142     std::vector<double> min_limits, max_limits;
00143     for(int i=0; i<7; i++){
00144       min_limits.push_back(response.kinematic_tree_info.limits[i].min_position);
00145       max_limits.push_back(response.kinematic_tree_info.limits[i].max_position);
00146     }
00147 
00148     //run forward kinematics on a random set of joints to get 
00149     //a corresponding Cartesian pose
00150     double angles[7];
00151     for(int i=0; i<7; i++){
00152       angles[i] =  gen_rand(std::max(min_limits[i],-M_PI),
00153                             std::min(max_limits[i],M_PI));
00154     }
00155     geometry_msgs::PoseStamped fk_response;
00156     run_fk(angles, fk_response, "r_wrist_roll_link");
00157 
00158     //run inverse kinematics on the resulting Cartesian pose to get 
00159     //another set of joint angles that makes that pose
00160     double solutionangles[7];
00161     double startangles[7] = {0,0,0,0,0,0,0};
00162     bool success = 1;
00163     success = run_ik(fk_response, startangles, solutionangles, "r_wrist_roll_link");
00164     if(!success){
00165       ROS_INFO("IK call failed!\n");
00166       return 0;
00167     }
00168 
00169     //run forward kinematics on the resulting joint angles to see 
00170     //if they match the first Cartesian pose
00171     geometry_msgs::PoseStamped fk_response2;
00172     fk_response2.header.frame_id = "base_link";
00173     run_fk(solutionangles, fk_response2, "r_wrist_roll_link");
00174 
00175     //check to see if the two poses are pretty close to each other
00176     success = 1;
00177     if(NOT_NEAR(fk_response.pose.position.x,
00178                 fk_response2.pose.position.x,IK_NEAR_TRANSLATE) || 
00179        NOT_NEAR(fk_response.pose.position.y,
00180                 fk_response2.pose.position.y,IK_NEAR_TRANSLATE) ||
00181        NOT_NEAR(fk_response.pose.position.z,
00182                 fk_response2.pose.position.z,IK_NEAR_TRANSLATE) ||
00183 
00184        NOT_NEAR(fk_response.pose.orientation.x,
00185                 fk_response2.pose.orientation.x,IK_NEAR) ||
00186        NOT_NEAR(fk_response.pose.orientation.y,
00187                 fk_response2.pose.orientation.y,IK_NEAR) ||
00188        NOT_NEAR(fk_response.pose.orientation.z,
00189                 fk_response2.pose.orientation.z,IK_NEAR) ||
00190        NOT_NEAR(fk_response.pose.orientation.w,
00191                 fk_response2.pose.orientation.w,IK_NEAR))
00192       {
00193         ROS_INFO("IK solution incorrect\n");
00194         ROS_INFO("ik request: %f, %f, %f :: %f %f %f %f",
00195                  fk_response.pose.position.x,
00196                  fk_response.pose.position.y,
00197                  fk_response.pose.position.z,
00198                  fk_response.pose.orientation.x,
00199                  fk_response.pose.orientation.y,
00200                  fk_response.pose.orientation.z,
00201                  fk_response.pose.orientation.w);
00202         ROS_INFO("fk response: %f, %f, %f :: %f %f %f %f\n",
00203                  fk_response2.pose.position.x,
00204                  fk_response2.pose.position.y,
00205                  fk_response2.pose.position.z,
00206                  fk_response2.pose.orientation.x,
00207                  fk_response2.pose.orientation.y,
00208                  fk_response2.pose.orientation.z,
00209                  fk_response2.pose.orientation.w);
00210         success = 0;
00211       }
00212     if(success){
00213       ROS_INFO("IK solution good\n");
00214     }
00215     else{
00216       ROS_INFO("IK solution bad\n");
00217     }
00218     return success;
00219   }
00220 
00221 };
00222 
00223 int main(int argc, char** argv){
00224 
00225   //init ROS node
00226   ros::init(argc, argv, "test_ik_and_fk");
00227 
00228   //make the class object
00229   TestIKandFK test_ik_and_fk = TestIKandFK();
00230 
00231   //run the test
00232   test_ik_and_fk.run_test();
00233 
00234   return 0;
00235 }
00236 


pr2_plugs_gazebo_demo
Author(s): John Hsu
autogenerated on Mon Jan 6 2014 12:04:30