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