Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00016 #include "JointPath.h"
00017 #include "Link.h"
00018 #include <hrpUtil/MatrixSolvers.h>
00019 #include <algorithm>
00020
00021 using namespace std;
00022 using namespace hrp;
00023
00024
00025 JointPath::JointPath()
00026 {
00027 initialize();
00028 }
00029
00030
00031 JointPath::JointPath(Link* base, Link* end)
00032 : linkPath(base, end),
00033 joints(linkPath.size())
00034 {
00035 initialize();
00036 extractJoints();
00037 }
00038
00039
00040 JointPath::JointPath(Link* end)
00041 : linkPath(end),
00042 joints(linkPath.size())
00043 {
00044 initialize();
00045 extractJoints();
00046 }
00047
00048
00049 void JointPath::initialize()
00050 {
00051 maxIKErrorSqr = 1.0e-6 * 1.0e-6;
00052 isBestEffortIKMode = false;
00053 }
00054
00055
00056 JointPath::~JointPath()
00057 {
00058
00059 }
00060
00061
00062 bool JointPath::find(Link* base, Link* end)
00063 {
00064 if(linkPath.find(base, end)){
00065 extractJoints();
00066 }
00067 onJointPathUpdated();
00068
00069 return (!joints.empty());
00070 }
00071
00072
00073 bool JointPath::find(Link* end)
00074 {
00075 linkPath.find(end);
00076 extractJoints();
00077 onJointPathUpdated();
00078
00079 return !joints.empty();
00080 }
00081
00082
00083 void JointPath::extractJoints()
00084 {
00085 numUpwardJointConnections = 0;
00086
00087 int n = linkPath.size();
00088 if(n <= 1){
00089 joints.clear();
00090 } else {
00091 int i = 0;
00092 if(linkPath.isDownward(i)){
00093 i++;
00094 }
00095 joints.resize(n);
00096 joints.clear();
00097 int m = n - 1;
00098 while(i < m){
00099 Link* link = linkPath[i];
00100 if(link->jointId >= 0){
00101 if(link->jointType == Link::ROTATIONAL_JOINT || link->jointType == Link::SLIDE_JOINT){
00102 joints.push_back(link);
00103 if(!linkPath.isDownward(i)){
00104 numUpwardJointConnections++;
00105 }
00106 }
00107 }
00108 ++i;
00109 }
00110 if(linkPath.isDownward(m-1)){
00111 Link* link = linkPath[m];
00112 if(link->jointId >= 0){
00113 if(link->jointType == Link::ROTATIONAL_JOINT || link->jointType == Link::SLIDE_JOINT){
00114 joints.push_back(link);
00115 }
00116 }
00117 }
00118 }
00119 }
00120
00121
00122 void JointPath::onJointPathUpdated()
00123 {
00124
00125 }
00126
00127
00128 void JointPath::calcJacobian(dmatrix& out_J, const Vector3& local_p) const
00129 {
00130 const int n = joints.size();
00131 out_J.resize(6, n);
00132
00133 if(n > 0){
00134
00135 Link* targetLink = linkPath.endLink();
00136
00137 for(int i=0; i < n; ++i){
00138
00139 Link* link = joints[i];
00140
00141 switch(link->jointType){
00142
00143 case Link::ROTATIONAL_JOINT:
00144 {
00145 Vector3 omega(link->R * link->a);
00146 Vector3 arm(targetLink->p + targetLink->R * local_p - link->p);
00147 if(!isJointDownward(i)){
00148 omega *= -1.0;
00149 }
00150 Vector3 dp(omega.cross(arm));
00151 out_J.col(i) << dp, omega;
00152 }
00153 break;
00154
00155 case Link::SLIDE_JOINT:
00156 {
00157 Vector3 dp(link->R * link->d);
00158 if(!isJointDownward(i)){
00159 dp *= -1.0;
00160 }
00161 out_J.col(i) << dp, Vector3::Zero();
00162 }
00163 break;
00164
00165 default:
00166 out_J.col(i).setZero();
00167 }
00168 }
00169 }
00170 }
00171
00172
00173 void JointPath::calcJacobianDot(dmatrix& out_dJ, const Vector3& local_p) const
00174 {
00175 const int n = joints.size();
00176 out_dJ.resize(6, n);
00177
00178 if (n > 0) {
00179
00180 Link* targetLink = linkPath.endLink();
00181
00182 for (int i=0; i < n; ++i) {
00183
00184 Link* link = joints[i];
00185
00186 switch (link->jointType) {
00187
00188 case Link::ROTATIONAL_JOINT:
00189 {
00190 Vector3 omega(link->R * link->a);
00191 Vector3 arm(targetLink->p + targetLink->R * local_p - link->p);
00192
00193 Vector3 omegaDot(hat(link->w) * link->R * link->a);
00194 Vector3 armDot(targetLink->v + hat(targetLink->w) * targetLink->R * local_p - link->v);
00195
00196 if (!isJointDownward(i)) {
00197 omega *= -1.0;
00198 omegaDot *= -1.0;
00199 }
00200
00201 Vector3 ddp(omegaDot.cross(arm) + omega.cross(armDot));
00202
00203 out_dJ.col(i) << ddp, omegaDot;
00204 }
00205 break;
00206
00207 case Link::SLIDE_JOINT:
00208 {
00209 Vector3 ddp(hat(link->w) * link->R * link->d);
00210 if (!isJointDownward(i)) {
00211 ddp *= -1.0;
00212 }
00213 out_dJ.col(i) << ddp, Vector3::Zero();
00214 }
00215 break;
00216
00217 default:
00218 out_dJ.col(i).setZero();
00219 }
00220 }
00221 }
00222 }
00223
00224
00225 void JointPath::setMaxIKError(double e)
00226 {
00227 maxIKErrorSqr = e * e;
00228 }
00229
00230
00231 void JointPath::setBestEffortIKMode(bool on)
00232 {
00233 isBestEffortIKMode = on;
00234 }
00235
00236
00237 bool JointPath::calcInverseKinematics
00238 (const Vector3& base_p, const Matrix33& base_R, const Vector3& end_p, const Matrix33& end_R)
00239 {
00240 Link* baseLink = linkPath.baseLink();
00241 baseLink->p = base_p;
00242 baseLink->R = base_R;
00243
00244 if(!hasAnalyticalIK()){
00245 calcForwardKinematics();
00246 }
00247
00248 return calcInverseKinematics(end_p, end_R);
00249 }
00250
00251
00252 bool JointPath::calcInverseKinematics(const Vector3& end_p, const Matrix33& end_R)
00253 {
00254 static const int MAX_IK_ITERATION = 50;
00255 static const double LAMBDA = 0.9;
00256 static const double JOINT_LIMIT_MARGIN = 0.05;
00257
00258 if(joints.empty()){
00259 if(linkPath.empty()){
00260 return false;
00261 }
00262 if(baseLink() == endLink()){
00263 baseLink()->p = end_p;
00264 baseLink()->R = end_R;
00265 return true;
00266 } else {
00267
00268 return false;
00269 }
00270 }
00271
00272 const int n = numJoints();
00273
00274 Link* target = linkPath.endLink();
00275
00276 std::vector<double> qorg(n);
00277 for(int i=0; i < n; ++i){
00278 qorg[i] = joints[i]->q;
00279 }
00280
00281 dmatrix J(6, n);
00282 dvector dq(n);
00283 dvector v(6);
00284
00285 double errsqr = maxIKErrorSqr * 100.0;
00286 bool converged = false;
00287
00288 for(int i=0; i < MAX_IK_ITERATION; i++){
00289
00290 calcJacobian(J);
00291
00292 Vector3 dp(end_p - target->p);
00293 Vector3 omega(target->R * omegaFromRot(target->R.transpose() * end_R));
00294
00295 if(isBestEffortIKMode){
00296 const double errsqr0 = errsqr;
00297 errsqr = dp.dot(dp) + omega.dot(omega);
00298 if(fabs(errsqr - errsqr0) < maxIKErrorSqr){
00299 converged = true;
00300 break;
00301 }
00302 } else {
00303 const double errsqr = dp.dot(dp) + omega.dot(omega);
00304 if(errsqr < maxIKErrorSqr){
00305 converged = true;
00306 break;
00307 }
00308 }
00309
00310 v << dp, omega;
00311
00312 if(n == 6){
00313 solveLinearEquationLU(J, v, dq);
00314 } else {
00315 solveLinearEquationSVD(J, v, dq);
00316 }
00317
00318 for(int j=0; j < n; ++j){
00319 joints[j]->q += LAMBDA * dq(j);
00320 if (joints[j]->q > joints[j]->ulimit){
00321 joints[j]->q = joints[j]->ulimit - JOINT_LIMIT_MARGIN;
00322 }else if(joints[j]->q < joints[j]->llimit){
00323 joints[j]->q = joints[j]->llimit + JOINT_LIMIT_MARGIN;
00324 }
00325 }
00326
00327 calcForwardKinematics();
00328 }
00329
00330 if(!converged){
00331 for(int i=0; i < n; ++i){
00332 joints[i]->q = qorg[i];
00333 }
00334 calcForwardKinematics();
00335 }
00336
00337 return converged;
00338 }
00339
00340
00341 bool JointPath::hasAnalyticalIK()
00342 {
00343 return false;
00344 }
00345
00346
00347 std::ostream& operator<<(std::ostream& os, JointPath& path)
00348 {
00349 int n = path.numJoints();
00350 for(int i=0; i < n; ++i){
00351 Link* link = path.joint(i);
00352 os << link->name;
00353 if(i != n){
00354 os << (path.isJointDownward(i) ? " => " : " <= ");
00355 }
00356 }
00357 os << std::endl;
00358 return os;
00359 }