Go to the documentation of this file.00001
00030 #include "constrained_ik/constraints/avoid_joint_limits.h"
00031 #include "constrained_ik/constrained_ik.h"
00032 #include <ros/ros.h>
00033 #include <pluginlib/class_list_macros.h>
00034 PLUGINLIB_EXPORT_CLASS(constrained_ik::constraints::AvoidJointLimits, constrained_ik::Constraint)
00035
00036 const double DEFAULT_THRESHOLD = 0.05;
00037 const double DEFAULT_WEIGHT = 1.0;
00039 namespace constrained_ik
00040 {
00041 namespace constraints
00042 {
00043
00044 using namespace Eigen;
00045 using namespace std;
00046
00047 AvoidJointLimits::AvoidJointLimits(): Constraint(), weight_(DEFAULT_WEIGHT), threshold_(DEFAULT_THRESHOLD) {}
00048
00049 constrained_ik::ConstraintResults AvoidJointLimits::evalConstraint(const SolverState &state) const
00050 {
00051 constrained_ik::ConstraintResults output;
00052 AvoidJointLimits::AvoidJointLimitsData cdata(state, this);
00053
00054 output.error = calcError(cdata);
00055 output.jacobian = calcJacobian(cdata);
00056 output.status = checkStatus(cdata);
00057
00058 return output;
00059 }
00060
00061 Eigen::VectorXd AvoidJointLimits::calcError(const AvoidJointLimits::AvoidJointLimitsData &cdata) const
00062 {
00063 size_t nRows = cdata.limited_joints_.size();
00064 VectorXd error(nRows);
00065
00066 for (int ii=0; ii<nRows; ++ii)
00067 {
00068 size_t jntIdx = cdata.limited_joints_[ii];
00069 int velSign;
00070 const LimitsT &lim = limits_[jntIdx];
00071 double limit;
00072 if (cdata.nearLowerLimit(jntIdx))
00073 {
00074 velSign = 1;
00075 limit = lim.min_pos;
00076 }
00077 else
00078 {
00079 velSign = -1;
00080 limit = lim.max_pos;
00081 }
00082
00083 error(ii) = velSign * weight_ * lim.cubicVelRamp(cdata.state_.joints[jntIdx], limit);
00084
00085 if (debug_)
00086 {
00087 ROS_WARN_STREAM("iteration " << cdata.state_.iter << std::endl <<
00088 "Joint position: " << cdata.state_.joints(jntIdx) << " / " << limit << std::endl <<
00089 "velocity error: " << error(ii));
00090 }
00091 }
00092 return error;
00093 }
00094
00095 Eigen::MatrixXd AvoidJointLimits::calcJacobian(const AvoidJointLimits::AvoidJointLimitsData &cdata) const
00096 {
00097 size_t nRows = cdata.limited_joints_.size();
00098 MatrixXd jacobian(nRows, numJoints());
00099
00100 for (int ii=0; ii<nRows; ++ii)
00101 {
00102 size_t jntIdx = cdata.limited_joints_[ii];
00103
00104 VectorXd tmpRow = VectorXd::Zero(numJoints());
00105 tmpRow(jntIdx) = 1.0;
00106
00107 jacobian.row(ii) = tmpRow * weight_;
00108 }
00109
00110 return jacobian;
00111 }
00112
00113 void AvoidJointLimits::init(const Constrained_IK *ik)
00114 {
00115 Constraint::init(ik);
00116
00117
00118 MatrixXd joint_limits = ik->getKin().getLimits();
00119 for (size_t ii=0; ii<numJoints(); ++ii)
00120 limits_.push_back( LimitsT(joint_limits(ii,0), joint_limits(ii,1), threshold_ ) );
00121 }
00122
00123 void AvoidJointLimits::loadParameters(const XmlRpc::XmlRpcValue &constraint_xml)
00124 {
00125 XmlRpc::XmlRpcValue local_xml = constraint_xml;
00126 double threshold;
00127 if (getParam(local_xml, "threshold", threshold))
00128 {
00129 setThreshold(threshold);
00130 }
00131 else
00132 {
00133 ROS_WARN("Avoid Joint Limits: Unable to retrieve threshold member, default parameter will be used.");
00134 }
00135
00136 double weight;
00137 if (getParam(local_xml, "weights", weight))
00138 {
00139 setWeight(weight);
00140 }
00141 else
00142 {
00143 ROS_WARN("Avoid Joint Limits: Unable to retrieve weights member, default parameter will be used.");
00144 }
00145
00146 bool debug;
00147 if (getParam(local_xml, "debug", debug))
00148 {
00149 setDebug(debug);
00150 }
00151 else
00152 {
00153 ROS_WARN("Avoid Joint Limits: Unable to retrieve debug member, default parameter will be used.");
00154 }
00155 }
00156
00161 template<class T>
00162 std::ostream& operator<< (std::ostream& os, const std::vector<T>& v)
00163 {
00164 if (!v.empty())
00165 {
00166 copy(v.begin(), v.end()-1, std::ostream_iterator<T>(os, ", "));
00167 os << v.back();
00168 }
00169 return os;
00170 }
00171
00172 AvoidJointLimits::AvoidJointLimitsData::AvoidJointLimitsData(const SolverState &state, const constraints::AvoidJointLimits *parent): ConstraintData(state)
00173 {
00174 if (!parent->initialized_) return;
00175 parent_ = parent;
00176
00177
00178 for (size_t ii=0; ii<parent_->numJoints(); ++ii)
00179 if ( nearLowerLimit(ii) || nearUpperLimit(ii) )
00180 limited_joints_.push_back(ii);
00181
00182
00183 if (parent_->debug_ && !limited_joints_.empty())
00184 ROS_WARN_STREAM(limited_joints_.size() << " joint limits active: " << limited_joints_);
00185 }
00186
00187 bool AvoidJointLimits::AvoidJointLimitsData::nearLowerLimit(size_t idx) const
00188 {
00189 if (idx >= state_.joints.size() || idx >= parent_->limits_.size() )
00190 return false;
00191
00192 return state_.joints(idx) < parent_->limits_[idx].lower_thresh;
00193 }
00194
00195 bool AvoidJointLimits::AvoidJointLimitsData::nearUpperLimit(size_t idx) const
00196 {
00197 if (idx >= state_.joints.size() || idx >= parent_->limits_.size() )
00198 return false;
00199
00200 return state_.joints(idx) > parent_->limits_[idx].upper_thresh;
00201 }
00202
00203
00204 AvoidJointLimits::LimitsT::LimitsT(double minPos, double maxPos, double threshold)
00205 {
00206 min_pos = minPos;
00207 max_pos = maxPos;
00208
00209
00210 e = threshold * (maxPos - minPos);
00211 lower_thresh = minPos + e;
00212 upper_thresh = maxPos - e;
00213
00214
00215
00216
00217 k3 = 1.0/(2 * e * e);
00218 }
00219
00220 double AvoidJointLimits::LimitsT::cubicVelRamp(double angle, double limit) const
00221 {
00222 double d = std::abs(angle - limit);
00223 return k3 * std::pow(e-d,3);
00224 }
00225
00226 }
00227 }