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