$search
00001 //Software License Agreement (BSD License) 00002 00003 //Copyright (c) 2008, Willow Garage, Inc. 00004 //All rights reserved. 00005 00006 //Redistribution and use in source and binary forms, with or without 00007 //modification, are permitted provided that the following conditions 00008 //are met: 00009 00010 // * Redistributions of source code must retain the above copyright 00011 // notice, this list of conditions and the following disclaimer. 00012 // * Redistributions in binary form must reproduce the above 00013 // copyright notice, this list of conditions and the following 00014 // disclaimer in the documentation and/or other materials provided 00015 // with the distribution. 00016 // * Neither the name of Willow Garage, Inc. nor the names of its 00017 // contributors may be used to endorse or promote products derived 00018 // from this software without specific prior written permission. 00019 00020 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00021 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00022 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00023 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00024 //COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00025 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00026 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00027 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00028 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00029 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00030 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00031 //POSSIBILITY OF SUCH DAMAGE. 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 // define the service messages 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 // define the service messages 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 // define the service messages 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) ); // initialize random seed 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 // define the service messages 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 // define the service messages 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 }