Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

CMPackWalkMC.cc

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

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:37 2016 by Doxygen 1.6.3