Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

WalkMC.cc

Go to the documentation of this file.
00001 //This class is ported from Carnegie Mellon's 2001 Robosoccer entry, and falls under their license:
00002 /*=========================================================================
00003     CMPack'02 Source Code Release for OPEN-R SDK v1.0
00004     Copyright (C) 2002 Multirobot Lab [Project Head: Manuela Veloso]
00005     School of Computer Science, Carnegie Mellon University
00006   -------------------------------------------------------------------------
00007     This software is distributed under the GNU General Public License,
00008     version 2.  If you do not have a copy of this licence, visit
00009     www.gnu.org, or write: Free Software Foundation, 59 Temple Place,
00010     Suite 330 Boston, MA 02111-1307 USA.  This program is distributed
00011     in the hope that it will be useful, but WITHOUT ANY WARRANTY,
00012     including MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00013   -------------------------------------------------------------------------
00014     Additionally licensed to Sony Corporation under the following terms:
00015 
00016     This software is provided by the copyright holders AS IS and any
00017     express or implied warranties, including, but not limited to, the
00018     implied warranties of merchantability and fitness for a particular
00019     purpose are disclaimed.  In no event shall authors be liable for
00020     any direct, indirect, incidental, special, exemplary, or consequential
00021     damages (including, but not limited to, procurement of substitute
00022     goods or services; loss of use, data, or profits; or business
00023     interruption) however caused and on any theory of liability, whether
00024     in contract, strict liability, or tort (including negligence or
00025     otherwise) arising in any way out of the use of this software, even if
00026     advised of the possibility of such damage.
00027   =========================================================================
00028 */
00029 
00030 #include "WalkMC.h"
00031 
00032 #include "Shared/WorldState.h"
00033 #include "Events/EventRouter.h"
00034 #include "Events/LocomotionEvent.h"
00035 #include "Wireless/Socket.h"
00036 #include "Shared/Config.h"
00037 
00038 #include "Motion/MotionManager.h"
00039 
00040 #include <stdlib.h>
00041 #include <stdio.h>
00042 #include <iostream>
00043 #include <fcntl.h>
00044 #include <unistd.h>
00045 #include <fstream>
00046 #include <cmath>
00047 
00048 //REGIMP(WalkMC);
00049 
00050 //#define BOUND_MOTION
00051 
00052 const float WalkMC::MAX_DX   = 180;//225; // mm/sec
00053 const float WalkMC::MAX_DY   = 140;//170; // mm/sec
00054 const float WalkMC::MAX_DA   = 1.8;//2.1; // rad/sec
00055 // tss "SmoothWalk" modification follows
00056 // const vector3d WalkMC::max_accel_xya(MAX_DX*2,MAX_DY*2,MAX_DA*2);
00057 const vector3d WalkMC::max_accel_xya(MAX_DX*2,MAX_DY*2,MAX_DA*2);
00058 
00059 unsigned int checksum(const char *data,int num); //!< computes a file checksum
00060 
00061 WalkMC::WalkMC(const char* pfile/*=NULL*/)
00062   : MotionCommand(), isPaused(false), wp(), cp(), body_loc(), body_angle(),
00063     acc_style(DEFAULT_ACCEL), step_count(-1), step_threshold(0), last_cycle(0),
00064     pos_delta(0,0,0), angle_delta(0), travelTime(get_time()),
00065     time(get_time()), TimeStep(FrameTime), slowmo(1.0f),
00066     CycleOffset(0), TimeOffset(0), NewCycleOffset(false),
00067     vel_xya(0,0,0), target_vel_xya(0,0,0), last_target_vel_xya(0,0,0)
00068 {
00069   init(pfile);
00070 }
00071 
00072 WalkMC::CalibrationParam::CalibrationParam() {
00073   for(unsigned int r=0; r<3; r++) {
00074     for(unsigned int c=0; c<11; c++)
00075       f_calibration[r][c]=b_calibration[r][c]=0;
00076     f_calibration[r][r]=b_calibration[r][r]=1;
00077   }
00078   for(unsigned int d=0; d<NUM_DIM; d++)
00079     max_accel[d]=0;
00080   max_vel[0]=max_vel[1]=MAX_DX;
00081   max_vel[2]=MAX_DY;
00082   max_vel[3]=MAX_DA;
00083 }
00084 
00085 
00086 void WalkMC::DoStart() {
00087   MotionCommand::DoStart();
00088   LocomotionEvent e(EventBase::locomotionEGID,getID(),EventBase::activateETID,0);
00089   e.setXYA(target_vel_xya.x,target_vel_xya.y,target_vel_xya.z);
00090   postEvent(e);
00091   travelTime=get_time();
00092 }
00093 
00094 void WalkMC::DoStop() {
00095   unsigned int t=get_time();
00096   LocomotionEvent e(EventBase::locomotionEGID,getID(),EventBase::deactivateETID,t-travelTime);
00097   //leave values at 0!
00098   //e.setXYA(target_vel_xya.x,target_vel_xya.y,target_vel_xya.z);
00099   postEvent(e);
00100   travelTime=t;
00101   MotionCommand::DoStop();
00102 }
00103 
00104 void WalkMC::init(const char* pfile)
00105 {
00106   //  RegInit();
00107   body_loc.init(vector3d(0,0,wp.body_height),vector3d(0,0,0));
00108   body_angle.init(vector3d(0,wp.body_angle,0),vector3d(0,0,0));
00109 
00110   for(unsigned int i=0; i<NumLegs; i++)
00111     legw[i].air = false;
00112 
00113   if(pfile!=NULL)
00114     loadFile(pfile);
00115   else
00116     loadFile(config->motion.walk.c_str());
00117 
00118   double zeros[JointsPerLeg];
00119   for(unsigned int i=0; i<JointsPerLeg; i++)
00120     zeros[i]=0;
00121   resetLegPos();
00122 
00123   //  cmds[HeadOffset+TiltOffset].set(.3333,1);
00124 }
00125 
00126 // tss "SmoothWalk" addition follows
00127 int WalkMC::isDirty()
00128 {
00129   if(isPaused)
00130     return 0;
00131   if(step_count==0)
00132     return 0;
00133   if((target_vel_xya.x == 0) && (target_vel_xya.y == 0) && (target_vel_xya.z == 0)) {
00134     // we may stopping, but not stopped yet...
00135     return ((vel_xya.x != 0) || (vel_xya.y != 0) || (vel_xya.z != 0));
00136   }
00137   return JointsPerLeg*NumLegs;
00138 }
00139 // tss "SmoothWalk" addition ends
00140 
00141   
00142 unsigned int WalkMC::getBinSize() const {
00143   unsigned int used=0;
00144   used+=creatorSize("WalkMC-2.2");
00145   used+=sizeof(wp);
00146   used+=sizeof(cp);
00147   return used;  
00148 }
00149 
00150 unsigned int WalkMC::loadBuffer(const char buf[], unsigned int len) {
00151   enum {
00152     VER1, // original CMPack version
00153     VER2, // added calibration parameters
00154     VER3 // added diff drive and sag parameter
00155   } version;
00156   
00157   unsigned int origlen=len;
00158   if(checkCreatorInc("WalkMC-2.2",buf,len,false)) {
00159     version=VER3;
00160   } else if(checkCreatorInc("WalkMC",buf,len,false)) {
00161     sout->printf("Pre-2.2 release walk parameter file\n");
00162     version=VER2;
00163   } else {
00164     // backwards compatability - if there's no creator code, just assume it's a straight WalkParam
00165     sout->printf("Assuming CMPack format walk parameter file\n");
00166     version=VER1;
00167   }
00168   
00169   // Leg parameters
00170   for(unsigned int i=0; i<NumLegs; ++i) {
00171     if(!decodeInc(wp.leg[i].neutral.x,buf,len)) return 0;
00172     if(!decodeInc(wp.leg[i].neutral.y,buf,len)) return 0;
00173     if(!decodeInc(wp.leg[i].neutral.z,buf,len)) return 0;
00174     if(!decodeInc(wp.leg[i].lift_vel.x,buf,len)) return 0;
00175     if(!decodeInc(wp.leg[i].lift_vel.y,buf,len)) return 0;
00176     if(!decodeInc(wp.leg[i].lift_vel.z,buf,len)) return 0;
00177     if(!decodeInc(wp.leg[i].down_vel.x,buf,len)) return 0;
00178     if(!decodeInc(wp.leg[i].down_vel.y,buf,len)) return 0;
00179     if(!decodeInc(wp.leg[i].down_vel.z,buf,len)) return 0;
00180     if(!decodeInc(wp.leg[i].lift_time,buf,len)) return 0;
00181     if(!decodeInc(wp.leg[i].down_time,buf,len)) return 0;
00182   }
00183   // Body parameters
00184   if(!decodeInc(wp.body_height,buf,len)) return 0;
00185   if(!decodeInc(wp.body_angle,buf,len)) return 0;
00186   if(!decodeInc(wp.hop,buf,len)) return 0;
00187   if(!decodeInc(wp.sway,buf,len)) return 0;
00188   if(!decodeInc(wp.period,buf,len)) return 0;
00189   if(version<VER3) wp.useDiffDrive=0; else if(!decodeInc(wp.useDiffDrive,buf,len)) return 0;
00190   if(version<VER3) wp.sag=0; else if(!decodeInc(wp.sag,buf,len)) return 0;
00191   if(!decodeInc(wp.reserved,buf,len)) return 0;
00192   // Calibration parameters
00193   if(version<VER2) {
00194     cp=CalibrationParam();
00195   } else {
00196     for(unsigned int i=0; i<3; ++i)
00197       for(unsigned int j=0; j<11; ++j)
00198         if(!decodeInc(cp.f_calibration[i][j],buf,len)) return 0;
00199     for(unsigned int i=0; i<3; ++i)
00200       for(unsigned int j=0; j<11; ++j)
00201         if(!decodeInc(cp.b_calibration[i][j],buf,len)) return 0;
00202     for(unsigned int i=0; i<CalibrationParam::NUM_DIM; ++i)
00203       if(!decodeInc(cp.max_accel[i],buf,len)) return 0;
00204     for(unsigned int i=0; i<CalibrationParam::NUM_DIM; ++i)
00205       if(!decodeInc(cp.max_vel[i],buf,len)) return 0;
00206   }
00207   return origlen-len; 
00208 }
00209 
00210 unsigned int WalkMC::saveBuffer(char buf[], unsigned int len) const {
00211   unsigned int origlen=len;
00212   // Leg parameters
00213   if(!saveCreatorInc("WalkMC-2.2",buf,len)) return 0;
00214   for(unsigned int i=0; i<NumLegs; ++i) {
00215     if(!encodeInc(wp.leg[i].neutral.x,buf,len)) return 0;
00216     if(!encodeInc(wp.leg[i].neutral.y,buf,len)) return 0;
00217     if(!encodeInc(wp.leg[i].neutral.z,buf,len)) return 0;
00218     if(!encodeInc(wp.leg[i].lift_vel.x,buf,len)) return 0;
00219     if(!encodeInc(wp.leg[i].lift_vel.y,buf,len)) return 0;
00220     if(!encodeInc(wp.leg[i].lift_vel.z,buf,len)) return 0;
00221     if(!encodeInc(wp.leg[i].down_vel.x,buf,len)) return 0;
00222     if(!encodeInc(wp.leg[i].down_vel.y,buf,len)) return 0;
00223     if(!encodeInc(wp.leg[i].down_vel.z,buf,len)) return 0;
00224     if(!encodeInc(wp.leg[i].lift_time,buf,len)) return 0;
00225     if(!encodeInc(wp.leg[i].down_time,buf,len)) return 0;
00226   }
00227   // Body parameters
00228   if(!encodeInc(wp.body_height,buf,len)) return 0;
00229   if(!encodeInc(wp.body_angle,buf,len)) return 0;
00230   if(!encodeInc(wp.hop,buf,len)) return 0;
00231   if(!encodeInc(wp.sway,buf,len)) return 0;
00232   if(!encodeInc(wp.period,buf,len)) return 0;
00233   if(!encodeInc(wp.useDiffDrive,buf,len)) return 0;
00234   if(!encodeInc(wp.sag,buf,len)) return 0;
00235   if(!encodeInc(wp.reserved,buf,len)) return 0;
00236   // Calibration parameters
00237   for(unsigned int i=0; i<3; ++i)
00238     for(unsigned int j=0; j<11; ++j)
00239       if(!encodeInc(cp.f_calibration[i][j],buf,len)) return 0;
00240   for(unsigned int i=0; i<3; ++i)
00241     for(unsigned int j=0; j<11; ++j)
00242       if(!encodeInc(cp.b_calibration[i][j],buf,len)) return 0;
00243   for(unsigned int i=0; i<CalibrationParam::NUM_DIM; ++i)
00244     if(!encodeInc(cp.max_accel[i],buf,len)) return 0;
00245   for(unsigned int i=0; i<CalibrationParam::NUM_DIM; ++i)
00246     if(!encodeInc(cp.max_vel[i],buf,len)) return 0;
00247   return origlen-len; 
00248 }
00249 
00250 unsigned int WalkMC::loadFile(const char* filename) {
00251   return LoadSave::loadFile(config->motion.makePath(filename).c_str());
00252 }
00253 unsigned int WalkMC::saveFile(const char* filename) const {
00254   return LoadSave::saveFile(config->motion.makePath(filename).c_str());
00255 }
00256 
00257 void WalkMC::setTargetVelocity(double dx,double dy,double da,int n)
00258 {
00259 #ifdef BOUND_MOTION
00260   da = bound(da, -cp.rotate_max_vel, cp.rotate_max_vel);
00261   double fa = 1.0 - fabs(da / cp.rotate_max_vel);
00262 
00263   vector2d v(dx>0?dx/cp.forward_max_vel:dx/cp.reverse_max_vel,dy/cp.strafe_max_vel);
00264   double l = v.length();
00265   if(l > 1) v /= l;
00266 
00267   dx = (dx>0?cp.forward_max_vel:cp.reverse_max_vel) * v.x * fa;
00268   dy = cp.strafe_max_vel * v.y * fa;
00269 #endif
00270 
00271   target_vel_xya.set(dx,dy,da);
00272   // we just modified the target velocity, but we'll hold off on generating
00273   // an event until the changes are actually picked up by the motion system
00274 
00275   step_count=n;
00276 }
00277 
00278 void WalkMC::setTargetDisplacement(double dx, double dy, double da, unsigned int n) {
00279   if(n==0) {
00280     setTargetVelocity(0,0,0,0);
00281   } else {
00282     //compute the point in cycle of the mid-step
00283     float midsteps[NumLegs];
00284     for(unsigned int i=0; i<NumLegs; i++)
00285       midsteps[i] = (wp.leg[i].down_time+wp.leg[i].lift_time)/2;
00286     //find the number of unique steps per cycle
00287     unsigned int steps_per_cycle=4;
00288     for(unsigned int i=0; i<NumLegs-1; i++)
00289       for(unsigned int j=i+1; j<NumLegs; j++)
00290         if(midsteps[i]==midsteps[j]) {
00291           steps_per_cycle--;
00292           break;
00293         }
00294     //compute velocity needed to move requested distance in the time it takes to do n steps
00295     double scale=steps_per_cycle/(n*wp.period/1000.0);
00296     double vx=dx*scale;
00297     double vy=dy*scale;
00298     double va=da*scale;
00299     setTargetVelocity(vx,vy,va,n); //apply new value
00300   }
00301 }
00302   
00303 int WalkMC::updateOutputs() {
00304   //  cout << "WalkMC,,," << flush;
00305   if(!isDirty())
00306     return 0;
00307 
00308   if(vel_xya.sqlength()==0) {
00309     // we had been stopped - better check someone else didn't move the legs while we weren't using them...
00310     resetLegPos(); 
00311   }
00312 
00313   unsigned int curT=get_time();
00314   if(last_target_vel_xya!=target_vel_xya) {
00315     last_target_vel_xya=target_vel_xya;
00316     LocomotionEvent e(EventBase::locomotionEGID,getID(),EventBase::statusETID,getTravelTime());
00317     e.setXYA(target_vel_xya.x,target_vel_xya.y,target_vel_xya.z);
00318     //cout << e.getDescription(true) << endl;
00319     postEvent(e);
00320     travelTime=curT;
00321   }
00322   
00323   float tm = TimeStep * slowmo / 1000;
00324 
00325   vector3d cal_target_vel_xya(target_vel_xya);
00326   if(target_vel_xya.x<0)
00327     cal_target_vel_xya.x/=cp.max_vel[CalibrationParam::reverse];
00328   else
00329     cal_target_vel_xya.x/=cp.max_vel[CalibrationParam::forward];
00330   cal_target_vel_xya.y/=cp.max_vel[CalibrationParam::strafe];
00331   cal_target_vel_xya.z/=cp.max_vel[CalibrationParam::rotate];
00332   if(cal_target_vel_xya.sqlength()>.0025)
00333     if(target_vel_xya.x<0)
00334       applyCalibration(cp.b_calibration,target_vel_xya,cal_target_vel_xya);
00335     else
00336       applyCalibration(cp.f_calibration,target_vel_xya,cal_target_vel_xya);
00337 
00338   if(step_count<0 && (acc_style==CALIBRATION_ACCEL || acc_style==DEFAULT_ACCEL && !config->motion.inf_walk_accel)) {
00339     //software accel:
00340     vel_xya.x = bound(cal_target_vel_xya.x, vel_xya.x-max_accel_xya.x*tm, vel_xya.x+max_accel_xya.x*tm);
00341     vel_xya.y = bound(cal_target_vel_xya.y, vel_xya.y-max_accel_xya.y*tm, vel_xya.y+max_accel_xya.y*tm);
00342     vel_xya.z = bound(cal_target_vel_xya.z, vel_xya.z-max_accel_xya.z*tm, vel_xya.z+max_accel_xya.z*tm);
00343   } else {
00344     //no software accel:
00345     vel_xya=cal_target_vel_xya;
00346   }
00347 
00348   BodyPosition delta;
00349   delta.loc.set(vel_xya.x*tm,vel_xya.y*tm,0);
00350   delta.angle.set(0,0,vel_xya.z*tm);
00351 
00352   time=(int)(curT*slowmo);
00353 
00354 // tss "SmoothWalk" addition follows
00355   // If necessary, we compute a new TimeOffset here.
00356   if(NewCycleOffset) {
00357     TimeOffset = CycleOffset - time % wp.period;
00358     NewCycleOffset = false;
00359   }
00360 
00361   // Adjusted time--time adjusted for cycle matching
00362   int AdjustedTime = time + TimeOffset;
00363 
00364   // If walking speeds have dwindled down to zero, save our time offset from the beginning of the current walk cycle. Once we start walking again, we start up at the same offset to prevent jerky starts.
00365   if((vel_xya.x == 0) && (vel_xya.y == 0) && (vel_xya.z == 0)) {
00366     CycleOffset = AdjustedTime % wp.period;
00367     NewCycleOffset = true;
00368   }
00369 // tss "SmoothWalk" addition ends
00370 
00371   for(unsigned int frame=0; frame<NumFrames; frame++) {
00372     cal_target_vel_xya.rotate_z(-delta.angle.z);
00373 
00374     // incorporate movement delta
00375     angle_delta += delta.angle.z;
00376     pos_delta += delta.loc.rotate_z(angle_delta);
00377 
00378     //    cout << "setup,,," << flush;
00379 
00380 // tss "SmoothWalk" modification follows
00381     // double cycle = (double)(time % wp.period) / wp.period;
00382     AdjustedTime = time + TimeOffset + (int)(frame*TimeStep*slowmo);
00383     double cycle = (double)(AdjustedTime % wp.period) / wp.period;
00384 
00385     if(step_count>0) {
00386       for(unsigned int i=0; i<NumLegs; i++){
00387         float midstep;
00388         if(step_threshold<=.5f)
00389           midstep=wp.leg[i].lift_time+(wp.leg[i].down_time-wp.leg[i].lift_time)*step_threshold*2;
00390         else
00391           midstep=wp.leg[i].down_time+(1-wp.leg[i].down_time+wp.leg[i].lift_time)*(step_threshold-.5)*2;
00392         midstep-=floorf(midstep);
00393         //cout << "leg "<<i<<": " <<AdjustedTime << ' ' << cycle << ' ' << last_cycle << ' ' << midstep << ' ' <<step_count ;
00394         bool above_last= (last_cycle<midstep);
00395         bool below_cur = (midstep<=cycle);
00396         bool wrap      = (cycle<last_cycle);
00397         //need any 2 of the conditions: above_last && below_cur || wrap && (above_last || below_cur)
00398         if(above_last+below_cur+wrap>1) { //we just completed a step
00399           step_count--;
00400           //cout << " -> " << step_count << endl;
00401           if(step_count==0) { //we're done, copy out any completed frames
00402             for(unsigned int f=0; f<frame; f++)
00403               for(unsigned int joint=LegOffset; joint<LegOffset+NumLegJoints; joint++)
00404                 motman->setOutput(this,joint,cmds[joint][f],f);
00405             CycleOffset = AdjustedTime % wp.period;
00406             NewCycleOffset = true;
00407             last_cycle=cycle;
00408             target_vel_xya.set(0,0,0);
00409             last_target_vel_xya=target_vel_xya;
00410             LocomotionEvent e(EventBase::locomotionEGID,getID(),EventBase::statusETID,getTravelTime());
00411             e.setXYA(target_vel_xya.x,target_vel_xya.y,target_vel_xya.z);
00412             //cout << e.getDescription(true) << endl;
00413             postEvent(e);
00414             postEvent(EventBase(EventBase::motmanEGID,getID(),EventBase::statusETID,getTravelTime()));
00415             //    cout << "WalkMC-done" << endl;
00416             return frame==0?0:NumLegs*JointsPerLeg;
00417           }
00418           break; //don't count legs moving in sync as two steps, only ever one step at a time
00419         }
00420         //cout << endl;
00421       }
00422     }
00423     
00424 
00425     double sway   = wp.sway*cos(2*M_PI*cycle);
00426     double hop    = wp.hop*sin(4*M_PI*cycle);
00427     double height = wp.body_height;
00428     BodyPosition nextpos;
00429     nextpos.loc.set(0,-sway,height+hop);
00430     nextpos.angle.set(0,wp.body_angle,0);
00431 
00432     //    cout << "loop,,," << flush;
00433     for(unsigned int i=0; i<NumLegs; i++){
00434 
00435       //interpret a down time before a lift time as a request to move the leg in reverse (has its uses)
00436       float lift_time=wp.leg[i].lift_time;
00437       float down_time=wp.leg[i].down_time;
00438       float dir=1;
00439       if(down_time==lift_time)
00440         dir=0;
00441       else if(down_time<lift_time) {
00442         lift_time=wp.leg[i].down_time;
00443         down_time=wp.leg[i].lift_time;
00444         dir=-1;
00445       }
00446 
00447       bool air = (cycle >= lift_time) && (cycle < down_time);
00448       double air_f = down_time - lift_time;
00449       double nextlegangles[JointsPerLeg];
00450 
00451       if(air != legw[i].air){
00452         if(air){
00453           /*
00454             cout << i << ":   ";
00455             cout << legpos[i].x << ' ' << legpos[i].y << ' ' << legpos[i].z << "  ->  ";
00456             GetLegAngles(nextlegangles,legpos[i],nextpos,i);
00457             for(unsigned int j=0; j<JointsPerLeg; j++)
00458               cout << nextlegangles[j] << ' ';
00459             cout << endl;
00460           */
00461           tm = wp.period/1000.0 * 0.75; //wtf is the 0.75 based on?  Don't ask me, i just work here! (ejt)
00462           vector3d vfp;
00463           double vfa;
00464           if(step_count<0 && (acc_style==CALIBRATION_ACCEL || acc_style==DEFAULT_ACCEL && !config->motion.inf_walk_accel)) {
00465             //software accel:
00466             vfp.x = bound(cal_target_vel_xya.x, vel_xya.x-max_accel_xya.x*tm, vel_xya.x+max_accel_xya.x*tm);
00467             vfp.y = bound(cal_target_vel_xya.y, vel_xya.y-max_accel_xya.y*tm, vel_xya.y+max_accel_xya.y*tm);
00468             vfa   = bound(cal_target_vel_xya.z, vel_xya.z-max_accel_xya.z*tm, vel_xya.z+max_accel_xya.z*tm);
00469           } else {
00470             //no software accel:
00471             vfp.x=cal_target_vel_xya.x;
00472             vfp.y=cal_target_vel_xya.y;
00473             vfa=cal_target_vel_xya.z;
00474           }
00475           
00476           vfp.z = 0.0;
00477           double b = (wp.period/1000.0) * (1.0 - air_f) / 2.0;
00478           vector3d target;
00479           if(wp.useDiffDrive) {
00480             float rot = vfa/cp.max_vel[CalibrationParam::rotate];
00481             if((i&1)==0)
00482               rot=-rot;
00483             vfp.x += cp.max_vel[CalibrationParam::forward]*rot;
00484             target = (wp.leg[i].neutral + vfp*b*dir);
00485           } else {
00486             target = (wp.leg[i].neutral + vfp*b*dir).rotate_z(vfa*b);
00487           }
00488           target.z+=wp.sag;
00489           liftPos[i]=legpos[i];
00490           downPos[i]=target;
00491           legw[i].airpath.create(legpos[i],target,wp.leg[i].lift_vel,wp.leg[i].down_vel);
00492         }else{
00493           legpos[i].z = wp.leg[i].neutral.z;
00494         }
00495         legw[i].air = air;
00496       }
00497 
00498       if(air){
00499         legw[i].cyc = (cycle - lift_time) / air_f;
00500         legpos[i] = legw[i].airpath.eval(legw[i].cyc);
00501 
00502 // Core tss "SmoothWalk" addition follows
00503         // KLUDGY MOD. Goal: reduce the height of the
00504         // AIBO's steps as its velocity nears zero.
00505         // Since I don't know how most of this code 
00506         // works, I'll directly alter legpos[i].z in
00507         // the following code to change the z height
00508         // with velocity.
00509         double velfraction_x = fabs(vel_xya.x / MAX_DX);
00510         double velfraction_y = fabs(vel_xya.y / MAX_DY);
00511         double velfraction_a = fabs(vel_xya.z / MAX_DA * 2); //rotation seems more sensitive
00512 
00513         // Choose the biggest velfraction
00514         double velfraction =
00515           (velfraction_x > velfraction_y) ?
00516             velfraction_x : velfraction_y;
00517         if(velfraction_a > velfraction)
00518           velfraction = velfraction_a;
00519 
00520         // Modify legpos[i].z with velfraction to
00521         // shrink it down
00522         //velfraction = atan(velfraction * M_PI);
00523 
00524         velfraction-=1;
00525         velfraction*=velfraction;
00526         velfraction*=velfraction;
00527 
00528         legpos[i].z *= 1-velfraction;
00529 // Core tss "SmoothWalk" addition ends
00530       }else{
00531         if(dir==0)
00532           legpos[i]=wp.leg[i].neutral;
00533         else {
00534           if(wp.useDiffDrive) {
00535             tm = wp.period/1000.0 * 0.75; //wtf is the 0.75 based on?  Don't ask me, i just work here! (ejt)
00536             double vfa;
00537             if(step_count<0 && (acc_style==CALIBRATION_ACCEL || acc_style==DEFAULT_ACCEL && !config->motion.inf_walk_accel)) {
00538               vfa   = bound(cal_target_vel_xya.z, vel_xya.z-max_accel_xya.z*tm, vel_xya.z+max_accel_xya.z*tm);
00539             } else {
00540               vfa   = cal_target_vel_xya.z;
00541             }
00542             legpos[i] -= delta.loc*dir;
00543             float rot = vfa/cp.max_vel[CalibrationParam::rotate]*TimeStep * slowmo / 1000;
00544             if((i&1)==0)
00545               rot=-rot;
00546             legpos[i].x -= cp.max_vel[CalibrationParam::forward]*rot;
00547           } else {
00548             legpos[i] = (legpos[i] - delta.loc*dir).rotate_z(-delta.angle.z);
00549           }
00550         }
00551       }
00552 
00553       GetLegAngles(nextlegangles,legpos[i],nextpos,i);
00554       for(unsigned int j=0; j<JointsPerLeg; j++)
00555         cmds[LegOffset+i*JointsPerLeg+j][frame].set(nextlegangles[j]);
00556 
00557     }
00558 
00559     last_cycle=cycle;
00560   }
00561   
00562   for(unsigned int joint=LegOffset; joint<LegOffset+NumLegJoints; joint++)
00563     motman->setOutput(this,joint,cmds[joint]);
00564 
00565   //    cout << "WalkMC-done" << endl;
00566   return NumLegs*JointsPerLeg;
00567 }
00568 
00569 void WalkMC::resetLegPos() {
00570   BodyPosition nextpos;
00571   nextpos.loc.set(0,0,wp.body_height);
00572   nextpos.angle.set(0,wp.body_angle,0);
00573   for(unsigned int i=0; i<NumLegs; i++) {
00574     double tmp[JointsPerLeg];
00575     for(unsigned int j=0; j<JointsPerLeg; j++)
00576       tmp[j]=state->outputs[LegOffset+i*JointsPerLeg+j];
00577     GetLegPosition(legpos[i],tmp,nextpos,i);
00578     /*
00579       for(unsigned int j=0; j<JointsPerLeg; j++)
00580       cout << state->outputs[LegOffset+i*JointsPerLeg+j] << ' ';
00581       cout << "  ->  " << legpos[i].x << ' ' << legpos[i].y << ' ' << legpos[i].z << endl;
00582     */
00583   }
00584   //cout << "----------------------" << endl;
00585 }
00586 
00587 unsigned int checksum(const char *data,int num)
00588 {
00589   unsigned long c;
00590   int i;
00591 
00592   c = 0;
00593   for(i=0; i<num; i++){
00594     c = c ^ (data[i]*13 + 37);
00595     c = (c << 13) | (c >> 19);
00596   }
00597 
00598   return(c);
00599 }
00600 
00601 void WalkMC::applyCalibration(const float mat[3][11], const vector3d& in, vector3d& out) {
00602   float inmat[11];
00603   inmat[0]=in.x;
00604   inmat[1]=in.y;
00605   inmat[2]=in.z;
00606   inmat[3]=fabs(in.y);
00607   inmat[4]=fabs(in.z);
00608   inmat[5]=exp(-.5f*in.z*in.z)*sin(in.z*2.5f);
00609   inmat[6]=in.x*in.x+in.y*in.y;
00610   inmat[7]=in.x*in.z;
00611   inmat[8]=in.y*in.x;
00612   inmat[9]=in.z*in.y;
00613   inmat[10]=1;
00614   out.set(0,0,0);
00615   for(unsigned int c=0; c<11; c++)
00616     out.x+=mat[0][c]*inmat[c];
00617   for(unsigned int c=0; c<11; c++)
00618     out.y+=mat[1][c]*inmat[c];
00619   for(unsigned int c=0; c<11; c++)
00620     out.z+=mat[2][c]*inmat[c];
00621 }
00622 
00623 /*! @file
00624  * @brief Implements WalkMC, a MotionCommand for walking around
00625  * @author CMU RoboSoccer 2001-2002 (Creator)
00626  * @author ejt (ported)
00627  *
00628  * @verbinclude CMPack_license.txt
00629  *
00630  * $Author: ejt $
00631  * $Name: tekkotsu-3_0 $
00632  * $Revision: 1.38 $
00633  * $State: Exp $
00634  * $Date: 2006/09/10 18:48:46 $
00635  */
00636 

Tekkotsu v3.0
Generated Wed Oct 4 00:03:47 2006 by Doxygen 1.4.7