00001 #include "ThirdRobotInterface/ThirdRobotInterface.h"
00002
00003
00004 #include <fstream>
00005 #include <iostream>
00006 #include <stdexcept>
00007 #include <string>
00008 #include <vector>
00009
00010
00011 #include <cstdio>
00012 #include <cstdlib>
00013 #include <cstring>
00014 #include <fcntl.h>
00015 #include <math.h>
00016 #include <netinet/in.h>
00017 #include <sys/ioctl.h>
00018 #include <sys/stat.h>
00019 #include <sys/types.h>
00020 #include <unistd.h>
00021
00023 static constexpr int ROBOT_MAX_ENCODER_COUNTS {65535};
00025 static constexpr double WHEELBASE_LENGTH {0.94};
00027 static constexpr double MAX_LIN_VEL {1.11};
00028
00029 using namespace std;
00030
00031 cirkit::ThirdRobotInterface::ThirdRobotInterface(const std::string& new_serial_port_imcs01, int new_baudrate_imcs01)
00032 : imcs01_port_name {new_serial_port_imcs01},
00033 fd_imcs01 {-1},
00034 baudrate_imcs01 {new_baudrate_imcs01},
00035 steer_angle {0.0},
00036 last_rear_encoder_time {0},
00037 stasis_ {ROBOT_STASIS_FORWARD_STOP}
00038 {
00039 for (int i = 0; i < 2; i++)
00040 {
00041 delta_rear_encoder_counts[i] = -1;
00042 last_rear_encoder_counts[i] = 0;
00043 }
00044
00045 resetOdometry();
00046 }
00047
00048 cirkit::ThirdRobotInterface::~ThirdRobotInterface()
00049 {
00050
00051 cmd_ccmd.offset[0] = 65535;
00052 cmd_ccmd.offset[1] = 32767;
00053 cmd_ccmd.offset[2] = 32767;
00054 cmd_ccmd.offset[3] = 32767;
00055 ioctl(fd_imcs01, URBTC_COUNTER_SET);
00056 write(fd_imcs01, &cmd_ccmd, sizeof(cmd_ccmd));
00057
00059 if (fd_imcs01 > 0)
00060 {
00061 tcsetattr(fd_imcs01, TCSANOW, &oldtio_imcs01);
00062 close(fd_imcs01);
00063 }
00064 fd_imcs01 = -1;
00065 }
00066
00067
00068
00069
00070 int cirkit::ThirdRobotInterface::openSerialPort()
00071 {
00072 try
00073 {
00074 setSerialPort();
00075 }
00076 catch(exception &e)
00077 {
00078 cerr << e.what() << endl;
00079 return -1;
00080 }
00081 return 0;
00082 }
00083
00084
00085
00086 int cirkit::ThirdRobotInterface::setSerialPort()
00087 {
00088
00089 if (fd_imcs01 > 0)
00090 {
00091 throw logic_error("imcs01 is already open");
00092 }
00093 fd_imcs01 = open(imcs01_port_name.c_str(), O_RDWR);
00094 if (fd_imcs01 > 0)
00095 {
00096 tcgetattr(fd_imcs01, &oldtio_imcs01);
00097 }
00098 else
00099 {
00100 throw logic_error("Faild to open port: imcs01");
00101 }
00102 if (ioctl(fd_imcs01, URBTC_CONTINUOUS_READ) < 0)
00103 {
00104 throw logic_error("Faild to ioctl: URBTC_CONTINUOUS_READ");
00105 }
00106
00107 cmd_ccmd.selout = SET_SELECT | CH0 | CH1 | CH2 | CH3;
00108 cmd_ccmd.selin = SET_SELECT;
00109 cmd_ccmd.setoffset = CH0 | CH1 | CH2 | CH3;
00110 cmd_ccmd.offset[0] = 58981;
00111 cmd_ccmd.offset[1] = 58981;
00112 cmd_ccmd.offset[2] = 58981;
00113 cmd_ccmd.offset[3] = 58981;
00114 cmd_ccmd.setcounter = CH0 | CH1 | CH2 | CH3;
00115 cmd_ccmd.counter[1] = -3633;
00116 cmd_ccmd.counter[2] = 0;
00117 cmd_ccmd.posneg = SET_POSNEG | CH0 | CH1 | CH2 | CH3;
00118 cmd_ccmd.breaks = SET_BREAKS | CH0 | CH1 | CH2 | CH3;
00119 cmd_ccmd.magicno = 0x00;
00120
00121 if (ioctl(fd_imcs01, URBTC_COUNTER_SET) < 0)
00122 {
00123 throw logic_error("Faild to ioctl: URBTC_COUNTER_SET");
00124 }
00125 if (write(fd_imcs01, &cmd_ccmd, sizeof(cmd_ccmd)) < 0)
00126 {
00127 throw logic_error("Faild to write");
00128 }
00129
00130 cmd_ccmd.setcounter = 0;
00131
00132 cout << "ThirdRobotInterface (iMCs01)Connected to : " << imcs01_port_name << endl;
00133 return 0;
00134 }
00135
00136
00137
00138 void cirkit::ThirdRobotInterface::setParams(double pulse_rate, double geer_rate, double wheel_diameter_right, double wheel_diameter_left, double tred_width)
00139 {
00141 PulseRate = pulse_rate;
00142 ROS_INFO("PulseRate : %lf", PulseRate);
00144 GeerRate = geer_rate;
00145 ROS_INFO("GeerRate : %lf", GeerRate);
00147 WheelDiameter[0] = wheel_diameter_right;
00148 WheelDiameter[1] = wheel_diameter_left;
00149 ROS_INFO("wheelDiameter[right] : %lf", WheelDiameter[0]);
00150 ROS_INFO("wheelDiameter[left] : %lf", WheelDiameter[1]);
00151
00153 TredWidth = tred_width;
00154 ROS_INFO("TredWidth : %lf", TredWidth);
00155 }
00156
00157
00158 int cirkit::ThirdRobotInterface::closeSerialPort()
00159 {
00160 drive(0.0, 0.0);
00161 usleep(1000);
00162
00163 if (fd_imcs01 > 0)
00164 {
00165 tcsetattr(fd_imcs01, TCSANOW, &oldtio_imcs01);
00166 close(fd_imcs01);
00167 fd_imcs01 = -1;
00168 }
00169
00170 return 0;
00171 }
00172
00173
00174
00175
00176
00177 geometry_msgs::Twist cirkit::ThirdRobotInterface::drive(double linear_speed, double angular_speed)
00178 {
00179
00180 double front_angle_deg = 0;
00181 double rear_speed_m_s = 0;
00182
00183 if (-0.005 < linear_speed && linear_speed < 0.005 && fabs(angular_speed) > 0.0)
00184 {
00185 rear_speed_m_s = 0.3;
00186 if (angular_speed > 0)
00187 {
00188 front_angle_deg = 60;
00189 }
00190 else
00191 {
00192 front_angle_deg = -60;
00193 }
00194 }
00195 else
00196 {
00197 rear_speed_m_s = linear_speed*1.0;
00198 front_angle_deg = angular_speed*1.2*(180.0/M_PI);
00199
00200 }
00201
00202 return driveDirect(front_angle_deg, rear_speed_m_s);
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 geometry_msgs::Twist cirkit::ThirdRobotInterface::driveDirect(double front_angular, double rear_speed)
00219 {
00220 static int forward_stop_cnt = 0;
00221 static int back_stop_cnt = 0;
00222 static int max_spped_x = 3.0;
00223 static double average_spped_x = 0;
00224 static double u = 32767.0;
00225 static double u1 = 32767.0;
00226 static double u2 = 32767.0;
00227 static double e = 0;
00228 static double e1 = 0;
00229 static double e2 = 0;
00230
00231 static double gain_p = 10000.0;
00232 static double gain_i = 100000.0;
00233 static double gain_d = 1000.0;
00234
00235 double duty = 0;
00236
00237
00238 if (rear_speed >= 0.0)
00239 {
00240 double rear_speed_m_s = MIN(rear_speed, MAX_LIN_VEL);
00241 if (stasis_ == ROBOT_STASIS_FORWARD || stasis_ == ROBOT_STASIS_FORWARD_STOP)
00242 {
00243
00244
00245
00246
00247
00248
00249 average_spped_x = (average_spped_x + rear_speed)/2.0;
00250 u = (int)(32767.0 + 32767.0 * average_spped_x *1.0);
00251
00252
00253 if (rear_speed == 0.0)
00254 {
00255 u = 32767;
00256 average_spped_x = 0;
00257 }
00258 duty = MIN(u, 60000);
00259 duty = MAX(duty, 32767);
00260 u2 = u1;
00261 u1 = duty;
00262 e2 = e1;
00263 e1 = e;
00264 cmd_ccmd.offset[0] = 65535;
00265 cmd_ccmd.offset[1] = (int)(duty);
00266
00267 writeCmd(cmd_ccmd);
00268
00269 stasis_ = ROBOT_STASIS_FORWARD;
00270 }
00271 else
00272 {
00273
00274
00275 cmd_ccmd.offset[0] = 65535;
00276 cmd_ccmd.offset[1] = 32767;
00277
00278 u = 32767;
00279 duty = u;
00280 u2 = u1;
00281 u1 = duty;
00282 e2 = e1;
00283 e1 = e;
00284 average_spped_x = 0;
00285 writeCmd(cmd_ccmd);
00286
00287 if (forward_stop_cnt >= 20)
00288 {
00289 stasis_ = ROBOT_STASIS_FORWARD_STOP;
00290 forward_stop_cnt = 0;
00291 for (int i = 0; i < 10; ++i)
00292 {
00293 cmd_ccmd.offset[0] = 65535;
00294 cmd_ccmd.offset[1] = 32767;
00295 writeCmd(cmd_ccmd);
00296 }
00297 }
00298 else
00299 {
00300 stasis_ = ROBOT_STASIS_OTHERWISE;
00301 forward_stop_cnt++;
00302 }
00303 }
00304 }
00305 else
00306 {
00307
00308 average_spped_x = 0;
00309 if (stasis_ == ROBOT_STASIS_BACK_STOP || stasis_ == ROBOT_STASIS_BACK)
00310 {
00311
00312 cmd_ccmd.offset[0] = 32767;
00313 cmd_ccmd.offset[1] = 60000;
00314
00315 u = 32767;
00316 duty = MIN(u, 62176);
00317 u2 = u1; u1 = duty; e2 = e1; e1 = e;
00318
00319 writeCmd(cmd_ccmd);
00320
00321 stasis_ = ROBOT_STASIS_BACK;
00322 ROS_INFO("ROBOT_STASIS_BACK");
00323 }
00324 else
00325 {
00326
00327 if (back_stop_cnt >= 10)
00328 {
00329 stasis_ = ROBOT_STASIS_BACK_STOP;
00330 back_stop_cnt = 0;
00331 cmd_ccmd.offset[0] = 32767;
00332 cmd_ccmd.offset[1] = 32767;
00333 writeCmd(cmd_ccmd);
00334 for (int i = 0; i < 300; ++i) usleep(1000);
00335 ROS_INFO("ROBOT_STASIS_BACK_STOP");
00336 }
00337 else
00338 {
00339 cmd_ccmd.offset[0] = 65535;
00340 cmd_ccmd.offset[1] = 32767;
00341 usleep(50000);
00342 writeCmd(cmd_ccmd);
00343 stasis_ = ROBOT_STASIS_OTHERWISE;
00344 back_stop_cnt++;
00345 ROS_INFO("ROBOT_STASIS_OTHERWISE");
00346 }
00347 }
00348 }
00349
00350
00351
00352
00353 double input_angle = 0;
00354 input_angle = MAX(front_angular, -60.0);
00355 input_angle = MIN(input_angle, 60.0);
00356
00357
00358 double angdiff = (input_angle - steer_angle);
00359
00360
00361
00362 return fixFrontAngle(angdiff);
00363 }
00364
00365
00366
00367 int cirkit::ThirdRobotInterface::getEncoderPacket()
00368 {
00369 std::lock_guard<std::mutex> lck {communication_mutex_};
00370 if (read(fd_imcs01, &cmd_uin, sizeof(cmd_uin)) != sizeof(cmd_uin))
00371 {
00372 return -1;
00373 }
00374 else
00375 {
00376 return parseEncoderPackets();
00377 }
00378 }
00379
00380
00381
00382 int cirkit::ThirdRobotInterface::parseEncoderPackets()
00383 {
00384 parseFrontEncoderCounts();
00385 parseRearEncoderCounts();
00386 return 0;
00387 }
00388
00389 int cirkit::ThirdRobotInterface::parseFrontEncoderCounts()
00390 {
00391 const int ave_num = 5;
00392 static int cnt = 0;
00393 static vector<double> move_ave(ave_num);
00394
00395 int steer_encoder_counts = (int)(cmd_uin.ct[1]);
00396
00397 double alpha = 0.0;
00398 double beta = 0.0;
00399 double R = 0.0;
00400 const double n = 1.00;
00401
00402 if (steer_encoder_counts == 0.0)
00403 {
00404 steer_angle = 0.0;
00405 }
00406 else
00407 {
00408 double tmp = steer_encoder_counts*67.0/3633.0;
00409 tmp = tmp * M_PI /180;
00410 R = 0.96/tan(tmp);
00411
00412 steer_angle = atan(WHEELBASE_LENGTH/R);
00413
00414 steer_angle = steer_angle*(180.0/M_PI);
00415 }
00416
00417 move_ave[cnt%5] = steer_angle;
00418 size_t size = move_ave.size();
00419 double sum = 0;
00420 for (unsigned int i = 0; i < size; i++)
00421 {
00422 sum += move_ave[i];
00423 }
00424 steer_angle = sum / (double)size;
00425 cnt++;
00426
00427 return 0;
00428 }
00429
00430 int cirkit::ThirdRobotInterface::parseRearEncoderCounts()
00431 {
00433 int rear_encoder_counts[2] {(int)(cmd_uin.ct[2]), -(int)(cmd_uin.ct[3])};
00434
00435 delta_rear_encoder_time = (double)(cmd_uin.time) - last_rear_encoder_time;
00436 if (delta_rear_encoder_time < 0)
00437 {
00438 delta_rear_encoder_time = 65535 - (last_rear_encoder_time - cmd_uin.time);
00439 }
00440 delta_rear_encoder_time = delta_rear_encoder_time / 1000.0;
00441 last_rear_encoder_time = (double)(cmd_uin.time);
00442
00443 for (int i = 0; i < 2; i++)
00444 {
00445 if (delta_rear_encoder_counts[i] == -1
00446 || rear_encoder_counts[i] == last_rear_encoder_counts[i])
00447 {
00448
00449 delta_rear_encoder_counts[i] = 0;
00450
00451 }
00452 else
00453 {
00454 delta_rear_encoder_counts[i] = rear_encoder_counts[i] - last_rear_encoder_counts[i];
00455
00456
00457 if (delta_rear_encoder_counts[i] > ROBOT_MAX_ENCODER_COUNTS/10)
00458 {
00459 delta_rear_encoder_counts[i] = delta_rear_encoder_counts[i] - ROBOT_MAX_ENCODER_COUNTS;
00460 }
00461 if (delta_rear_encoder_counts[i] < -ROBOT_MAX_ENCODER_COUNTS/10)
00462 {
00463 delta_rear_encoder_counts[i] = delta_rear_encoder_counts[i] + ROBOT_MAX_ENCODER_COUNTS;
00464 }
00465 }
00466 last_rear_encoder_counts[i] = rear_encoder_counts[i];
00467 }
00468
00469 return 0;
00470 }
00471
00472
00473
00474
00475 void cirkit::ThirdRobotInterface::resetOdometry()
00476 {
00477 setOdometry(0.0, 0.0, 0.0);
00478 }
00479
00480
00481
00482 void cirkit::ThirdRobotInterface::setOdometry(double new_x, double new_y, double new_yaw)
00483 {
00484 odometry_x_ = new_x;
00485 odometry_y_ = new_y;
00486 odometry_yaw_ = new_yaw;
00487 }
00488
00489
00490
00491
00492 void cirkit::ThirdRobotInterface::calculateOdometry()
00493 {
00494
00495 for (int i = 0; i < 2; i++)
00496 {
00497 delta_dist[i] = (delta_rear_encoder_counts[i]/PulseRate/GeerRate)*(WheelDiameter[i]*M_PI);
00498 }
00499
00500 linear_velocity = (delta_dist[0] + delta_dist[1])/2.0;
00501 linear_velocity = linear_velocity / delta_rear_encoder_time;
00502
00503
00504
00505
00506
00507 odometry_yaw_ += ((last_delta_dist[0] - last_delta_dist[1] + delta_dist[0] - delta_dist[1]) /
00508 0.7 * TredWidth);
00509 odometry_x_ += (((last_delta_dist[0] + last_delta_dist[1]) * cos(last_odometry_yaw) +
00510 (delta_dist[0] + delta_dist[1]) * cos(odometry_yaw_)) / 4.0);
00511 odometry_y_ += (((last_delta_dist[0] + last_delta_dist[1]) * sin(last_odometry_yaw) +
00512 (delta_dist[0] + delta_dist[1]) * sin(odometry_yaw_)) / 4.0);
00513
00514 for (int i = 0; i < 2; i++)
00515 {
00516 last_delta_dist[i] = delta_dist[i];
00517 }
00518 last_odometry_yaw = odometry_yaw_;
00519 }
00520
00521
00522 void cirkit::ThirdRobotInterface::writeCmd(ccmd cmd)
00523 {
00524 if (ioctl(fd_imcs01, URBTC_COUNTER_SET) < 0)
00525 {
00526 ROS_WARN("URBTC_COUNTER_SET fail.");
00527 }
00528 std::lock_guard<std::mutex> lck {communication_mutex_};
00529 if (write(fd_imcs01, &cmd, sizeof(cmd)) < 0)
00530 {
00531 ROS_WARN("iMCs01 write fail.");
00532 }
00533 }
00534
00535 geometry_msgs::Twist cirkit::ThirdRobotInterface::fixFrontAngle(double angular_diff)
00536 {
00537 geometry_msgs::Twist ret_steer;
00538 if (angular_diff > 0)
00539 {
00540 ret_steer.angular.z = 1;
00541 ret_steer.angular.x = fabs(angular_diff);
00542 return ret_steer;
00543 }
00544 else if(angular_diff < 0)
00545 {
00546 ret_steer.angular.z = -1;
00547 ret_steer.angular.x = fabs(angular_diff);
00548 return ret_steer;
00549 }
00550 else
00551 {
00552 ret_steer.angular.z = 0;
00553 ret_steer.angular.x = 0;
00554 return ret_steer;
00555 }
00556 }
00557
00558 int plus_or_minus(double value)
00559 {
00560 if (value > 0)
00561 {
00562 return 1;
00563 }
00564 else if(value < 0)
00565 {
00566 return -1;
00567 }
00568 else
00569 {
00570 return 0;
00571 }
00572 }