00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00027 #include <urdf/joint.h>
00028 #include <urdf/model.h>
00029 #include <tf_conversions/tf_kdl.h>
00030 #include "tree_kinematics/tree_kinematics.h"
00031
00032 static const std::string FK_SERVICE = "get_position_fk";
00033 static const std::string IK_SERVICE = "get_position_ik";
00034
00035
00036 namespace tree_kinematics
00037 {
00038
00039 bool TreeKinematics::init()
00040 {
00041
00042 std::string urdf_xml, full_urdf_xml;
00043 nh_.param("urdf_xml_model",urdf_xml,std::string("robot_description"));
00044 nh_.searchParam(urdf_xml,full_urdf_xml);
00045 ROS_DEBUG("Reading xml file from parameter server ...");
00046 std::string result;
00047 if (!nh_.getParam(full_urdf_xml, result))
00048 {
00049 ROS_FATAL("Could not load the xml from parameter server: %s!", urdf_xml.c_str());
00050 return false;
00051 }
00052
00053
00054 KDL::JntArray joint_min;
00055 KDL::JntArray joint_max;
00056 KDL::JntArray joint_vel_max;
00057
00058 if (!loadModel(result, kdl_tree_, tree_root_name_, nr_of_jnts_, joint_min, joint_max, joint_vel_max))
00059 {
00060 ROS_FATAL("Could not load model!");
00061 return false;
00062 }
00063
00064
00065 int nr_of_endpts = 0;
00066 std::vector<std::string> endpts;
00067 endpts.clear();
00068 if(nh_private_.getParam("nr_of_endpoints", nr_of_endpts) && nr_of_endpts >= 0)
00069 {
00070 for(int i = 0; i < nr_of_endpts; ++i)
00071 {
00072 std::string elementname;
00073 std::string endpt_name;
00074 std::stringstream ss;
00075 ss << "endpoint_" << i;
00076 ss >> elementname;
00077 if(nh_private_.getParam(elementname, endpt_name))
00078 {
00079 endpts.push_back(endpt_name);
00080 ROS_DEBUG("Added endpoint '%s'", endpts[i].c_str());
00081 }
00082 else
00083 {
00084 ROS_FATAL("Couldn't get the name of an endpoint!");
00085 return false;
00086 }
00087 }
00088 }
00089 nh_private_.param("srv_call_frequency", srv_call_frequency_, 10);
00090 double x_dot_trans_max, x_dot_rot_max, x_dot_trans_min, x_dot_rot_min;
00091 double q_dot_min_factor, q_dot_max_factor;
00092 double epsilon, low_pass_factor;
00093 int max_iterations;
00094 nh_private_.param("epsilon", epsilon, 1e-3);
00095 nh_private_.param("max_iterations", max_iterations, 10);
00096 nh_private_.param("low_pass_factor", low_pass_factor, 0.0);
00097 nh_private_.param("x_dot_trans_max", x_dot_trans_max, 1.0);
00098 nh_private_.param("x_dot_rot_max", x_dot_rot_max, 1.0);
00099 nh_private_.param("x_dot_trans_min", x_dot_trans_min, 0.0);
00100 nh_private_.param("x_dot_rot_min", x_dot_rot_min, 0.0);
00101 nh_private_.param("q_dot_max_factor", q_dot_max_factor, 1.0);
00102 nh_private_.param("q_dot_min_factor", q_dot_min_factor, 0.0);
00103 x_dot_trans_max = x_dot_trans_max / srv_call_frequency_;
00104 x_dot_rot_max = x_dot_rot_max / srv_call_frequency_;
00105 x_dot_trans_min = x_dot_trans_min / srv_call_frequency_;
00106 x_dot_rot_min = x_dot_rot_min / srv_call_frequency_;
00107 q_dot_max_factor = q_dot_max_factor / srv_call_frequency_;
00108 q_dot_min_factor = q_dot_min_factor / srv_call_frequency_;
00109 KDL::Multiply(joint_vel_max, q_dot_max_factor, joint_vel_max);
00110 KDL::JntArray joint_vel_min(nr_of_jnts_);
00111 for (unsigned int i = 0; i < joint_vel_min.rows(); ++i)
00112 {
00113 joint_vel_min(i) = 1.0;
00114 }
00115 KDL::Multiply(joint_vel_min, q_dot_min_factor, joint_vel_min);
00116
00117 ROS_DEBUG("srv_call_frequency = %d", srv_call_frequency_);
00118 ROS_DEBUG("x_dot_trans_max = %f, x_dot_rot_max = %f", x_dot_trans_max, x_dot_rot_max);
00119 ROS_DEBUG("x_dot_trans_min = %f, x_dot_rot_min = %f", x_dot_trans_min, x_dot_rot_min);
00120 ROS_DEBUG("q_dot_max_factor = %f", q_dot_max_factor);
00121 ROS_DEBUG("q_dot_min_factor = %f", q_dot_min_factor);
00122 ROS_DEBUG("maximum iterations = %d", max_iterations);
00123 ROS_DEBUG("precision = %f", epsilon);
00124 ROS_DEBUG("low_pass_factor = %f", low_pass_factor);
00125
00126
00127 fk_solver_.reset(new KDL::TreeFkSolverPos_recursive(kdl_tree_));
00128 ik_vel_solver_.reset(new KDL::TreeIkSolverVel_wdls(kdl_tree_, endpts));
00129 ik_pos_solver_.reset(new KDL::TreeIkSolverPos_Online(nr_of_jnts_,
00130 endpts,
00131 *fk_solver_,
00132 *ik_vel_solver_,
00133 joint_min,
00134 joint_max,
00135 joint_vel_min,
00136 joint_vel_max,
00137 x_dot_trans_max,
00138 x_dot_rot_max,
00139 x_dot_trans_min,
00140 x_dot_rot_min,
00141 low_pass_factor,
00142 max_iterations,
00143 epsilon));
00144
00145
00146
00147 js_w_matr_ = KDL::MatrixXd::Identity(nr_of_jnts_, nr_of_jnts_);
00148 ROS_DEBUG("filling the joint space weight matrix:");
00149 for (unsigned int i = 0 ; i < nr_of_jnts_ ; ++i)
00150 {
00151 std::string elementname;
00152 std::stringstream ss;
00153 ss << "js_w_matr/j" << i;
00154 ss >> elementname;
00155 double elementvalue;
00156 nh_private_.param(elementname, elementvalue, 1.0);
00157 js_w_matr_( i, i ) = elementvalue;
00158 ROS_DEBUG("qs_w_matr_(%d,%d) = %f", i, i, js_w_matr_( i, i ));
00159 }
00160 ik_vel_solver_->setWeightJS(js_w_matr_);
00161
00162
00163 ts_w_matr_ = KDL::MatrixXd::Identity( 6 * endpts.size(), 6 * endpts.size() );
00164 std::vector<std::string> ending;
00165 ending.clear();
00166 ending.push_back("px");
00167 ending.push_back("py");
00168 ending.push_back("pz");
00169 ending.push_back("rx");
00170 ending.push_back("ry");
00171 ending.push_back("rz");
00172 ROS_DEBUG("filling the task space weight matrix:");
00173 for (unsigned int i = 0 ; i < endpts.size() ; ++i)
00174 {
00175 for (unsigned int j = 0 ; j < 6; ++j)
00176 {
00177 std::string elementname;
00178 std::stringstream ss;
00179 ss << "ts_w_matr/endpt" << i << "/";
00180 ss << ending[j];
00181 ss >> elementname;
00182 double elementvalue;
00183 nh_private_.param(elementname, elementvalue, 0.0);
00184 ts_w_matr_( i * 6 + j, i * 6 + j ) = elementvalue;
00185 ROS_DEBUG("ts_w_matr_(%d,%d) = %f", i * 6 + j, i * 6 + j, ts_w_matr_( i * 6 + j, i * 6 + j ));
00186 }
00187 }
00188 ik_vel_solver_->setWeightTS(ts_w_matr_);
00189
00190
00191 nh_private_.param("lambda", lambda_, 0.01);
00192 ROS_DEBUG("lambda = %f", lambda_);
00193 ik_vel_solver_->setLambda(lambda_);
00194
00195 fk_service_ = nh_private_.advertiseService(FK_SERVICE, &TreeKinematics::getPositionFk, this);
00196 ik_service_ = nh_private_.advertiseService(IK_SERVICE, &TreeKinematics::getPositionIk, this);
00197
00198 return true;
00199 }
00200
00201
00202 bool TreeKinematics::loadModel(const std::string xml,
00203 KDL::Tree &kdl_tree,
00204 std::string &tree_root_name,
00205 unsigned int &nr_of_jnts,
00206 KDL::JntArray &joint_min,
00207 KDL::JntArray &joint_max,
00208 KDL::JntArray &joint_vel_max)
00209 {
00210 urdf::Model robot_model;
00211 if (!robot_model.initString(xml))
00212 {
00213 ROS_FATAL("Could not initialize robot model!");
00214 return false;
00215 }
00216 if (!kdl_parser::treeFromUrdfModel(robot_model, kdl_tree))
00217 {
00218 ROS_FATAL("Could not initialize tree object!");
00219 return false;
00220 }
00221 if (!readJoints(robot_model, kdl_tree, tree_root_name, nr_of_jnts, joint_min, joint_max, joint_vel_max))
00222 {
00223 ROS_FATAL("Could not read information about the joints!");
00224 return false;
00225 }
00226 return true;
00227 }
00228
00229
00230 bool TreeKinematics::readJoints(urdf::Model &robot_model,
00231 KDL::Tree &kdl_tree,
00232 std::string &tree_root_name,
00233 unsigned int &nr_of_jnts,
00234 KDL::JntArray &joint_min,
00235 KDL::JntArray &joint_max,
00236 KDL::JntArray &joint_vel_max)
00237 {
00238 KDL::SegmentMap segmentMap;
00239 segmentMap = kdl_tree.getSegments();
00240 tree_root_name = kdl_tree.getRootSegment()->second.segment.getName();
00241 nr_of_jnts = kdl_tree.getNrOfJoints();
00242 ROS_DEBUG( "the tree's number of joints: [%d]", nr_of_jnts );
00243 joint_min.resize(nr_of_jnts);
00244 joint_max.resize(nr_of_jnts);
00245 joint_vel_max.resize(nr_of_jnts);
00246 info_.joint_names.resize(nr_of_jnts);
00247 info_.limits.resize(nr_of_jnts);
00248
00249
00250
00251
00252 ROS_DEBUG("Extracting all joints from the tree, which are not of type KDL::Joint::None.");
00253 boost::shared_ptr<const urdf::Joint> joint;
00254 for (KDL::SegmentMap::const_iterator seg_it = segmentMap.begin(); seg_it != segmentMap.end(); ++seg_it)
00255 {
00256 if (seg_it->second.segment.getJoint().getType() != KDL::Joint::None)
00257 {
00258
00259 joint = robot_model.getJoint(seg_it->second.segment.getJoint().getName().c_str());
00260 if (!joint)
00261 {
00262 ROS_FATAL("Joint '%s' has not been found in the URDF robot model!", joint->name.c_str());
00263 return false;
00264 }
00265
00266 if (joint->type != urdf::Joint::UNKNOWN && joint->type != urdf::Joint::FIXED)
00267 {
00268 ROS_DEBUG( "getting information about joint: [%s]", joint->name.c_str() );
00269 double lower = 0.0, upper = 0.0, vel_limit = 0.0;
00270 unsigned int has_pos_limits = 0, has_vel_limits = 0;
00271
00272 if ( joint->type != urdf::Joint::CONTINUOUS )
00273 {
00274 ROS_DEBUG("joint is not continuous.");
00275 lower = joint->limits->lower;
00276 upper = joint->limits->upper;
00277 has_pos_limits = 1;
00278 if (joint->limits->velocity)
00279 {
00280 has_vel_limits = 1;
00281 vel_limit = joint->limits->velocity;
00282 ROS_DEBUG("joint has following velocity limit: %f", vel_limit);
00283 }
00284 else
00285 {
00286 has_vel_limits = 0;
00287 vel_limit = 0.0;
00288 ROS_DEBUG("joint has no velocity limit.");
00289 }
00290 }
00291 else
00292 {
00293 ROS_DEBUG("joint is continuous.");
00294 lower = -M_PI;
00295 upper = M_PI;
00296 has_pos_limits = 0;
00297 if(joint->limits && joint->limits->velocity)
00298 {
00299 has_vel_limits = 1;
00300 vel_limit = joint->limits->velocity;
00301 ROS_DEBUG("joint has following velocity limit: %f", vel_limit);
00302 }
00303 else
00304 {
00305 has_vel_limits = 0;
00306 vel_limit = 0.0;
00307 ROS_DEBUG("joint has no velocity limit.");
00308 }
00309 }
00310
00311 joint_min(seg_it->second.q_nr) = lower;
00312 joint_max(seg_it->second.q_nr) = upper;
00313 joint_vel_max(seg_it->second.q_nr) = vel_limit;
00314 ROS_DEBUG("pos_min = %f, pos_max = %f, vel_max = %f", lower, upper, vel_limit);
00315
00316 info_.joint_names[seg_it->second.q_nr] = joint->name;
00317 info_.limits[seg_it->second.q_nr].joint_name = joint->name;
00318 info_.limits[seg_it->second.q_nr].has_position_limits = has_pos_limits;
00319 info_.limits[seg_it->second.q_nr].min_position = lower;
00320 info_.limits[seg_it->second.q_nr].max_position = upper;
00321 info_.limits[seg_it->second.q_nr].has_velocity_limits = has_vel_limits;
00322 info_.limits[seg_it->second.q_nr].max_velocity = vel_limit;
00323 }
00324 }
00325 }
00326 return true;
00327 }
00328
00329
00330 int TreeKinematics::getJointIndex(const std::string &name)
00331 {
00332 for (unsigned int i=0; i < info_.joint_names.size(); ++i)
00333 {
00334 if (info_.joint_names[i] == name)
00335 return i;
00336 }
00337 return -1;
00338 }
00339
00340
00341 bool TreeKinematics::getPositionFk(kinematics_msgs::GetPositionFK::Request& request,
00342 kinematics_msgs::GetPositionFK::Response& response)
00343 {
00344 ROS_DEBUG("getPositionFK method invoked.");
00345 KDL::JntArray q_in;
00346 double nr_of_jnts = request.robot_state.joint_state.name.size();
00347 q_in.resize(nr_of_jnts);
00348
00349 for (unsigned int i=0; i < nr_of_jnts; ++i)
00350 {
00351 int tmp_index = getJointIndex(request.robot_state.joint_state.name[i]);
00352 if (tmp_index >=0)
00353 {
00354 q_in(tmp_index) = request.robot_state.joint_state.position[i];
00355 ROS_DEBUG("joint '%s' is now number '%d'", request.robot_state.joint_state.name[i].c_str(), tmp_index);
00356 }
00357 else
00358 {
00359 ROS_FATAL("i: %d, No joint index for %s!", i, request.robot_state.joint_state.name[i].c_str());
00360 ROS_FATAL("Service call aborted.");
00361 return false;
00362 }
00363 }
00364
00365 response.pose_stamped.resize(request.fk_link_names.size());
00366 response.fk_link_names.resize(request.fk_link_names.size());
00367 KDL::Frame p_out;
00368 geometry_msgs::PoseStamped pose;
00369 tf::Stamped<tf::Pose> tf_pose;
00370 for (unsigned int i=0; i < request.fk_link_names.size(); i++)
00371 {
00372 ROS_DEBUG("End effector name: %s",request.fk_link_names[i].c_str());
00373 int fk_ret = fk_solver_->JntToCart(q_in, p_out, request.fk_link_names[i]);
00374 if (fk_ret >= 0)
00375 {
00376 tf_pose.frame_id_ = tree_root_name_;
00377 tf_pose.stamp_ = ros::Time::now();
00378 tf::PoseKDLToTF(p_out, tf_pose);
00379 try
00380 {
00381 tf_listener_.transformPose(request.header.frame_id, tf_pose, tf_pose);
00382 }
00383 catch (tf::TransformException const &ex)
00384 {
00385 ROS_FATAL("Could not transform FK pose to frame: %s",request.header.frame_id.c_str());
00386 response.error_code.val = response.error_code.FRAME_TRANSFORM_FAILURE;
00387 return false;
00388 }
00389 tf::poseStampedTFToMsg(tf_pose, pose);
00390 response.pose_stamped[i] = pose;
00391 response.fk_link_names[i] = request.fk_link_names[i];
00392 response.error_code.val = response.error_code.SUCCESS;
00393 }
00394 else
00395 {
00396 ROS_WARN("A FK solution could not be found for %s (error code = %d)",
00397 request.fk_link_names[i].c_str(), fk_ret);
00398 response.error_code.val = response.error_code.NO_FK_SOLUTION;
00399 }
00400 }
00401
00402 return true;
00403 }
00404
00405
00406 bool TreeKinematics::getPositionIk(tree_kinematics::get_tree_position_ik::Request &request,
00407 tree_kinematics::get_tree_position_ik::Response &response)
00408 {
00409 ik_srv_duration_ = ros::Time::now().toSec();
00410 ROS_DEBUG("getPositionIK method invoked.");
00411
00412
00413 KDL::JntArray q, q_desi;
00414 double nr_of_jnts = request.pos_ik_request[0].ik_seed_state.joint_state.name.size();
00415 q.resize(nr_of_jnts);
00416 q_desi.resize(nr_of_jnts);
00417 for (unsigned int i=0; i < nr_of_jnts; ++i)
00418 {
00419 int tmp_index = getJointIndex(request.pos_ik_request[0].ik_seed_state.joint_state.name[i]);
00420 if (tmp_index >=0)
00421 {
00422 q(tmp_index) = request.pos_ik_request[0].ik_seed_state.joint_state.position[i];
00423 ROS_DEBUG("joint '%s' is now number '%d'", request.pos_ik_request[0].ik_seed_state.joint_state.name[i].c_str(),
00424 tmp_index);
00425 }
00426 else
00427 {
00428 ROS_FATAL("i: %d, No joint index for %s!",i,request.pos_ik_request[0].ik_seed_state.joint_state.name[i].c_str());
00429 ROS_FATAL("Service call aborted.");
00430 return false;
00431 }
00432 }
00433
00434
00435 geometry_msgs::PoseStamped pose_msg_in;
00436 geometry_msgs::PoseStamped pose_msg_transformed;
00437 tf::Stamped<tf::Pose> transform;
00438 tf::Stamped<tf::Pose> transform_root;
00439 KDL::Frames desired_poses;
00440 KDL::Frame desired_pose;
00441 for(unsigned int i = 0; i < request.pos_ik_request.size(); ++i)
00442 {
00443 pose_msg_in = request.pos_ik_request[i].pose_stamped;
00444 try
00445 {
00446 tf_listener_.waitForTransform(tree_root_name_, pose_msg_in.header.frame_id, pose_msg_in.header.stamp,
00447 ros::Duration(0.1));
00448 tf_listener_.transformPose(tree_root_name_, pose_msg_in, pose_msg_transformed);
00449 }
00450 catch (tf::TransformException const &ex)
00451 {
00452 ROS_FATAL("%s",ex.what());
00453 ROS_FATAL("Could not transform IK pose from '%s' to frame '%s'", tree_root_name_.c_str(),
00454 pose_msg_in.header.frame_id.c_str());
00455 response.error_code.val = response.error_code.FRAME_TRANSFORM_FAILURE;
00456 return false;
00457 }
00458 tf::PoseMsgToKDL(pose_msg_transformed.pose, desired_pose);
00459 desired_poses[request.pos_ik_request[i].ik_link_name] = desired_pose;
00460 }
00461
00462
00463 ik_duration_ = ros::Time::now().toSec();
00464 int ik_ret = ik_pos_solver_->CartToJnt_it(q, desired_poses, q_desi);
00465 ik_duration_ = ros::Time::now().toSec() - ik_duration_;
00466 ik_duration_median_ = ((ik_duration_median_ * (loop_count_ - 1)) + ik_duration_) / loop_count_;
00467
00468
00469 if (ik_ret >= 0 || ik_ret == -3)
00470 {
00471 response.solution.joint_state.name = info_.joint_names;
00472 response.solution.joint_state.position.resize(nr_of_jnts_);
00473 response.solution.joint_state.velocity.resize(nr_of_jnts_);
00474 for (unsigned int i=0; i < nr_of_jnts_; ++i)
00475 {
00476 response.solution.joint_state.position[i] = q_desi(i);
00477 response.solution.joint_state.velocity[i] = (q_desi(i) - q(i)) * srv_call_frequency_;
00478 ROS_DEBUG("IK Solution: %s %d: pos = %f, vel = %f",response.solution.joint_state.name[i].c_str(), i,
00479 response.solution.joint_state.position[i], response.solution.joint_state.velocity[i]);
00480 }
00481 response.error_code.val = response.error_code.SUCCESS;
00482
00483 ik_srv_duration_ = ros::Time::now().toSec() - ik_srv_duration_;
00484 ik_srv_duration_median_ = ((ik_srv_duration_median_ * (loop_count_ - 1)) + ik_srv_duration_) / loop_count_;
00485 loop_count_++;
00486
00487 ROS_INFO_THROTTLE(1.0, "tree_kinematics: ik_srv_duration %f and median %f", ik_srv_duration_,
00488 ik_srv_duration_median_);
00489 ROS_INFO_THROTTLE(1.0, "tree_kinematics: ik_duration %f and median %f", ik_duration_, ik_duration_median_);
00490
00491 if (ik_ret == -3)
00492 {
00493 ROS_WARN_THROTTLE(1.0, "Maximum iterations reached! (error code = %d)", ik_ret);
00494 }
00495 }
00496 else
00497 {
00498 ROS_WARN("An IK solution could not be found (error code = %d)", ik_ret);
00499 response.error_code.val = response.error_code.NO_IK_SOLUTION;
00500
00501 ik_srv_duration_ = ros::Time::now().toSec() - ik_srv_duration_;
00502 ik_srv_duration_median_ = ((ik_srv_duration_median_ * (loop_count_ - 1)) + ik_srv_duration_) / loop_count_;
00503 loop_count_++;
00504
00505 ROS_INFO_THROTTLE(1.0, "tree_kinematics: ik_srv_duration %f and median %f", ik_srv_duration_,
00506 ik_srv_duration_median_);
00507 ROS_INFO_THROTTLE(1.0, "tree_kinematics: ik_duration %f and median %f", ik_duration_, ik_duration_median_);
00508 }
00509 return true;
00510 }
00511
00512 }
00513