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
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
00059
00060 #ifdef TGT_HAS_LEGS
00061 const float CMPackWalkMC::MAX_DX = 180;
00062 const float CMPackWalkMC::MAX_DY = 140;
00063 const float CMPackWalkMC::MAX_DA = 1.8f;
00064 #else
00065
00066 const float CMPackWalkMC::MAX_DX = 225;
00067 const float CMPackWalkMC::MAX_DY = 0 ;
00068 const float CMPackWalkMC::MAX_DA = 2.1f;
00069 #endif
00070 #ifdef TGT_HAS_WHEELS
00071 const float CMPackWalkMC::OPTIMAL_DA = 0.9f;
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);
00077
00078 CMPackWalkMC::CMPackWalkMC(const char* pfile)
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);
00122 travelTime = t;
00123 postEvent(e);
00124 }
00125
00126
00127
00128 void CMPackWalkMC::init(const char* pfile)
00129 {
00130 #ifdef TGT_HAS_LEGS
00131
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
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
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,
00178 VER2,
00179 VER3
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
00190 sout->printf("Assuming CMPack format walk parameter file %s\n",filename);
00191 version=VER1;
00192 }
00193
00194
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
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
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
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
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
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;
00297 #endif
00298
00299
00300
00301
00302
00303
00304
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
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
00320 unsigned int steps_per_cycle=NumLegs;
00321 for(unsigned int i=0; int(i)<int(NumLegs)-1; i++) {
00322
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
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;
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
00357 step_count=1;
00358 #else
00359 (void)tx;
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;
00370
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
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
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
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
00418
00419 if(NewCycleOffset) {
00420 TimeOffset = CycleOffset - time % wp.period;
00421 NewCycleOffset = false;
00422 }
00423
00424
00425 int AdjustedTime = time + TimeOffset;
00426
00427
00428 if((vel_xya.x == 0) && (vel_xya.y == 0) && (vel_xya.z == 0)) {
00429 CycleOffset = AdjustedTime % wp.period;
00430 NewCycleOffset = true;
00431 }
00432
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
00441 angle_delta += (float)delta.angle.z;
00442 pos_delta += delta.loc.rotate_z(angle_delta);
00443
00444
00445
00446
00447
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
00460 bool above_last= (last_cycle<midstep);
00461 bool below_cur = (midstep<=cycle);
00462 bool wrap = (cycle<last_cycle);
00463
00464 if(above_last+below_cur+wrap>1) {
00465 step_count--;
00466
00467 if(step_count==0) {
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
00479 postEvent(e);
00480 postEvent(EventBase(EventBase::motmanEGID,getID(),EventBase::statusETID,getTravelTime()));
00481
00482 return frame==0?0:NumLegs*JointsPerLeg;
00483 }
00484 break;
00485 }
00486
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
00499 for(unsigned int i=0; i<NumLegs; i++){
00500
00501
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
00524
00525
00526
00527
00528
00529
00530 tm = wp.period/1000.f * 0.75f;
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
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
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
00572
00573
00574
00575
00576
00577
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);
00581
00582
00583 double velfraction =
00584 (velfraction_x > velfraction_y) ?
00585 velfraction_x : velfraction_y;
00586 if(velfraction_a > velfraction)
00587 velfraction = velfraction_a;
00588
00589
00590
00591
00592
00593 velfraction-=1;
00594 velfraction*=velfraction;
00595 velfraction*=velfraction;
00596
00597 legpos[i].z *= 1-velfraction;
00598
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;
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) {
00637 #ifdef TGT_IS_AIBO
00638
00639
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
00653 return NumLegs*JointsPerLeg;
00654
00655 #elif defined(TGT_HAS_WHEELS)
00656
00657 unsigned int t = getTravelTime();
00658 double adjustedTravelSeconds = t/1000.0;
00659
00660 if (step_count > 0)
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
00673 vel_xya=target_vel_xya;
00674 #ifdef TGT_IS_CREATE
00675
00676
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)
00683 turnvel = 0;
00684 float left = (float)vel_xya.x - turnvel;
00685 float right = (float)vel_xya.x + turnvel;
00686
00687
00688
00689
00690
00691
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
00718
00719
00720
00721 }
00722 #endif
00723
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
00763
00764
00765
00766
00767
00768
00769
00770 #endif // lock out wheeled robots