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 }