00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <time.h>
00036 #include <ros/ros.h>
00037 #include <kinematics_msgs/GetPositionIK.h>
00038 #include <kinematics_msgs/GetPositionFK.h>
00039 #include <kinematics_msgs/GetKinematicSolverInfo.h>
00040 
00041 #include <gtest/gtest.h>
00042 
00043 #define IK_NEAR 1e-4
00044 #define IK_NEAR_TRANSLATE 1e-5
00045 
00046 static const std::string ARM_FK_NAME = "/pr2_right_arm_kinematics/get_fk";
00047 static const std::string ARM_IK_NAME = "/pr2_right_arm_kinematics/get_ik";
00048 static const std::string FK_SOLVER_INFO = "/pr2_right_arm_kinematics/get_fk_solver_info";
00049 static const std::string IK_SOLVER_INFO = "/pr2_right_arm_kinematics/get_ik_solver_info";
00050 
00051 static const int NUM_TESTS = 1000;
00052 
00053 double gen_rand(double min, double max)
00054 {
00055   int rand_num = rand()%100+1;
00056   double result = min + (double)((max-min)*rand_num)/101.0;
00057   return result;
00058 }
00059 
00060 bool NOT_NEAR(const double &v1, const double &v2, const double &NEAR)
00061 {
00062   if(fabs(v1-v2) > NEAR)
00063     return true;
00064   return false;
00065 }
00066 
00067 TEST(PR2ArmIKNode, queryKinematics)
00068 {
00069   ros::NodeHandle rh;
00070   ros::service::waitForService(FK_SOLVER_INFO);
00071   ros::ServiceClient query_client = rh.serviceClient<kinematics_msgs::GetKinematicSolverInfo>(FK_SOLVER_INFO);
00072 
00073   
00074   kinematics_msgs::GetKinematicSolverInfo::Request request;
00075   kinematics_msgs::GetKinematicSolverInfo::Response response;
00076   bool service_call = query_client.call(request, response);
00077   ASSERT_TRUE(service_call);
00078   ASSERT_TRUE(!response.kinematic_solver_info.link_names.empty());
00079   ASSERT_TRUE(!response.kinematic_solver_info.joint_names.empty());
00080   ros::shutdown();
00081 }
00082 
00083 TEST(PR2ArmIKNode, forwardKinematics)
00084 {
00085   ros::NodeHandle rh;
00086   ros::service::waitForService(FK_SOLVER_INFO);
00087   ros::service::waitForService(ARM_FK_NAME);
00088   ros::ServiceClient query_client = rh.serviceClient<kinematics_msgs::GetKinematicSolverInfo>(FK_SOLVER_INFO);
00089   ros::ServiceClient fk_client = rh.serviceClient<kinematics_msgs::GetPositionFK>(ARM_FK_NAME);
00090 
00091   
00092   kinematics_msgs::GetKinematicSolverInfo::Request request;
00093   kinematics_msgs::GetKinematicSolverInfo::Response response;
00094             
00095   bool service_call = query_client.call(request, response);
00096   ASSERT_TRUE(service_call);
00097   ASSERT_TRUE(!response.kinematic_solver_info.link_names.empty());
00098 
00099   int num_joints;
00100   std::vector<double> min_limits, max_limits;
00101   num_joints = (int) response.kinematic_solver_info.joint_names.size();
00102   for(int i=0; i< num_joints; i++)
00103   {
00104     min_limits.push_back(-M_PI);
00105     max_limits.push_back(M_PI);
00106   }
00107   
00108   kinematics_msgs::GetPositionFK::Request  fk_request;
00109   kinematics_msgs::GetPositionFK::Response fk_response;
00110   fk_request.header.frame_id = "torso_lift_link";
00111   fk_request.fk_link_names.resize(2);
00112   fk_request.fk_link_names[0] = "r_wrist_roll_link";
00113   fk_request.fk_link_names[1] = "r_elbow_flex_link";
00114   fk_request.robot_state.joint_state.position.resize(num_joints);
00115   fk_request.robot_state.joint_state.name = response.kinematic_solver_info.joint_names;
00116   for(int i=0; i< num_joints; i++)
00117   {
00118     fk_request.robot_state.joint_state.position[i] = gen_rand(min_limits[i],max_limits[i]);
00119   }
00120   bool fk_service_call = fk_client.call(fk_request, fk_response);
00121   EXPECT_TRUE(fk_service_call);
00122   ASSERT_TRUE(!fk_response.pose_stamped.empty());
00123   ASSERT_TRUE(fk_response.pose_stamped.size()==2);
00124   ASSERT_TRUE(fk_response.fk_link_names.size()==2);
00125   ros::shutdown();
00126 }
00127 
00128 TEST(PR2ArmIKNode, inverseKinematics)
00129 {
00130   srand ( time(NULL) ); 
00131   ros::NodeHandle rh;
00132   ros::service::waitForService(IK_SOLVER_INFO);
00133   ros::service::waitForService(ARM_FK_NAME);
00134   ros::service::waitForService(ARM_IK_NAME);
00135   ros::ServiceClient query_client = rh.serviceClient<kinematics_msgs::GetKinematicSolverInfo>(IK_SOLVER_INFO);
00136   ros::ServiceClient fk_client = rh.serviceClient<kinematics_msgs::GetPositionFK>(ARM_FK_NAME);
00137   ros::ServiceClient ik_client = rh.serviceClient<kinematics_msgs::GetPositionIK>(ARM_IK_NAME);
00138 
00139   
00140   kinematics_msgs::GetKinematicSolverInfo::Request request;
00141   kinematics_msgs::GetKinematicSolverInfo::Response response;
00142             
00143   bool service_call = query_client.call(request, response);
00144   ASSERT_TRUE(service_call);
00145   ASSERT_TRUE(response.kinematic_solver_info.joint_names.size() == response.kinematic_solver_info.limits.size());
00146   ASSERT_TRUE(!response.kinematic_solver_info.link_names.empty());
00147 
00148   int num_joints;
00149   std::vector<double> min_limits, max_limits;
00150   num_joints = (int) response.kinematic_solver_info.joint_names.size();
00151   for(int i=0; i< num_joints; i++)
00152   {
00153     min_limits.push_back(response.kinematic_solver_info.limits[i].min_position);
00154     max_limits.push_back(response.kinematic_solver_info.limits[i].max_position);
00155   }
00156 
00157   
00158   kinematics_msgs::GetPositionFK::Request  fk_request;
00159   kinematics_msgs::GetPositionFK::Response fk_response;
00160   kinematics_msgs::GetPositionIK::Request  ik_request;
00161   kinematics_msgs::GetPositionIK::Response ik_response;
00162 
00163   fk_request.header.frame_id = "torso_lift_link";
00164   fk_request.fk_link_names.resize(1);
00165   fk_request.fk_link_names[0] = "r_wrist_roll_link";
00166   fk_request.robot_state.joint_state.name = response.kinematic_solver_info.joint_names;
00167   fk_request.robot_state.joint_state.position.resize(num_joints);
00168 
00169   int num_solutions = 0;
00170 
00171   for(int kk =0 ; kk < NUM_TESTS; kk++)
00172   {
00173     for(int i=0; i< num_joints; i++)
00174     {
00175       fk_request.robot_state.joint_state.position[i] =  gen_rand(std::max(min_limits[i],-M_PI),std::min(max_limits[i],M_PI));
00176     }
00177     bool fk_service_call = fk_client.call(fk_request, fk_response);
00178 
00179     ik_request.ik_request.pose_stamped = fk_response.pose_stamped[0];
00180     ik_request.ik_request.ik_seed_state.joint_state.name = response.kinematic_solver_info.joint_names;
00181     ik_request.ik_request.ik_seed_state.joint_state.position.resize(num_joints);
00182     ik_request.ik_request.ik_link_name = response.kinematic_solver_info.link_names[0];
00183     ik_request.timeout = ros::Duration(2.0);
00184     for(int i=0; i< num_joints; i++)
00185     {
00186       ik_request.ik_request.ik_seed_state.joint_state.position[i] = gen_rand(std::max(min_limits[i],-M_PI),std::min(max_limits[i],M_PI));
00187     }
00188     bool ik_service_call = ik_client.call(ik_request,ik_response);
00189     if(!ik_service_call)
00190     {
00191       ROS_ERROR("IK service call failed: %d",kk);
00192       continue;
00193     }
00194     if(ik_response.error_code.val != ik_response.error_code.SUCCESS)
00195     {
00196       ROS_ERROR("IK failed: %d",kk);
00197       continue;
00198     }
00199 
00200     ROS_DEBUG("IK response: num positions %d, num solution joints %d",(int)ik_response.solution.joint_state.position.size(),(int)ik_response.solution.joint_state.name.size());
00201 
00202     fk_request.robot_state.joint_state.position = ik_response.solution.joint_state.position;
00203     fk_request.robot_state.joint_state.name = ik_response.solution.joint_state.name;
00204     fk_service_call = fk_client.call(fk_request, fk_response);
00205 
00206     ASSERT_TRUE(!fk_response.pose_stamped.empty());
00207 
00208     if(NOT_NEAR(ik_request.ik_request.pose_stamped.pose.position.x,fk_response.pose_stamped[0].pose.position.x,IK_NEAR_TRANSLATE) || 
00209        NOT_NEAR(ik_request.ik_request.pose_stamped.pose.position.y,fk_response.pose_stamped[0].pose.position.y,IK_NEAR_TRANSLATE) ||
00210        NOT_NEAR(ik_request.ik_request.pose_stamped.pose.position.z,fk_response.pose_stamped[0].pose.position.z,IK_NEAR_TRANSLATE) ||
00211 
00212        NOT_NEAR(ik_request.ik_request.pose_stamped.pose.orientation.x,fk_response.pose_stamped[0].pose.orientation.x,IK_NEAR) ||
00213        NOT_NEAR(ik_request.ik_request.pose_stamped.pose.orientation.y,fk_response.pose_stamped[0].pose.orientation.y,IK_NEAR) ||
00214        NOT_NEAR(ik_request.ik_request.pose_stamped.pose.orientation.z,fk_response.pose_stamped[0].pose.orientation.z,IK_NEAR) ||
00215        NOT_NEAR(ik_request.ik_request.pose_stamped.pose.orientation.w,fk_response.pose_stamped[0].pose.orientation.w,IK_NEAR))
00216     {
00217       ROS_DEBUG("IK solution incorrect: %d",kk);
00218       ROS_ERROR("ik request: %s, %f, %f, %f :: %f %f %f %f",ik_request.ik_request.pose_stamped.header.frame_id.c_str(),ik_request.ik_request.pose_stamped.pose.position.x,
00219                 ik_request.ik_request.pose_stamped.pose.position.y,
00220                 ik_request.ik_request.pose_stamped.pose.position.z,
00221                 ik_request.ik_request.pose_stamped.pose.orientation.x,
00222                 ik_request.ik_request.pose_stamped.pose.orientation.y,
00223                 ik_request.ik_request.pose_stamped.pose.orientation.z,
00224                 ik_request.ik_request.pose_stamped.pose.orientation.w);
00225       ROS_ERROR("fk response: %s, %f, %f, %f :: %f %f %f %f\n",fk_response.pose_stamped[0].header.frame_id.c_str(),fk_response.pose_stamped[0].pose.position.x,
00226                 fk_response.pose_stamped[0].pose.position.y,
00227                 fk_response.pose_stamped[0].pose.position.z,
00228                 fk_response.pose_stamped[0].pose.orientation.x,
00229                 fk_response.pose_stamped[0].pose.orientation.y,
00230                 fk_response.pose_stamped[0].pose.orientation.z,
00231                 fk_response.pose_stamped[0].pose.orientation.w);
00232       continue;
00233     }
00234     num_solutions++;
00235   }
00236   double percent_success = ((double) num_solutions)/((double) NUM_TESTS);
00237   bool success = percent_success > 0.99;
00238   EXPECT_TRUE(success); 
00239   ROS_INFO("Num tests: %d, num solutions: %d",NUM_TESTS,num_solutions); 
00240   ros::shutdown();
00241 }
00242 
00243 int main(int argc, char **argv){
00244   testing::InitGoogleTest(&argc, argv);
00245   ros::init (argc, argv, "pr2_ik_node_regression_test");
00246   return RUN_ALL_TESTS();
00247 }