Homepage Demos Overview Downloads Tutorials 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 
00034 #include "Events/EventRouter.h"
00035 #include "Events/LocomotionEvent.h"
00036 
00037 #include "Motion/MotionManager.h"
00038 
00039 #include <stdlib.h>
00040 #include <stdio.h>
00041 #include <iostream>
00042 #include <fcntl.h>
00043 #include <unistd.h>
00044 #include <fstream>
00045 #include <cmath>
00046 
00047 //REGIMP(WalkMC);
00048 
00049 #define BOUND_MOTION
00050 
00051 const float WalkMC::MAX_DX   = 180;//225; // mm/sec
00052 const float WalkMC::MAX_DY   = 140;//170; // mm/sec
00053 const float WalkMC::MAX_DA   = 1.8;//2.1; // rad/sec
00054 // tss "SmoothWalk" modification follows
00055 // const vector3d WalkMC::max_accel_xya(MAX_DX*2,MAX_DY*2,MAX_DA*2);
00056 const vector3d WalkMC::max_accel_xya(MAX_DX*2,MAX_DY*2,MAX_DA*2);
00057 
00058 unsigned int checksum(const char *data,int num); //!< computes a file checksum
00059 template <class data> int read_file(data *arr,int num,const char *filename); //!< reads a set of walk parameters from a file
00060 template <class data> int save_file(data *arr,int num,const char *filename); //!< saves the current walk parameters to a file
00061 
00062 WalkMC::WalkMC(const char* pfile/*=NULL*/)
00063 // tss "SmoothWalk" modification follows
00064 //  : MotionCommand(), isPaused(false), wp(), body_loc(), body_angle(),
00065 //    pos_delta(0,0,0), angle_delta(0), travelTime(get_time()),
00066 //    time(get_time()), TimeStep(FrameTime), vel_xya(0,0,0),
00067 //    target_vel_xya(0,0,0)
00068   : MotionCommand(), isPaused(false), wp(), body_loc(), body_angle(),
00069     pos_delta(0,0,0), angle_delta(0), travelTime(get_time()),
00070     time(get_time()), TimeStep(FrameTime), slowmo(1.0f),
00071     CycleOffset(0), TimeOffset(0), NewCycleOffset(false),
00072     vel_xya(0,0,0), target_vel_xya(0,0,0)
00073 {
00074   init(pfile);
00075 }
00076 
00077 void WalkMC::DoStart() {
00078   MotionCommand::DoStart();
00079   LocomotionEvent e(EventBase::locomotionEGID,getID(),EventBase::activateETID,0);
00080   e.setXYA(target_vel_xya.x,target_vel_xya.y,target_vel_xya.z);
00081   postEvent(e);
00082   travelTime=get_time();
00083 }
00084 
00085 void WalkMC::DoStop() {
00086   unsigned int t=get_time();
00087   LocomotionEvent e(EventBase::locomotionEGID,getID(),EventBase::deactivateETID,t-travelTime);
00088   e.setXYA(target_vel_xya.x,target_vel_xya.y,target_vel_xya.z);
00089   postEvent(e);
00090   travelTime=t;
00091   MotionCommand::DoStop();
00092 }
00093 
00094 void WalkMC::init(const char* pfile)
00095 {
00096   //  RegInit();
00097   body_loc.init(vector3d(0,0,wp.body_height),vector3d(0,0,0));
00098   body_angle.init(vector3d(0,wp.body_angle,0),vector3d(0,0,0));
00099 
00100   for(unsigned int i=0; i<4; i++){
00101     legw[i].air = false;
00102   }
00103 
00104   if(pfile!=NULL)
00105     load(pfile);
00106   else
00107     load("walk.prm");
00108 
00109   double zeros[JointsPerLeg];
00110   for(unsigned int i=0; i<JointsPerLeg; i++)
00111     zeros[i]=0;
00112   for(unsigned int i=0; i<NumLegs; i++)
00113     GetLegPosition(legpos[i],zeros,i);
00114 
00115   //  cmds[HeadOffset+TiltOffset].set(.3333,1);
00116 }
00117 
00118 // tss "SmoothWalk" addition follows
00119 int WalkMC::isDirty()
00120 {
00121   if(isPaused) return false;
00122   if((target_vel_xya.x == 0) && (target_vel_xya.y == 0) && (target_vel_xya.z == 0)) {
00123   if((vel_xya.x != 0) || (vel_xya.y != 0) || (vel_xya.z != 0)) return true
00124 ;
00125   else return false;
00126   }
00127   return true;
00128 }
00129 // tss "SmoothWalk" addition ends
00130 
00131 void WalkMC::load(const char* pfile)
00132 {
00133   mzero(wp);
00134   int n = read_file(&wp,1,pfile);
00135   //  pprintf(TextOutputStream,"Loaded WalkMC Paramaters %s n=%d checksum=0x%X\n\xFF",pfile,n,checksum((char*)&wp,sizeof(wp)));
00136   printf("Loaded WalkMC Parameters %s n=%ud checksum=0x%X\n",pfile,n,checksum(reinterpret_cast<const char*>(&wp),sizeof(wp)));
00137 }
00138 
00139 void WalkMC::save(const char* pfile) const {
00140   int n = save_file(&wp,1,pfile);
00141   printf("Saved WalkMC Parameters %s n=%ud checksum=0x%X\n",pfile,n,checksum(reinterpret_cast<const char*>(&wp),sizeof(wp)));
00142 }
00143 
00144 
00145 void WalkMC::setTargetVelocity(double dx,double dy,double da)
00146 {
00147 #ifdef BOUND_MOTION
00148   da = bound(da, -MAX_DA, MAX_DA);
00149   double fa = 1.0 - fabs(da / MAX_DA);
00150 
00151   vector2d v(dx/MAX_DX,dy/MAX_DY);
00152   double l = v.length();
00153   if(l > 1) v /= l;
00154 
00155   dx = MAX_DX * v.x * fa;
00156   dy = MAX_DY * v.y * fa;
00157 #endif
00158 
00159   target_vel_xya.set(dx,dy,da);
00160 
00161   if(isActive()) {
00162     unsigned int t=get_time();
00163     LocomotionEvent e(EventBase::locomotionEGID,getID(),EventBase::statusETID,t-travelTime);
00164     e.setXYA(dx,dy,da);
00165     postEvent(e);
00166     travelTime=t;
00167   }
00168 }
00169 
00170 int WalkMC::updateOutputs() {
00171   //  cout << "WalkMC,,," << flush;
00172   if(!isDirty())
00173     return 0;
00174   
00175   double t = TimeStep * slowmo / 1000;
00176 
00177   vel_xya.x = bound(target_vel_xya.x, vel_xya.x-max_accel_xya.x*t, vel_xya.x+max_accel_xya.x*t);
00178   vel_xya.y = bound(target_vel_xya.y, vel_xya.y-max_accel_xya.y*t, vel_xya.y+max_accel_xya.y*t);
00179   vel_xya.z = bound(target_vel_xya.z, vel_xya.z-max_accel_xya.z*t, vel_xya.z+max_accel_xya.z*t);
00180 
00181   BodyPosition delta;
00182   delta.loc.set(vel_xya.x*t,vel_xya.y*t,0);
00183   delta.angle.set(0,0,vel_xya.z*t);
00184 
00185   time=(int)(get_time()*slowmo);
00186 
00187 // tss "SmoothWalk" addition follows
00188   // If necessary, we compute a new TimeOffset here.
00189   if(NewCycleOffset) {
00190     TimeOffset = CycleOffset - time % wp.period;
00191     NewCycleOffset = false;
00192   }
00193 
00194   // Adjusted time--time adjusted for cycle matching
00195   int AdjustedTime = time + TimeOffset;
00196 
00197   // 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.
00198   if((vel_xya.x == 0) && (vel_xya.y == 0) && (vel_xya.z == 0)) {
00199     CycleOffset = AdjustedTime % wp.period;
00200     NewCycleOffset = true;
00201   }
00202 // tss "SmoothWalk" addition ends
00203 
00204   for(unsigned int frame=0; frame<NumFrames; frame++) {
00205     target_vel_xya.rotate_z(-delta.angle.z);
00206 
00207     // incorporate movement delta
00208     angle_delta += delta.angle.z;
00209     pos_delta += delta.loc.rotate_z(angle_delta);
00210 
00211     //    cout << "setup,,," << flush;
00212 
00213 // tss "SmoothWalk" modification follows
00214     // double cycle = (double)(time % wp.period) / wp.period;
00215     double cycle = (double)(AdjustedTime % wp.period) / wp.period;
00216     double sway   = wp.sway*cos(2*M_PI*cycle);
00217     double hop    = wp.hop*sin(4*M_PI*cycle);
00218     double height = wp.body_height;
00219     BodyPosition nextpos;
00220     nextpos.loc.set(0,-sway,height+hop);
00221     nextpos.angle.set(0,wp.body_angle,0);
00222 
00223     //    cout << "loop,,," << flush;
00224     for(unsigned int i=0; i<NumLegs; i++){
00225 
00226       bool air = (cycle >= wp.leg[i].lift_time) && (cycle < wp.leg[i].down_time);
00227       double air_f = wp.leg[i].down_time - wp.leg[i].lift_time;
00228       double nextlegangles[JointsPerLeg];
00229 
00230       if(air != legw[i].air){
00231         if(air){
00232           t = wp.period/1000.0 * 0.75;
00233           vector3d vfp;
00234           vfp.x = bound(target_vel_xya.x, vel_xya.x-max_accel_xya.x*t, vel_xya.x+max_accel_xya.x*t);
00235           vfp.y = bound(target_vel_xya.y, vel_xya.y-max_accel_xya.y*t, vel_xya.y+max_accel_xya.y*t);
00236           vfp.z = 0.0;
00237           double vfa   = bound(target_vel_xya.z, vel_xya.z-max_accel_xya.z*t, vel_xya.z+max_accel_xya.z*t);
00238           double b = (wp.period/1000.0) * (1.0 - air_f) / 2.0;
00239           vector3d target = (wp.leg[i].neutral + vfp*b).rotate_z(vfa*b);
00240           legw[i].airpath.create(legpos[i],target,wp.leg[i].lift_vel,wp.leg[i].down_vel);
00241         }else{
00242           legpos[i].z = 0.0;
00243         }
00244         legw[i].air = air;
00245       }
00246 
00247       if(air){
00248         t = (cycle - wp.leg[i].lift_time) / air_f;
00249         legpos[i] = legw[i].airpath.eval(t);
00250 
00251 // Core tss "SmoothWalk" addition follows
00252         // KLUDGY MOD. Goal: reduce the height of the
00253         // AIBO's steps as its velocity nears zero.
00254         // Since I don't know how most of this code 
00255         // works, I'll directly alter legpos[i].z in
00256         // the following code to change the z height
00257         // with velocity.
00258         double velfraction_x = fabs(vel_xya.x / MAX_DX);
00259         double velfraction_y = fabs(vel_xya.y / MAX_DY);
00260         double velfraction_a = fabs(vel_xya.z / MAX_DA);
00261 
00262         // Choose the biggest velfraction
00263         double velfraction =
00264           (velfraction_x > velfraction_y) ?
00265             velfraction_x : velfraction_y;
00266         if(velfraction_a > velfraction)
00267           velfraction = velfraction_a;
00268 
00269         // Modify legpos[i].z with velfraction to
00270         // shrink it down
00271         //velfraction = atan(velfraction * M_PI);
00272 
00273         velfraction-=1;
00274         velfraction*=velfraction;
00275         velfraction*=velfraction;
00276 
00277         legpos[i].z *= 1-velfraction;
00278 // Core tss "SmoothWalk" addition ends
00279       }else{
00280         legpos[i] = (legpos[i] - delta.loc).rotate_z(-delta.angle.z);
00281       }
00282 
00283       GetLegAngles(nextlegangles,legpos[i],nextpos,i);
00284       for(unsigned int j=0; j<JointsPerLeg; j++)
00285         cmds[LegOffset+i*JointsPerLeg+j][frame].set(nextlegangles[j]);
00286     }
00287 
00288     // tss "SmoothWalk" modification follows
00289     AdjustedTime = time+TimeOffset+(int)(frame*TimeStep*slowmo);
00290   }
00291   
00292   for(unsigned int joint=LegOffset; joint<LegOffset+NumLegJoints; joint++)
00293     motman->setOutput(this,joint,cmds[joint]);
00294 
00295   //    cout << "WalkMC-done" << endl;
00296   return NumLegs*JointsPerLeg;
00297 }
00298 
00299 void WalkMC::resetLegPos() {
00300   for(unsigned int i=0; i<NumLegs; i++) {
00301     double tmp[JointsPerLeg];
00302     for(unsigned int j=0; j<JointsPerLeg; j++)
00303       tmp[j]=state->outputs[LegOffset+i*JointsPerLeg+j];
00304     GetLegPosition(legpos[i],tmp,i);
00305   }
00306 }
00307 
00308 unsigned int checksum(const char *data,int num)
00309 {
00310   unsigned long c;
00311   int i;
00312 
00313   c = 0;
00314   for(i=0; i<num; i++){
00315     c = c ^ (data[i]*13 + 37);
00316     c = (c << 13) | (c >> 19);
00317   }
00318 
00319   return(c);
00320 }
00321 
00322 template <class data>
00323 int read_file(data *arr,int num,const char *filename)
00324 {
00325   char name[256];
00326   int fd;
00327   // HFS::FILE *in;
00328   int n;
00329 
00330   sprintf(name,"/ms/data/motion/%s",filename);
00331 
00332   fd = open(name,O_RDONLY);
00333   if(fd < 0) return(0);
00334   n = read(fd,arr,sizeof(data)*num);
00335   // cprintf(OutputBuf,"read_file: %d of %d\n\xFF",n,sizeof(data)*num);
00336   close(fd);
00337   if(n%sizeof(data)!=0)
00338     cout << "*** WARNING - short data read" << endl;
00339   n /= sizeof(data);
00340 
00341   return(n);
00342 }
00343 
00344 template <class data>
00345 int save_file(data *arr,int num,const char *filename) {
00346   char name[256];
00347   int fd;
00348   // HFS::FILE *in;
00349   int n;
00350 
00351   sprintf(name,"/ms/data/motion/%s",filename);
00352 
00353   cout << "writing " << name << " " << sizeof(data) << endl;
00354   fd = open(name,O_RDWR|O_CREAT|O_TRUNC);
00355   if(fd < 0) {
00356     cout << "open returned " << fd << endl;
00357     return(0);
00358   }
00359   n = write(fd,(const void*)arr,sizeof(data)*num);
00360   // cprintf(OutputBuf,"read_file: %d of %d\n\xFF",n,sizeof(data)*num);
00361   close(fd);
00362   if(n%sizeof(data)!=0)
00363     cout << "*** WARNING - short data write" << endl;
00364   n /= sizeof(data);
00365 
00366   return(n);
00367 }
00368 
00369 /*! @file
00370  * @brief Implements WalkMC, a MotionCommand for walking around
00371  * @author CMU RoboSoccer 2001-2002 (Creator)
00372  * @author ejt (ported)
00373  *
00374  * @verbinclude CMPack_license.txt
00375  *
00376  * $Author: ejt $
00377 <<<<<<< WalkMC.cc
00378  * $Name: tekkotsu-1_5 $
00379  * $Revision: 1.16 $
00380  * $State: Rel $
00381  * $Date: 2003/09/12 02:01:44 $
00382 =======
00383  * $Name: tekkotsu-1_5 $
00384  * $Revision: 1.16 $
00385  * $State: Rel $
00386  * $Date: 2003/09/12 02:01:44 $
00387 >>>>>>> 1.15
00388  */
00389 

Tekkotsu v1.5
Generated Fri Oct 10 15:52:00 2003 by Doxygen 1.3.4