00001 #include "UPennWalkMC.h"
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 using namespace std; 
00015 
00016 #include <math.h>
00017 
00018 #ifndef PI
00019 #define PI M_PI
00020 #endif
00021 
00022 const size_t MAX_WIDTH = 208;
00023 const size_t MAX_HEIGHT = 160;
00024 const size_t LAYERM_WIDTH = 104;
00025 const size_t LAYERM_HEIGHT = 80;
00026 
00027 const double FIELD_VIEW_H = 56.9*(PI/180);
00028 const double FIELD_VIEW_V = 45.2*(PI/180);
00029 const double FOCAL_LENGTH = 192.0; 
00030 const unsigned int IMAGE_WIDTH = 208;
00031 const unsigned int IMAGE_HEIGHT = 160;
00032 
00033 const double BODY_TILT = -13*PI/180; 
00034 
00035 const double BODY_WIDTH = 134.4;
00036 const double BODY_LENGTH = 130.0;
00037 
00038 const size_t NUM_LEG = 4;
00039 const size_t NUM_LEG_JOINT = 3*NUM_LEG;
00040 
00041 
00042 const double LEG_FORE_UPPER_Z = 69.5;
00043 const double LEG_FORE_UPPER_Y = 9.0;
00044 const double LEG_FORE_LOWER_Z = 76.4;  
00045 const double LEG_FORE_LOWER_Y = -9.0;
00046 
00047 const double LEG_HIND_UPPER_Z = 69.5;
00048 const double LEG_HIND_UPPER_Y = 9.0;
00049 const double LEG_HIND_LOWER_Z = 78.9; 
00050 const double LEG_HIND_LOWER_Y = -9.0;
00051 
00052 
00053 
00054 const double NECK_TILT2_TO_CAMERA_Y = 81.0;
00055 const double NECK_TILT2_TO_CAMERA_Z = -14.6;
00056 const double NECK_TILT_TO_TILT2 = 80.0;
00057 const double SHOULDER_TO_NECK_TILT_Y = 2.5;
00058 const double SHOULDER_TO_NECK_TILT_Z = 19.5;
00059 
00060 const double MIN_SHOULDER_HEIGHT = 50.0;
00061 
00062 const double TURN_OFFSET = 75.0;
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 const double STANCE_BODY_TILT = 0*PI/180;
00072 const double STANCE_SHOULDER_HEIGHT = 105.;
00073 
00074 const double STANCE_FORE_X0 = 7.;
00075 
00076 const double STANCE_FORE_Y0 = 60.;
00077 const double STANCE_HIND_X0 = 2.;
00078 const double STANCE_HIND_Y0 = -45.;
00079 
00080 const int WALK_QUARTER_PERIOD = 3;
00081 const double WALK_MAX_DISTANCE = 13.; 
00082 
00083 const double WALK_FORE_LIFT_INITIAL = 25;
00084 const double WALK_FORE_LIFT_FINAL = 45;
00085 
00086 const double WALK_HIND_LIFT_INITIAL = 25;
00087 const double WALK_HIND_LIFT_FINAL = 25;
00088 
00089 const double WALK_FORE_XMIN = -10;
00090 const double WALK_FORE_XMAX = 30;
00091 const double WALK_FORE_YMIN = 25;
00092 
00093 const double WALK_FORE_YMAX = 90;
00094 
00095 const double WALK_HIND_XMIN = -15;
00096 const double WALK_HIND_XMAX = 35;
00097 const double WALK_HIND_YMIN = -70;
00098 const double WALK_HIND_YMAX = -15;
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 enum LegIdentifier {
00132   LEG_LEFT_FORE = 0,
00133   LEG_LEFT_HIND = 1,
00134   LEG_RIGHT_FORE = 2,
00135   LEG_RIGHT_HIND = 3
00136 };
00137 
00138 UPennWalkMC::UPennWalkMC()
00139   : MotionCommand(), xVel(0), yVel(0), aVel(0),
00140     
00141     body_tilt(STANCE_BODY_TILT), shoulder_height(STANCE_SHOULDER_HEIGHT),
00142     fore_x0(STANCE_FORE_X0), fore_y0(STANCE_FORE_Y0),
00143     hind_x0(STANCE_HIND_X0), hind_y0(STANCE_HIND_Y0),
00144     
00145     walk_phase(0),walk_phase_direction(1),
00146     walk_quarter_period(WALK_QUARTER_PERIOD), walk_max_distance(WALK_MAX_DISTANCE),
00147     walk_fore_lift_initial(WALK_FORE_LIFT_INITIAL), walk_fore_lift_final(WALK_FORE_LIFT_FINAL),
00148     walk_hind_lift_initial(WALK_HIND_LIFT_INITIAL), walk_hind_lift_final(WALK_HIND_LIFT_FINAL),
00149     walk_fore_xmin(WALK_FORE_XMIN), walk_fore_xmax(WALK_FORE_XMAX),
00150     walk_fore_ymin(WALK_FORE_YMIN), walk_fore_ymax(WALK_FORE_YMAX),
00151     walk_hind_xmin(WALK_HIND_XMIN), walk_hind_xmax(WALK_HIND_XMAX),
00152     walk_hind_ymin(WALK_HIND_YMIN), walk_hind_ymax(WALK_HIND_YMAX)
00153 {
00154   for (int i = 0; i < 4; i++) {
00155     walk_current_x[i] = 0.0;
00156     walk_current_y[i] = 0.0;
00157   }
00158 }
00159 
00160 void
00161 UPennWalkMC::SetLegJoints(double * x) {
00162 #ifdef TGT_HAS_REK_LEGS
00163   motman->setOutput(this,LFrLegOffset+RotatorOffset,(float)x[LEG_LEFT_FORE*JointsPerLeg+0]);
00164   motman->setOutput(this,LFrLegOffset+ElevatorOffset,(float)x[LEG_LEFT_FORE*JointsPerLeg+1]);
00165   motman->setOutput(this,LFrLegOffset+KneeOffset,(float)x[LEG_LEFT_FORE*JointsPerLeg+2]);
00166   
00167   motman->setOutput(this,RFrLegOffset+RotatorOffset,(float)x[LEG_RIGHT_FORE*JointsPerLeg+0]);
00168   motman->setOutput(this,RFrLegOffset+ElevatorOffset,(float)x[LEG_RIGHT_FORE*JointsPerLeg+1]);
00169   motman->setOutput(this,RFrLegOffset+KneeOffset,(float)x[LEG_RIGHT_FORE*JointsPerLeg+2]);
00170   
00171   motman->setOutput(this,LBkLegOffset+RotatorOffset,(float)x[LEG_LEFT_HIND*JointsPerLeg+0]);
00172   motman->setOutput(this,LBkLegOffset+ElevatorOffset,(float)x[LEG_LEFT_HIND*JointsPerLeg+1]);
00173   motman->setOutput(this,LBkLegOffset+KneeOffset,(float)x[LEG_LEFT_HIND*JointsPerLeg+2]);
00174   
00175   motman->setOutput(this,RBkLegOffset+RotatorOffset,(float)x[LEG_RIGHT_HIND*JointsPerLeg+0]);
00176   motman->setOutput(this,RBkLegOffset+ElevatorOffset,(float)x[LEG_RIGHT_HIND*JointsPerLeg+1]);
00177   motman->setOutput(this,RBkLegOffset+KneeOffset,(float)x[LEG_RIGHT_HIND*JointsPerLeg+2]);
00178 #endif
00179 }
00180 
00181 void
00182 UPennWalkMC::SetStanceParameters(double bodyTilt, double shoulderHeight,
00183           double foreX0, double foreY0,
00184           double hindX0, double hindY0) {
00185   body_tilt = bodyTilt;
00186   shoulder_height = shoulderHeight;
00187   fore_x0 = foreX0;
00188   fore_y0 = foreY0;
00189   hind_x0 = hindX0;
00190   hind_y0 = hindY0;
00191 }
00192 
00193 void
00194 UPennWalkMC::SetWalkSpeeds(int quarterPeriod, double maxDistance,
00195         double foreLiftInitial, double foreLiftFinal,
00196         double hindLiftInitial, double hindLiftFinal) {
00197   walk_quarter_period = quarterPeriod;
00198   walk_max_distance = maxDistance;
00199   walk_fore_lift_initial = foreLiftInitial;
00200   walk_fore_lift_final = foreLiftFinal;
00201   walk_hind_lift_initial = hindLiftInitial;
00202   walk_hind_lift_final = hindLiftFinal;
00203 }
00204 
00205 void
00206 UPennWalkMC::SetWalkWorkspace(double foreXMin, double foreXMax,
00207        double foreYMin, double foreYMax,
00208        double hindXMin, double hindXMax,
00209        double hindYMin, double hindYMax) {
00210   walk_fore_xmin = foreXMin;
00211   walk_fore_xmax = foreXMax;
00212   walk_fore_ymin = foreYMin;
00213   walk_fore_ymax = foreYMax;
00214 
00215   walk_hind_xmin = hindXMin;
00216   walk_hind_xmax = hindXMax;
00217   walk_hind_ymin = hindYMin;
00218   walk_hind_ymax = hindYMax;
00219 }
00220 
00221 
00222 
00223 
00224 void
00225 UPennWalkMC::LegPositionsToAngles(double *a)
00226 {
00227   double cosTilt = cos(body_tilt);
00228   double sinTilt = sin(body_tilt);
00229 
00230   double foreHeight = shoulder_height;
00231   double hindHeight = shoulder_height - BODY_LENGTH*sinTilt;
00232 
00233   for (int iLeg = 0; iLeg < 4; iLeg++) {
00234     double posX=0, posY=0, posZ=0;
00235     double dUpperZ = 0.0, dUpperY = 0.0, dLowerZ = 0.0, dLowerY = 0.0;
00236 
00237     switch (iLeg) {
00238     case LEG_LEFT_FORE:
00239       
00240       a[0] -= fore_x0;
00241       a[1] += fore_y0;
00242       a[2] -= foreHeight;
00243 
00244       posX = -(a[0]);
00245       posY = (cosTilt*a[1]+sinTilt*a[2]);
00246       posZ = (-sinTilt*a[1]+cosTilt*a[2]);
00247       dUpperZ = LEG_FORE_UPPER_Z;
00248       dUpperY = LEG_FORE_UPPER_Y;
00249       dLowerZ = LEG_FORE_LOWER_Z;
00250       dLowerY = LEG_FORE_LOWER_Y;
00251       break;
00252     case LEG_LEFT_HIND:
00253       
00254       a[0] -= hind_x0;
00255       a[1] += hind_y0;
00256       a[2] -= hindHeight;
00257 
00258       posX = -(a[0]);
00259       posY = -(cosTilt*a[1]+sinTilt*a[2]);
00260       posZ = (-sinTilt*a[1]+cosTilt*a[2]);
00261 
00262       dUpperZ = LEG_HIND_UPPER_Z;
00263       dUpperY = LEG_HIND_UPPER_Y;
00264       dLowerZ = LEG_HIND_LOWER_Z;
00265       dLowerY = LEG_HIND_LOWER_Y;
00266       break;
00267     case LEG_RIGHT_FORE:
00268       
00269       a[0] += fore_x0;
00270       a[1] += fore_y0;
00271       a[2] -= foreHeight;
00272 
00273       posX = (a[0]);
00274       posY = (cosTilt*a[1]+sinTilt*a[2]);
00275       posZ = (-sinTilt*a[1]+cosTilt*a[2]);
00276 
00277       dUpperZ = LEG_FORE_UPPER_Z;
00278       dUpperY = LEG_FORE_UPPER_Y;
00279       dLowerZ = LEG_FORE_LOWER_Z;
00280       dLowerY = LEG_FORE_LOWER_Y;
00281       break;
00282     case LEG_RIGHT_HIND:
00283       
00284       a[0] += hind_x0;
00285       a[1] += hind_y0;
00286       a[2] -= hindHeight;
00287 
00288       posX = (a[0]);
00289       posY = -(cosTilt*a[1]+sinTilt*a[2]);
00290       posZ = (-sinTilt*a[1]+cosTilt*a[2]);
00291 
00292       dUpperZ = LEG_HIND_UPPER_Z;
00293       dUpperY = LEG_HIND_UPPER_Y;
00294       dLowerZ = LEG_HIND_LOWER_Z;
00295       dLowerY = LEG_HIND_LOWER_Y;
00296       break;
00297     default:
00298       cerr << "UPennWalkMC::LegPositionsToAngles(): Unknown leg.\n" << endl;
00299     }
00300 
00301     double dUpper = sqrt(dUpperY*dUpperY+dUpperZ*dUpperZ);
00302     double angleUpper = tan(dUpperY/dUpperZ);  
00303 
00304     double dLower = sqrt(dLowerY*dLowerY+dLowerZ*dLowerZ);
00305     double angleLower = tan(dLowerY/dLowerZ);  
00306 
00307     double posSumSq = posX*posX+posY*posY+posZ*posZ;
00308     
00309     double cosJ3 = .5*(posSumSq-dUpper*dUpper-dLower*dLower)/(dUpper*dLower);
00310     cosJ3 = clip(cosJ3, -1.0, 1.0);
00311     
00312     a[2] = acos(cosJ3)+angleUpper-angleLower;
00313 
00314     double aZ = -dUpperZ-dLower*cos(a[2]+angleLower);
00315     double aY = dUpperY+dLower*sin(a[2]+angleLower);
00316 
00317     double sinJ2 = -posX/aZ;
00318     sinJ2 = clip(sinJ2, -1.0, 1.0);
00319     a[1] = asin(sinJ2);
00320 
00321     double J1a = atan2(aZ*cos(a[1]), aY);
00322     double J1b = atan2(posZ, posY);
00323     double J1 = J1b-J1a;
00324     while (J1 > PI) J1 -= 2*PI;
00325     while (J1 < -PI) J1 += 2*PI;
00326     a[0] = J1;
00327 
00328     a += 3;
00329   }
00330 }
00331 
00332 void
00333 UPennWalkMC::StandLegs(double x, double y, double z)
00334 {
00335   static double leg_joints[NUM_LEG_JOINT];
00336   double *a = leg_joints;
00337 
00338   for (int iLeg = 0; iLeg < 4; iLeg++) {
00339     double center_x = 0, center_y = 0;
00340     switch (iLeg) {
00341     case LEG_LEFT_FORE:
00342       center_x = -fore_x0;
00343       center_y = fore_y0;
00344       break;
00345     case LEG_LEFT_HIND:
00346       center_x = -hind_x0;
00347       center_y = hind_y0;
00348       break;
00349     case LEG_RIGHT_FORE:
00350       center_x = fore_x0;
00351       center_y = fore_y0;
00352       break;
00353     case LEG_RIGHT_HIND:
00354       center_x = hind_x0;
00355       center_y = hind_y0;
00356       break;
00357     default:
00358       cerr << "UPennWalkMC::StandLegs(): Unknown leg.\n" << endl;
00359     }
00360 
00361     a[0] = -x;
00362     a[1] = -y;
00363     a[2] = -z;
00364 
00365     walk_current_x[iLeg] = center_x - x;
00366     walk_current_y[iLeg] = center_y - y;
00367 
00368     
00369     a += 3;
00370   }
00371 
00372   LegPositionsToAngles(leg_joints);
00373   SetLegJoints(leg_joints);
00374 
00375 }
00376 
00377 int
00378 UPennWalkMC::GetWalkPhase() {
00379   return walk_phase;
00380 }
00381 
00382 void
00383 UPennWalkMC::SetWalkPhase(int phase) {
00384   walk_phase = phase;
00385 }
00386 
00387 
00388 void
00389 UPennWalkMC::WalkLegs(double xWalk, double yWalk, double aWalk)
00390 {
00391   
00392   if ((walk_phase == 0) &&
00393       (xWalk == 0.0) && (yWalk == 0.0) && (aWalk == 0.0)) {
00394     
00395     return;
00396   }
00397   
00398   static double leg_joints[NUM_LEG_JOINT];
00399   double *a = leg_joints;
00400   bool switch_phase_direction = false;
00401 
00402   
00403   double afactor = .85*BODY_LENGTH*aWalk; 
00404   double rnorm = sqrt(afactor*afactor + xWalk*xWalk + yWalk*yWalk);
00405   if (rnorm > walk_max_distance) {
00406     double scale = walk_max_distance/rnorm;
00407     aWalk *= scale;
00408     xWalk *= scale;
00409     yWalk *= scale;
00410   }
00411 
00412   
00413   int phase_diff_from_switch = walk_quarter_period+walk_phase_direction*walk_phase;
00414   int phase_diff_to_switch = walk_quarter_period-walk_phase_direction*walk_phase;
00415 
00416   double half_width = .5*BODY_WIDTH;
00417   double half_length = .5*BODY_LENGTH*cos(body_tilt);
00418 
00419   for (int iLeg = 0; iLeg < 4; iLeg++) {
00420     double center_x = 0, center_y = 0; 
00421     double leg_offset_x = 0, leg_offset_y = 0; 
00422     double leg_lift_initial = 0, leg_lift_final = 0; 
00423     double xmin = 0.0, xmax = 0.0, ymin = 0.0, ymax = 0.0; 
00424     int leg_sign = 1;
00425 
00426     double current_x = walk_current_x[iLeg];
00427     double current_y = walk_current_y[iLeg];
00428     
00429     switch (iLeg) {
00430     case LEG_LEFT_FORE:
00431       leg_sign = 1;
00432       center_x = -fore_x0;
00433       center_y = fore_y0;
00434 
00435       leg_offset_x = -half_width+center_x;
00436       leg_offset_y = half_length+center_y;
00437 
00438       leg_lift_initial = walk_fore_lift_initial;
00439       leg_lift_final = walk_fore_lift_final;
00440 
00441       xmin = -walk_fore_xmax; xmax = -walk_fore_xmin;
00442       ymin = walk_fore_ymin; ymax = walk_fore_ymax;
00443       break;
00444     case LEG_LEFT_HIND:
00445       leg_sign = -1;
00446       center_x = -hind_x0;
00447       center_y = hind_y0;
00448 
00449       leg_offset_x = -half_width+center_x;
00450       leg_offset_y = -half_length+center_y;
00451 
00452       leg_lift_initial = walk_hind_lift_initial;
00453       leg_lift_final = walk_hind_lift_final;
00454 
00455       xmin = -walk_hind_xmax; xmax = -walk_hind_xmin;
00456       ymin = walk_hind_ymin; ymax = walk_hind_ymax;
00457       break;
00458     case LEG_RIGHT_FORE:
00459       leg_sign = -1;
00460       center_x = fore_x0;
00461       center_y = fore_y0;
00462 
00463       leg_offset_x = half_width+center_x;
00464       leg_offset_y = half_length+center_y;
00465 
00466       leg_lift_initial = walk_fore_lift_initial;
00467       leg_lift_final = walk_fore_lift_final;
00468 
00469       xmin = walk_fore_xmin; xmax = walk_fore_xmax;
00470       ymin = walk_fore_ymin; ymax = walk_fore_ymax;
00471       break;
00472     case LEG_RIGHT_HIND:
00473       leg_sign = 1;
00474       center_x = hind_x0;
00475       center_y = hind_y0;
00476 
00477       leg_offset_x = half_width+center_x;
00478       leg_offset_y = -half_length+center_y;
00479 
00480       leg_lift_initial = walk_hind_lift_initial;
00481       leg_lift_final = walk_hind_lift_final;
00482 
00483       xmin = walk_hind_xmin; xmax = walk_hind_xmax;
00484       ymin = walk_hind_ymin; ymax = walk_hind_ymax;
00485       break;
00486     default:
00487       cerr << "UPennWalkMC::WalkLegs(): Unknown leg.\n" << endl;
00488     }
00489 
00490     
00491     current_x -= center_x;
00492     current_y -= center_y;
00493     xmin -= center_x;
00494     xmax -= center_x;
00495     ymin -= center_y;
00496     ymax -= center_y;
00497 
00498     double dx, dy;
00499 
00500     
00501     if (leg_sign == walk_phase_direction) {
00502       
00503       if (phase_diff_from_switch > 0) {
00504 
00505   dx = xWalk + (cos(aWalk)-1)*leg_offset_x-sin(aWalk)*leg_offset_y;
00506   dy = yWalk + sin(aWalk)*leg_offset_x+(cos(aWalk)-1)*leg_offset_y;
00507 
00508   double destination_x = walk_quarter_period*dx;
00509   double destination_y = walk_quarter_period*dy;
00510 
00511       
00512   dx = (destination_x-current_x)/(phase_diff_to_switch+1);
00513   dy = (destination_y-current_y)/(phase_diff_to_switch+1);
00514 
00515   current_x += dx;
00516   current_y += dy;
00517       }
00518 
00519       current_x = clip(current_x, xmin, xmax);
00520       current_y = clip(current_y, ymin, ymax);
00521 
00522       a[0] = current_x;
00523       a[1] = current_y;
00524       a[2] = (phase_diff_from_switch*leg_lift_final+
00525         phase_diff_to_switch*leg_lift_initial)/(2*walk_quarter_period);
00526 
00527     }
00528     else {
00529       
00530 
00531       leg_offset_x += current_x;
00532       leg_offset_y += current_y;
00533       dx = xWalk + (cos(aWalk)-1)*leg_offset_x-sin(aWalk)*leg_offset_y;
00534       dy = yWalk + sin(aWalk)*leg_offset_x+(cos(aWalk)-1)*leg_offset_y;
00535 
00536       current_x -= dx; 
00537       current_y -= dy; 
00538 
00539       a[0] = current_x;
00540       a[1] = current_y;
00541       a[2] = 0;
00542 
00543       
00544       
00545       current_x = clip(current_x, xmin, xmax);
00546       current_y = clip(current_y, ymin, ymax);
00547 
00548       
00549 
00550 
00551 
00552 
00553 
00554 
00555 
00556 
00557 
00558 
00559 
00560 
00561 
00562 
00563 
00564 
00565 
00566 
00567 
00568 
00569 
00570 
00571 
00572 
00573     }
00574 
00575     
00576 
00577     
00578     walk_current_x[iLeg] = current_x+center_x;
00579     walk_current_y[iLeg] = current_y+center_y;
00580 
00581     
00582     a += 3;
00583   }
00584 
00585   
00586 
00587 
00588 
00589 
00590   
00591   
00592   walk_phase += walk_phase_direction;
00593   if ((walk_phase > walk_quarter_period) ||
00594       (walk_phase < -walk_quarter_period)) {
00595     switch_phase_direction = true;
00596   }
00597 
00598   if (switch_phase_direction) {
00599     
00600     walk_phase = walk_phase_direction*walk_quarter_period;
00601     walk_phase_direction = -walk_phase_direction;
00602   }
00603   
00604   LegPositionsToAngles(leg_joints);
00605   SetLegJoints(leg_joints);
00606 
00607   
00608   
00609   
00610   
00611 }
00612 
00613 
00614 
00615 
00616 
00617 
00618 
00619 
00620 
00621 
00622 
00623 
00624 
00625 
00626 
00627 
00628 
00629 
00630