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 #include "constrained_ik/constrained_ik.h"
00020 #include "constrained_ik/constraint_group.h"
00021 #include <ros/ros.h>
00022
00023 namespace constrained_ik
00024 {
00025
00026 using Eigen::MatrixXd;
00027 using Eigen::VectorXd;
00028 using Eigen::Affine3d;
00029
00030 Constrained_IK::Constrained_IK()
00031 {
00032 initialized_ = false;
00033 joint_update_gain_ = 0.09;
00034 max_iter_ = 500;
00035 joint_convergence_tol_ = 0.0001;
00036 debug_ = false;
00037 }
00038
00039 Eigen::VectorXd Constrained_IK::calcConstraintError()
00040 {
00041 return constraints_.calcError();
00042 }
00043
00044 Eigen::MatrixXd Constrained_IK::calcConstraintJacobian()
00045 {
00046 return constraints_.calcJacobian();
00047 }
00048
00049 void Constrained_IK::calcInvKin(const Eigen::Affine3d &goal, const Eigen::VectorXd &joint_seed, Eigen::VectorXd &joint_angles)
00050 {
00051 if (!checkInitialized())
00052 throw std::runtime_error("Must call init() before using Constrained_IK");
00053
00054
00055
00056 joint_angles = joint_seed;
00057 reset(goal, joint_seed);
00058 update(joint_angles);
00059
00060
00061 while (!checkStatus())
00062 {
00063
00064
00065 MatrixXd J = calcConstraintJacobian();
00066 VectorXd err = calcConstraintError();
00067
00068
00069 VectorXd dJoint;
00070
00071 kin_.solvePInv(J, err, dJoint);
00072
00073
00074 joint_angles += dJoint * joint_update_gain_;
00075 clipToJointLimits(joint_angles);
00076
00077
00078 update(joint_angles);
00079 }
00080
00081 ROS_INFO_STREAM("IK solution: " << joint_angles.transpose());
00082 }
00083
00084 bool Constrained_IK::checkStatus() const
00085 {
00086
00087 if (constraints_.checkStatus())
00088 return true;
00089
00090
00091 if (state_.iter > max_iter_)
00092 throw std::runtime_error("Maximum iterations reached. IK solution may be invalid.");
00093
00094
00095
00096 if (state_.joints_delta.cwiseAbs().maxCoeff() < joint_convergence_tol_)
00097 {
00098
00099
00100
00101 ROS_WARN_STREAM("Reached " << state_.iter << " / " << max_iter_ << " iterations before convergence.");
00102 return true;
00103 }
00104
00105 return false;
00106 }
00107
00108 void Constrained_IK::clearConstraintList()
00109 {
00110 constraints_.clear();
00111 }
00112
00113 void Constrained_IK::clipToJointLimits(Eigen::VectorXd &joints)
00114 {
00115 const MatrixXd limits = kin_.getLimits();
00116 const VectorXd orig_joints(joints);
00117
00118 if (joints.size() != limits.rows())
00119 throw std::invalid_argument("clipToJointLimits: Unexpected number of joints");
00120
00121 for (size_t i=0; i<limits.rows(); ++i)
00122 {
00123 joints[i] = std::max(limits(i,0), std::min(limits(i,1), joints[i]));
00124 }
00125 if (debug_ && !joints.isApprox(orig_joints))
00126 ROS_WARN("Joints have been clipped");
00127 }
00128
00129 void Constrained_IK::init(const urdf::Model &robot, const std::string &base_name, const std::string &tip_name)
00130 {
00131 basic_kin::BasicKin kin;
00132 if (! kin.init(robot, base_name, tip_name))
00133 throw std::runtime_error("Failed to initialize BasicKin");
00134
00135 init(kin);
00136 }
00137
00138 void Constrained_IK::init(const basic_kin::BasicKin &kin)
00139 {
00140 if (!kin.checkInitialized())
00141 throw std::invalid_argument("Input argument 'BasicKin' must be initialized");
00142
00143 kin_ = kin;
00144 initialized_ = true;
00145 constraints_.init(this);
00146 }
00147
00148 double Constrained_IK::rangedAngle(double angle)
00149 {
00150 angle = copysign(fmod(fabs(angle),2.0*M_PI), angle);
00151 if (angle < -M_PI) return angle+2.*M_PI;
00152 if (angle > M_PI) return angle-2.*M_PI;
00153 return angle;
00154 }
00155
00156 void Constrained_IK::reset(const Eigen::Affine3d &goal, const Eigen::VectorXd &joint_seed)
00157 {
00158 if (!kin_.checkJoints(joint_seed))
00159 throw std::invalid_argument("Seed doesn't match kinematic model");
00160
00161 if (!goal.matrix().block(0,0,3,3).isUnitary(1e-6))
00162 throw std::invalid_argument("Goal pose not proper affine");
00163
00164 state_.reset(goal, joint_seed);
00165 constraints_.reset();
00166
00167 }
00168
00169 void Constrained_IK::update(const Eigen::VectorXd &joints)
00170 {
00171
00172 state_.iter++;
00173
00174
00175 state_.joints_delta = joints - state_.joints;
00176 state_.joints = joints;
00177 kin_.calcFwdKin(joints, state_.pose_estimate);
00178
00179 if (debug_)
00180 iteration_path_.push_back(joints);
00181
00182 constraints_.update(state_);
00183 }
00184
00185 }
00186