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
00036
00037 #include <moveit/robot_state/robot_state.h>
00038 #include <eigen_conversions/eigen_msg.h>
00039 #include <boost/bind.hpp>
00040 #include <boost/math/constants/constants.hpp>
00041 #include <algorithm>
00042 #include <Eigen/SVD>
00043
00044 robot_state::JointStateGroup::JointStateGroup(RobotState *state,
00045 const robot_model::JointModelGroup *jmg) :
00046 kinematic_state_(state), joint_model_group_(jmg)
00047 {
00048 const std::vector<const robot_model::JointModel*>& joint_model_vector = jmg->getJointModels();
00049 for (std::size_t i = 0; i < joint_model_vector.size() ; ++i)
00050 {
00051 assert(kinematic_state_->hasJointState(joint_model_vector[i]->getName()));
00052 JointState* js = kinematic_state_->getJointState(joint_model_vector[i]->getName());
00053 joint_state_vector_.push_back(js);
00054 joint_state_map_[joint_model_vector[i]->getName()] = js;
00055 }
00056 const std::vector<const robot_model::LinkModel*>& link_model_vector = jmg->getUpdatedLinkModels();
00057 for (unsigned int i = 0; i < link_model_vector.size(); i++)
00058 {
00059 assert(kinematic_state_->hasLinkState(link_model_vector[i]->getName()));
00060 LinkState* ls = kinematic_state_->getLinkState(link_model_vector[i]->getName());
00061 updated_links_.push_back(ls);
00062 }
00063
00064 const std::vector<const robot_model::JointModel*>& joint_root_vector = jmg->getJointRoots();
00065 for (std::size_t i = 0; i < joint_root_vector.size(); ++i)
00066 {
00067 JointState* js = kinematic_state_->getJointState(joint_root_vector[i]->getName());
00068 if (js)
00069 joint_roots_.push_back(js);
00070 }
00071 }
00072
00073 robot_state::JointStateGroup::~JointStateGroup()
00074 {
00075 }
00076
00077 random_numbers::RandomNumberGenerator& robot_state::JointStateGroup::getRandomNumberGenerator()
00078 {
00079 if (!rng_)
00080 rng_.reset(new random_numbers::RandomNumberGenerator());
00081 return *rng_;
00082 }
00083
00084 bool robot_state::JointStateGroup::hasJointState(const std::string &joint) const
00085 {
00086 return joint_state_map_.find(joint) != joint_state_map_.end();
00087 }
00088
00089 bool robot_state::JointStateGroup::setVariableValues(const std::vector<double> &joint_state_values)
00090 {
00091 if (joint_state_values.size() != getVariableCount())
00092 {
00093 logError("JointStateGroup: Incorrect variable count specified for array of joint values. Expected %u but got %u values in group '%s'",
00094 getVariableCount(), (int)joint_state_values.size(), joint_model_group_->getName().c_str() );
00095 return false;
00096 }
00097
00098 unsigned int value_counter = 0;
00099 for(unsigned int i = 0; i < joint_state_vector_.size(); i++)
00100 {
00101 unsigned int dim = joint_state_vector_[i]->getVariableCount();
00102 if (dim != 0)
00103 {
00104 joint_state_vector_[i]->setVariableValues(&joint_state_values[value_counter]);
00105 value_counter += dim;
00106 }
00107 }
00108 updateLinkTransforms();
00109 return true;
00110 }
00111
00112 bool robot_state::JointStateGroup::setVariableValues(const Eigen::VectorXd &joint_state_values)
00113 {
00114 std::vector<double> values(joint_state_values.rows());
00115 for (std::size_t i = 0; i < joint_state_values.rows(); i++)
00116 values[i] = joint_state_values(i);
00117 setVariableValues(values);
00118 }
00119
00120 void robot_state::JointStateGroup::setVariableValues(const std::map<std::string, double>& joint_state_map)
00121 {
00122 for(unsigned int i = 0; i < joint_state_vector_.size(); ++i)
00123 joint_state_vector_[i]->setVariableValues(joint_state_map);
00124 updateLinkTransforms();
00125 }
00126
00127 void robot_state::JointStateGroup::setVariableValues(const sensor_msgs::JointState& js)
00128 {
00129 std::map<std::string, double> v;
00130 for (std::size_t i = 0 ; i < js.name.size() ; ++i)
00131 v[js.name[i]] = js.position[i];
00132 setVariableValues(v);
00133 }
00134
00135 void robot_state::JointStateGroup::updateLinkTransforms()
00136 {
00137 for(unsigned int i = 0; i < updated_links_.size(); ++i)
00138 updated_links_[i]->computeTransform();
00139 }
00140
00141 robot_state::JointStateGroup& robot_state::JointStateGroup::operator=(const JointStateGroup &other)
00142 {
00143 if (this != &other)
00144 copyFrom(other);
00145 return *this;
00146 }
00147
00148 void robot_state::JointStateGroup::copyFrom(const JointStateGroup &other_jsg)
00149 {
00150 const std::vector<JointState*> &ojsv = other_jsg.getJointStateVector();
00151 for (std::size_t i = 0 ; i < ojsv.size() ; ++i)
00152 joint_state_vector_[i]->setVariableValues(ojsv[i]->getVariableValues());
00153 updateLinkTransforms();
00154 }
00155
00156 void robot_state::JointStateGroup::setToDefaultValues()
00157 {
00158 std::map<std::string, double> default_joint_values;
00159 for (std::size_t i = 0 ; i < joint_state_vector_.size() ; ++i)
00160 joint_state_vector_[i]->getJointModel()->getVariableDefaultValues(default_joint_values);
00161 setVariableValues(default_joint_values);
00162 }
00163
00164 bool robot_state::JointStateGroup::setToDefaultState(const std::string &name)
00165 {
00166 std::map<std::string, double> default_joint_values;
00167 if (!joint_model_group_->getVariableDefaultValues(name, default_joint_values))
00168 return false;
00169 setVariableValues(default_joint_values);
00170 return true;
00171 }
00172
00173 void robot_state::JointStateGroup::setToRandomValues()
00174 {
00175 random_numbers::RandomNumberGenerator &rng = getRandomNumberGenerator();
00176 std::vector<double> random_joint_states;
00177 joint_model_group_->getVariableRandomValues(rng, random_joint_states);
00178 setVariableValues(random_joint_states);
00179 }
00180
00181 void robot_state::JointStateGroup::setToRandomValuesNearBy(const std::vector<double> &near,
00182 const std::map<robot_model::JointModel::JointType, double> &distance_map)
00183 {
00184 random_numbers::RandomNumberGenerator &rng = getRandomNumberGenerator();
00185 std::vector<double> variable_values;
00186 joint_model_group_->getVariableRandomValuesNearBy(rng, variable_values, near, distance_map);
00187 setVariableValues(variable_values);
00188 }
00189
00190 void robot_state::JointStateGroup::setToRandomValuesNearBy(const std::vector<double> &near,
00191 const std::vector<double> &distances)
00192 {
00193 random_numbers::RandomNumberGenerator &rng = getRandomNumberGenerator();
00194 std::vector<double> variable_values;
00195 joint_model_group_->getVariableRandomValuesNearBy(rng, variable_values, near, distances);
00196 setVariableValues(variable_values);
00197 }
00198
00199 void robot_state::JointStateGroup::getVariableValues(std::vector<double>& joint_state_values) const
00200 {
00201 joint_state_values.clear();
00202 for(unsigned int i = 0; i < joint_state_vector_.size(); i++)
00203 {
00204 const std::vector<double> &jv = joint_state_vector_[i]->getVariableValues();
00205 joint_state_values.insert(joint_state_values.end(), jv.begin(), jv.end());
00206 }
00207 }
00208
00209 void robot_state::JointStateGroup::getVariableValues(Eigen::VectorXd& joint_state_values) const
00210 {
00211 joint_state_values.resize(getVariableCount());
00212 unsigned int count = 0;
00213 for(unsigned int i = 0; i < joint_state_vector_.size(); i++)
00214 {
00215 const std::vector<double> &jv = joint_state_vector_[i]->getVariableValues();
00216 for (std::size_t j = 0; j < jv.size() ; ++j)
00217 joint_state_values(count++) = jv[j];
00218 }
00219 }
00220
00221 bool robot_state::JointStateGroup::satisfiesBounds(double margin) const
00222 {
00223 for (std::size_t i = 0 ; i < joint_state_vector_.size() ; ++i)
00224 if (!joint_state_vector_[i]->satisfiesBounds(margin))
00225 return false;
00226 return true;
00227 }
00228
00229 void robot_state::JointStateGroup::enforceBounds()
00230 {
00231 for (std::size_t i = 0 ; i < joint_state_vector_.size() ; ++i)
00232 joint_state_vector_[i]->enforceBounds();
00233 updateLinkTransforms();
00234 }
00235
00236 double robot_state::JointStateGroup::infinityNormDistance(const JointStateGroup *other) const
00237 {
00238 if (joint_state_vector_.empty())
00239 return 0.0;
00240 double max_d = joint_state_vector_[0]->distance(other->joint_state_vector_[0]);
00241 for (std::size_t i = 1 ; i < joint_state_vector_.size() ; ++i)
00242 {
00243 double d = joint_state_vector_[i]->distance(other->joint_state_vector_[i]);
00244 if (d > max_d)
00245 max_d = d;
00246 }
00247 return max_d;
00248 }
00249
00250 double robot_state::JointStateGroup::distance(const JointStateGroup *other) const
00251 {
00252 double d = 0.0;
00253 for (std::size_t i = 0 ; i < joint_state_vector_.size() ; ++i)
00254 d += joint_state_vector_[i]->distance(other->joint_state_vector_[i]) * joint_state_vector_[i]->getJointModel()->getDistanceFactor();
00255 return d;
00256 }
00257
00258 void robot_state::JointStateGroup::interpolate(const JointStateGroup *to, const double t, JointStateGroup *dest) const
00259 {
00260 for (std::size_t i = 0 ; i < joint_state_vector_.size() ; ++i)
00261 joint_state_vector_[i]->interpolate(to->joint_state_vector_[i], t, dest->joint_state_vector_[i]);
00262 dest->updateLinkTransforms();
00263 }
00264
00265 void robot_state::JointStateGroup::getVariableValues(std::map<std::string, double>& joint_state_values) const
00266 {
00267 joint_state_values.clear();
00268 for (std::size_t i = 0; i < joint_state_vector_.size(); ++i)
00269 {
00270 const std::vector<double> &jsv = joint_state_vector_[i]->getVariableValues();
00271 const std::vector<std::string> &jsn = joint_state_vector_[i]->getVariableNames();
00272 for (std::size_t j = 0 ; j < jsv.size(); ++j)
00273 joint_state_values[jsn[j]] = jsv[j];
00274 }
00275 }
00276
00277 robot_state::JointState* robot_state::JointStateGroup::getJointState(const std::string &name) const
00278 {
00279 std::map<std::string, JointState*>::const_iterator it = joint_state_map_.find(name);
00280 if (it == joint_state_map_.end())
00281 {
00282 logError("Joint '%s' not found", name.c_str());
00283 return NULL;
00284 }
00285 else
00286 return it->second;
00287 }
00288
00289 bool robot_state::JointStateGroup::setFromIK(const geometry_msgs::Pose &pose, unsigned int attempts, double timeout, const StateValidityCallbackFn &constraint, const kinematics::KinematicsQueryOptions &options)
00290 {
00291 const kinematics::KinematicsBaseConstPtr& solver = joint_model_group_->getSolverInstance();
00292 if (!solver)
00293 {
00294 logError("No kinematics solver instantiated for this group");
00295 return false;
00296 }
00297 return setFromIK(pose, solver->getTipFrame(), attempts, timeout, constraint, options);
00298 }
00299
00300 bool robot_state::JointStateGroup::setFromIK(const geometry_msgs::Pose &pose, unsigned int attempts, double timeout, const kinematics::KinematicsQueryOptions &options)
00301 {
00302 const kinematics::KinematicsBaseConstPtr& solver = joint_model_group_->getSolverInstance();
00303 if (!solver)
00304 {
00305 logError("No kinematics solver instantiated for this group");
00306 return false;
00307 }
00308 static StateValidityCallbackFn constraint = StateValidityCallbackFn();
00309 return setFromIK(pose, solver->getTipFrame(), attempts, timeout, constraint, options);
00310 }
00311
00312 bool robot_state::JointStateGroup::setFromIK(const geometry_msgs::Pose &pose, const std::string &tip, unsigned int attempts, double timeout, const StateValidityCallbackFn &constraint, const kinematics::KinematicsQueryOptions &options)
00313 {
00314 Eigen::Affine3d mat;
00315 tf::poseMsgToEigen(pose, mat);
00316 return setFromIK(mat, tip, attempts, timeout, constraint, options);
00317 }
00318
00319 bool robot_state::JointStateGroup::setFromIK(const Eigen::Affine3d &pose, unsigned int attempts, double timeout, const StateValidityCallbackFn &constraint, const kinematics::KinematicsQueryOptions &options)
00320 {
00321 const kinematics::KinematicsBaseConstPtr& solver = joint_model_group_->getSolverInstance();
00322 if (!solver)
00323 {
00324 logError("No kinematics solver instantiated for this group");
00325 return false;
00326 }
00327 static std::vector<double> consistency_limits;
00328 return setFromIK(pose, solver->getTipFrame(), consistency_limits, attempts, timeout, constraint, options);
00329 }
00330
00331 bool robot_state::JointStateGroup::setFromIK(const Eigen::Affine3d &pose_in, const std::string &tip_in, unsigned int attempts, double timeout, const StateValidityCallbackFn &constraint, const kinematics::KinematicsQueryOptions &options)
00332 {
00333 static std::vector<double> consistency_limits;
00334 return setFromIK(pose_in, tip_in, consistency_limits, attempts, timeout, constraint, options);
00335 }
00336
00337 bool robot_state::JointStateGroup::setFromIK(const Eigen::Affine3d &pose_in, const std::string &tip_in, unsigned int attempts, double timeout, const kinematics::KinematicsQueryOptions &options)
00338 {
00339 static std::vector<double> consistency_limits;
00340 static StateValidityCallbackFn constraint = StateValidityCallbackFn();
00341 return setFromIK(pose_in, tip_in, consistency_limits, attempts, timeout, constraint, options);
00342 }
00343
00344 bool robot_state::JointStateGroup::setFromIK(const Eigen::Affine3d &pose_in, unsigned int attempts, double timeout, const kinematics::KinematicsQueryOptions &options)
00345 {
00346 static std::vector<double> consistency_limits;
00347 static StateValidityCallbackFn constraint = StateValidityCallbackFn();
00348 const kinematics::KinematicsBaseConstPtr& solver = joint_model_group_->getSolverInstance();
00349 if (!solver)
00350 {
00351 logError("No kinematics solver instantiated for this group");
00352 return false;
00353 }
00354 return setFromIK(pose_in, solver->getTipFrame(), consistency_limits, attempts, timeout, constraint, options);
00355 }
00356
00357 bool robot_state::JointStateGroup::setFromIK(const Eigen::Affine3d &pose_in, const std::string &tip_in, const std::vector<double> &consistency_limits, unsigned int attempts, double timeout, const StateValidityCallbackFn &constraint, const kinematics::KinematicsQueryOptions &options)
00358 {
00359 const kinematics::KinematicsBaseConstPtr& solver = joint_model_group_->getSolverInstance();
00360 if (!solver)
00361 {
00362 logError("No kinematics solver instantiated for this group");
00363 return false;
00364 }
00365
00366 Eigen::Affine3d pose = pose_in;
00367 std::string tip = tip_in;
00368
00369
00370 const std::string &ik_frame = solver->getBaseFrame();
00371 if (ik_frame != joint_model_group_->getParentModel()->getModelFrame())
00372 {
00373 const LinkState *ls = kinematic_state_->getLinkState(ik_frame);
00374 if (!ls)
00375 return false;
00376 pose = ls->getGlobalLinkTransform().inverse() * pose;
00377 }
00378
00379
00380 const std::string &tip_frame = solver->getTipFrame();
00381 if (tip != tip_frame)
00382 {
00383 if (kinematic_state_->hasAttachedBody(tip))
00384 {
00385 const AttachedBody *ab = kinematic_state_->getAttachedBody(tip);
00386 const EigenSTL::vector_Affine3d &ab_trans = ab->getFixedTransforms();
00387 if (ab_trans.size() != 1)
00388 {
00389 logError("Cannot use an attached body with multiple geometries as a reference frame.");
00390 return false;
00391 }
00392 tip = ab->getAttachedLinkName();
00393 pose = pose * ab_trans[0].inverse();
00394 }
00395 if (tip != tip_frame)
00396 {
00397 const robot_model::LinkModel *lm = joint_model_group_->getParentModel()->getLinkModel(tip);
00398 if (!lm)
00399 return false;
00400 const robot_model::LinkModel::AssociatedFixedTransformMap &fixed_links = lm->getAssociatedFixedTransforms();
00401 for (std::map<const robot_model::LinkModel*, Eigen::Affine3d>::const_iterator it = fixed_links.begin() ; it != fixed_links.end() ; ++it)
00402 if (it->first->getName() == tip_frame)
00403 {
00404 tip = tip_frame;
00405 pose = pose * it->second;
00406 break;
00407 }
00408 }
00409 }
00410
00411 if (tip != tip_frame)
00412 {
00413 logError("Cannot compute IK for tip reference frame '%s'", tip.c_str());
00414 return false;
00415 }
00416
00417
00418 if (timeout < std::numeric_limits<double>::epsilon())
00419 timeout = joint_model_group_->getDefaultIKTimeout();
00420
00421 if (attempts == 0)
00422 attempts = joint_model_group_->getDefaultIKAttempts();
00423
00424 const std::vector<unsigned int> &bij = joint_model_group_->getKinematicsSolverJointBijection();
00425 Eigen::Quaterniond quat(pose.rotation());
00426 Eigen::Vector3d point(pose.translation());
00427 geometry_msgs::Pose ik_query;
00428 ik_query.position.x = point.x();
00429 ik_query.position.y = point.y();
00430 ik_query.position.z = point.z();
00431 ik_query.orientation.x = quat.x();
00432 ik_query.orientation.y = quat.y();
00433 ik_query.orientation.z = quat.z();
00434 ik_query.orientation.w = quat.w();
00435
00436 kinematics::KinematicsBase::IKCallbackFn ik_callback_fn;
00437 if (constraint)
00438 ik_callback_fn = boost::bind(&JointStateGroup::ikCallbackFnAdapter, this, constraint, _1, _2, _3);
00439
00440 bool first_seed = true;
00441 std::vector<double> initial_values;
00442 getVariableValues(initial_values);
00443 for (unsigned int st = 0 ; st < attempts ; ++st)
00444 {
00445 std::vector<double> seed(bij.size());
00446
00447
00448 if (first_seed)
00449 {
00450 first_seed = false;
00451 for (std::size_t i = 0 ; i < bij.size() ; ++i)
00452 seed[bij[i]] = initial_values[i];
00453 }
00454 else
00455 {
00456
00457 random_numbers::RandomNumberGenerator &rng = getRandomNumberGenerator();
00458 std::vector<double> random_values;
00459 joint_model_group_->getVariableRandomValues(rng, random_values);
00460 for (std::size_t i = 0 ; i < bij.size() ; ++i)
00461 seed[bij[i]] = random_values[i];
00462
00463 if (options.lock_redundant_joints)
00464 {
00465 std::vector<unsigned int> red_joints;
00466 solver->getRedundantJoints(red_joints);
00467 if (!red_joints.empty())
00468 {
00469 for(std::size_t i = 0 ; i < red_joints.size(); ++i)
00470 {
00471 seed[bij[red_joints[i]]] = initial_values[red_joints[i]];
00472 }
00473 }
00474 }
00475 }
00476
00477
00478 std::vector<double> ik_sol;
00479 moveit_msgs::MoveItErrorCodes error;
00480 if (ik_callback_fn ?
00481 solver->searchPositionIK(ik_query, seed, timeout, consistency_limits, ik_sol, ik_callback_fn, error, options) :
00482 solver->searchPositionIK(ik_query, seed, timeout, consistency_limits, ik_sol, error, options))
00483 {
00484 std::vector<double> solution(bij.size());
00485 for (std::size_t i = 0 ; i < bij.size() ; ++i)
00486 solution[i] = ik_sol[bij[i]];
00487 setVariableValues(solution);
00488 return true;
00489 }
00490 }
00491 return false;
00492 }
00493
00494 bool robot_state::JointStateGroup::setFromIK(const EigenSTL::vector_Affine3d &poses_in,
00495 const std::vector<std::string> &tips_in,
00496 unsigned int attempts,
00497 double timeout,
00498 const StateValidityCallbackFn &constraint,
00499 const kinematics::KinematicsQueryOptions &options)
00500 {
00501 static const std::vector<std::vector<double> > consistency_limits;
00502 return setFromIK(poses_in, tips_in, consistency_limits, attempts, timeout, constraint, options);
00503 }
00504
00505 bool robot_state::JointStateGroup::setFromIK(const EigenSTL::vector_Affine3d &poses_in,
00506 const std::vector<std::string> &tips_in,
00507 const std::vector<std::vector<double> > &consistency_limits,
00508 unsigned int attempts,
00509 double timeout,
00510 const StateValidityCallbackFn &constraint,
00511 const kinematics::KinematicsQueryOptions &options)
00512 {
00513 if (poses_in.size() == 1 && tips_in.size() == 1 && consistency_limits.size() <= 1)
00514 {
00515 if (consistency_limits.empty())
00516 return setFromIK(poses_in[0], tips_in[0], attempts, timeout, constraint, options);
00517 else
00518 return setFromIK(poses_in[0], tips_in[0], consistency_limits[0], attempts, timeout, constraint, options);
00519 }
00520
00521 const std::vector<std::string>& sub_group_names = joint_model_group_->getSubgroupNames();
00522
00523 if (poses_in.size() != sub_group_names.size())
00524 {
00525 logError("Number of poses must be the same as number of sub-groups");
00526 return false;
00527 }
00528
00529 if (tips_in.size() != sub_group_names.size())
00530 {
00531 logError("Number of tip names must be the same as number of sub-groups");
00532 return false;
00533 }
00534
00535 if (!consistency_limits.empty() && consistency_limits.size() != sub_group_names.size())
00536 {
00537 logError("Number of consistency limit vectors must be the same as number of sub-groups");
00538 return false;
00539 }
00540
00541 if (!consistency_limits.empty())
00542 {
00543 for (std::size_t i = 0 ; i < consistency_limits.size() ; ++i)
00544 {
00545 if (consistency_limits[i].size() != joint_model_group_->getParentModel()->getJointModelGroup(sub_group_names[i])->getVariableCount())
00546 {
00547 logError("Number of joints in consistency_limits is %u but it should be should be %u", (unsigned int)i,
00548 joint_model_group_->getParentModel()->getJointModelGroup(sub_group_names[i])->getVariableCount());
00549 return false;
00550 }
00551 }
00552 }
00553
00554 std::vector<kinematics::KinematicsBaseConstPtr> solvers;
00555 for(std::size_t i = 0; i < poses_in.size() ; ++i)
00556 {
00557 kinematics::KinematicsBaseConstPtr solver = joint_model_group_->getParentModel()->getJointModelGroup(sub_group_names[i])->getSolverInstance();
00558 if (!solver)
00559 {
00560 logError("Could not find solver for %s", sub_group_names[i].c_str());
00561 return false;
00562 }
00563 solvers.push_back(solver);
00564 }
00565
00566 EigenSTL::vector_Affine3d transformed_poses = poses_in;
00567 std::vector<std::string> tip_names = tips_in;
00568
00569 for(std::size_t i = 0 ; i < poses_in.size() ; ++i)
00570 {
00571 Eigen::Affine3d pose = poses_in[i];
00572 std::string tip = tips_in[i];
00573
00574
00575 const std::string &ik_frame = solvers[i]->getBaseFrame();
00576 if (ik_frame != joint_model_group_->getParentModel()->getModelFrame())
00577 {
00578 const LinkState *ls = kinematic_state_->getLinkState(ik_frame);
00579 if (!ls)
00580 return false;
00581 pose = ls->getGlobalLinkTransform().inverse() * pose;
00582 }
00583
00584
00585 const std::string &tip_frame = solvers[i]->getTipFrame();
00586 if (tip != tip_frame)
00587 {
00588 if (kinematic_state_->hasAttachedBody(tip))
00589 {
00590 const AttachedBody *ab = kinematic_state_->getAttachedBody(tip);
00591 const EigenSTL::vector_Affine3d &ab_trans = ab->getFixedTransforms();
00592 if (ab_trans.size() != 1)
00593 {
00594 logError("Cannot use an attached body with multiple geometries as a reference frame.");
00595 return false;
00596 }
00597 tip = ab->getAttachedLinkName();
00598 pose = pose * ab_trans[0].inverse();
00599 }
00600 if (tip != tip_frame)
00601 {
00602 const robot_model::LinkModel *lm = joint_model_group_->getParentModel()->getLinkModel(tip);
00603 if (!lm)
00604 return false;
00605 const robot_model::LinkModel::AssociatedFixedTransformMap &fixed_links = lm->getAssociatedFixedTransforms();
00606 for (std::map<const robot_model::LinkModel*, Eigen::Affine3d>::const_iterator it = fixed_links.begin() ; it != fixed_links.end() ; ++it)
00607 if (it->first->getName() == tip_frame)
00608 {
00609 tip = tip_frame;
00610 pose = pose * it->second;
00611 break;
00612 }
00613 }
00614 }
00615
00616 if (tip != tip_frame)
00617 {
00618 logError("Cannot compute IK for tip reference frame '%s'", tip.c_str());
00619 return false;
00620 }
00621 transformed_poses[i] = pose;
00622 tip_names[i] = tip;
00623 }
00624
00625 std::vector<geometry_msgs::Pose> ik_queries(poses_in.size());
00626 kinematics::KinematicsBase::IKCallbackFn ik_callback_fn;
00627 if (constraint)
00628 ik_callback_fn = boost::bind(&JointStateGroup::ikCallbackFnAdapter, this, constraint, _1, _2, _3);
00629
00630 for(std::size_t i = 0; i < transformed_poses.size(); ++i)
00631 {
00632 Eigen::Quaterniond quat(transformed_poses[i].rotation());
00633 Eigen::Vector3d point(transformed_poses[i].translation());
00634 ik_queries[i].position.x = point.x();
00635 ik_queries[i].position.y = point.y();
00636 ik_queries[i].position.z = point.z();
00637 ik_queries[i].orientation.x = quat.x();
00638 ik_queries[i].orientation.y = quat.y();
00639 ik_queries[i].orientation.z = quat.z();
00640 ik_queries[i].orientation.w = quat.w();
00641 }
00642
00643 if (attempts == 0)
00644 attempts = joint_model_group_->getDefaultIKAttempts();
00645
00646 bool first_seed = true;
00647 for (unsigned int st = 0 ; st < attempts ; ++st)
00648 {
00649 bool found_solution = true;
00650 for(std::size_t sg = 0; sg < sub_group_names.size(); ++sg)
00651 {
00652 robot_state::JointStateGroup* joint_state_group = getRobotState()->getJointStateGroup(sub_group_names[sg]);
00653 const std::vector<unsigned int>& bij = joint_state_group->getJointModelGroup()->getKinematicsSolverJointBijection();
00654 std::vector<double> seed(bij.size());
00655
00656 if (first_seed)
00657 {
00658 if(sg == sub_group_names.size()-1)
00659 first_seed = false;
00660 std::vector<double> initial_values;
00661 joint_state_group->getVariableValues(initial_values);
00662 for (std::size_t i = 0 ; i < bij.size() ; ++i)
00663 seed[bij[i]] = initial_values[i];
00664 }
00665 else
00666 {
00667
00668 random_numbers::RandomNumberGenerator &rng = getRandomNumberGenerator();
00669 std::vector<double> random_values;
00670 joint_state_group->getJointModelGroup()->getVariableRandomValues(rng, random_values);
00671 for (std::size_t i = 0 ; i < bij.size() ; ++i)
00672 seed[bij[i]] = random_values[i];
00673 }
00674
00675
00676 std::vector<double> ik_sol;
00677 moveit_msgs::MoveItErrorCodes error;
00678 if (!consistency_limits.empty() ?
00679 solvers[sg]->searchPositionIK(ik_queries[sg], seed, timeout < std::numeric_limits<double>::epsilon() ? joint_state_group->getDefaultIKTimeout() : timeout,
00680 consistency_limits[sg], ik_sol, error) :
00681 solvers[sg]->searchPositionIK(ik_queries[sg], seed, timeout < std::numeric_limits<double>::epsilon() ? joint_state_group->getDefaultIKTimeout() : timeout,
00682 ik_sol, error))
00683 {
00684 std::vector<double> solution(bij.size());
00685 for (std::size_t i = 0 ; i < bij.size() ; ++i)
00686 solution[i] = ik_sol[bij[i]];
00687 joint_state_group->setVariableValues(solution);
00688 }
00689 else
00690 {
00691 found_solution = false;
00692 break;
00693 }
00694 if(found_solution && sg == (sub_group_names.size() - 1))
00695 {
00696 std::vector<double> full_solution;
00697 getVariableValues(full_solution);
00698 if(constraint ? constraint(this, full_solution) : true)
00699 {
00700 logDebug("Found IK solution");
00701 return true;
00702 }
00703 }
00704 logDebug("IK attempt: %d of %d", st, attempts);
00705 }
00706 }
00707 return false;
00708 }
00709
00710 void robot_state::JointStateGroup::computeJointVelocity(Eigen::VectorXd &qdot, const Eigen::VectorXd &twist, const std::string &tip, const SecondaryTaskFn &st) const
00711 {
00712
00713 Eigen::MatrixXd J(6, getVariableCount());
00714 Eigen::Vector3d reference_point(0.0, 0.0, 0.0);
00715 getJacobian(tip, reference_point, J);
00716
00717
00718 Eigen::Affine3d eMb = getRobotState()->getLinkState(tip)->getGlobalLinkTransform().inverse();
00719 Eigen::MatrixXd eWb = Eigen::ArrayXXd::Zero(6, 6);
00720 eWb.block(0, 0, 3, 3) = eMb.matrix().block(0, 0, 3, 3);
00721 eWb.block(3, 3, 3, 3) = eMb.matrix().block(0, 0, 3, 3);
00722 J = eWb * J;
00723
00724
00725 Eigen::JacobiSVD<Eigen::MatrixXd> svdOfJ(J, Eigen::ComputeThinU | Eigen::ComputeThinV);
00726 const Eigen::MatrixXd U = svdOfJ.matrixU();
00727 const Eigen::MatrixXd V = svdOfJ.matrixV();
00728 const Eigen::VectorXd S = svdOfJ.singularValues();
00729
00730 Eigen::VectorXd Sinv = S;
00731 static const double pinvtoler = std::numeric_limits<float>::epsilon();
00732 double maxsv = 0.0 ;
00733 for (std::size_t i = 0; i < S.rows(); ++i)
00734 if (fabs(S(i)) > maxsv) maxsv = fabs(S(i));
00735 for (std::size_t i = 0; i < S.rows(); ++i)
00736 {
00737
00738 if ( fabs(S(i)) > maxsv * pinvtoler )
00739 Sinv(i) = 1.0 / S(i);
00740 else Sinv(i) = 0.0;
00741 }
00742 Eigen::MatrixXd Jinv = ( V * Sinv.asDiagonal() * U.transpose() );
00743
00744
00745 qdot = Jinv * twist;
00746
00747
00748 if (st)
00749 {
00750 Eigen::VectorXd cost_vector = Eigen::VectorXd::Zero(qdot.rows());
00751 st(this, cost_vector);
00752 qdot += (Eigen::MatrixXd::Identity(qdot.rows(), qdot.rows()) - Jinv * J) * cost_vector;
00753 }
00754 }
00755
00756 bool robot_state::JointStateGroup::setFromDiffIK(const Eigen::VectorXd &twist, const std::string &tip, double dt, const StateValidityCallbackFn &constraint, const SecondaryTaskFn &st)
00757 {
00758 Eigen::VectorXd qdot;
00759 computeJointVelocity(qdot, twist, tip, st);
00760 return integrateJointVelocity(qdot, dt, constraint);
00761 }
00762
00763 bool robot_state::JointStateGroup::setFromDiffIK(const geometry_msgs::Twist &twist, const std::string &tip, double dt, const StateValidityCallbackFn &constraint, const SecondaryTaskFn &st)
00764 {
00765 Eigen::Matrix<double, 6, 1> t;
00766 tf::twistMsgToEigen(twist, t);
00767 return setFromDiffIK(t, tip, dt, constraint, st);
00768 }
00769
00770 bool robot_state::JointStateGroup::integrateJointVelocity(const Eigen::VectorXd &qdot, double dt, const StateValidityCallbackFn &constraint)
00771 {
00772 Eigen::VectorXd q(getVariableCount());
00773 getVariableValues(q);
00774 q = q + dt * qdot;
00775 setVariableValues(q);
00776 enforceBounds();
00777
00778 if (constraint)
00779 {
00780 std::vector<double> values;
00781 getVariableValues(values);
00782 return constraint(this, values);
00783 }
00784 else
00785 return true;
00786 }
00787
00788 bool robot_state::JointStateGroup::avoidJointLimitsSecondaryTask(const robot_state::JointStateGroup *joint_state_group, Eigen::VectorXd &stvector,
00789 double activation_threshold, double gain) const
00790 {
00791
00792 Eigen::VectorXd q;
00793 joint_state_group->getVariableValues(q);
00794
00795
00796 const std::vector<moveit_msgs::JointLimits> &qlimits = joint_state_group->getJointModelGroup()->getVariableLimits();
00797 Eigen::VectorXd qmin(qlimits.size());
00798 Eigen::VectorXd qmax(qlimits.size());
00799 Eigen::VectorXd qrange(qlimits.size());
00800 stvector.resize(qlimits.size());
00801 stvector = Eigen::ArrayXd::Zero(qlimits.size());
00802
00803 for (std::size_t i = 0; i < qlimits.size(); ++i)
00804 {
00805 qmin(i) = qlimits[i].min_position;
00806 qmax(i) = qlimits[i].max_position;
00807 qrange(i) = qmax(i) - qmin(i);
00808
00809
00810 const std::vector<const robot_model::JointModel*> joint_models = joint_state_group->getJointModelGroup()->getJointModels();
00811 if (qrange(i) == 0)
00812 {
00813
00814 stvector(i) = 0;
00815 }
00816 else if (joint_models[i]->getType() == robot_model::JointModel::REVOLUTE)
00817 {
00818
00819 const robot_model::RevoluteJointModel *rjoint = static_cast<const robot_model::RevoluteJointModel*>(joint_models[i]);
00820 if (rjoint->isContinuous())
00821 stvector(i) = 0;
00822 }
00823 else
00824 {
00825 if (q(i) > (qmax(i) - qrange(i) * activation_threshold))
00826 {
00827 stvector(i) = -gain * (q(i) - (qmax(i) - qrange(i) * activation_threshold)) / qrange(i);
00828 }
00829 else if (q(i) < (qmin(i) + qrange(i) * activation_threshold))
00830 {
00831 stvector(i) = -gain * (q(i) - (qmin(i) + qrange(i) * activation_threshold)) / qrange(i);
00832 }
00833 }
00834 }
00835
00836 return true;
00837 }
00838
00839 double robot_state::JointStateGroup::computeCartesianPath(std::vector<RobotStatePtr> &traj, const std::string &link_name, const Eigen::Vector3d &direction, bool global_reference_frame,
00840 double distance, double max_step, double jump_threshold, const StateValidityCallbackFn &validCallback, const kinematics::KinematicsQueryOptions &options)
00841 {
00842 const LinkState *link_state = kinematic_state_->getLinkState(link_name);
00843 if (!link_state)
00844 return 0.0;
00845
00846
00847 const Eigen::Affine3d &start_pose = link_state->getGlobalLinkTransform();
00848
00849
00850 const Eigen::Vector3d &rotated_direction = global_reference_frame ? direction : start_pose.rotation() * direction;
00851
00852
00853 Eigen::Affine3d target_pose = start_pose;
00854 target_pose.translation() += rotated_direction * distance;
00855
00856
00857 return (distance * computeCartesianPath(traj, link_name, target_pose, true, max_step, jump_threshold, validCallback, options));
00858 }
00859
00860 double robot_state::JointStateGroup::computeCartesianPath(std::vector<RobotStatePtr> &traj, const std::string &link_name, const Eigen::Affine3d &target, bool global_reference_frame,
00861 double max_step, double jump_threshold, const StateValidityCallbackFn &validCallback, const kinematics::KinematicsQueryOptions &options)
00862 {
00863 const LinkState *link_state = kinematic_state_->getLinkState(link_name);
00864 if (!link_state)
00865 return 0.0;
00866
00867 const std::vector<const robot_model::JointModel*> &jnt = joint_model_group_->getJointModels();
00868
00869
00870 std::map<std::string, double> upd_continuous_joints;
00871 for (std::size_t i = 0 ; i < jnt.size() ; ++i)
00872 if (jnt[i]->getType() == robot_model::JointModel::REVOLUTE)
00873 {
00874 if (static_cast<const robot_model::RevoluteJointModel*>(jnt[i])->isContinuous())
00875 {
00876 double initial = joint_state_vector_[i]->getVariableValues()[0];
00877 joint_state_vector_[i]->enforceBounds();
00878 double after = joint_state_vector_[i]->getVariableValues()[0];
00879 if (fabs(initial - after) > std::numeric_limits<double>::epsilon())
00880 upd_continuous_joints[joint_state_vector_[i]->getName()] = initial - after;
00881 }
00882 }
00883
00884
00885 Eigen::Affine3d start_pose = link_state->getGlobalLinkTransform();
00886
00887
00888 Eigen::Affine3d rotated_target = global_reference_frame ? target : start_pose * target;
00889
00890 bool test_joint_space_jump = jump_threshold > 0.0;
00891
00892
00893 double distance = (rotated_target.translation() - start_pose.translation()).norm();
00894 unsigned int steps = (test_joint_space_jump ? 5 : 1) + (unsigned int)floor(distance / max_step);
00895
00896 traj.clear();
00897 traj.push_back(RobotStatePtr(new RobotState(*kinematic_state_)));
00898
00899 std::vector<std::vector<double> > previous_values(joint_state_vector_.size());
00900 std::vector<double> dist_vector;
00901 double total_dist = 0.0;
00902
00903 if (test_joint_space_jump)
00904 for (std::size_t k = 0 ; k < joint_state_vector_.size() ; ++k)
00905 previous_values[k] = joint_state_vector_[k]->getVariableValues();
00906
00907 double last_valid_percentage = 0.0;
00908 Eigen::Quaterniond start_quaternion(start_pose.rotation());
00909 Eigen::Quaterniond target_quaternion(rotated_target.rotation());
00910 for (unsigned int i = 1; i <= steps ; ++i)
00911 {
00912 double percentage = (double)i / (double)steps;
00913
00914 Eigen::Affine3d pose(start_quaternion.slerp(percentage, target_quaternion));
00915 pose.translation() = percentage * rotated_target.translation() + (1 - percentage) * start_pose.translation();
00916
00917 if (setFromIK(pose, link_name, 1, 0.0, validCallback, options))
00918 {
00919 traj.push_back(RobotStatePtr(new RobotState(*kinematic_state_)));
00920
00921
00922 if (test_joint_space_jump)
00923 {
00924 double dist_prev_point = 0.0;
00925 for (std::size_t k = 0 ; k < joint_state_vector_.size() ; ++k)
00926 {
00927 double d_k = jnt[k]->distance(joint_state_vector_[k]->getVariableValues(), previous_values[k]);
00928 if (dist_prev_point < 0.0 || dist_prev_point < d_k)
00929 dist_prev_point = d_k;
00930 previous_values[k] = joint_state_vector_[k]->getVariableValues();
00931 }
00932 dist_vector.push_back(dist_prev_point);
00933 total_dist += dist_prev_point;
00934 }
00935 }
00936 else
00937 break;
00938 last_valid_percentage = percentage;
00939 }
00940
00941 if (test_joint_space_jump)
00942 {
00943
00944 double thres = jump_threshold * (total_dist / (double)dist_vector.size());
00945 for (std::size_t i = 0 ; i < dist_vector.size() ; ++i)
00946 if (dist_vector[i] > thres)
00947 {
00948 logDebug("Truncating Cartesian path due to detected jump in joint-space distance");
00949 last_valid_percentage = (double)i / (double)steps;
00950 traj.resize(i);
00951 break;
00952 }
00953 }
00954
00955 return last_valid_percentage;
00956 }
00957
00958 double robot_state::JointStateGroup::computeCartesianPath(std::vector<RobotStatePtr> &traj, const std::string &link_name, const EigenSTL::vector_Affine3d &waypoints,
00959 bool global_reference_frame, double max_step, double jump_threshold, const StateValidityCallbackFn &validCallback, const kinematics::KinematicsQueryOptions &options)
00960 {
00961 double percentage_solved = 0.0;
00962 for (std::size_t i = 0; i < waypoints.size(); ++i)
00963 {
00964 std::vector<RobotStatePtr> waypoint_traj;
00965 double wp_percentage_solved = computeCartesianPath(waypoint_traj, link_name, waypoints[i], global_reference_frame, max_step, jump_threshold, validCallback);
00966 if (fabs(wp_percentage_solved - 1.0) < std::numeric_limits<double>::epsilon())
00967 {
00968 percentage_solved = (double)(i + 1) / (double)waypoints.size();
00969 traj.insert(traj.end(), waypoint_traj.begin(), waypoint_traj.end());
00970 }
00971 else
00972 {
00973 percentage_solved += wp_percentage_solved / (double)waypoints.size();
00974 traj.insert(traj.end(), waypoint_traj.begin(), waypoint_traj.end());
00975 break;
00976 }
00977 }
00978
00979 return percentage_solved;
00980 }
00981
00982 void robot_state::JointStateGroup::ikCallbackFnAdapter(const StateValidityCallbackFn &constraint,
00983 const geometry_msgs::Pose &, const std::vector<double> &ik_sol, moveit_msgs::MoveItErrorCodes &error_code)
00984 {
00985 const std::vector<unsigned int> &bij = joint_model_group_->getKinematicsSolverJointBijection();
00986 std::vector<double> solution(bij.size());
00987 for (std::size_t i = 0 ; i < bij.size() ; ++i)
00988 solution[i] = ik_sol[bij[i]];
00989 if (constraint(this, solution))
00990 error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
00991 else
00992 error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
00993 }
00994
00995 bool robot_state::JointStateGroup::getJacobian(const std::string &link_name,
00996 const Eigen::Vector3d &reference_point_position,
00997 Eigen::MatrixXd& jacobian,
00998 bool use_quaternion_representation) const
00999 {
01000 if (!joint_model_group_->isChain())
01001 {
01002 logError("The group '%s' is not a chain. Cannot compute Jacobian", joint_model_group_->getName().c_str());
01003 return false;
01004 }
01005 if (!joint_model_group_->isLinkUpdated(link_name))
01006 {
01007 logError("Link name '%s' does not exist in the chain '%s' or is not a child for this chain", link_name.c_str(), joint_model_group_->getName().c_str());
01008 return false;
01009 }
01010
01011 const robot_model::JointModel* root_joint_model = (joint_model_group_->getJointRoots())[0];
01012 const robot_state::LinkState *root_link_state = kinematic_state_->getLinkState(root_joint_model->getParentLinkModel()->getName());
01013 Eigen::Affine3d reference_transform = root_link_state ? root_link_state->getGlobalLinkTransform() : kinematic_state_->getRootTransform();
01014 reference_transform = reference_transform.inverse();
01015 int rows = use_quaternion_representation ? 7 : 6;
01016 int columns = joint_model_group_->getVariableCount();
01017 jacobian = Eigen::MatrixXd::Zero(rows, columns);
01018
01019 const robot_state::LinkState *link_state = kinematic_state_->getLinkState(link_name);
01020 Eigen::Affine3d link_transform = reference_transform*link_state->getGlobalLinkTransform();
01021 Eigen::Vector3d point_transform = link_transform*reference_point_position;
01022
01023 logDebug("Point from reference origin expressed in world coordinates: %f %f %f",
01024 point_transform.x(),
01025 point_transform.y(),
01026 point_transform.z());
01027
01028 Eigen::Vector3d joint_axis;
01029 Eigen::Affine3d joint_transform;
01030
01031 while (link_state)
01032 {
01033
01034
01035
01036
01037
01038
01039
01040
01041 if (joint_model_group_->isActiveDOF(link_state->getParentJointState()->getJointModel()->getName()))
01042 {
01043 unsigned int joint_index = joint_model_group_->getJointVariablesIndexMap().find(link_state->getParentJointState()->getJointModel()->getName())->second;
01044 double multiplier = 1.0;
01045 if (link_state->getParentJointState()->getJointModel()->getMimic())
01046 {
01047 joint_index = joint_model_group_->getJointVariablesIndexMap().find(link_state->getParentJointState()->getJointModel()->getMimic()->getName())->second;
01048 multiplier = link_state->getParentJointState()->getJointModel()->getMimicFactor();
01049 }
01050 if (link_state->getParentJointState()->getJointModel()->getType() == robot_model::JointModel::REVOLUTE)
01051 {
01052 joint_transform = reference_transform*link_state->getGlobalLinkTransform();
01053 joint_axis = joint_transform.rotation()*(static_cast<const robot_model::RevoluteJointModel*>(link_state->getParentJointState()->getJointModel()))->getAxis();
01054 jacobian.block<3,1>(0,joint_index) = jacobian.block<3,1>(0,joint_index) + multiplier * joint_axis.cross(point_transform - joint_transform.translation());
01055 jacobian.block<3,1>(3,joint_index) = jacobian.block<3,1>(3,joint_index) + multiplier * joint_axis;
01056 }
01057 if (link_state->getParentJointState()->getJointModel()->getType() == robot_model::JointModel::PRISMATIC)
01058 {
01059 joint_transform = reference_transform*link_state->getGlobalLinkTransform();
01060 joint_axis = joint_transform*(static_cast<const robot_model::PrismaticJointModel*>(link_state->getParentJointState()->getJointModel()))->getAxis();
01061 jacobian.block<3,1>(0,joint_index) = jacobian.block<3,1>(0,joint_index) + multiplier * joint_axis;
01062 }
01063 if (link_state->getParentJointState()->getJointModel()->getType() == robot_model::JointModel::PLANAR)
01064 {
01065 joint_transform = reference_transform*link_state->getGlobalLinkTransform();
01066 joint_axis = joint_transform*Eigen::Vector3d(1.0,0.0,0.0);
01067 jacobian.block<3,1>(0,joint_index) = jacobian.block<3,1>(0,joint_index) + multiplier * joint_axis;
01068 joint_axis = joint_transform*Eigen::Vector3d(0.0,1.0,0.0);
01069 jacobian.block<3,1>(0,joint_index+1) = jacobian.block<3,1>(0,joint_index+1) + multiplier * joint_axis;
01070 joint_axis = joint_transform*Eigen::Vector3d(0.0,0.0,1.0);
01071 jacobian.block<3,1>(0,joint_index+2) = jacobian.block<3,1>(0,joint_index+2) + multiplier * joint_axis.cross(point_transform - joint_transform.translation());
01072 jacobian.block<3,1>(3,joint_index+2) = jacobian.block<3,1>(3,joint_index+2) + multiplier * joint_axis;
01073 }
01074 }
01075 if (link_state->getParentJointState()->getJointModel() == root_joint_model)
01076 break;
01077 link_state = link_state->getParentLinkState();
01078 }
01079 if (use_quaternion_representation) {
01080
01081
01082
01083
01084
01085 Eigen::Quaterniond q(link_transform.rotation());
01086 double w = q.w(), x = q.x(), y = q.y(), z = q.z();
01087 Eigen::MatrixXd quaternion_update_matrix(4,3);
01088 quaternion_update_matrix << -x, -y, -z,
01089 w, -z, y,
01090 z, w, -x,
01091 -y, x, w;
01092 jacobian.block(3,0,4,columns) = 0.5*quaternion_update_matrix*jacobian.block(3,0, 3, columns);
01093 }
01094 return true;
01095 }
01096
01097 std::pair<double,int> robot_state::JointStateGroup::getMinDistanceToBounds() const
01098 {
01099 double distance = std::numeric_limits<double>::max();
01100 int index = -1;
01101 for(std::size_t i=0; i < joint_state_vector_.size(); ++i)
01102 {
01103 if(joint_state_vector_[i]->getType() == robot_model::JointModel::REVOLUTE)
01104 {
01105 const robot_model::RevoluteJointModel* revolute_model = dynamic_cast<const robot_model::RevoluteJointModel*> (joint_state_vector_[i]->getJointModel());
01106 if(revolute_model->isContinuous())
01107 continue;
01108 }
01109 if(joint_state_vector_[i]->getType() == robot_model::JointModel::PLANAR)
01110 {
01111 const std::vector<std::pair<double, double> >& planar_bounds = joint_state_vector_[i]->getVariableBounds();
01112 if(planar_bounds[0].first == -std::numeric_limits<double>::max() || planar_bounds[0].second == std::numeric_limits<double>::max() ||
01113 planar_bounds[1].first == -std::numeric_limits<double>::max() || planar_bounds[1].second == std::numeric_limits<double>::max() ||
01114 planar_bounds[2].first == -boost::math::constants::pi<double>() || planar_bounds[2].second == boost::math::constants::pi<double>())
01115 continue;
01116 }
01117 if(joint_state_vector_[i]->getType() == robot_model::JointModel::FLOATING)
01118 {
01119
01120 continue;
01121 }
01122
01123 const std::vector<double>& joint_values = joint_state_vector_[i]->getVariableValues();
01124 const std::vector<std::pair<double, double> >& bounds = joint_state_vector_[i]->getVariableBounds();
01125 std::vector<double> lower_bounds, upper_bounds;
01126 for(std::size_t j=0; j < bounds.size(); ++j)
01127 {
01128 lower_bounds.push_back(bounds[j].first);
01129 upper_bounds.push_back(bounds[j].second);
01130 }
01131 double new_distance = joint_state_vector_[i]->getJointModel()->distance(joint_values, lower_bounds);
01132 if(new_distance < distance)
01133 {
01134 index = i;
01135 distance = new_distance;
01136 }
01137 new_distance = joint_state_vector_[i]->getJointModel()->distance(joint_values, upper_bounds);
01138 if(new_distance < distance)
01139 {
01140 index = i;
01141 distance = new_distance;
01142 }
01143 }
01144 return std::pair<double,int>(distance,index);
01145 }