00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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
00048
00049 #define BOUND_MOTION
00050
00051 const float WalkMC::MAX_DX = 180;
00052 const float WalkMC::MAX_DY = 140;
00053 const float WalkMC::MAX_DA = 1.8;
00054
00055
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);
00059 template <class data> int read_file(data *arr,int num,const char *filename);
00060 template <class data> int save_file(data *arr,int num,const char *filename);
00061
00062 WalkMC::WalkMC(const char* pfile)
00063
00064
00065
00066
00067
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
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
00116 }
00117
00118
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
00130
00131 void WalkMC::load(const char* pfile)
00132 {
00133 mzero(wp);
00134 int n = read_file(&wp,1,pfile);
00135
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
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
00188
00189 if(NewCycleOffset) {
00190 TimeOffset = CycleOffset - time % wp.period;
00191 NewCycleOffset = false;
00192 }
00193
00194
00195 int AdjustedTime = time + TimeOffset;
00196
00197
00198 if((vel_xya.x == 0) && (vel_xya.y == 0) && (vel_xya.z == 0)) {
00199 CycleOffset = AdjustedTime % wp.period;
00200 NewCycleOffset = true;
00201 }
00202
00203
00204 for(unsigned int frame=0; frame<NumFrames; frame++) {
00205 target_vel_xya.rotate_z(-delta.angle.z);
00206
00207
00208 angle_delta += delta.angle.z;
00209 pos_delta += delta.loc.rotate_z(angle_delta);
00210
00211
00212
00213
00214
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
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
00252
00253
00254
00255
00256
00257
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
00263 double velfraction =
00264 (velfraction_x > velfraction_y) ?
00265 velfraction_x : velfraction_y;
00266 if(velfraction_a > velfraction)
00267 velfraction = velfraction_a;
00268
00269
00270
00271
00272
00273 velfraction-=1;
00274 velfraction*=velfraction;
00275 velfraction*=velfraction;
00276
00277 legpos[i].z *= 1-velfraction;
00278
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
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
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
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
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
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
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
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389