00001 #include "Shared/RobotInfo.h"
00002
00003 #if defined(TGT_HAS_LEGS) && !defined(TGT_IS_AIBO) && (!defined(__GNUC__) || __GNUC__>=4)
00004
00005 #include "GaitedFootsteps.h"
00006 #include "Motion/KinematicJoint.h"
00007 #include "Motion/IKSolver.h"
00008 #include <algorithm>
00009 #include <iterator>
00010
00011 fmat::fmatReal GaitedFootsteps::State::ROUND=1/6.0;
00012 const fmat::fmatReal GaitedFootsteps::State::ORIROUND=30/M_PI;
00013
00014 GaitedFootsteps::~GaitedFootsteps() {
00015 delete kinematics;
00016 kinematics=NULL;
00017 for(std::vector<PlannerObstacle2D*>::const_iterator it=obstacles.begin(); it!=obstacles.end(); ++it)
00018 delete *it;
00019 obstacles.clear();
00020 }
00021
00022 float GaitedFootsteps::heuristic(const State& st, const State& goal) const {
00023 if(speed>0)
00024 return (st.pos - goal.pos).norm() / speed * relaxation;
00025 else
00026 return (st.pos - goal.pos).norm() / p.strideLenX * flightDuration * relaxation;
00027 }
00028
00029 bool GaitedFootsteps::validate(const State& st) const {
00030 return true;
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 }
00041
00042
00043
00044
00045
00046
00047
00048
00049 const std::vector<std::pair<float,GaitedFootsteps::State> >& GaitedFootsteps::expand(const State* parent, const State& st, const State& goal) const {
00050
00051 static std::vector<std::pair<float,GaitedFootsteps::State> > ans;
00052 ans.clear();
00053
00054
00055 std::vector<fmat::Column<2> > support;
00056 support.reserve(NumLegs - groups[st.phase].size());
00057 fmat::Column<3> gravOriAxis = fmat::crossProduct(fmat::UNIT3_Z,gravity);
00058 fmat::Quaternion gravOri = fmat::Quaternion::fromAxisAngle(gravOriAxis,std::asin(gravOriAxis.norm()));
00059 for(size_t i=0; i<NumLegs; ++i) {
00060 if(groups[st.phase].count(i) == 0) {
00061 fmat::Column<3> lpos3 = fmat::pack( st.oriRot.transpose()*(st.footPos[i]-st.pos), 0);
00062 support.push_back(fmat::SubVector<2,const fmat::fmatReal>(gravOri * lpos3));
00063
00064 p.projectToGround(ground, p.groundPlane[3], gravity, lpos3);
00065 IKSolver& solver = childMap[FootFrameOffset + i]->getIK();
00066 bool success = solver.solve(fmat::Column<3>(),*childMap[FootFrameOffset + i],IKSolver::Point(lpos3));
00067 if(!success)
00068 return ans;
00069 }
00070 }
00071 ConvexPolyObstacle supportPoly;
00072 supportPoly.hull(std::set<fmat::Column<2> >(support.begin(),support.end()));
00073 fmat::Column<3> com; float totalMass;
00074 kinematics->sumCenterOfMass(com,totalMass);
00075 if(!supportPoly.collides(fmat::SubVector<2,const fmat::fmatReal>(gravOri * com)))
00076 return ans;
00077
00078 const fmat::Column<2> gd = goal.pos - st.pos;
00079 const float goalDir = stepReorient ? std::atan2(gd[1],gd[0])-st.oriAngle : 0;
00080 addCandidate(parent, st, goalDir, ans, gd.norm());
00081 addCandidate(parent, st, goalDir+(float)M_PI, ans);
00082 for(size_t i=1; i<ncand/2; ++i) {
00083 float per = i/float(ncand/2);
00084
00085 addCandidate(parent, st, goalDir + static_cast<float>(M_PI)*per, ans);
00086 addCandidate(parent, st, goalDir - static_cast<float>(M_PI)*per, ans);
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 return ans;
00104 }
00105
00106 PlannerObstacle2D* GaitedFootsteps::checkObstacles(const fmat::Column<2>& pt) const {
00107 for(std::vector< PlannerObstacle2D* >::const_iterator oit=obstacles.begin(); oit!=obstacles.end(); ++oit) {
00108
00109 if((*oit)->collides(pt)) {
00110
00111 return *oit;
00112 }
00113 }
00114 return NULL;
00115 }
00116
00117 bool GaitedFootsteps::addRotation(const State& st, float strideAngle, float strideDist, const fmat::Column<2>& strideDir, const fmat::Column<2>& stride, std::vector<std::pair<float,GaitedFootsteps::State> >& candidates, float maxDist) const {
00118 float rotAngle = 2 * std::atan2(strideDist/2,rotDist);
00119 if(strideDir[0]>0) {
00120
00121 if(strideAngle>0) {
00122
00123 rotAngle = std::min(strideAngle,rotAngle);
00124 } else {
00125
00126 rotAngle = -std::min(-strideAngle,rotAngle);
00127 }
00128 } else {
00129 if(strideAngle<0)
00130 rotAngle=-rotAngle;
00131 }
00132 fmat::Matrix<2,2> rot = fmat::rotation2D(st.oriAngle+rotAngle);
00133
00134 std::vector< std::pair<size_t,fmat::Column<2> > > footPos;
00135 footPos.reserve(groups[st.phase].size());
00136 for(std::set<size_t>::const_iterator lit=groups[st.phase].begin(); lit!=groups[st.phase].end(); ++lit) {
00137
00138 fmat::Column<2> lpos2 = st.pos + rot*(neutrals[*lit] + stride);
00139
00140 PlannerObstacle2D* obs = checkObstacles(lpos2);
00141 if(obs!=NULL) {
00142 if(!stepRehab)
00143 return false;
00144
00145 fmat::Column<2> v = obs->gradient(lpos2);
00146 lpos2 += v + v*(0.25f/v.norm());
00147
00148 fmat::Column<3> lpos3 = fmat::pack( rot.transpose()*(lpos2-st.pos), 0);
00149
00150
00151
00152 p.projectToGround(ground, p.groundPlane[3], gravity, lpos3);
00153 IKSolver& solver = childMap[FootFrameOffset + *lit]->getIK();
00154 bool success = solver.solve(fmat::Column<3>(),*childMap[FootFrameOffset + *lit],IKSolver::Point(lpos3));
00155
00156
00157
00158
00159
00160
00161
00162
00163 if(!success)
00164 return false;
00165
00166
00167 if(checkObstacles(lpos2)!=NULL)
00168 return false;
00169 }
00170 footPos.push_back(std::make_pair(*lit,lpos2));
00171
00172 }
00173
00174 float t = strideDist / groups.size();
00175 if(maxDist>0)
00176 t = std::min(maxDist,t);
00177
00178 candidates.push_back(std::make_pair(speed>0?t/speed:flightDuration,st));
00179 State& nxt = candidates.back().second;
00180 if(++nxt.phase >= groups.size())
00181 nxt.phase=0;
00182 for(size_t i=0; i<footPos.size(); ++i)
00183 nxt.footPos[footPos[i].first] = footPos[i].second;
00184 nxt.oriAngle += rotAngle / groups.size();
00185 nxt.oriRot = fmat::rotation2D(nxt.oriAngle);
00186
00187 nxt.pos += st.oriRot*strideDir*t;
00188 return true;
00189 }
00190
00191 void GaitedFootsteps::addCandidate(const State* parent, const State& st, float angle, std::vector<std::pair<float,GaitedFootsteps::State> >& candidates, float maxDist) const {
00192 const fmat::Column<2> dir = fmat::pack(std::cos(angle),std::sin(angle));
00193 if(parent!=NULL && fmat::dotProduct(dir,st.pos-parent->pos)<-0.5)
00194 return;
00195 const fmat::Column<2> d = fmat::pack(p.strideLenX*dir[1], p.strideLenY*dir[0]);
00196 const float strideDist = p.strideLenX*p.strideLenY / d.norm();
00197
00198 const fmat::Column<2> stride = dir*strideDist;
00199 addRotation(st,angle,strideDist,dir,stride,candidates,maxDist);
00200
00201
00202
00203 std::vector< std::pair<size_t,fmat::Column<2> > > footPos;
00204 footPos.reserve(groups[st.phase].size());
00205 for(std::set<size_t>::const_iterator lit=groups[st.phase].begin(); lit!=groups[st.phase].end(); ++lit) {
00206
00207 fmat::Column<2> lpos2 = st.pos + st.oriRot * (neutrals[*lit] + stride);
00208
00209 PlannerObstacle2D* obs = checkObstacles(lpos2);
00210 if(obs!=NULL) {
00211 if(!stepRehab)
00212 return;
00213
00214 fmat::Column<2> v = obs->gradient(lpos2);
00215 lpos2 += v + v*(0.25f/v.norm());
00216
00217 fmat::Column<3> lpos3 = fmat::pack(st.oriRot.transpose()*(lpos2-st.pos),0);
00218
00219
00220
00221 p.projectToGround(ground, p.groundPlane[3], gravity, lpos3);
00222 IKSolver& solver = childMap[FootFrameOffset + *lit]->getIK();
00223 bool success = solver.solve(fmat::Column<3>(),*childMap[FootFrameOffset + *lit],IKSolver::Point(lpos3));
00224
00225
00226
00227
00228
00229
00230
00231
00232 if(!success)
00233 return;
00234
00235
00236 if(checkObstacles(lpos2)!=NULL)
00237 return;
00238 }
00239 footPos.push_back(std::make_pair(*lit,lpos2));
00240
00241 }
00242
00243 float t = strideDist / groups.size();
00244 if(maxDist>0)
00245 t = std::min(maxDist,t);
00246
00247 candidates.push_back(std::make_pair(speed>0?t/speed:flightDuration,st));
00248 State& nxt = candidates.back().second;
00249 if(++nxt.phase >= groups.size())
00250 nxt.phase=0;
00251 for(size_t i=0; i<footPos.size(); ++i)
00252 nxt.footPos[footPos[i].first] = footPos[i].second;
00253
00254 nxt.pos += st.oriRot*dir*t;
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 }
00277
00278 void GaitedFootsteps::setGait(const KinematicJoint& kj, const XWalkParameters& xp, size_t discretization) {
00279 std::fill(childMap, childMap+NumReferenceFrames, static_cast<KinematicJoint*>(NULL));
00280 delete kinematics;
00281 kinematics = dynamic_cast<KinematicJoint*>(kj.clone());
00282 kinematics->buildChildMap(childMap,0,NumReferenceFrames);
00283
00284 ncand = discretization;
00285
00286 p.setParseTree(xp.stealParseTree());
00287 p.readParseTree();
00288
00289 p.packGroundGravity(ground,gravity);
00290
00291
00292
00293 neutrals.resize(NumLegs);
00294 fmat::Column<2> neutralPos[NumLegs];
00295 for(unsigned int leg=0; leg<NumLegs; ++leg) {
00296 XWalkParameters::LegParameters& legParam = p.legParams[leg];
00297 #if defined(TGT_IS_MANTIS)
00298 const unsigned int JointsPerLeg = 4;
00299 #endif
00300 KinematicJoint * legRoot = childMap[LegOffset+JointsPerLeg*leg];
00301 fmat::Column<3> fstPos = legRoot->getWorldPosition();
00302 neutralPos[leg][0] = fstPos[0] + legParam.strideBias;
00303 neutralPos[leg][1] = ((fstPos[1]<0) ? -*legParam.stanceWidth : *legParam.stanceWidth);
00304
00305 neutrals[leg] = neutralPos[leg];
00306
00307
00308
00309
00310 flightDuration = std::max(p.legParams[leg].flightDuration/1000.f, flightDuration);
00311 }
00312
00313
00314
00315
00316 rotDist=0;
00317 for(unsigned int leg=0; leg<NumLegs; ++leg) {
00318 rotDist = std::max(neutrals[leg].norm(), rotDist);
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 groups.clear();
00367 std::map< float, std::set<size_t> > phasedGroups;
00368 for(size_t leg=0; leg<NumLegs; ++leg)
00369 phasedGroups[p.legParams[leg].flightPhase].insert(leg);
00370 for(std::map< float, std::set<size_t> >::const_iterator it=phasedGroups.begin(); it!=phasedGroups.end(); ++it)
00371 groups.push_back(it->second);
00372
00373 for(size_t i=0; i<groups.size(); ++i) {
00374 std::cout << "Group " << i << ": ";
00375 for(std::set<size_t>::const_iterator git=groups[i].begin(); git!=groups[i].end(); ++git)
00376 std::cout << "\t" << *git;
00377 std::cout << std::endl;
00378 }
00379
00380 State::ROUND = 1 / (std::min(p.strideLenX,p.strideLenY)/groups.size()/2);
00381 std::cout << p.strideLenX << ' ' << p.strideLenY << " Rounding factor " << State::ROUND << std::endl;
00382 }
00383
00384 #endif