Go to the documentation of this file.00001
00029 #include "constrained_ik/constrained_ik.h"
00030 #include "constrained_ik/constraints/avoid_singularities.h"
00031 #include "ros/ros.h"
00032 #include <pluginlib/class_list_macros.h>
00033 PLUGINLIB_EXPORT_CLASS(constrained_ik::constraints::AvoidSingularities, constrained_ik::Constraint)
00034
00035 const double DEFAULT_WEIGHT = 1.0;
00036 const double DEFAULT_ENABLE_THRESHOLD = 0.01;
00037 const double DEFAULT_IGNORE_THRESHOLD = 1e-5;
00039 namespace constrained_ik
00040 {
00041 namespace constraints
00042 {
00043
00044 using namespace Eigen;
00045
00046
00047 AvoidSingularities::AvoidSingularities() : Constraint(),
00048 weight_(DEFAULT_WEIGHT),
00049 enable_threshold_(DEFAULT_ENABLE_THRESHOLD),
00050 ignore_threshold_(DEFAULT_IGNORE_THRESHOLD)
00051 {
00052 }
00053
00054 constrained_ik::ConstraintResults AvoidSingularities::evalConstraint(const SolverState &state) const
00055 {
00056 constrained_ik::ConstraintResults output;
00057 AvoidSingularities::AvoidSingularitiesData cdata(state, this);
00058
00059 output.error = calcError(cdata);
00060 output.jacobian = calcJacobian(cdata);
00061 output.status = checkStatus(cdata);
00062
00063 return output;
00064 }
00065
00066 Eigen::VectorXd AvoidSingularities::calcError(const AvoidSingularities::AvoidSingularitiesData &cdata) const
00067 {
00068 size_t n(cdata.avoidance_enabled_? numJoints():0);
00069 VectorXd err(n);
00070 if (cdata.avoidance_enabled_)
00071 {
00072 for (size_t jntIdx=0; jntIdx<n; ++jntIdx)
00073 {
00074 err(jntIdx) = (cdata.Ui_.transpose() * jacobianPartialDerivative(cdata, jntIdx) * cdata.Vi_)(0);
00075 }
00076 err *= (weight_*cdata.smallest_sv_);
00077 err = err.cwiseMax(VectorXd::Constant(n,.25));
00078 }
00079 return err;
00080 }
00081
00082 Eigen::MatrixXd AvoidSingularities::calcJacobian(const AvoidSingularities::AvoidSingularitiesData &cdata) const
00083 {
00084 size_t n(cdata.avoidance_enabled_? numJoints():0);
00085 MatrixXd J = MatrixXd::Identity(n,n);
00086 J *= (weight_*cdata.smallest_sv_);
00087 return J;
00088 }
00089
00090 Eigen::MatrixXd AvoidSingularities::jacobianPartialDerivative(const AvoidSingularities::AvoidSingularitiesData &cdata, size_t jntIdx, double eps) const
00091 {
00092 MatrixXd jacobian_increment;
00093 Eigen::VectorXd joints = cdata.state_.joints;
00094 joints(jntIdx) += eps;
00095
00096 if (!ik_->getKin().checkJoints(joints))
00097 {
00098 eps = -eps;
00099 joints(jntIdx) += 2*eps;
00100 }
00101 if (!ik_->getKin().calcJacobian(joints, jacobian_increment))
00102 ROS_WARN("Could not calculate jacobian in AvoidSingularities");
00103 return (jacobian_increment-cdata.jacobian_orig_)/eps;
00104 }
00105
00106 void AvoidSingularities::loadParameters(const XmlRpc::XmlRpcValue &constraint_xml)
00107 {
00108 XmlRpc::XmlRpcValue local_xml = constraint_xml;
00109 if (!getParam(local_xml, "enable_threshold", enable_threshold_))
00110 {
00111 ROS_WARN("Avoid Singularities: Unable to retrieve enable_threshold member, default parameter will be used.");
00112 }
00113
00114 if (!getParam(local_xml, "ignore_threshold", ignore_threshold_))
00115 {
00116 ROS_WARN("Avoid Singularities: Unable to retrieve ignore_threshold member, default parameter will be used.");
00117 }
00118
00119 if (!getParam(local_xml, "weights", weight_))
00120 {
00121 ROS_WARN("Avoid Singularities: Unable to retrieve weights member, default parameter will be used.");
00122 }
00123
00124 if (!getParam(local_xml, "debug", debug_))
00125 {
00126 ROS_WARN("Avoid Singularities: Unable to retrieve debug member, default parameter will be used.");
00127 }
00128 }
00129
00130 AvoidSingularities::AvoidSingularitiesData::AvoidSingularitiesData(const SolverState &state, const constraints::AvoidSingularities *parent): ConstraintData(state)
00131 {
00132 if (!parent->initialized_) return;
00133 parent_ = parent;
00134
00135 parent_->ik_->getKin().calcJacobian(state_.joints, jacobian_orig_);
00136 Eigen::JacobiSVD<MatrixXd> svd(jacobian_orig_, Eigen::ComputeThinU | Eigen::ComputeThinV);
00137 Ui_ = svd.matrixU().rightCols(1);
00138 Vi_ = svd.matrixV().rightCols(1);
00139 smallest_sv_ = svd.singularValues().tail(1)(0);
00140 avoidance_enabled_ = smallest_sv_ < parent_->enable_threshold_ && smallest_sv_ > parent_->ignore_threshold_;
00141 if (avoidance_enabled_)
00142 ROS_INFO_STREAM("Sing. avoidance with s=" << svd.singularValues().tail(1));
00143 }
00144
00145 }
00146 }
00147