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
00034
00035
00040 #include <reem_kinematics_constraint_aware/reem_arm_kinematics_plugin.h>
00041 #include <pluginlib/class_list_macros.h>
00042
00043 using namespace KDL;
00044 using namespace tf;
00045 using namespace std;
00046 using namespace ros;
00047
00048 const double BOUNDS_EPSILON = .00001;
00049
00050
00051 PLUGINLIB_DECLARE_CLASS(reem_kinematics_constraint_aware,ReemKinematicsPlugin, reem_kinematics_constraint_aware::ReemKinematicsPlugin, kinematics::KinematicsBase)
00052
00053 namespace reem_kinematics_constraint_aware {
00054
00055 ReemKinematicsPlugin::ReemKinematicsPlugin():active_(false)
00056 {
00057 srand ( time(NULL) );
00058 }
00059
00060 bool ReemKinematicsPlugin::isActive()
00061 {
00062 if(active_)
00063 return true;
00064 return false;
00065 }
00066
00067 double ReemKinematicsPlugin::genRandomNumber(const double &min, const double &max)
00068 {
00069 int rand_num = rand()%100+1;
00070 double result = min + (double)((max-min)*rand_num)/101.0;
00071 return result;
00072 }
00073
00074 KDL::JntArray ReemKinematicsPlugin::getRandomConfiguration()
00075 {
00076 KDL::JntArray jnt_array;
00077 jnt_array.resize(dimension_);
00078 for(unsigned int i=0; i < dimension_; ++i)
00079 jnt_array(i) = genRandomNumber(joint_min_(i),joint_max_(i));
00080 return jnt_array;
00081 }
00082
00083 KDL::JntArray ReemKinematicsPlugin::getRandomConfiguration(const KDL::JntArray& seed_state,
00084 const unsigned int& redundancy,
00085 const double& consistency_limit)
00086 {
00087 KDL::JntArray jnt_array;
00088 jnt_array.resize(dimension_);
00089 for(unsigned int i=0; i < dimension_; i++) {
00090 if(i != redundancy) {
00091 jnt_array(i) = genRandomNumber(joint_min_(i),joint_max_(i));
00092 } else {
00093 double jmin = fmin(joint_min_(i), seed_state(i)-consistency_limit);
00094 double jmax = fmax(joint_max_(i), seed_state(i)+consistency_limit);
00095 jnt_array(i) = genRandomNumber(jmin, jmax);
00096 }
00097 }
00098 return jnt_array;
00099 }
00100
00101 bool ReemKinematicsPlugin::checkConsistency(const KDL::JntArray& seed_state,
00102 const unsigned int& redundancy,
00103 const double& consistency_limit,
00104 const KDL::JntArray& solution) const
00105 {
00106 KDL::JntArray jnt_array;
00107 jnt_array.resize(dimension_);
00108 for(unsigned int i=0; i < dimension_; i++) {
00109 if(i == redundancy) {
00110 double jmin = fmin(joint_min_(i), seed_state(i)-consistency_limit);
00111 double jmax = fmax(joint_max_(i), seed_state(i)+consistency_limit);
00112 if(solution(i) < jmin || solution(i) > jmax) {
00113 return false;
00114 }
00115 }
00116 }
00117 return true;
00118 }
00119
00120 bool ReemKinematicsPlugin::initialize(const std::string& group_name,
00121 const std::string& base_name,
00122 const std::string& tip_name,
00123 const double& search_discretization)
00124 {
00125 setValues(group_name, base_name, tip_name, search_discretization);
00126
00127 std::string urdf_xml, full_urdf_xml;
00128 ros::NodeHandle node_handle;
00129 ros::NodeHandle private_handle("~"+group_name);
00130 ROS_INFO_STREAM("Private handle registered under " << private_handle.getNamespace());
00131 node_handle.param("urdf_xml",urdf_xml,std::string("robot_description"));
00132 node_handle.searchParam(urdf_xml,full_urdf_xml);
00133 ROS_DEBUG("Reading xml file from parameter server");
00134 std::string result;
00135 if (!node_handle.getParam(full_urdf_xml, result)) {
00136 ROS_FATAL("Could not load the xml from parameter server: %s", urdf_xml.c_str());
00137 return false;
00138 }
00139
00140
00141 if (!loadModel(result)) {
00142 ROS_FATAL("Could not load models!");
00143 return false;
00144 }
00145
00146
00147 std::map<std::string, int> joint_name_to_idx;
00148 for (size_t i = 0; i < kdl_chain_.getNrOfSegments(); ++i)
00149 {
00150 const KDL::Joint& joint = kdl_chain_.getSegment(i).getJoint();
00151 if (joint.getType() != KDL::Joint::None)
00152 {
00153 joint_name_to_idx[joint.getName()] = i;
00154 }
00155 }
00156
00157
00158 const int q_dim = kdl_chain_.getNrOfJoints();
00159 const int x_dim = 6;
00160
00161
00162 int max_iterations;
00163 double epsilon;
00164 double max_delta_x;
00165 double max_delta_q;
00166 double velik_gain;
00167
00168 private_handle.param("max_solver_iterations", max_iterations, 500);
00169 private_handle.param("max_search_iterations", max_search_iterations_, 3);
00170 private_handle.param("epsilon", epsilon, 1e-5);
00171 private_handle.param("max_delta_x", max_delta_x, 0.006);
00172 private_handle.param("max_delta_q", max_delta_q, 0.03);
00173 private_handle.param("velik_gain", velik_gain, 1.0);
00174
00175
00176 Eigen::VectorXd Wqinv = Eigen::VectorXd::Ones(q_dim);
00177 default_posture_.resize(q_dim);
00178 for (size_t i = 0; i < kdl_chain_.getNrOfSegments(); ++i)
00179 {
00180 const KDL::Joint& joint = kdl_chain_.getSegment(i).getJoint();
00181 if (joint.getType() != KDL::Joint::None)
00182 {
00183 private_handle.param("joint_weights/" + joint.getName(), Wqinv(joint_name_to_idx[joint.getName()]), 1.0);
00184 private_handle.param("default_posture/" + joint.getName(), default_posture_[joint_name_to_idx[joint.getName()]], 0.0);
00185 }
00186 }
00187
00188
00189 Eigen::VectorXd Wxinv = Eigen::VectorXd::Ones(x_dim);
00190 private_handle.param("task_weights/position/x", Wxinv(0), 1.0);
00191 private_handle.param("task_weights/position/y", Wxinv(1), 1.0);
00192 private_handle.param("task_weights/position/z", Wxinv(2), 1.0);
00193 private_handle.param("task_weights/orientation/x", Wxinv(3), 1.0);
00194 private_handle.param("task_weights/orientation/y", Wxinv(4), 1.0);
00195 private_handle.param("task_weights/orientation/z", Wxinv(5), 1.0);
00196
00197
00198 fk_solver_.reset(new KDL::ChainFkSolverPos_recursive(kdl_chain_));
00199 ik_solver_.reset(new IkSolver(kdl_chain_));
00200 ik_solver_->setJointPositionLimits(joint_min_.data, joint_max_.data);
00201 ik_solver_->setEpsilon(epsilon);
00202 ik_solver_->setMaxIterations(max_iterations);
00203 ik_solver_->setMaxDeltaPosTask(max_delta_x);
00204 ik_solver_->setMaxDeltaPosJoint(max_delta_q);
00205 ik_solver_->setVelocityIkGain(velik_gain);
00206 ik_solver_->setJointSpaceWeights(Wqinv);
00207 ik_solver_->setTaskSpaceWeights(Wxinv);
00208 active_ = true;
00209 return true;
00210 }
00211
00212 bool ReemKinematicsPlugin::loadModel(const std::string xml)
00213 {
00214 urdf::Model robot_model;
00215 KDL::Tree tree;
00216
00217 if (!robot_model.initString(xml)) {
00218 ROS_FATAL("Could not initialize robot model");
00219 return -1;
00220 }
00221 if (!kdl_parser::treeFromString(xml, tree)) {
00222 ROS_ERROR("Could not initialize tree object");
00223 return false;
00224 }
00225 if (!tree.getChain(base_name_, tip_name_, kdl_chain_)) {
00226 ROS_ERROR("Could not initialize chain object");
00227 return false;
00228 }
00229 if (!readJoints(robot_model)) {
00230 ROS_FATAL("Could not read information about the joints");
00231 return false;
00232 }
00233 return true;
00234 }
00235
00236 bool ReemKinematicsPlugin::readJoints(urdf::Model &robot_model)
00237 {
00238 dimension_ = 0;
00239
00240 boost::shared_ptr<const urdf::Link> link = robot_model.getLink(tip_name_);
00241 boost::shared_ptr<const urdf::Joint> joint;
00242 while (link && link->name != base_name_) {
00243 joint = robot_model.getJoint(link->parent_joint->name);
00244 if (!joint) {
00245 ROS_ERROR("Could not find joint: %s",link->parent_joint->name.c_str());
00246 return false;
00247 }
00248 if (joint->type != urdf::Joint::UNKNOWN && joint->type != urdf::Joint::FIXED) {
00249 ROS_INFO( "adding joint: [%s]", joint->name.c_str() );
00250 dimension_++;
00251 }
00252 link = robot_model.getLink(link->getParent()->name);
00253 }
00254 joint_min_.resize(dimension_);
00255 joint_max_.resize(dimension_);
00256 chain_info_.joint_names.resize(dimension_);
00257 chain_info_.limits.resize(dimension_);
00258 link = robot_model.getLink(tip_name_);
00259 if(link)
00260 chain_info_.link_names.push_back(tip_name_);
00261
00262 unsigned int i = 0;
00263 while (link && i < dimension_) {
00264 joint = robot_model.getJoint(link->parent_joint->name);
00265 if (joint->type != urdf::Joint::UNKNOWN && joint->type != urdf::Joint::FIXED) {
00266 ROS_INFO( "getting bounds for joint: [%s]", joint->name.c_str() );
00267
00268 float lower, upper;
00269 int hasLimits;
00270 if ( joint->type != urdf::Joint::CONTINUOUS ) {
00271 if(joint->safety) {
00272 lower = joint->safety->soft_lower_limit+BOUNDS_EPSILON;
00273 upper = joint->safety->soft_upper_limit-BOUNDS_EPSILON;
00274 } else {
00275 lower = joint->limits->lower+BOUNDS_EPSILON;
00276 upper = joint->limits->upper-BOUNDS_EPSILON;
00277 }
00278 hasLimits = 1;
00279 } else {
00280 lower = -M_PI;
00281 upper = M_PI;
00282 hasLimits = 0;
00283 }
00284 int index = dimension_ - i -1;
00285
00286 joint_min_.data[index] = lower;
00287 joint_max_.data[index] = upper;
00288 chain_info_.joint_names[index] = joint->name;
00289 chain_info_.limits[index].joint_name = joint->name;
00290 chain_info_.limits[index].has_position_limits = hasLimits;
00291 chain_info_.limits[index].min_position = lower;
00292 chain_info_.limits[index].max_position = upper;
00293 ++i;
00294 }
00295 link = robot_model.getLink(link->getParent()->name);
00296 }
00297 return true;
00298 }
00299
00300 int ReemKinematicsPlugin::getJointIndex(const std::string &name)
00301 {
00302 for (unsigned int i=0; i < chain_info_.joint_names.size(); ++i) {
00303 if (chain_info_.joint_names[i] == name)
00304 return i;
00305 }
00306 return -1;
00307 }
00308
00309 int ReemKinematicsPlugin::getKDLSegmentIndex(const std::string &name)
00310 {
00311 int i=0;
00312 while (i < (int)kdl_chain_.getNrOfSegments()) {
00313 if (kdl_chain_.getSegment(i).getName() == name) {
00314 return i+1;
00315 }
00316 ++i;
00317 }
00318 return -1;
00319 }
00320
00321 bool ReemKinematicsPlugin::getPositionIK(const geometry_msgs::Pose &ik_pose,
00322 const std::vector<double> &ik_seed_state,
00323 const std::vector<double> &posture,
00324 std::vector<double> &solution,
00325 int &error_code)
00326 {
00327 ros::WallTime n1 = ros::WallTime::now();
00328 if(!active_)
00329 {
00330 ROS_ERROR("kinematics not active");
00331 return false;
00332 }
00333
00334 ROS_DEBUG_STREAM("getPositionIK1:Position request pose is " <<
00335 ik_pose.position.x << " " <<
00336 ik_pose.position.y << " " <<
00337 ik_pose.position.z << " " <<
00338 ik_pose.orientation.x << " " <<
00339 ik_pose.orientation.y << " " <<
00340 ik_pose.orientation.z << " " <<
00341 ik_pose.orientation.w);
00342
00343 KDL::Frame pose_desired;
00344 tf::PoseMsgToKDL(ik_pose, pose_desired);
00345
00346 KDL::JntArray jnt_pos_in(dimension_);
00347 KDL::JntArray jnt_pos_out(dimension_);
00348 KDL::JntArray jnt_posture(dimension_);
00349 for(unsigned int i=0; i < dimension_; ++i)
00350 {
00351 jnt_pos_in(i) = ik_seed_state[i];
00352 jnt_posture(i) = posture[i];
00353 }
00354 ik_solver_->setPosture(jnt_posture);
00355 bool ik_valid = ik_solver_->solve(jnt_pos_in, pose_desired, jnt_pos_out);
00356 ROS_DEBUG_STREAM("IK success " << ik_valid << " time " << (ros::WallTime::now()-n1).toSec());
00357 solution.resize(dimension_);
00358
00359 for(unsigned int i=0; i < dimension_; ++i)
00360 {
00361 solution[i] = jnt_pos_out(i);
00362 }
00363 if(ik_valid)
00364 {
00365 error_code = kinematics::SUCCESS;
00366 return true;
00367 }
00368 else
00369 {
00370 ROS_DEBUG("An IK solution could not be found");
00371 error_code = kinematics::NO_IK_SOLUTION;
00372 return false;
00373 }
00374 }
00375
00376 bool ReemKinematicsPlugin::getPositionIK(const geometry_msgs::Pose &ik_pose,
00377 const std::vector<double> &ik_seed_state,
00378 std::vector<double> &solution,
00379 int &error_code)
00380 {
00381 return getPositionIK(ik_pose,
00382 ik_seed_state,
00383 default_posture_,
00384 solution,
00385 error_code);
00386 }
00387
00388 bool ReemKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00389 const std::vector<double> &ik_seed_state,
00390 const double &timeout,
00391 std::vector<double> &solution,
00392 int &error_code)
00393 {
00394 ros::WallTime n1 = ros::WallTime::now();
00395 if(!active_)
00396 {
00397 ROS_ERROR("kinematics not active");
00398 error_code = kinematics::INACTIVE;
00399 return false;
00400 }
00401 KDL::Frame pose_desired;
00402 tf::PoseMsgToKDL(ik_pose, pose_desired);
00403
00404 ROS_DEBUG_STREAM("searchPositionIK1:Position request pose is " <<
00405 ik_pose.position.x << " " <<
00406 ik_pose.position.y << " " <<
00407 ik_pose.position.z << " " <<
00408 ik_pose.orientation.x << " " <<
00409 ik_pose.orientation.y << " " <<
00410 ik_pose.orientation.z << " " <<
00411 ik_pose.orientation.w);
00412
00413
00414 KDL::JntArray jnt_pos_in;
00415 KDL::JntArray jnt_pos_out;
00416 jnt_pos_in.resize(dimension_);
00417 KDL::JntArray posture(dimension_);
00418 for(unsigned int i=0; i < dimension_; ++i)
00419 {
00420 jnt_pos_in(i) = ik_seed_state[i];
00421 posture(i) = default_posture_[i];
00422 }
00423 for(int i=0; i < max_search_iterations_; ++i)
00424 {
00425 for(unsigned int j=0; j < dimension_; ++j)
00426 {
00427 ROS_DEBUG_STREAM("seed state " << j << " " << jnt_pos_in(j));
00428 }
00429 ik_solver_->setPosture(posture);
00430 bool ik_valid = ik_solver_->solve(jnt_pos_in, pose_desired, jnt_pos_out);
00431 ROS_DEBUG_STREAM("IK success " << ik_valid << " time " << (ros::WallTime::now()-n1).toSec());
00432 if(ik_valid) {
00433 solution.resize(dimension_);
00434 for(unsigned int j=0; j < dimension_; ++j) {
00435 solution[j] = jnt_pos_out(j);
00436 }
00437 error_code = kinematics::SUCCESS;
00438 ROS_DEBUG_STREAM("Solved after " << i+1 << " iterations");
00439 return true;
00440 }
00441 jnt_pos_in = getRandomConfiguration();
00442 }
00443 ROS_DEBUG("An IK solution could not be found");
00444 error_code = kinematics::NO_IK_SOLUTION;
00445 return false;
00446 }
00447
00448 bool ReemKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00449 const std::vector<double> &ik_seed_state,
00450 const double &timeout,
00451 const unsigned int& redundancy,
00452 const double &consistency_limit,
00453 std::vector<double> &solution,
00454 int &error_code)
00455 {
00456 ros::WallTime n1 = ros::WallTime::now();
00457 if(!active_)
00458 {
00459 ROS_ERROR("kinematics not active");
00460 error_code = kinematics::INACTIVE;
00461 return false;
00462 }
00463 KDL::Frame pose_desired;
00464 tf::PoseMsgToKDL(ik_pose, pose_desired);
00465
00466 ROS_DEBUG_STREAM("searchPositionIK1:Position request pose is " <<
00467 ik_pose.position.x << " " <<
00468 ik_pose.position.y << " " <<
00469 ik_pose.position.z << " " <<
00470 ik_pose.orientation.x << " " <<
00471 ik_pose.orientation.y << " " <<
00472 ik_pose.orientation.z << " " <<
00473 ik_pose.orientation.w);
00474
00475
00476 KDL::JntArray jnt_pos_in;
00477 KDL::JntArray jnt_pos_out;
00478 KDL::JntArray jnt_seed_state;
00479 jnt_pos_in.resize(dimension_);
00480 KDL::JntArray posture(dimension_);
00481 for(unsigned int i=0; i < dimension_; ++i)
00482 {
00483 jnt_seed_state(i) = ik_seed_state[i];
00484 posture(i) = default_posture_[i];
00485 }
00486 jnt_pos_in = jnt_seed_state;
00487 for(int i=0; i < max_search_iterations_; ++i)
00488 {
00489 for(unsigned int j=0; j < dimension_; ++j)
00490 {
00491 ROS_DEBUG_STREAM("seed state " << j << " " << jnt_pos_in(j));
00492 }
00493 ik_solver_->setPosture(posture);
00494 int ik_valid = ik_solver_->solve(jnt_pos_in, pose_desired, jnt_pos_out);
00495 ROS_DEBUG_STREAM("IK success " << ik_valid << " time " << (ros::WallTime::now()-n1).toSec());
00496 if(ik_valid >= 0 && checkConsistency(jnt_seed_state, redundancy, consistency_limit, jnt_pos_out)) {
00497 solution.resize(dimension_);
00498 for(unsigned int j=0; j < dimension_; j++) {
00499 solution[j] = jnt_pos_out(j);
00500 }
00501 error_code = kinematics::SUCCESS;
00502 ROS_DEBUG_STREAM("Solved after " << i+1 << " iterations");
00503 return true;
00504 }
00505 jnt_pos_in = getRandomConfiguration(jnt_seed_state, redundancy, consistency_limit);
00506 }
00507 ROS_DEBUG("An IK solution could not be found");
00508 error_code = kinematics::NO_IK_SOLUTION;
00509 return false;
00510 }
00511
00512 bool ReemKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00513 const std::vector<double> &ik_seed_state,
00514 const double &timeout,
00515 std::vector<double> &solution,
00516 const boost::function<void(const geometry_msgs::Pose &ik_pose,const std::vector<double> &ik_solution,int &error_code)> &desired_pose_callback,
00517 const boost::function<void(const geometry_msgs::Pose &ik_pose,const std::vector<double> &ik_solution,int &error_code)> &solution_callback,
00518 int &error_code)
00519 {
00520 if(!active_)
00521 {
00522 ROS_ERROR("kinematics not active");
00523 error_code = kinematics::INACTIVE;
00524 return false;
00525 }
00526 KDL::Frame pose_desired;
00527 tf::PoseMsgToKDL(ik_pose, pose_desired);
00528
00529 ROS_DEBUG_STREAM("searchPositionIK2: Position request pose is " <<
00530 ik_pose.position.x << " " <<
00531 ik_pose.position.y << " " <<
00532 ik_pose.position.z << " " <<
00533 ik_pose.orientation.x << " " <<
00534 ik_pose.orientation.y << " " <<
00535 ik_pose.orientation.z << " " <<
00536 ik_pose.orientation.w);
00537
00538
00539 KDL::JntArray jnt_pos_in;
00540 KDL::JntArray jnt_pos_out;
00541 jnt_pos_in.resize(dimension_);
00542 KDL::JntArray posture(dimension_);
00543 for(unsigned int i=0; i < dimension_; ++i)
00544 {
00545 jnt_pos_in(i) = ik_seed_state[i];
00546 posture(i) = default_posture_[i];
00547 }
00548
00549 if(!desired_pose_callback.empty())
00550 desired_pose_callback(ik_pose,ik_seed_state,error_code);
00551
00552 if(error_code < 0)
00553 {
00554 ROS_DEBUG("Could not find inverse kinematics for desired end-effector pose since the pose may be in collision");
00555 return false;
00556 }
00557 for(int i=0; i < max_search_iterations_; ++i)
00558 {
00559 ik_solver_->setPosture(posture);
00560 bool ik_valid = ik_solver_->solve(jnt_pos_in, pose_desired, jnt_pos_out);
00561 jnt_pos_in = getRandomConfiguration();
00562 if(!ik_valid)
00563 continue;
00564 std::vector<double> solution_local;
00565 solution_local.resize(dimension_);
00566 for(unsigned int j=0; j < dimension_; ++j)
00567 solution_local[j] = jnt_pos_out(j);
00568 solution_callback(ik_pose,solution_local,error_code);
00569 if(error_code == kinematics::SUCCESS)
00570 {
00571 solution = solution_local;
00572 ROS_DEBUG_STREAM("Solved after " << i+1 << " iterations");
00573 return true;
00574 }
00575 }
00576 ROS_DEBUG("An IK that satisifes the constraints and is collision free could not be found");
00577 error_code = kinematics::NO_IK_SOLUTION;
00578 return false;
00579 }
00580
00581 bool ReemKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00582 const std::vector<double> &ik_seed_state,
00583 const double &timeout,
00584 const unsigned int& redundancy,
00585 const double& consistency_limit,
00586 std::vector<double> &solution,
00587 const boost::function<void(const geometry_msgs::Pose &ik_pose,const std::vector<double> &ik_solution,int &error_code)> &desired_pose_callback,
00588 const boost::function<void(const geometry_msgs::Pose &ik_pose,const std::vector<double> &ik_solution,int &error_code)> &solution_callback,
00589 int &error_code)
00590 {
00591 if(!active_)
00592 {
00593 ROS_ERROR("kinematics not active");
00594 error_code = kinematics::INACTIVE;
00595 return false;
00596 }
00597 KDL::Frame pose_desired;
00598 tf::PoseMsgToKDL(ik_pose, pose_desired);
00599
00600 ROS_DEBUG_STREAM("searchPositionIK2: Position request pose is " <<
00601 ik_pose.position.x << " " <<
00602 ik_pose.position.y << " " <<
00603 ik_pose.position.z << " " <<
00604 ik_pose.orientation.x << " " <<
00605 ik_pose.orientation.y << " " <<
00606 ik_pose.orientation.z << " " <<
00607 ik_pose.orientation.w);
00608
00609
00610
00611 KDL::JntArray jnt_pos_in;
00612 KDL::JntArray jnt_pos_out;
00613 KDL::JntArray jnt_seed_state;
00614 jnt_pos_in.resize(dimension_);
00615 KDL::JntArray posture(dimension_);
00616 for(unsigned int i=0; i < dimension_; ++i)
00617 {
00618 jnt_seed_state(i) = ik_seed_state[i];
00619 posture(i) = default_posture_[i];
00620 }
00621 jnt_pos_in = jnt_seed_state;
00622
00623 if(!desired_pose_callback.empty())
00624 desired_pose_callback(ik_pose,ik_seed_state,error_code);
00625
00626 if(error_code < 0)
00627 {
00628 ROS_DEBUG("Could not find inverse kinematics for desired end-effector pose since the pose may be in collision");
00629 return false;
00630 }
00631 for(int i=0; i < max_search_iterations_; ++i)
00632 {
00633 ik_solver_->setPosture(posture);
00634 int ik_valid = ik_solver_->solve(jnt_pos_in,pose_desired,jnt_pos_out);
00635 jnt_pos_in = getRandomConfiguration(jnt_seed_state, redundancy, consistency_limit);
00636 if(ik_valid < 0 || !checkConsistency(jnt_seed_state, redundancy, consistency_limit, jnt_pos_out))
00637 continue;
00638 std::vector<double> solution_local;
00639 solution_local.resize(dimension_);
00640 for(unsigned int j=0; j < dimension_; j++)
00641 solution_local[j] = jnt_pos_out(j);
00642 solution_callback(ik_pose,solution_local,error_code);
00643 if(error_code == kinematics::SUCCESS)
00644 {
00645 solution = solution_local;
00646 ROS_DEBUG_STREAM("Solved after " << i+1 << " iterations");
00647 return true;
00648 }
00649 }
00650 ROS_DEBUG("An IK that satisifes the constraints and is collision free could not be found");
00651 error_code = kinematics::NO_IK_SOLUTION;
00652 return false;
00653 }
00654
00655 bool ReemKinematicsPlugin::getPositionFK(const std::vector<std::string> &link_names,
00656 const std::vector<double> &joint_angles,
00657 std::vector<geometry_msgs::Pose> &poses)
00658 {
00659 if(!active_)
00660 {
00661 ROS_ERROR("kinematics not active");
00662 return false;
00663 }
00664
00665 KDL::Frame p_out;
00666 KDL::JntArray jnt_pos_in;
00667 geometry_msgs::PoseStamped pose;
00668 tf::Stamped<tf::Pose> tf_pose;
00669
00670 jnt_pos_in.resize(dimension_);
00671 for(unsigned int i=0; i < dimension_; ++i)
00672 {
00673 jnt_pos_in(i) = joint_angles[i];
00674 }
00675
00676 poses.resize(link_names.size());
00677
00678 bool valid = true;
00679 for(unsigned int i=0; i < poses.size(); ++i)
00680 {
00681 if(fk_solver_->JntToCart(jnt_pos_in,p_out,getKDLSegmentIndex(link_names[i])) >=0)
00682 {
00683 tf::PoseKDLToMsg(p_out,poses[i]);
00684 }
00685 else
00686 {
00687 ROS_ERROR("Could not compute FK for %s",link_names[i].c_str());
00688 valid = false;
00689 }
00690 }
00691 return valid;
00692 }
00693
00694 std::string ReemKinematicsPlugin::getBaseFrame()
00695 {
00696 if(!active_)
00697 {
00698 ROS_ERROR("kinematics not active");
00699 return std::string("");
00700 }
00701 return base_name_;
00702 }
00703
00704 std::string ReemKinematicsPlugin::getToolFrame()
00705 {
00706 if(!active_ || chain_info_.link_names.empty())
00707 {
00708 ROS_ERROR("kinematics not active");
00709 return std::string("");
00710 }
00711 return chain_info_.link_names[0];
00712 }
00713
00714 const std::vector<std::string>& ReemKinematicsPlugin::getJointNames() const
00715 {
00716 if(!active_)
00717 {
00718 ROS_ERROR("kinematics not active");
00719 }
00720 return chain_info_.joint_names;
00721 }
00722
00723 const std::vector<std::string>& ReemKinematicsPlugin::getLinkNames() const
00724 {
00725 if(!active_)
00726 {
00727 ROS_ERROR("kinematics not active");
00728 }
00729 return chain_info_.link_names;
00730 }
00731
00732 }