00001 #include "IKGradientSolver.h"
00002 #include "Shared/fmat.h"
00003 #include <cmath>
00004 #include <valarray>
00005
00006 using namespace std;
00007
00008 const std::string IKGradientSolver::autoRegisterIKGradientSolver = IKSolver::getRegistry().registerType<IKGradientSolver>("IKGradientSolver");
00009 const std::string IKGradientSolver::autoRegisterDefaultIKSolver = IKSolver::getRegistry().registerType<IKGradientSolver>("");
00010
00011 bool IKGradientSolver::solve(const Point& pEff, const Rotation& oriEff,
00012 KinematicJoint& j, const Position& pTgt, float posPri,
00013 const Orientation& oriTgt, float oriPri) const {
00014 if (posPri==0 && oriPri==0)
00015 return true;
00016
00017 posPri=std::max(0.f,posPri);
00018 oriPri=std::max(0.f,oriPri);
00019
00020 KinematicJoint* firstMobileJoint = NULL;
00021 for(KinematicJoint *ancestor = &j; ancestor!=NULL; ancestor = ancestor->getParent())
00022 if (ancestor->isMobile())
00023 firstMobileJoint = ancestor;
00024 if (firstMobileJoint==NULL)
00025 return false;
00026
00027
00028 fmat::Transform Tj = j.getT(*firstMobileJoint);
00029 fmat::Column<3> pEffFMJ(Tj*pEff);
00030 fmat::fmatReal pDist = pEffFMJ.norm()/10;
00031
00032
00033 fmat::fmatReal oriDist = 1;
00034
00035 std::valarray<fmat::fmatReal> q(j.getDepth()+1);
00036 for(KinematicJoint * ancestor = &j; ancestor!=NULL; ancestor = ancestor->getParent())
00037 q[ancestor->getDepth()] = ancestor->getQ();
00038 std::valarray<fmat::fmatReal> dq, ndq(j.getDepth()+1);
00039 unsigned int iterCnt=0, overCnt=0;
00040 bool solved=false;
00041 while(iterCnt<MAX_ITER) {
00042 IKSolver::StepResult_t res = step(pEff,oriEff,j,pTgt,pDist,posPri,oriTgt,oriDist,oriPri,false);
00043 if (res==SUCCESS) {
00044 solved=true;
00045 break;
00046 }
00047 if (res!=PROGRESS) {
00048 std::cout << "Result " << res << std::endl;
00049 break;
00050 }
00051 for(KinematicJoint * ancestor = &j; ancestor!=NULL; ancestor = ancestor->getParent()) {
00052 ndq[ancestor->getDepth()] = ancestor->getQ() - q[ancestor->getDepth()];
00053 q[ancestor->getDepth()] = ancestor->getQ();
00054 }
00055 fmat::fmatReal qa=1;
00056 if (dq.size()==0) {
00057 dq.resize(j.getDepth()+1);
00058 dq=ndq;
00059 } else {
00060 qa = (dq*ndq).sum();
00061 std::swap(dq,ndq);
00062 }
00063
00064 if ( std::max(std::abs(dq.max()), std::abs(dq.min())) < QTOL ) {
00065 std::cout << "Converged" << std::endl;
00066 break;
00067 }
00068 if (qa<0) {
00069
00070
00071
00072 pDist *= 0.75f;
00073 oriDist *= 0.75f;
00074 ++overCnt;
00075 }
00076
00077
00078
00079
00080 ++iterCnt;
00081 }
00082 cout << "Iterations: " << iterCnt << " Overshoots: " << overCnt << endl;
00083 return solved;
00084 }
00085
00086 IKSolver::StepResult_t IKGradientSolver::step(const Point& pEff, const Rotation& oriEff,
00087 KinematicJoint& j, const Position& pTgt, float pDist, float posPri,
00088 const Orientation& oriTgt, float oriDist, float oriPri,
00089 bool successInReach) const {
00090 if ((posPri<=0 && oriPri<=0) || (pDist<=0 && oriDist<=0))
00091 return SUCCESS;
00092
00093 posPri=std::max(0.f,posPri);
00094 oriPri=std::max(0.f,oriPri);
00095 pDist=std::max(0.f,pDist);
00096 oriDist=std::max(0.f,oriDist);
00097
00098 const float totPri = posPri+oriPri;
00099 posPri/=totPri;
00100 oriPri/=totPri;
00101
00102
00103 StepResult_t result = LIMITS;
00104
00105
00106 std::vector<int> mobile;
00107 mobile.reserve(j.getDepth()+1);
00108 for(KinematicJoint * ancestor=&j; ancestor!=NULL; ancestor=ancestor->getParent()) {
00109 if (ancestor->isMobile())
00110 mobile.push_back(ancestor->getDepth());
00111
00112
00113 }
00114 std::reverse(mobile.begin(),mobile.end());
00115
00116
00117 fmat::fmatReal distRemain = pDist;
00118 fmat::fmatReal angRemain = oriDist;
00119
00120 while(mobile.size()>0) {
00121
00122 fmat::Transform Tj = j.getFullT();
00123 fmat::Column<3> pEffBase(Tj*pEff);
00124 fmat::Quaternion qj = j.getWorldQuaternion();
00125 Rotation oEffBase = qj*oriEff;
00126
00127 fmat::Column<3> pErr;
00128 pTgt.computeErrorGradient(pEffBase,oEffBase,pErr);
00129
00130 fmat::Quaternion oriErr;
00131 oriTgt.computeErrorGradient(pEffBase,oEffBase,oriErr);
00132 oriErr.normalize();
00133
00134 fmat::fmatReal pErrMagnitude = pErr.norm();
00135 fmat::fmatReal oriErrMagnitude = std::abs(oriErr.angle());
00136
00137
00138 if (pErrMagnitude/distRemain*posPri < .001 && oriErrMagnitude/angRemain*oriPri < .001) {
00139
00140 return SUCCESS;
00141 }
00142 if (pErrMagnitude*posPri < PTOL && oriErrMagnitude*oriPri < OTOL) {
00143
00144 return SUCCESS;
00145 }
00146 if (pErrMagnitude<distRemain && oriErrMagnitude<angRemain) {
00147 distRemain=pErrMagnitude;
00148 angRemain=oriErrMagnitude;
00149 if (successInReach)
00150 result = SUCCESS;
00151 } else if (pErrMagnitude<distRemain) {
00152 distRemain=pErrMagnitude;
00153 if (oriPri==0 && successInReach)
00154 result = SUCCESS;
00155 } else if (oriErrMagnitude<angRemain) {
00156 angRemain=oriErrMagnitude;
00157 if (posPri==0 && successInReach)
00158 result = SUCCESS;
00159 }
00160
00161 std::vector<fmat::Column<6> > J;
00162 j.getFullJacobian(pEffBase,J);
00163
00164 std::vector<fmat::Column<6> > Jm(mobile.size());
00165 for(size_t i=0; i<mobile.size(); ++i)
00166 Jm[i] = J[mobile[i]];
00167
00168
00169 std::valarray<fmat::fmatReal> q(mobile.size());
00170
00171 if (posPri>0 && distRemain>0) {
00172
00173
00174
00175
00176
00177
00178
00179 std::valarray<fmat::fmatReal> posQ(Jm.size());
00180 for(unsigned int i=0; i<posQ.size(); ++i) {
00181 posQ[i]=fmat::dotProduct(fmat::SubVector<3>(Jm[i]),pErr);
00182 }
00183
00184
00185
00186
00187 fmat::Column<3> move;
00188 for(unsigned int i=0; i<posQ.size(); ++i)
00189 move+=fmat::SubVector<3>(Jm[i])*posQ[i];
00190
00191 fmat::fmatReal moveSize = move.norm();
00192 if (moveSize > std::numeric_limits<float>::epsilon())
00193 posQ *= distRemain / moveSize;
00194
00195
00196 if (oriErrMagnitude*oriPri < OTOL) {
00197
00198
00199 fmat::fmatReal moveCos = fmat::dotProduct(pErr/pErrMagnitude, move/moveSize);
00200 if (moveCos < QTOL) {
00201
00202 return RANGE;
00203 }
00204
00205
00206 fmat::fmatReal posqsum=0;
00207 for(unsigned int i=0; i<posQ.size(); ++i)
00208 posqsum+=posQ[i]*posQ[i];
00209 if (std::sqrt(posqsum) < std::numeric_limits<float>::epsilon()) {
00210
00211 return RANGE;
00212 }
00213 }
00214
00215
00216 posQ*=posPri;
00217 q += posQ;
00218 }
00219
00220 if (oriPri>0 && angRemain>0) {
00221
00222 std::valarray<fmat::fmatReal> oriQ(Jm.size());
00223 fmat::Column<3> oriErrV = oriErr.axis();
00224
00225 for(unsigned int i=0; i<oriQ.size(); ++i) {
00226 oriQ[i] = fmat::dotProduct(fmat::SubVector<3>(Jm[i],3),oriErrV);
00227
00228 }
00229
00230
00231 fmat::fmatReal rotSize=0;
00232 for(unsigned int i=0; i<oriQ.size(); ++i)
00233 rotSize+=oriQ[i]*oriQ[i];
00234 rotSize=std::sqrt(rotSize);
00235
00236
00237
00238 if (rotSize > std::numeric_limits<float>::epsilon())
00239 oriQ *= oriDist * angRemain / rotSize;
00240
00241
00242 oriQ*=oriPri;
00243 q += oriQ;
00244 }
00245
00246
00247 size_t prevSize=mobile.size();
00248 KinematicJoint * ancestor=&j;
00249 for(int i=mobile.size()-1; i>=0; --i) {
00250 while(ancestor!=NULL && ancestor->getDepth()>static_cast<typeof(ancestor->getDepth())>(mobile[i]))
00251 ancestor=ancestor->getParent();
00252 q[i]+=ancestor->getQ();
00253 if (!ancestor->validQ(q[i])) {
00254
00255
00256 ancestor->tryQ(q[i]);
00257 std::vector<int>::iterator it=mobile.begin();
00258 std::advance(it,i);
00259 mobile.erase(it);
00260 }
00261 }
00262 if (mobile.size()<prevSize) {
00263
00264 fmat::Column<3> newpEffBase(j.getFullT()*pEff);
00265 distRemain -= (newpEffBase - pEffBase).norm();
00266
00267 fmat::Quaternion newoEffBase = j.getWorldQuaternion()*oriEff;
00268 fmat::Quaternion angMoved = crossProduct(newoEffBase, oEffBase);
00269
00270 angRemain -= std::abs(angMoved.angle());
00271
00272
00273 if (angRemain<=0 && distRemain<=0)
00274 return PROGRESS;
00275 if (distRemain<std::numeric_limits<float>::epsilon())
00276 distRemain=std::numeric_limits<float>::epsilon();
00277 if (angRemain<std::numeric_limits<float>::epsilon())
00278 angRemain=std::numeric_limits<float>::epsilon();
00279 } else {
00280
00281 ancestor=&j;
00282 for(int i=mobile.size()-1; i>=0; --i) {
00283 while(ancestor!=NULL && ancestor->getDepth()>static_cast<typeof(ancestor->getDepth())>(mobile[i]))
00284 ancestor=ancestor->getParent();
00285 ancestor->setQ(q[i]);
00286 }
00287 return (result==LIMITS) ? PROGRESS : result;
00288 }
00289 }
00290 return result;
00291 }
00292
00293
00294
00295
00296