Go to the documentation of this file.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 #include "constrained_ik/constraints/avoid_joint_limits.h"
00026 #include "constrained_ik/constrained_ik.h"
00027 #include <ros/ros.h>
00028
00029 namespace constrained_ik
00030 {
00031 namespace constraints
00032 {
00033
00034 using namespace Eigen;
00035 using namespace std;
00036
00037 Eigen::VectorXd AvoidJointLimits::calcError()
00038 {
00039 size_t nRows = limited_joints_.size();
00040 VectorXd error(nRows);
00041
00042 for (int ii=0; ii<nRows; ++ii)
00043 {
00044 size_t jntIdx = limited_joints_[ii];
00045 int velSign;
00046 const LimitsT &lim = limits_[jntIdx];
00047 double limit;
00048 if (nearLowerLimit(jntIdx))
00049 {
00050 velSign = 1;
00051 limit = lim.min_pos;
00052 }
00053 else
00054 {
00055 velSign = -1;
00056 limit = lim.max_pos;
00057 }
00058
00059 error(ii) = velSign * weight_ * lim.cubicVelRamp(state_.joints[jntIdx], limit);
00060
00061 if (debug_)
00062 {
00063 ROS_WARN_STREAM("iteration " << state_.iter << std::endl <<
00064 "Joint position: " << state_.joints(jntIdx) << " / " << limit << std::endl <<
00065 "velocity error: " << error(ii) << " / " << lim.e/2.0);
00066 }
00067 }
00068 return error;
00069 }
00070
00071 Eigen::MatrixXd AvoidJointLimits::calcJacobian()
00072 {
00073 size_t nRows = limited_joints_.size();
00074 MatrixXd jacobian(nRows, numJoints());
00075
00076 for (int ii=0; ii<nRows; ++ii)
00077 {
00078 size_t jntIdx = limited_joints_[ii];
00079
00080 VectorXd tmpRow = VectorXd::Zero(numJoints());
00081 tmpRow(jntIdx) = 1.0;
00082
00083 jacobian.row(ii) = tmpRow * weight_;
00084 }
00085
00086 return jacobian;
00087 }
00088
00089 bool AvoidJointLimits::checkStatus() const
00090 {
00091 size_t n = state_.joints.size();
00092 for (size_t ii = 0; ii<n; ++ii)
00093 if (state_.joints[ii] > limits_[ii].max_pos || state_.joints[ii] < limits_[ii].min_pos)
00094 return false;
00095 return true;
00096 }
00097
00098 void AvoidJointLimits::init(const Constrained_IK *ik)
00099 {
00100 Constraint::init(ik);
00101
00102
00103 MatrixXd joint_limits = ik->getKin().getLimits();
00104 for (size_t ii=0; ii<numJoints(); ++ii)
00105 limits_.push_back( LimitsT(joint_limits(ii,0), joint_limits(ii,1), threshold_ ) );
00106 }
00107
00108 bool AvoidJointLimits::nearLowerLimit(size_t idx)
00109 {
00110 if (idx >= state_.joints.size() || idx >= limits_.size() )
00111 return false;
00112
00113 return state_.joints(idx) < limits_[idx].lower_thresh;
00114 }
00115 bool AvoidJointLimits::nearUpperLimit(size_t idx)
00116 {
00117 if (idx >= state_.joints.size() || idx >= limits_.size() )
00118 return false;
00119
00120 return state_.joints(idx) > limits_[idx].upper_thresh;
00121 }
00122
00123 void AvoidJointLimits::reset()
00124 {
00125 limited_joints_.clear();
00126 }
00127
00128
00129 template<class T>
00130 std::ostream& operator<< (std::ostream& os, const std::vector<T>& v)
00131 {
00132 if (!v.empty())
00133 {
00134 copy(v.begin(), v.end()-1, std::ostream_iterator<T>(os, ", "));
00135 os << v.back();
00136 }
00137 return os;
00138 }
00139
00140 void AvoidJointLimits::update(const SolverState &state)
00141 {
00142 if (!initialized_) return;
00143 Constraint::update(state);
00144 limited_joints_.clear();
00145
00146
00147 for (size_t ii=0; ii<numJoints(); ++ii)
00148 if ( nearLowerLimit(ii) || nearUpperLimit(ii) )
00149 limited_joints_.push_back(ii);
00150
00151
00152 if (debug_ && !limited_joints_.empty())
00153 ROS_WARN_STREAM(limited_joints_.size() << " joint limits active: " << limited_joints_);
00154 }
00155
00156 AvoidJointLimits::LimitsT::LimitsT(double minPos, double maxPos, double threshold)
00157 {
00158 min_pos = minPos;
00159 max_pos = maxPos;
00160
00161
00162
00163
00164 e = threshold * (maxPos - minPos);
00165 lower_thresh = minPos + e;
00166 upper_thresh = maxPos - e;
00167
00168
00169
00170
00171 k3 = 1.0/(2 * e * e);
00172 }
00173
00174 double AvoidJointLimits::LimitsT::cubicVelRamp(double angle, double limit) const
00175 {
00176 double d = std::abs(angle - limit);
00177 return k3 * std::pow(e-d,3);
00178 }
00179
00180 }
00181 }