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/kinematics_metrics/kinematics_metrics.h>
00038 #include <Eigen/Eigenvalues>
00039 #include <boost/math/constants/constants.hpp>
00040 
00041 namespace kinematics_metrics
00042 {
00043 
00044 double KinematicsMetrics::getJointLimitsPenalty(const robot_state::RobotState &state, const robot_model::JointModelGroup *joint_model_group) const
00045 {
00046   if (fabs(penalty_multiplier_) <= boost::math::tools::epsilon<double>())
00047      return 1.0;
00048   double joint_limits_multiplier(1.0);
00049   const std::vector<const robot_model::JointModel*> &joint_model_vector = joint_model_group->getJointModels();
00050   for (std::size_t i = 0; i < joint_model_vector.size(); ++i)
00051   {
00052     if (joint_model_vector[i]->getType() == robot_model::JointModel::REVOLUTE)
00053     {
00054       const robot_model::RevoluteJointModel* revolute_model = static_cast<const robot_model::RevoluteJointModel*>(joint_model_vector[i]);
00055       if (revolute_model->isContinuous())
00056         continue;
00057     }
00058     if (joint_model_vector[i]->getType() == robot_model::JointModel::PLANAR)
00059     {
00060       const robot_model::JointModel::Bounds &bounds = joint_model_vector[i]->getVariableBounds();
00061       if (bounds[0].min_position_ == -std::numeric_limits<double>::max() || bounds[0].max_position_ == std::numeric_limits<double>::max() ||
00062           bounds[1].min_position_ == -std::numeric_limits<double>::max() || bounds[1].max_position_ == std::numeric_limits<double>::max() ||
00063           bounds[2].min_position_ == -boost::math::constants::pi<double>() || bounds[2].max_position_ == boost::math::constants::pi<double>())
00064         continue;
00065     }
00066     if (joint_model_vector[i]->getType() == robot_model::JointModel::FLOATING)
00067     {
00068       
00069       continue;
00070     }
00071     const double *joint_values = state.getJointPositions(joint_model_vector[i]);
00072     const robot_model::JointModel::Bounds &bounds = joint_model_vector[i]->getVariableBounds();
00073     std::vector<double> lower_bounds, upper_bounds;
00074     for (std::size_t j = 0; j < bounds.size(); ++j)
00075     {
00076       lower_bounds.push_back(bounds[j].min_position_);
00077       upper_bounds.push_back(bounds[j].max_position_);
00078     }
00079     double lower_bound_distance = joint_model_vector[i]->distance(joint_values, &lower_bounds[0]);
00080     double upper_bound_distance = joint_model_vector[i]->distance(joint_values, &upper_bounds[0]);
00081     double range = lower_bound_distance + upper_bound_distance;
00082     if (range <= boost::math::tools::epsilon<double>())
00083       continue;
00084     joint_limits_multiplier *= (lower_bound_distance * upper_bound_distance/(range*range));
00085   }
00086   return (1.0 - exp(-penalty_multiplier_*joint_limits_multiplier));
00087 }
00088 
00089 bool KinematicsMetrics::getManipulabilityIndex(const robot_state::RobotState &state,
00090                                                const std::string &group_name,
00091                                                double &manipulability_index,
00092                                                bool translation) const
00093 {
00094   const robot_model::JointModelGroup *joint_model_group = robot_model_->getJointModelGroup(group_name);
00095   if (joint_model_group)
00096     return getManipulabilityIndex(state, joint_model_group, manipulability_index, translation);
00097   else
00098     return false;
00099 }
00100 
00101 bool KinematicsMetrics::getManipulabilityIndex(const robot_state::RobotState &state,
00102                                                const robot_model::JointModelGroup *joint_model_group,
00103                                                double &manipulability_index,
00104                                                bool translation) const
00105 {
00106   
00107   if(!joint_model_group->isChain())
00108   {
00109     return false;
00110   }
00111 
00112   Eigen::MatrixXd jacobian = state.getJacobian(joint_model_group);
00113   
00114   double penalty = getJointLimitsPenalty(state, joint_model_group);
00115   if (translation)
00116   {
00117     if(jacobian.cols()<6)
00118     {
00119       Eigen::JacobiSVD<Eigen::MatrixXd> svdsolver(jacobian.topLeftCorner(3,jacobian.cols()));
00120       Eigen::MatrixXd singular_values = svdsolver.singularValues();
00121       manipulability_index = 1.0;
00122       for(unsigned int i=0; i < singular_values.rows(); ++i)
00123       {
00124         logDebug("moveit.kin_metrics: Singular value: %d %f",i,singular_values(i,0));
00125         manipulability_index *= singular_values(i,0);
00126       }
00127       
00128       manipulability_index = penalty * manipulability_index;
00129     }
00130     else
00131     {
00132       Eigen::MatrixXd jacobian_2 = jacobian.topLeftCorner(3,jacobian.cols());
00133       Eigen::MatrixXd matrix = jacobian_2*jacobian_2.transpose();
00134       
00135       manipulability_index = penalty * sqrt(matrix.determinant());
00136     }
00137   }
00138   else
00139   {
00140     if(jacobian.cols()<6)
00141     {
00142       Eigen::JacobiSVD<Eigen::MatrixXd> svdsolver(jacobian);
00143       Eigen::MatrixXd singular_values = svdsolver.singularValues();
00144       manipulability_index = 1.0;
00145       for(unsigned int i=0; i < singular_values.rows(); ++i)
00146       {
00147         logDebug("moveit.kin_metrics: Singular value: %d %f",i,singular_values(i,0));
00148         manipulability_index *= singular_values(i,0);
00149       }
00150       
00151       manipulability_index = penalty * manipulability_index;
00152     }
00153     else
00154     {
00155       Eigen::MatrixXd matrix = jacobian*jacobian.transpose();
00156       
00157       manipulability_index = penalty * sqrt(matrix.determinant());
00158     }
00159   }
00160   return true;
00161 }
00162 
00163 bool KinematicsMetrics::getManipulabilityEllipsoid(const robot_state::RobotState &state,
00164                                                    const std::string &group_name,
00165                                                    Eigen::MatrixXcd &eigen_values,
00166                                                    Eigen::MatrixXcd &eigen_vectors) const
00167 {
00168   const robot_model::JointModelGroup *joint_model_group = robot_model_->getJointModelGroup(group_name);
00169   if (joint_model_group)
00170     return getManipulabilityEllipsoid(state, joint_model_group, eigen_values, eigen_vectors);
00171   else
00172     return false;
00173 }
00174 
00175 bool KinematicsMetrics::getManipulabilityEllipsoid(const robot_state::RobotState &state,
00176                                                    const robot_model::JointModelGroup *joint_model_group,
00177                                                    Eigen::MatrixXcd &eigen_values,
00178                                                    Eigen::MatrixXcd &eigen_vectors) const
00179 {
00180   
00181   if(!joint_model_group->isChain())
00182   {
00183     return false;
00184   }
00185 
00186   Eigen::MatrixXd jacobian = state.getJacobian(joint_model_group);
00187   Eigen::MatrixXd matrix = jacobian*jacobian.transpose();
00188   Eigen::EigenSolver<Eigen::MatrixXd> eigensolver(matrix.block(0, 0, 3, 3));
00189   eigen_values = eigensolver.eigenvalues();
00190   eigen_vectors = eigensolver.eigenvectors();
00191   return true;
00192 }
00193 
00194 bool KinematicsMetrics::getManipulability(const robot_state::RobotState &state,
00195                                           const std::string &group_name,
00196                                           double &manipulability,
00197                                           bool translation) const
00198 {
00199   const robot_model::JointModelGroup *joint_model_group = robot_model_->getJointModelGroup(group_name);
00200   if (joint_model_group)
00201     return getManipulability(state, joint_model_group, manipulability, translation);
00202   else
00203     return false;
00204 }
00205 
00206 bool KinematicsMetrics::getManipulability(const robot_state::RobotState &state,
00207                                           const robot_model::JointModelGroup *joint_model_group,
00208                                           double &manipulability,
00209                                           bool translation) const
00210 {
00211   
00212   if(!joint_model_group->isChain())
00213   {
00214     return false;
00215   }
00216   
00217   double penalty = getJointLimitsPenalty(state, joint_model_group);
00218   if (translation)
00219   {
00220     Eigen::MatrixXd jacobian = state.getJacobian(joint_model_group);
00221     Eigen::JacobiSVD<Eigen::MatrixXd> svdsolver(jacobian.topLeftCorner(3,jacobian.cols()));
00222     Eigen::MatrixXd singular_values = svdsolver.singularValues();
00223     for (int i = 0; i < singular_values.rows(); ++i)
00224       logDebug("moveit.kin_metrics: Singular value: %d %f",i,singular_values(i,0));
00225     manipulability = penalty * singular_values.minCoeff()/singular_values.maxCoeff();
00226   }
00227   else
00228   {
00229     Eigen::MatrixXd jacobian = state.getJacobian(joint_model_group);
00230     Eigen::JacobiSVD<Eigen::MatrixXd> svdsolver(jacobian);
00231     Eigen::MatrixXd singular_values = svdsolver.singularValues();
00232     for(int i=0; i < singular_values.rows(); ++i)
00233       logDebug("moveit.kin_metrics: Singular value: %d %f",i,singular_values(i,0));
00234     manipulability = penalty * singular_values.minCoeff()/singular_values.maxCoeff();
00235   }
00236   return true;
00237 }
00238 
00239 }