00001
00007
00008 #include <geometry_msgs/PoseStamped.h>
00009 #include <kdl_parser/kdl_parser.hpp>
00010 #include <tf_conversions/tf_kdl.h>
00011 #include <ros/ros.h>
00012 #include <algorithm>
00013 #include <numeric>
00014 #include <moveit/kinematics_base/kinematics_base.h>
00015 #include <urdf/model.h>
00016 #include <moveit_msgs/GetPositionIK.h>
00017 #include <boost/shared_ptr.hpp>
00018
00019
00020 #define ARRAY_LENGTH(array) (int(sizeof(array) / sizeof(array[0])))
00021
00022 using namespace KDL;
00023 using namespace tf;
00024 using namespace std;
00025 using namespace ros;
00026
00027 namespace eus_kinematics {
00028
00029 class EusKinematicsPlugin : public kinematics::KinematicsBase
00030 {
00031 std::vector<std::string> joint_names_;
00032 std::vector<double> joint_min_vector_;
00033 std::vector<double> joint_max_vector_;
00034 std::vector<bool> joint_has_limits_vector_;
00035 std::vector<std::string> link_names_;
00036 size_t num_joints_;
00037 bool active_;
00038
00039 const std::vector<std::string>& getJointNames() const { return joint_names_; }
00040 const std::vector<std::string>& getLinkNames() const { return link_names_; }
00041
00042 boost::shared_ptr<ros::ServiceClient> ik_service_client;
00043
00044 public:
00045
00049 EusKinematicsPlugin():active_(false){}
00050
00060
00061 bool getPositionIK(const geometry_msgs::Pose &ik_pose,
00062 const std::vector<double> &ik_seed_state,
00063 std::vector<double> &solution,
00064 moveit_msgs::MoveItErrorCodes &error_code,
00065 const kinematics::KinematicsQueryOptions &options = kinematics::KinematicsQueryOptions()) const;
00066
00075 bool searchPositionIK(const geometry_msgs::Pose &ik_pose,
00076 const std::vector<double> &ik_seed_state,
00077 double timeout,
00078 std::vector<double> &solution,
00079 moveit_msgs::MoveItErrorCodes &error_code,
00080 const kinematics::KinematicsQueryOptions &options = kinematics::KinematicsQueryOptions()) const;
00081
00091 bool searchPositionIK(const geometry_msgs::Pose &ik_pose,
00092 const std::vector<double> &ik_seed_state,
00093 double timeout,
00094 const std::vector<double> &consistency_limits,
00095 std::vector<double> &solution,
00096 moveit_msgs::MoveItErrorCodes &error_code,
00097 const kinematics::KinematicsQueryOptions &options = kinematics::KinematicsQueryOptions()) const;
00098
00107 bool searchPositionIK(const geometry_msgs::Pose &ik_pose,
00108 const std::vector<double> &ik_seed_state,
00109 double timeout,
00110 std::vector<double> &solution,
00111 const IKCallbackFn &solution_callback,
00112 moveit_msgs::MoveItErrorCodes &error_code,
00113 const kinematics::KinematicsQueryOptions &options = kinematics::KinematicsQueryOptions()) const;
00114
00125 bool searchPositionIK(const geometry_msgs::Pose &ik_pose,
00126 const std::vector<double> &ik_seed_state,
00127 double timeout,
00128 const std::vector<double> &consistency_limits,
00129 std::vector<double> &solution,
00130 const IKCallbackFn &solution_callback,
00131 moveit_msgs::MoveItErrorCodes &error_code,
00132 const kinematics::KinematicsQueryOptions &options = kinematics::KinematicsQueryOptions()) const;
00133
00145 bool getPositionFK(const std::vector<std::string> &link_names,
00146 const std::vector<double> &joint_angles,
00147 std::vector<geometry_msgs::Pose> &poses) const;
00148
00149 private:
00150
00151 bool initialize(const std::string &robot_description,
00152 const std::string& group_name,
00153 const std::string& base_name,
00154 const std::string& tip_name,
00155 double search_discretization);
00156
00157 int ComputeIkEus(const geometry_msgs::Pose ik_pose, std::vector<double> &result_angle) const;
00158 void ComputeFkEus(void) const;
00159
00160 };
00161
00162 bool EusKinematicsPlugin::initialize(const std::string &robot_description,
00163 const std::string& group_name,
00164 const std::string& base_name,
00165 const std::string& tip_name,
00166 double search_discretization)
00167 {
00168 setValues(robot_description, group_name, base_name, tip_name, search_discretization);
00169
00170 ros::NodeHandle node_handle(group_name);
00171
00172 ik_service_client = boost::make_shared<ros::ServiceClient>(node_handle.serviceClient<moveit_msgs::GetPositionIK>("eus_ik_request"));
00173 ROS_INFO_STREAM("service client started. service name: " << ik_service_client->getService());
00174
00175 std::string robot;
00176 node_handle.param("robot",robot,std::string());
00177
00178 urdf::Model robot_model;
00179 std::string xml_string;
00180
00181 std::string urdf_xml,full_urdf_xml;
00182 node_handle.param("urdf_xml",urdf_xml,robot_description);
00183 node_handle.searchParam(urdf_xml,full_urdf_xml);
00184
00185 ROS_DEBUG_STREAM("Reading xml file from parameter server");
00186 if (!node_handle.getParam(full_urdf_xml, xml_string))
00187 {
00188 ROS_FATAL_STREAM("Could not load the xml from parameter server " << urdf_xml.c_str());
00189 return false;
00190 }
00191
00192 node_handle.param(full_urdf_xml,xml_string,std::string());
00193 robot_model.initString(xml_string);
00194
00195 ROS_DEBUG_STREAM("Reading joints and links from URDF");
00196
00197 boost::shared_ptr<urdf::Link> link = boost::const_pointer_cast<urdf::Link>(robot_model.getLink(tip_frame_));
00198 while(link->name != base_frame_)
00199 {
00200 ROS_DEBUG_STREAM("Link " << link->name.c_str());
00201 link_names_.push_back(link->name);
00202 boost::shared_ptr<urdf::Joint> joint = link->parent_joint;
00203 if(joint)
00204 {
00205 if (joint->type != urdf::Joint::UNKNOWN && joint->type != urdf::Joint::FIXED)
00206 {
00207 ROS_DEBUG_STREAM("Adding joint " << joint->name );
00208
00209 joint_names_.push_back(joint->name);
00210 float lower, upper;
00211 int hasLimits;
00212 if ( joint->type != urdf::Joint::CONTINUOUS )
00213 {
00214 if(joint->safety)
00215 {
00216 lower = joint->safety->soft_lower_limit;
00217 upper = joint->safety->soft_upper_limit;
00218 } else {
00219 lower = joint->limits->lower;
00220 upper = joint->limits->upper;
00221 }
00222 hasLimits = 1;
00223 }
00224 else
00225 {
00226 lower = -M_PI;
00227 upper = M_PI;
00228 hasLimits = 0;
00229 }
00230 if(hasLimits)
00231 {
00232 joint_has_limits_vector_.push_back(true);
00233 joint_min_vector_.push_back(lower);
00234 joint_max_vector_.push_back(upper);
00235 }
00236 else
00237 {
00238 joint_has_limits_vector_.push_back(false);
00239 joint_min_vector_.push_back(-M_PI);
00240 joint_max_vector_.push_back(M_PI);
00241 }
00242 }
00243 } else
00244 {
00245 ROS_WARN_STREAM("no joint corresponding to " << link->name.c_str());
00246 }
00247 link = link->getParent();
00248 }
00249
00250 num_joints_ = joint_names_.size();
00251
00252 if(joint_names_.size() != num_joints_)
00253 {
00254 ROS_FATAL_STREAM("Joint numbers mismatch: URDF has " << joint_names_.size() << " and EusIK has " << num_joints_);
00255 return false;
00256 }
00257
00258 std::reverse(link_names_.begin(),link_names_.end());
00259 std::reverse(joint_names_.begin(),joint_names_.end());
00260 std::reverse(joint_min_vector_.begin(),joint_min_vector_.end());
00261 std::reverse(joint_max_vector_.begin(),joint_max_vector_.end());
00262 std::reverse(joint_has_limits_vector_.begin(), joint_has_limits_vector_.end());
00263
00264 ROS_INFO_STREAM("eus_kinematics_plugin was called for plannning group " << getGroupName());
00265 for(size_t i=0; i <num_joints_; ++i)
00266 ROS_INFO_STREAM(joint_names_[i] << " " << joint_min_vector_[i] << " " << joint_max_vector_[i] << " " << joint_has_limits_vector_[i]);
00267
00268 active_ = true;
00269 return true;
00270 }
00271
00272 bool EusKinematicsPlugin::getPositionIK(const geometry_msgs::Pose &ik_pose,
00273 const std::vector<double> &ik_seed_state,
00274 std::vector<double> &solution,
00275 moveit_msgs::MoveItErrorCodes &error_code,
00276 const kinematics::KinematicsQueryOptions &options) const
00277 {
00278 ROS_DEBUG_STREAM("getPositionIK");
00279
00280 if(!active_)
00281 {
00282 ROS_ERROR_STREAM("Kinematics not active");
00283 error_code.val = error_code.NO_IK_SOLUTION;
00284 return false;
00285 }
00286
00287 error_code.val = ComputeIkEus(ik_pose, solution);
00288
00289 ROS_INFO_STREAM("ComputeIKEus() was called.");
00290
00291 if(error_code.val != 1)
00292 {
00293 ROS_DEBUG_STREAM("No IK solution");
00294 return false;
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304 return true;
00305 }
00306
00307 bool EusKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00308 const std::vector<double> &ik_seed_state,
00309 double timeout,
00310 std::vector<double> &solution,
00311 moveit_msgs::MoveItErrorCodes &error_code,
00312 const kinematics::KinematicsQueryOptions &options) const
00313 {
00314 static IKCallbackFn solution_callback = 0;
00315 static std::vector<double> consistency_limits;
00316 return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code);
00317 }
00318
00319 bool EusKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00320 const std::vector<double> &ik_seed_state,
00321 double timeout,
00322 const std::vector<double> &consistency_limits,
00323 std::vector<double> &solution,
00324 moveit_msgs::MoveItErrorCodes &error_code,
00325 const kinematics::KinematicsQueryOptions &options) const
00326 {
00327 static IKCallbackFn solution_callback = 0;
00328 return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code);
00329 }
00330
00331 bool EusKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00332 const std::vector<double> &ik_seed_state,
00333 double timeout,
00334 std::vector<double> &solution,
00335 const IKCallbackFn &solution_callback,
00336 moveit_msgs::MoveItErrorCodes &error_code,
00337 const kinematics::KinematicsQueryOptions &options) const
00338 {
00339 static std::vector<double> consistency_limits;
00340 return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code);
00341 }
00342
00343 bool EusKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00344 const std::vector<double> &ik_seed_state,
00345 double timeout,
00346 const std::vector<double> &consistency_limits,
00347 std::vector<double> &solution,
00348 const IKCallbackFn &solution_callback,
00349 moveit_msgs::MoveItErrorCodes &error_code,
00350 const kinematics::KinematicsQueryOptions &options) const
00351 {
00352 return EusKinematicsPlugin::getPositionIK(ik_pose, ik_seed_state, solution, error_code, options);
00353 }
00354
00355 bool EusKinematicsPlugin::getPositionFK(const std::vector<std::string> &link_names,
00356 const std::vector<double> &joint_angles,
00357 std::vector<geometry_msgs::Pose> &poses) const
00358 {
00359 KDL::Frame p_out;
00360 if(link_names.size() == 0) {
00361 ROS_WARN_STREAM("Link names with nothing");
00362 return false;
00363 }
00364
00365 if(link_names.size()!=1 || link_names[0]!=tip_frame_){
00366 ROS_ERROR_STREAM("Can compute FK for " << tip_frame_.c_str() << " only");
00367 return false;
00368 }
00369
00370 bool valid = true;
00371
00372 double eerot[9],eetrans[3];
00373
00374 ComputeFkEus();
00375 ROS_DEBUG_STREAM("ComputeFKEus() was called. angle: " << angle << " trans: " << eetrans << " rot: " << eerot);
00376
00377 for(int i=0; i<3;++i)
00378 p_out.p.data[i] = eetrans[i];
00379
00380 for(int i=0; i<9;++i)
00381 p_out.M.data[i] = eerot[i];
00382
00383 poses.resize(1);
00384 tf::poseKDLToMsg(p_out,poses[0]);
00385
00386 return valid;
00387 }
00388
00389 int EusKinematicsPlugin::ComputeIkEus(const geometry_msgs::Pose ik_pose, std::vector<double> &result_angle) const
00390 {
00391 moveit_msgs::GetPositionIK ik_srv;
00392 geometry_msgs::PoseStamped ik_pose_st;
00393
00394 ik_pose_st.pose = ik_pose;
00395
00396 ik_srv.request.ik_request.group_name = getGroupName();
00397 ik_srv.request.ik_request.robot_state.joint_state.name = joint_names_;
00398 ik_srv.request.ik_request.pose_stamped = ik_pose_st;
00399
00400 ROS_INFO_STREAM("service was called. service name: " << ik_service_client->getService() << "ik_request:");
00401 ROS_INFO_STREAM(ik_srv.request.ik_request);
00402 if (ik_service_client->call(ik_srv))
00403 {
00404 result_angle = ik_srv.response.solution.joint_state.position;
00405 ROS_INFO_STREAM("service succeeded. solution:");
00406 ROS_INFO_STREAM(ik_srv.response.solution);
00407 }
00408 else
00409 {
00410 ROS_ERROR_STREAM("service failed. service name: " << ik_service_client->getService());
00411 }
00412
00413 return ik_srv.response.error_code.val;
00414 }
00415
00416 void EusKinematicsPlugin::ComputeFkEus(void) const
00417 {
00418 return;
00419 }
00420
00421 }
00422
00423
00424 #include <pluginlib/class_list_macros.h>
00425 PLUGINLIB_EXPORT_CLASS(eus_kinematics::EusKinematicsPlugin, kinematics::KinematicsBase);