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
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
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
00061
00062
00063
00064
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
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
00135 bool run_test(){
00136 srand ( time(NULL) );
00137
00138
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
00149
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
00159
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
00170
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
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
00226 ros::init(argc, argv, "test_ik_and_fk");
00227
00228
00229 TestIKandFK test_ik_and_fk = TestIKandFK();
00230
00231
00232 test_ik_and_fk.run_test();
00233
00234 return 0;
00235 }
00236