00001 #include <ros/console.h>
00002
00003 #include <algorithm>
00004 #include <cmath>
00005 #include <cstdio>
00006
00007 #include <net/if.h>
00008 #include <sys/ioctl.h>
00009 #include <linux/can.h>
00010
00011 #include "comm.h"
00012 #include "kurt.h"
00013
00014 Kurt::~Kurt()
00015 {
00016 if(use_rotunit_)
00017 can_rotunit_send(0.0);
00018 k_hard_stop();
00019 if(!use_microcontroller_)
00020 {
00021 free(pwm_v_l_);
00022 free(pwm_v_r_);
00023 }
00024 }
00025
00026 bool Kurt::setPWMData(const std::string &speedPwmLeerlaufTable, double feedforward_turn, double ki, double kp)
00027 {
00028 ki_l = ki_r = ki;
00029 kp_l = kp_r = kp;
00030
00031 int nr;
00032 double *v_pwm_l, *v_pwm_r;
00033 if (!read_speed_to_pwm_leerlauf_tabelle(speedPwmLeerlaufTable, &nr, &v_pwm_l, &v_pwm_r))
00034 {
00035 return false;
00036 }
00037 make_pwm_v_tab(nr, v_pwm_l, v_pwm_r, nr_v_, &pwm_v_l_, &pwm_v_r_, &vmax_);
00038 free(v_pwm_l);
00039 free(v_pwm_r);
00040 use_microcontroller_ = false;
00041
00042 return true;
00043 }
00044
00045 int Kurt::can_motor(int left_pwm, char left_dir, char left_brake,
00046 int right_pwm, char right_dir, char right_brake)
00047 {
00048 char left_dir_brake = (left_dir << 1) + left_brake;
00049 char right_dir_brake = (right_dir << 1) + right_brake;
00050
00051 can_frame frame;
00052 frame.can_id = CAN_CONTROL;
00053 frame.can_dlc = 8;
00054 frame.data[0] = RAW >> 8;
00055 frame.data[1] = RAW;
00056 frame.data[2] = (left_dir_brake);
00057 frame.data[3] = (left_pwm >> 8);
00058 frame.data[4] = (left_pwm);
00059 frame.data[5] = (right_dir_brake);
00060 frame.data[6] = (right_pwm >> 8);
00061 frame.data[7] = (right_pwm);
00062
00063 if (!can_.send_frame(&frame))
00064 {
00065 ROS_ERROR("can_motor: Error sending PWM data");
00066 return 1;
00067 }
00068 return 0;
00069 }
00070
00071 void Kurt::k_hard_stop(void)
00072 {
00073 unsigned short pwm_left, pwm_right;
00074 unsigned char dir_left, dir_right, brake_left, brake_right;
00075 pwm_left = 1023;
00076 dir_left = 0;
00077 brake_left = 1;
00078 pwm_right = 1023;
00079 dir_right = 0;
00080 brake_right = 1;
00081
00082 do
00083 { }
00084 while (!can_motor(pwm_left, dir_left, brake_left, pwm_right, dir_right, brake_right));
00085 }
00086
00087
00088
00089
00090
00091 void Kurt::set_wheel_speed1(double v_l, double v_r, int integration_l, int integration_r)
00092 {
00093 unsigned short pwm_left, pwm_right;
00094 unsigned char dir_left, dir_right, brake_left, brake_right;
00095
00096 int index_l, index_r;
00097
00098
00099 index_l = (int)(fabs(v_l) / vmax_ * nr_v_);
00100 index_r = (int)(fabs(v_r) / vmax_ * nr_v_);
00101
00102 index_l = std::min(nr_v_ - 1, index_l);
00103 index_r = std::min(nr_v_ - 1, index_r);
00104
00105
00106 if (fabs(v_l) > 0.01)
00107 pwm_left = std::max(0, std::min(1023, 1024 - pwm_v_l_[index_l] - leerlauf_adapt_ - integration_l));
00108 else
00109 pwm_left = 1023;
00110 if (fabs(v_r) > 0.01)
00111 pwm_right = std::max(0, std::min(1023, 1024 - pwm_v_r_[index_r] - leerlauf_adapt_ - integration_r));
00112 else
00113 pwm_right = 1023;
00114
00115 if (v_l >= 0.0)
00116 dir_left = 0;
00117 else
00118 dir_left = 1;
00119 if (v_r >= 0.0)
00120 dir_right = 0;
00121 else
00122 dir_right = 1;
00123
00124
00125 brake_left = 0;
00126 brake_right = 0;
00127
00128 can_motor(pwm_left, dir_left, brake_left, pwm_right, dir_right, brake_right);
00129 }
00130
00131
00132
00133
00134 void Kurt::set_wheel_speed2(double _v_l_soll, double _v_r_soll, double _v_l_ist,
00135 double _v_r_ist, double _omega, double _AntiWindup)
00136 {
00137
00138 static double zl = 0.0, zr = 0.0;
00139 static double last_zl = 0.0, last_zr = 0.0;
00140
00141 static double el = 0.0, er = 0.0;
00142 static double last_el = 0.0, last_er = 0.0;
00143
00144 static double int_el = 0.0, int_er = 0.0;
00145
00146 static double del = 0.0, der = 0.0;
00147
00148 double dt = 0.01;
00149
00150 static double last_v_l_ist = 0.0, last_v_r_ist = 0.0;
00151
00152
00153
00154
00155
00156
00157 static double v_l_list[MAX_V_LIST] = {0.0}, v_r_list[MAX_V_LIST] = {0.0};
00158 static int vl_index = 3, vr_index = 3;
00159 int i;
00160 static double f_v_l_ist, f_v_r_ist;
00161
00162 double kd_l = 0.0, kd_r = 0.0;
00163
00164 int_el *= _AntiWindup;
00165 int_er *= _AntiWindup;
00166
00167 last_v_l_ist *= _AntiWindup;
00168 last_v_r_ist *= _AntiWindup;
00169
00170 double turn_feedforward_l = -_omega / M_PI * feedforward_turn_;
00171 double turn_feedforward_r = _omega / M_PI * feedforward_turn_;
00172
00173
00174 if (fabs(_v_l_ist - last_v_l_ist) < 0.19)
00175 {
00176
00177 v_l_list[vl_index] = _v_l_ist;
00178 f_v_l_ist = (v_l_list[vl_index] + v_l_list[vl_index - 1] + v_l_list[vl_index - 2] + v_l_list[vl_index - 3]) / 4.0;
00179 vl_index++;
00180 if (vl_index >= MAX_V_LIST)
00181 {
00182 vl_index = 3;
00183 for (i = 0; i < 3; i++)
00184 v_l_list[2 - i] = v_l_list[MAX_V_LIST - i - 1];
00185 }
00186
00187 el = _v_l_soll - f_v_l_ist;
00188 del = (el - last_el) / dt;
00189 int_el += el * dt;
00190
00191 zl = kp_l * el + kd_l * del + ki_l * int_el + _v_l_soll + turn_feedforward_l;
00192
00193 last_el = el;
00194 }
00195
00196
00197 if (fabs(_v_r_ist - last_v_r_ist) < 0.19)
00198 {
00199
00200 v_r_list[vr_index] = _v_r_ist;
00201 f_v_r_ist = (v_r_list[vr_index] + v_r_list[vr_index - 1] + v_r_list[vr_index - 2] + v_r_list[vr_index - 3]) / 4.0;
00202 vr_index++;
00203 if (vr_index >= MAX_V_LIST)
00204 {
00205 vr_index = 3;
00206 for (i = 0; i < 3; i++)
00207 {
00208 v_r_list[2 - i] = v_r_list[MAX_V_LIST - i - 1];
00209 }
00210 }
00211
00212 er = _v_r_soll - f_v_r_ist;
00213 der = (er - last_er) / dt;
00214 int_er += er * dt;
00215
00216 zr = kp_r * er + kd_r * der + ki_r * int_er + _v_r_soll + turn_feedforward_r;
00217
00218 last_er = er;
00219 }
00220
00221
00222
00223
00224 if (zl > vmax_)
00225 {
00226 zl = vmax_;
00227 int_el -= el * dt;
00228 }
00229 if (zr > vmax_)
00230 {
00231 zr = vmax_;
00232 int_er -= er * dt;
00233 }
00234 if (zl < -vmax_)
00235 {
00236 zl = -vmax_;
00237 int_el -= el * dt;
00238 }
00239 if (zr < -vmax_)
00240 {
00241 zr = -vmax_;
00242 int_er -= er * dt;
00243 }
00244
00245
00246
00247 double step_max = vmax_ * 0.5;
00248
00249
00250
00251
00252 if ((zl - last_zl) > step_max)
00253 {
00254 zl = last_zl + step_max;
00255 }
00256 if ((zl - last_zl) < -step_max)
00257 {
00258 zl = last_zl - step_max;
00259 }
00260 if ((zr - last_zr) > step_max)
00261 {
00262 zr = last_zr + step_max;
00263 }
00264 if ((zr - last_zr) < -step_max)
00265 {
00266 zr = last_zr - step_max;
00267 }
00268
00269
00270 last_v_l_ist = _v_l_ist;
00271 last_v_r_ist = _v_r_ist;
00272 last_zl = zl;
00273 last_zr = zr;
00274
00275 set_wheel_speed1(zl, zr, 0, 0);
00276 }
00277
00278 void Kurt::set_wheel_speed2_mc(double _v_l_soll, double _v_r_soll, double _omega,
00279 double _AntiWindup)
00280 {
00281
00282 const long factor = 100;
00283 int left_speed = (int)(_v_l_soll * factor);
00284 int right_speed = (int)(_v_r_soll * factor);
00285 int omega = (int)(factor * _omega / M_PI);
00286 int AntiWindup = (int)_AntiWindup;
00287 int sign = omega < 0 ? 1 : 0;
00288 int windup = AntiWindup > 0 ? 1 : 0;
00289
00290 omega = abs(omega);
00291 omega = (omega << 1) + sign;
00292 omega = (omega << 1) + windup;
00293
00294 can_frame frame;
00295 frame.can_id = CAN_CONTROL;
00296 frame.can_dlc = 8;
00297 frame.data[0] = SPEED_CM >> 8;
00298 frame.data[1] = SPEED_CM;
00299 frame.data[2] = left_speed >> 8;
00300 frame.data[3] = left_speed;
00301 frame.data[4] = right_speed >> 8;
00302 frame.data[5] = right_speed;
00303 frame.data[6] = omega >> 8;
00304 frame.data[7] = omega;
00305
00306 if(!can_.send_frame(&frame))
00307 {
00308 ROS_ERROR("set_wheel_speed2_mc: Error sending speed");
00309 }
00310 }
00311
00312 void Kurt::set_wheel_speed(double _v_l_soll, double _v_r_soll, double _AntiWindup)
00313 {
00314 if (use_microcontroller_)
00315 {
00316
00317
00318 set_wheel_speed2_mc(_v_l_soll, _v_r_soll, 0, 1.0);
00319 }
00320 else
00321 {
00322 set_wheel_speed2(_v_l_soll, _v_r_soll, v_encoder_left_, v_encoder_right_, 0, _AntiWindup);
00323 }
00324 }
00325
00326
00327 bool Kurt::read_speed_to_pwm_leerlauf_tabelle(const std::string &filename, int *nr, double **v_pwm_l, double **v_pwm_r)
00328 {
00329 int i;
00330 FILE *fpr_fftable = NULL;
00331 double t, v, vl, vr;
00332 int pwm;
00333
00334 ROS_INFO("Open FeedForwardTabelle: %s", filename.c_str());
00335 fpr_fftable = fopen(filename.c_str(), "r");
00336
00337 if (fpr_fftable == NULL)
00338 {
00339 ROS_ERROR("ERROR opening speedtable.");
00340 return false;
00341 }
00342
00343 *nr = 1025;
00344 *v_pwm_l = (double *)calloc(*nr, sizeof(double));
00345 *v_pwm_r = (double *)calloc(*nr, sizeof(double));
00346 for (i = 0; i < *nr; i++)
00347 {
00348 if(fscanf(fpr_fftable, "%lf %lf %lf %lf %d", &t, &v, &vl, &vr, &pwm) == EOF)
00349 {
00350 ROS_ERROR("ERROR reading speedtable.");
00351 fclose(fpr_fftable);
00352 return false;
00353 }
00354 (*v_pwm_l)[pwm] = vl;
00355 (*v_pwm_r)[pwm] = vr;
00356 }
00357 fclose(fpr_fftable);
00358 return true;
00359 }
00360
00361
00362 void Kurt::make_pwm_v_tab(int nr, double *v_pwm_l, double *v_pwm_r, int nr_v, int **pwm_v_l, int **pwm_v_r, double *v_max)
00363 {
00364 int i, index_l, index_r;
00365
00366 double v_max_l = 0.0, v_max_r = 0.0;
00367 *v_max = 0.0;
00368
00369 *pwm_v_l = (int *)calloc(nr_v + 1, sizeof(int));
00370 *pwm_v_r = (int *)calloc(nr_v + 1, sizeof(int));
00371
00372
00373 for (i = 0; i < nr; i++)
00374 {
00375 if (v_pwm_l[i] > v_max_l)
00376 v_max_l = v_pwm_l[i];
00377 if (v_pwm_r[i] > v_max_r)
00378 v_max_r = v_pwm_r[i];
00379 *v_max = std::min(v_max_l, v_max_r);
00380 }
00381
00382
00383 for (i = 0; i < nr; i++)
00384 {
00385 index_l = std::min(nr_v, std::max(0, (int)((v_pwm_l[i]) * (nr_v) / *v_max)));
00386 (*pwm_v_l)[index_l] = i;
00387 index_r = std::min(nr_v, std::max(0, (int)((v_pwm_r[i]) * (nr_v) / *v_max)));
00388 (*pwm_v_r)[index_r] = i;
00389 }
00390 (*pwm_v_l)[0] = 0;
00391 (*pwm_v_r)[0] = 0;
00392
00393
00394
00395
00396 for (i = 1; i < nr_v; i++)
00397 {
00398
00399 if ((*pwm_v_l)[i] < (*pwm_v_l)[i - 1])
00400 (*pwm_v_l)[i] = (*pwm_v_l)[i - 1];
00401 if ((*pwm_v_r)[i] < (*pwm_v_r)[i - 1])
00402 (*pwm_v_r)[i] = (*pwm_v_r)[i - 1];
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415 }
00416 }
00417
00418 void Kurt::odometry(int wheel_a, int wheel_b)
00419 {
00420
00421 double time_diff = 0.01;
00422
00423
00424 double wheel_L = wheel_perimeter_ * wheel_a / ticks_per_turn_of_wheel_;
00425 double wheel_R = wheel_perimeter_ * wheel_b / ticks_per_turn_of_wheel_;
00426
00427
00428 v_encoder_left_ = wheel_L / time_diff;
00429 v_encoder_right_ = wheel_R / time_diff;
00430 double v_encoder = (v_encoder_right_ + v_encoder_left_) * 0.5;
00431
00432 double v_encoder_angular = (v_encoder_right_ - v_encoder_left_) / axis_length_ * turning_adaptation_;
00433
00434
00435 double local_dx, local_dz, dtheta_y = 0.0;
00436 const double EPSILON = 0.0001;
00437
00438 if (fabs(wheel_L - wheel_R) < EPSILON)
00439 {
00440 if (fabs(wheel_L) < EPSILON)
00441 {
00442 local_dx = 0.0;
00443 local_dz = 0.0;
00444 }
00445 else
00446 {
00447 local_dx = 0.0;
00448 local_dz = (wheel_L + wheel_R) * 0.5;
00449 }
00450 }
00451 else
00452 {
00453 double hypothenuse = 0.5 * (wheel_L + wheel_R);
00454
00455 dtheta_y = (wheel_L - wheel_R) / axis_length_ * turning_adaptation_;
00456
00457 local_dx = hypothenuse * sin(dtheta_y);
00458 local_dz = hypothenuse * cos(dtheta_y);
00459 }
00460
00461
00462 static double x_from_encoder = 0.0;
00463 static double z_from_encoder = 0.0;
00464 static double theta_from_encoder = 0.0;
00465
00466 x_from_encoder += local_dx * cos(theta_from_encoder) + local_dz * sin(theta_from_encoder);
00467 z_from_encoder += -local_dx * sin(theta_from_encoder) + local_dz * cos(theta_from_encoder);
00468
00469 theta_from_encoder += dtheta_y;
00470 if (theta_from_encoder > M_PI)
00471 theta_from_encoder -= 2.0 * M_PI;
00472 if (theta_from_encoder < -M_PI)
00473 theta_from_encoder += 2.0 * M_PI;
00474
00475 comm_.send_odometry(z_from_encoder, x_from_encoder, theta_from_encoder, v_encoder, v_encoder_angular, wheel_a, wheel_b, v_encoder_left_, v_encoder_right_);
00476 }
00477
00479
00480 void Kurt::can_rotunit_send(double speed)
00481 {
00482 int ticks = (int)(speed / (2.0 * M_PI) * 10240 / 20);
00483 can_frame frame;
00484 frame.can_id = CAN_SETROTUNT;
00485 frame.can_dlc = 8;
00486 frame.data[0] = (ticks >> 8);
00487 frame.data[1] = (ticks & 0xFF);
00488 frame.data[2] = 0;
00489 frame.data[3] = 0;
00490 frame.data[4] = 0;
00491 frame.data[5] = 0;
00492 frame.data[6] = 0;
00493 frame.data[7] = 0;
00494
00495 if(!can_.send_frame(&frame))
00496 {
00497 ROS_ERROR("can_rotunit_send: Error sending rotunit speed");
00498 }
00499 else
00500 {
00501 use_rotunit_ = true;
00502 }
00503 }
00504
00505 void Kurt::can_rotunit(const can_frame &frame)
00506 {
00507 int rot = (frame.data[1] << 8) + frame.data[2];
00508 double rot2 = rot * 2 * M_PI / 10240;
00509 comm_.send_rotunit(rot2);
00510 }
00511
00513
00514 void Kurt::can_encoder(const can_frame &frame)
00515 {
00516 int left_encoder = 0, right_encoder = 0;
00517 if (frame.data[0] & 0x80)
00518 left_encoder = (frame.data[0] << 8) + frame.data[1]-65536;
00519 else
00520 left_encoder = (frame.data[0] << 8) + frame.data[1];
00521
00522 if (frame.data[2] & 0x80)
00523 right_encoder = (frame.data[2] << 8) + frame.data[3]-65536;
00524 else
00525 right_encoder = (frame.data[2] << 8) + frame.data[3];
00526
00527 odometry(left_encoder, right_encoder);
00528 }
00529
00530 int Kurt::normalize_ir(int ir)
00531 {
00532 if (ir < IR_MIN * 1000 || ir > IR_MAX * 1000)
00533 {
00534 return -1;
00535 }
00536 return (int)(pow(30000.0 / ((double)ir - 10.0), 1.0 / 1.4) - 10.0);
00537 }
00538
00539 int Kurt::normalize_sonar(int s)
00540 {
00541 if (s < SONAR_MIN * 1000 || s > SONAR_MAX * 1000)
00542 {
00543 return -1;
00544 }
00545 return (int)((double)s * 0.110652 + 11.9231);
00546 }
00547
00548 void Kurt::can_sonar8_9(const can_frame &frame)
00549 {
00550 int sonar1 = normalize_ir((frame.data[2] << 8) + frame.data[3]);
00551
00552 comm_.send_sonar_leftBack(sonar1);
00553 }
00554
00555 void Kurt::can_sonar4_7(const can_frame &frame)
00556 {
00557 int sonar0 = normalize_ir((frame.data[0] << 8) + frame.data[1]);
00558 int sonar1 = normalize_sonar((frame.data[2] << 8) + frame.data[3]);
00559 int sonar2 = normalize_ir((frame.data[4] << 8) + frame.data[5]);
00560 int sonar3 = normalize_ir((frame.data[6] << 8) + frame.data[7]);
00561
00562 comm_.send_sonar_front_usound_leftFront_left(sonar0, sonar1, sonar2, sonar3);
00563 }
00564
00565 void Kurt::can_sonar0_3(const can_frame &frame)
00566 {
00567 int sonar0 = normalize_ir((frame.data[0] << 8) + frame.data[1]);
00568 int sonar1 = normalize_ir((frame.data[2] << 8) + frame.data[3]);
00569 int sonar2 = normalize_ir((frame.data[4] << 8) + frame.data[5]);
00570
00571 comm_.send_sonar_back_rightBack_rightFront(sonar0, sonar1, sonar2);
00572 }
00573
00574 void Kurt::can_tilt_comp(const can_frame &frame)
00575 {
00576 double a0, a1;
00577 unsigned int t0, t1;
00578
00579 t0 = (frame.data[0] << 8) + (frame.data[1]);
00580 t1 = (frame.data[2] << 8) + (frame.data[3]);
00581
00582
00583
00584
00585 a0 = ((double)t0 - 32768.0) / 3932.0;
00586 a1 = ((double)t1 - 32768.0) / 3932.0;
00587
00588
00589 double tilt_lr = asin(a0);
00590 double tilt_fb = asin(a1);
00591
00592 double roll = tilt_lr * 180.0 / M_PI;
00593 double pitch = tilt_fb * 180.0 / M_PI;
00594 comm_.send_pitch_roll(pitch, roll);
00595 }
00596
00597 void Kurt::can_gyro_mc1(const can_frame &frame)
00598 {
00599 static int gyro_offset_read = 0;
00600 static double offset, delta;
00601 signed long gyro_raw;
00602
00603 gyro_raw = (frame.data[0] << 24) + (frame.data[1] << 16)
00604 + (frame.data[2] << 8) + (frame.data[3]);
00605 double theta = (double)gyro_raw / 4992511.0 * M_PI / 180.0;
00606
00607 double sigma_deg = (double)((frame.data[4] << 24) + (frame.data[5] << 16)
00608 + (frame.data[6] << 8) + (frame.data[7])) / 10000;
00609
00610 double tmp = (sqrt(sigma_deg) * M_PI / 180.0);
00611 double sigma = tmp * tmp;
00612
00613
00614 if (gyro_offset_read++ < 100)
00615 return;
00616
00617 if(gyro_offset_read == 100)
00618 {
00619 offset = theta;
00620 delta = offset / 100.0;
00621 if (delta > M_PI) delta -= 2.0 * M_PI;
00622 if (delta < -M_PI) delta += 2.0 * M_PI;
00623 }
00624
00625 offset += delta;
00626 if (offset > M_PI) offset -= 2.0 * M_PI;
00627 if (offset < -M_PI) offset += 2.0 * M_PI;
00628
00629 theta -= offset;
00630
00631 if (theta > M_PI) theta -= 2.0 * M_PI;
00632 if (theta < -M_PI) theta += 2.0 * M_PI;
00633
00634 comm_.send_gyro(theta, sigma);
00635 }
00636
00637 int Kurt::can_read_fifo()
00638 {
00639 can_frame frame;
00640
00641 if(!can_.receive_frame(&frame))
00642 return -1;
00643
00644 switch (frame.can_id) {
00645 case CAN_ADC00_03:
00646 can_sonar0_3(frame);
00647 break;
00648 case CAN_ADC04_07:
00649 can_sonar4_7(frame);
00650 break;
00651 case CAN_ADC08_11:
00652 can_sonar8_9(frame);
00653 break;
00654 case CAN_ENCODER:
00655 can_encoder(frame);
00656 break;
00657 case CAN_TILT_COMP:
00658 can_tilt_comp(frame);
00659 break;
00660 case CAN_GYRO_MC1:
00661 can_gyro_mc1(frame);
00662 break;
00663 case CAN_GETROTUNIT:
00664 can_rotunit(frame);
00665 break;
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701 }
00702
00703 return frame.can_id;
00704 }