ixis_imcs01_driver.cpp
Go to the documentation of this file.
00001 #include "ixis_imcs01_driver/ixis_imcs01_driver.h"
00002 
00003 
00004 #include <sys/ioctl.h>
00005 #include <sys/stat.h>
00006 #include <sys/time.h>
00007 #include <sys/types.h>
00008 #include <fcntl.h>
00009 
00010 #include <ros/ros.h>
00011 
00012 static constexpr int ROBOT_MAX_ENCODER_COUNTS {65535};
00013 static constexpr double MAX_LIN_VEL {1.11}; // 1.11[m/s] => 4.0[km/h]
00014 
00015 IxisImcs01Driver::IxisImcs01Driver(std::string port_name)
00016   : imcs01_fd_(-1)
00017 {
00018   rear_last_encoder_counts_.resize(2);
00019   rear_delta_encoder_counts_.resize(2);
00020   state_.position.resize(3);
00021   state_.velocity.resize(3);
00022   state_.effort.resize(3);
00023   state_.name.resize(3);
00024   for (size_t i; i < 3; ++i) {
00025     rear_last_encoder_counts_[i] = 0;
00026     rear_delta_encoder_counts_[i] = -1;
00027     state_.position[i] = 0.0;
00028     state_.velocity[i] = 0.0;
00029     state_.effort[i] = 0;
00030   }
00031   state_.name[0] = "rear_right";
00032   state_.name[1] = "rear_left";
00033   state_.name[2] = "front";
00034   this->openPort(port_name);
00035 }
00036 
00037 IxisImcs01Driver::~IxisImcs01Driver()
00038 {
00039   this->closePort();
00040 }
00041 
00042 int IxisImcs01Driver::openPort(std::string port_name)
00043 {
00044   imcs01_fd_ = open(port_name.c_str(), O_RDWR);
00045   if(imcs01_fd_ < 0){
00046     ROS_ERROR_STREAM("iMCs01 Open Error : " << port_name);
00047     exit(-1);
00048   }else{
00049     this->setImcs01();
00050   }
00051   return 0;
00052 }
00053 
00054 int IxisImcs01Driver::closePort()
00055 {
00056   cmd_ccmd_.offset[0] = 65535; // iMCs01 CH101 PIN2 is 5[V]. Forwarding flag.
00057   cmd_ccmd_.offset[1] = 32767; // STOP
00058   cmd_ccmd_.offset[2] = 32767;
00059   cmd_ccmd_.offset[3] = 32767;
00061   if (imcs01_fd_ > 0){
00062     write(imcs01_fd_, &cmd_ccmd_, sizeof(cmd_ccmd_));
00063     tcsetattr(imcs01_fd_, TCSANOW, &oldtio_imcs01_);
00064     close(imcs01_fd_);
00065   }
00066 }
00067 
00068 int IxisImcs01Driver::setImcs01()
00069 {
00070   tcgetattr(imcs01_fd_, &oldtio_imcs01_);
00071   if(ioctl(imcs01_fd_, URBTC_CONTINUOUS_READ) < 0){
00072     ROS_ERROR_STREAM("iMCs01 ioctl URBTC_CONTINUOUS_READ error");
00073     exit(-1);
00074   }
00075   if(ioctl(imcs01_fd_, URBTC_BUFREAD) < 0){
00076     ROS_ERROR_STREAM("iMCs01 ioctl URBTC_BUFREAD error");
00077     //exit(-1);
00078   }
00079 
00080   cmd_ccmd_.selout     = SET_SELECT | CH0 | CH1 | CH2 | CH3; // All PWM.
00081   cmd_ccmd_.selin      = SET_SELECT; // All input using for encoder count.
00082   cmd_ccmd_.setoffset  = CH0 | CH1 | CH2 | CH3;
00083   cmd_ccmd_.offset[0]  = 58981;
00084   cmd_ccmd_.offset[1]  = 58981;
00085   cmd_ccmd_.offset[2]  = 58981;
00086   cmd_ccmd_.offset[3]  = 58981; // 1/2
00087   cmd_ccmd_.setcounter = CH0 | CH1 | CH2 | CH3;
00088   cmd_ccmd_.counter[1] = -3633; //-67[deg]*(1453/27), initialize.
00089   cmd_ccmd_.counter[2] = 0;
00090   cmd_ccmd_.posneg     = SET_POSNEG | CH0 | CH1 | CH2 | CH3; //POS PWM out.
00091   cmd_ccmd_.breaks     = SET_BREAKS | CH0 | CH1 | CH2 | CH3; //No Brake;
00092   cmd_ccmd_.magicno    = 0x00;
00093 
00094   if (ioctl(imcs01_fd_, URBTC_COUNTER_SET) < 0){
00095     ROS_ERROR_STREAM("Faild to ioctl: URBTC_COUNTER_SET");
00096     exit(-1);
00097   }
00098   if (write(imcs01_fd_, &cmd_ccmd_, sizeof(cmd_ccmd_)) < 0){
00099     ROS_ERROR_STREAM("Faild to ioctl: Faild to write");
00100     exit(-1);
00101   }
00102   cmd_ccmd_.setcounter = 0; // 次の書き込み時にエンコーダのカウンタを上書きしない
00103   ROS_INFO_STREAM( "iMCs01 is Connected.");
00104   return 0;
00105 }
00106 
00107 int IxisImcs01Driver::update()
00108 {
00109   std::lock_guard<std::mutex> lck {communication_mutex_};
00110   if(read(imcs01_fd_, &received_data_, sizeof(received_data_))
00111      != sizeof(received_data_)){
00112     //ROS_WARN_STREAM("iMCs01 update() read error");
00113     return -1;
00114   }else{
00115     this->parseEncoderTime();
00116     this->parseFrontEncoderCounts();
00117     this->parseRearEncoderCounts();
00118     return 0;
00119   }
00120 }
00121 
00122 int IxisImcs01Driver::parseEncoderTime()
00123 {
00124   delta_encoder_time_ = (double)(received_data_.time) - last_encoder_time_;
00125 
00126   if(delta_encoder_time_ < 0){
00127     delta_encoder_time_ = 65535 - (last_encoder_time_ - received_data_.time);
00128   }
00129   delta_encoder_time_ = delta_encoder_time_ / 1000.0; // [ms] -> [s]
00130   last_encoder_time_ = (double)(received_data_.time);
00131   return 0;
00132 }
00133 
00134 int IxisImcs01Driver::parseFrontEncoderCounts()
00135 {
00136   int steer_encoder_counts = (int)received_data_.ct[1];
00137   state_.position[JOINT_INDEX_FRONT] = steer_encoder_counts*M_PI*67.0/3633.0/180.0;
00138   // cirkit_unit03_driverでの実装だとここで移動平均をしてる
00139   return 0;
00140 }
00141 
00142 int IxisImcs01Driver::parseRearEncoderCounts()
00143 {
00144   int rear_encoder_counts[2]{(int)received_data_.ct[2], -(int)received_data_.ct[3]};
00145 
00146   for(int i = 0; i < 2; ++i){
00147     if(rear_delta_encoder_counts_[i] == -1
00148        || rear_encoder_counts[i] == rear_last_encoder_counts_[i]){ // First time.
00149 
00150      rear_delta_encoder_counts_[i] = 0;
00151 
00152     }else{
00153       rear_delta_encoder_counts_[i] = rear_encoder_counts[i] - rear_last_encoder_counts_[i];
00154 
00155       // checking iMCs01 counter overflow.
00156       if(rear_delta_encoder_counts_[i] > ROBOT_MAX_ENCODER_COUNTS/10){
00157         rear_delta_encoder_counts_[i] = rear_delta_encoder_counts_[i] - ROBOT_MAX_ENCODER_COUNTS;
00158       }
00159       if(rear_delta_encoder_counts_[i] < -ROBOT_MAX_ENCODER_COUNTS/10){
00160         rear_delta_encoder_counts_[i] = rear_delta_encoder_counts_[i] + ROBOT_MAX_ENCODER_COUNTS;
00161       }
00162     }
00163     rear_last_encoder_counts_[i] = rear_encoder_counts[i];
00164 
00165     // Update rear state
00166     // pulse rate : 40.0, gear_rate : 33.0
00167     // position = (counts / (40.0 * 33.0)) * pi = counts * 0.00237999...
00168     state_.position[i] += rear_delta_encoder_counts_[i]*0.0238;
00169     state_.velocity[i] = (rear_delta_encoder_counts_[i]*0.0238/delta_encoder_time_);
00170   }
00171 
00172   return 0;
00173 }
00174 
00175 sensor_msgs::JointState IxisImcs01Driver::getJointState()
00176 {
00177   return state_;
00178 }
00179 
00180 int IxisImcs01Driver::controlRearWheel(double rear_speed)
00181 {
00182   static int forward_stop_cnt = 0;
00183   static int back_stop_cnt = 0;
00184   static int max_spped_x = 3.0;
00185   static double average_spped_x = 0;
00186   static double u = 32767.0;
00187   double duty = 0;
00188 
00189   if (0.0 <= rear_speed && rear_speed <= 0.05){
00190     u = 32767.0;
00191     average_spped_x = 0;
00192     this->writeOffsetCmd(RunningMode::FORWARD, (unsigned short)u);
00193     running_state_ = RunningState::FORWARD_STOP;
00194     return 0;
00195   }
00196 
00197   // Forward
00198   if (rear_speed >= 0.0){
00199     double rear_speed_m_s = MIN(rear_speed, MAX_LIN_VEL); // return smaller
00200     if ((running_state_ == RunningState::FORWARD
00201          || running_state_ == RunningState::FORWARD_STOP) &&
00202         (state_.velocity[JOINT_INDEX_REAR_LEFT] >= 0
00203          || state_.velocity[JOINT_INDEX_REAR_RIGHT] >= 0)){
00204       // Now Forwarding
00205       average_spped_x = (average_spped_x + rear_speed)/2.0;
00206       u = 32767.0 + 32767.0 * average_spped_x *1.0;
00207       duty = MIN(u, 60000);
00208       duty = MAX(duty, 32767);
00209       this->writeOffsetCmd(RunningMode::FORWARD, (unsigned short)duty);
00210       running_state_ = RunningState::FORWARD;
00211       //ROS_INFO("ROBOT_STASIS_FORWARD");
00212     }else{
00213       // Now Backing
00214       // Need to stop once.
00215       duty = 32767; // STOP
00216       this->writeOffsetCmd(RunningMode::FORWARD, duty);
00217       average_spped_x = 0;
00218 
00219       if ((state_.velocity[JOINT_INDEX_REAR_LEFT] == 0.0
00220            && state_.velocity[JOINT_INDEX_REAR_RIGHT] == 0.0 )){
00221         running_state_ = RunningState::FORWARD_STOP;
00222         forward_stop_cnt = 0;
00223         duty = 32767;
00224         this->writeOffsetCmd(RunningMode::FORWARD, duty);
00225         for (int i = 0; i < 300; ++i){ usleep(1000); }
00226         //ROS_INFO("ROBOT_STASIS_FORWARD_STOP");
00227       }else{
00228         running_state_ = RunningState::OTHERWISE;
00229         forward_stop_cnt++;
00230         //ROS_INFO("ROBOT_STASIS_OTHERWISE");
00231       }
00232     }
00233   }else{
00234     // (rear_speed < 0) -> Back
00235     average_spped_x = 0;
00236     if (running_state_ == RunningState::BACK_STOP ||
00237         running_state_ == RunningState::BACK){
00238       // Now backing
00239       duty = 60000; // Back is constant speed
00240       this->writeOffsetCmd(RunningMode::BACK, duty);
00241       running_state_ = RunningState::BACK;
00242       //ROS_INFO("ROBOT_STASIS_BACK");
00243     }else{
00244       // Now forwarding
00245       if (back_stop_cnt >= 10){
00246         running_state_ = RunningState::BACK_STOP;
00247         back_stop_cnt = 0;
00248         duty = 32767; // STOP
00249         this->writeOffsetCmd(RunningMode::BACK, duty);
00250         for (int i = 0; i < 300; ++i){ usleep(1000); }
00251         //ROS_INFO("ROBOT_STASIS_BACK_STOP");
00252       }else{
00253         usleep(50000);
00254         duty = 32767; // STOP
00255         this->writeOffsetCmd(RunningMode::FORWARD, duty);
00256         running_state_ = RunningState::OTHERWISE;
00257         back_stop_cnt++;
00258         //ROS_INFO("ROBOT_STASIS_OTHERWISE");
00259       }
00260     }
00261   }
00262 }
00263 
00264 int IxisImcs01Driver::writeOffsetCmd(RunningMode mode,
00265                                      unsigned short duty)
00266 {
00267   switch (mode) {
00268     case RunningMode::FORWARD : {
00269       //ROS_INFO_STREAM("RunningMode::FORWARD");
00270       cmd_ccmd_.offset[0] = 65535;
00271       //cmd_ccmd_.offset[0] = 32767;
00272       break;
00273     }
00274     case RunningMode::BACK : {
00275       //ROS_INFO_STREAM("RunningMode::BACK");
00276       cmd_ccmd_.offset[0] = 32767;
00277       //cmd_ccmd_.offset[1] = 65535;
00278       break;
00279     }
00280     default:
00281       break;
00282   }
00283   cmd_ccmd_.offset[1] = duty;
00284   //ROS_INFO_STREAM("duty : " << duty);
00285   std::lock_guard<std::mutex> lck {communication_mutex_};
00286   if (write(imcs01_fd_, &cmd_ccmd_, sizeof(cmd_ccmd_)) < 0){
00287     ROS_ERROR_STREAM("iMCs01 write fail.");
00288     return -1;
00289   }else{
00290     return 0;
00291   }
00292 }


cirkit_unit03_base
Author(s): CIR-KIT
autogenerated on Thu Jun 6 2019 21:08:13