evarobot_driver.cpp
Go to the documentation of this file.
00001 
00008 #include "evarobot_driver/evarobot_driver.h"
00009 
00010 int i_error_code;
00011 
00012 IMDRIVER::IMDRIVER(double d_limit_voltage,
00013                    float f_max_lin_vel,
00014                    float f_max_ang_vel,
00015                    float f_wheel_separation,
00016                    float f_wheel_diameter,
00017                    double d_frequency,
00018                    unsigned int u_i_counts,
00019                    double d_duty,
00020                    int i_mode,
00021                    boost::shared_ptr< IMGPIO > * m1_in,
00022                    boost::shared_ptr< IMGPIO > * m2_in,
00023                    IMGPIO * m1_en,
00024                    IMGPIO * m2_en,
00025                    IMADC * adc,
00026                    ros::ServiceClient & client,
00027                    double _timeout):b_left_motor_error(false), b_right_motor_error(false), d_timeout(_timeout), b_motor_error(false)
00028 {
00029     this->client = client;
00030     this->adc = adc;
00031     this->d_limit_voltage = d_limit_voltage;
00032 
00033     this->f_left_motor_voltage = 0.0;
00034     this->f_right_motor_voltage = 0.0;
00035 
00036         this->u_i_counts = u_i_counts;
00037         this->i_const_count =  (u_i_counts - 1) / this->f_max_lin_vel;
00038         
00039         this->pwm = new IMPWM(d_frequency, u_i_counts, d_duty, i_mode);
00040 
00041         this->m1_in = m1_in;
00042         this->m2_in = m2_in;
00043         this->m1_en = m1_en;
00044         this->m2_en = m2_en;
00045 
00046     for(int i = 0; i < 2; i++)
00047         this->m1_in[i]->SetPinDirection(IMGPIO::OUTPUT);
00048 
00049     for(int i = 0; i < 2; i++)
00050         this->m2_in[i]->SetPinDirection(IMGPIO::OUTPUT);
00051 
00052     im_msgs::SetRGB srv;
00053 
00054     srv.request.times = -1;
00055     srv.request.mode = 0;
00056     srv.request.frequency = 1.0;
00057     srv.request.color = 0;
00058 
00059     if(this->client.call(srv) == 0)
00060     {
00061         ROS_INFO(GetErrorDescription(-77).c_str());
00062         i_error_code = -77;
00063     }
00064 
00065     // enable motors
00066     this->Enable();
00067 
00068 }
00069 
00070 IMDRIVER::~IMDRIVER()
00071 {
00072     im_msgs::SetRGB srv;
00073 
00074     srv.request.times = -1;
00075     srv.request.mode = 0;
00076     srv.request.frequency = 1.0;
00077     srv.request.color = 0;
00078 
00079     if(this->client.call(srv) == 0)
00080     {
00081         ROS_INFO(GetErrorDescription(-77).c_str());
00082         i_error_code = -77;
00083     }
00084         
00085     this->Disable();
00086     delete pwm;
00087     delete m1_en;
00088     delete m2_en;
00089     delete adc;
00090 //    delete [] m1_in;
00091 //    delete [] m2_in;
00092 
00093 
00094 }
00095 
00096 void IMDRIVER::UpdateParams()
00097 {
00098     if(b_is_received_params)
00099     {
00100         ROS_DEBUG("EvarobotDriver: Updating Driver Params...");
00101         ROS_DEBUG("EvarobotDriver: %f, %f", g_d_max_lin, g_d_max_ang);
00102         ROS_DEBUG("EvarobotDriver: %f, %f", g_d_wheel_separation, g_d_wheel_diameter);
00103 
00104         this->f_max_lin_vel = g_d_max_lin;
00105         this->f_max_ang_vel = g_d_max_ang;
00106         this->f_wheel_separation = g_d_wheel_separation;
00107         this->f_wheel_diameter = g_d_wheel_diameter;
00108 
00109         b_is_received_params = false;
00110     }
00111 }
00112 
00113 void IMDRIVER::ApplyVel(float f_left_wheel_velocity, float f_right_wheel_velocity)
00114 {
00115     if(f_left_wheel_velocity > 0)
00116     {
00117         this->m1_in[0]->SetPinValue(IMGPIO::LOW);
00118         this->m1_in[1]->SetPinValue(IMGPIO::HIGH);
00119     }
00120     else if(f_left_wheel_velocity < 0)
00121     {
00122         this->m1_in[0]->SetPinValue(IMGPIO::HIGH);
00123         this->m1_in[1]->SetPinValue(IMGPIO::LOW);
00124     }
00125     else
00126     {
00127         this->m1_in[0]->SetPinValue(IMGPIO::LOW);
00128         this->m1_in[1]->SetPinValue(IMGPIO::LOW);
00129     }
00130 
00131     if(f_right_wheel_velocity > 0)
00132     {
00133         this->m2_in[0]->SetPinValue(IMGPIO::HIGH);
00134         this->m2_in[1]->SetPinValue(IMGPIO::LOW);
00135     }
00136     else if(f_right_wheel_velocity < 0)
00137     {
00138         this->m2_in[0]->SetPinValue(IMGPIO::LOW);
00139         this->m2_in[1]->SetPinValue(IMGPIO::HIGH);
00140     }
00141     else
00142     {
00143         this->m2_in[0]->SetPinValue(IMGPIO::LOW);
00144         this->m2_in[1]->SetPinValue(IMGPIO::LOW);
00145     }
00146 
00147     int i_left_wheel_duty = int(fabs(f_left_wheel_velocity) * 255 / this->f_max_lin_vel);
00148     int i_right_wheel_duty = int(fabs(f_right_wheel_velocity) * 255 / this->f_max_lin_vel);
00149 
00150 
00151     i_left_wheel_duty = i_left_wheel_duty>=this->u_i_counts ? this->u_i_counts - 1:i_left_wheel_duty;
00152     i_right_wheel_duty = i_right_wheel_duty>=this->u_i_counts ? this->u_i_counts - 1:i_right_wheel_duty;
00153 
00154     if(i_left_wheel_duty != 0)
00155         pwm->SetDutyCycleCount(i_left_wheel_duty, 0);
00156 
00157     if(i_right_wheel_duty != 0)
00158         pwm->SetDutyCycleCount(i_right_wheel_duty, 1);
00159 
00160     /*  if(this->CheckError() == -1)
00161         {
00162                 ROS_ERROR("Failure at Left Motor.");
00163         }
00164         else if(this->CheckError() == -2)
00165         {
00166                 ROS_ERROR("Failure at Right Motor.");
00167         }
00168         else if(this->CheckError() == -3)
00169         {
00170                 ROS_ERROR("Failure at Both of Motors.");
00171         }*/
00172 }
00173 
00174 void IMDRIVER::Enable()
00175 {
00176     this->m1_en->SetPinDirection(IMGPIO::OUTPUT);
00177     this->m2_en->SetPinDirection(IMGPIO::OUTPUT);
00178 
00179     this->m1_en->SetPinValue(IMGPIO::HIGH);
00180     this->m2_en->SetPinValue(IMGPIO::HIGH);
00181 
00182     /*          this->m1_en->SetPinDirection(IMGPIO::INPUT);
00183         this->m2_en->SetPinDirection(IMGPIO::INPUT);*/
00184 }
00185 
00186 void IMDRIVER::Disable()
00187 {
00188     this->m1_en->SetPinDirection(IMGPIO::OUTPUT);
00189     this->m2_en->SetPinDirection(IMGPIO::OUTPUT);
00190 
00191     this->m1_en->SetPinValue(IMGPIO::LOW);
00192     this->m2_en->SetPinValue(IMGPIO::LOW);
00193 
00194 }
00195 
00196 int IMDRIVER::CheckError()
00197 {
00198     int i_ret = 0;
00199 
00200     string str_m1_data;
00201     string str_m2_data;
00202 
00203     this->m1_en->GetPinValue(str_m1_data);
00204     this->m2_en->GetPinValue(str_m2_data);
00205 
00206     if(str_m1_data == IMGPIO::LOW)
00207     {
00208         --i_ret;
00209     }
00210 
00211     if(str_m2_data == IMGPIO::LOW)
00212     {
00213         --i_ret;
00214     }
00215 
00216     return i_ret;
00217 }
00218 
00219 im_msgs::Voltage IMDRIVER::GetMotorVoltage() const
00220 {
00221     im_msgs::Voltage ret;
00222     ret.left_motor = this->f_left_motor_voltage;
00223     ret.right_motor = this->f_right_motor_voltage;
00224 
00225     return ret;
00226 }
00227 
00228 bool IMDRIVER::CheckMotorCurrent()
00229 {
00230     bool b_ret = true;
00231 
00232     this->f_left_motor_voltage = (float)(this->adc->ReadMotorChannel(0)*5.0/4096.0);
00233     this->f_right_motor_voltage = (float)(this->adc->ReadMotorChannel(1)*5.0/4096.0);
00234 
00235     ROS_DEBUG("EvarobotDriver: LEFT MOTOR: -- %f", this->f_left_motor_voltage);
00236     ROS_DEBUG("EvarobotDriver: RIGHT MOTOR: -- %f", this->f_right_motor_voltage);
00237 
00238     if(this->f_left_motor_voltage >= this->d_limit_voltage)
00239     {
00240         ROS_INFO(GetErrorDescription(-78).c_str());
00241         i_error_code = -78;
00242         b_ret = false;
00243         this->b_motor_error = true;
00244         this->b_left_motor_error = true;
00245     }
00246 
00247     if(this->f_right_motor_voltage >= this->d_limit_voltage)
00248     {
00249         ROS_INFO(GetErrorDescription(-79).c_str());
00250         i_error_code = -79;
00251         b_ret = false;
00252         this->b_motor_error = true;
00253         this->b_right_motor_error = true;
00254     }
00255 
00256     if(!b_ret)
00257     {
00258         im_msgs::SetRGB srv;
00259 
00260         srv.request.times = -1;
00261         srv.request.mode = 8;
00262         srv.request.frequency = -1;
00263         srv.request.color = 0;
00264 
00265         if(this->client.call(srv) == 0)
00266         {
00267             ROS_INFO(GetErrorDescription(-77).c_str());
00268             i_error_code = -77;
00269         }
00270 
00271         this->Disable();
00272     }
00273     /*  else if(b_ret & this->b_motor_error)
00274         {
00275                 this->b_motor_error = false;
00276                 im_msgs::SetRGB srv;
00277 
00278                 srv.request.times = -1;
00279                 srv.request.mode = 0;
00280                 srv.request.frequency = 1.0;
00281                 srv.request.color = 0;
00282 
00283                 if(this->client.call(srv) == 0)
00284                 {
00285                         ROS_ERROR("Failed to call service evarobot_rgb/SetRGB");
00286                 }
00287 
00288                 //this->Enable();
00289 
00290         }*/
00291 
00292     return b_ret;
00293 }
00294 
00295 void IMDRIVER::ProduceDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00296 {
00297     if(i_error_code < 0)
00298     {
00299         stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, GetErrorDescription(i_error_code).c_str());
00300         i_error_code = 0;
00301     }
00302     else
00303     {
00304         stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Motors are OK!");
00305     }
00306 
00307     stat.add("Right Motor Voltage", this->f_right_motor_voltage);
00308     stat.add("Left Motor Voltage", this->f_left_motor_voltage);
00309 }
00310 
00311 bool IMDRIVER::CheckTimeout()
00312 {
00313     double dt;
00314 
00315     dt = (ros::Time::now() - this->curr_vel_time).toSec();
00316 
00317     if(dt > this->d_timeout)
00318     {
00319         ROS_INFO(GetErrorDescription(-80).c_str());
00320         i_error_code = -80;
00321         this->ApplyVel(0.0, 0.0);
00322         b_timeout_err = true;
00323     }
00324     else if(dt < 0)
00325     {
00326         ROS_INFO(GetErrorDescription(-81).c_str());
00327         i_error_code = -81;
00328         this->ApplyVel(0.0, 0.0);
00329         b_timeout_err = true;
00330     }
00331     else
00332     {
00333         b_timeout_err = false;
00334     }
00335 
00336     return this->b_timeout_err;
00337 }
00338 
00339 void IMDRIVER::CallbackWheelVel(const im_msgs::WheelVel::ConstPtr & msg)
00340 {
00341     float f_left_wheel_velocity = msg->left_vel;
00342     float f_right_wheel_velocity = msg->right_vel;
00343     this->curr_vel_time = msg->header.stamp;
00344 
00345     // UpdateParams
00346     this->UpdateParams();
00347 
00348     // ApplyVel
00349     this->ApplyVel(f_left_wheel_velocity, f_right_wheel_velocity);
00350 }
00351 
00352 void CallbackReconfigure(evarobot_driver::ParamsConfig &config, uint32_t level)
00353 {
00354     b_is_received_params = true;
00355 
00356     g_d_max_lin = config.maxLinearVel;
00357     g_d_max_ang = config.maxAngularVel;
00358     g_d_wheel_separation = config.wheelSeparation;
00359     g_d_wheel_diameter = config.wheelDiameter;
00360 
00361 }
00362 
00363 int main(int argc, char **argv)
00364 {
00365         unsigned char u_c_spi_mode;
00366         
00367   ros::init(argc, argv, "/evarobot_driver");
00368   ros::NodeHandle n;
00369   
00370   string str_driver_path;
00371   
00372   double d_max_lin_vel;
00373   double d_max_ang_vel;
00374   
00375   double d_wheel_diameter;
00376   double d_wheel_separation;
00377   
00378   double d_frequency;
00379   double d_duty;
00380   double d_limit_voltage;
00381   
00382   double d_timeout;
00383     
00384   int i_counts;
00385   int i_mode;
00386   int i_m1_in1, i_m1_in2, i_m1_en;
00387   int i_m2_in1, i_m2_in2, i_m2_en;
00388   
00389   int i_spi_mode, i_spi_speed, i_spi_bits, i_adc_bits;
00390   
00391   // ADC & SPI Params
00392   n.param<string>("evarobot_driver/driverPath", str_driver_path, "/dev/spidev0.1");
00393   n.param("evarobot_driver/spiMode", i_spi_mode, 0);
00394   n.param("evarobot_driver/spiSpeed", i_spi_speed, 1000000);
00395   n.param("evarobot_driver/spiBits", i_spi_bits, 8);
00396   n.param("evarobot_driver/adcBits", i_adc_bits, 12);
00397   // ------ ---- --- -- - -
00398   
00399   n.param<int>("evarobot_driver/M1_IN1", i_m1_in1, 1);
00400   n.param<int>("evarobot_driver/M1_IN2", i_m1_in2, 12);
00401   n.param<int>("evarobot_driver/M1_EN", i_m1_en, 5);
00402 
00403   
00404   n.param<int>("evarobot_driver/M2_IN1", i_m2_in1, 0);
00405   n.param<int>("evarobot_driver/M2_IN2", i_m2_in2, 19);
00406   n.param<int>("evarobot_driver/M2_EN", i_m2_en, 6);
00407 
00408   n.param<double>("evarobot_driver/limitVoltage", d_limit_voltage, 0.63);
00409   n.param<double>("evarobot_driver/timeout", d_timeout, 0.5);
00410   
00411         if(!n.getParam("evarobot_driver/maxLinearVel", d_max_lin_vel))
00412         {
00413                         ROS_INFO(GetErrorDescription(-82).c_str());
00414                         i_error_code = -82;
00415         }
00416 
00417         if(!n.getParam("evarobot_driver/maxAngularVel", d_max_ang_vel))
00418         {
00419                         ROS_INFO(GetErrorDescription(-83).c_str());
00420                         i_error_code = -83;
00421         }
00422 
00423         if(!n.getParam("evarobot_driver/wheelSeparation", d_wheel_separation))
00424         {
00425                         ROS_INFO(GetErrorDescription(-84).c_str());
00426                         i_error_code = -84;
00427         }
00428 
00429         if(!n.getParam("evarobot_driver/wheelDiameter", d_wheel_diameter))
00430         {
00431                         ROS_INFO(GetErrorDescription(-85).c_str());
00432                         i_error_code = -85;
00433         }
00434 
00435         if(!n.getParam("evarobot_driver/pwmFrequency", d_frequency))
00436         {
00437                         ROS_INFO(GetErrorDescription(-86).c_str());
00438                         i_error_code = -86;
00439         }
00440 
00441         if(!n.getParam("evarobot_driver/pwmDuty", d_duty))
00442         {
00443                         ROS_INFO(GetErrorDescription(-87).c_str());
00444                         i_error_code = -87;
00445         }
00446 
00447         if(!n.getParam("evarobot_driver/pwmCounts", i_counts))
00448         {
00449                         ROS_INFO(GetErrorDescription(-88).c_str());
00450                         i_error_code = -88;
00451         }
00452 
00453         if(!n.getParam("evarobot_driver/pwmMode", i_mode))
00454         {
00455                         ROS_INFO(GetErrorDescription(-91).c_str());
00456                         i_error_code = -91;
00457         }
00458   
00459   // PWMMODE = 1; --- MSMODE = 2
00460         if(i_mode != IMPWM::PWMMODE && i_mode != IMPWM::MSMODE)
00461         {
00462                         ROS_INFO(GetErrorDescription(-89).c_str());
00463                         i_error_code = -89;
00464         }
00465   
00466   // Dynamic Reconfigure
00467   dynamic_reconfigure::Server<evarobot_driver::ParamsConfig> srv;
00468   dynamic_reconfigure::Server<evarobot_driver::ParamsConfig>::CallbackType f;
00469   f = boost::bind(&CallbackReconfigure, _1, _2);
00470   srv.setCallback(f);
00472 
00473         switch(i_spi_mode)
00474         {       
00475                 case 0:
00476                 {
00477                         u_c_spi_mode = SPI_MODE_0;
00478                         break;
00479                 }
00480 
00481                 case 1:
00482                 {
00483                         u_c_spi_mode = SPI_MODE_1;
00484                         break;
00485                 }
00486 
00487                 case 2:
00488                 {
00489                         u_c_spi_mode = SPI_MODE_2;
00490                         break;
00491                 }
00492 
00493                 case 3:
00494                 {
00495                         u_c_spi_mode = SPI_MODE_3;
00496                         break;
00497                 }
00498 
00499                 default:
00500                 {
00501                         ROS_INFO(GetErrorDescription(-90).c_str());
00502                         i_error_code = -90;
00503                 }
00504         }
00505         
00506         IMSPI * p_im_spi;
00507         IMADC * p_im_adc;
00508         boost::shared_ptr<IMGPIO> gpio_m1_in[2];
00509         boost::shared_ptr<IMGPIO> gpio_m2_in[2];
00510         IMGPIO * gpio_m1_en;
00511         IMGPIO * gpio_m2_en;
00512 
00513         try {
00514                         // Creating spi and adc objects.
00515                         p_im_spi = new IMSPI(str_driver_path, u_c_spi_mode, i_spi_speed, i_spi_bits);
00516                         p_im_adc = new IMADC(p_im_spi, i_adc_bits);
00517         } catch(int e) {
00518                         ROS_INFO(GetErrorDescription(e).c_str());
00519                         i_error_code = e;
00520                         return 0;
00521         }
00522 
00523         try {
00524                         stringstream ss1, ss2;
00525 
00526                         ss1 << i_m1_in1;
00527                         ss2 << i_m1_in2;
00528 
00529                         gpio_m1_in[0] = boost::shared_ptr< IMGPIO >( new IMGPIO(ss1.str()) );
00530                         gpio_m1_in[1] = boost::shared_ptr< IMGPIO >( new IMGPIO(ss2.str()) );
00531                         
00532 ss1.str("");
00533                         ss2.str("");
00534                         ss1 << i_m2_in1;
00535                         ss2 << i_m2_in2;
00536 
00537                         gpio_m2_in[0] = boost::shared_ptr< IMGPIO >( new IMGPIO(ss1.str()) );
00538                         gpio_m2_in[1] = boost::shared_ptr< IMGPIO >( new IMGPIO(ss2.str()) );
00539         
00540 ss1.str("");
00541                         ss2.str("");
00542                         ss1 << i_m1_en;
00543                         ss2 << i_m2_en;
00544 
00545                         gpio_m1_en = new IMGPIO(ss1.str());
00546                         gpio_m2_en = new IMGPIO(ss2.str());
00547         } catch(int e) {
00548                         ROS_INFO(GetErrorDescription(e).c_str());
00549                         i_error_code = e;
00550                         return 0;
00551         }
00552 
00553         ros::ServiceClient client = n.serviceClient<im_msgs::SetRGB>("evarobot_rgb/SetRGB");
00554 
00555         IMDRIVER imdriver(d_limit_voltage, (float)d_max_lin_vel, (float)d_max_ang_vel,
00556                                                                                 (float)d_wheel_separation, (float)d_wheel_diameter,
00557                                                                                 d_frequency, i_counts, d_duty, i_mode,
00558                                                                                 gpio_m1_in, gpio_m2_in, gpio_m1_en, gpio_m2_en, p_im_adc, client, d_timeout);
00559 
00560         ros::Subscriber sub = n.subscribe("cntr_wheel_vel", 2, &IMDRIVER::CallbackWheelVel, &imdriver);
00561         ros::Publisher pub = n.advertise<im_msgs::Voltage>("motor_voltages", 1);
00562 
00563         // Diagnostics
00564         diagnostic_updater::Updater updater;
00565         updater.setHardwareID("None");
00566         updater.add("MotorVoltages", &imdriver, &IMDRIVER::ProduceDiagnostics);
00567 
00568         if(sub.getNumPublishers() < 1)
00569         {
00570                         ROS_WARN("No appropriate subscriber.");
00571         }
00572 
00573         // Define frequency
00574         ros::Rate loop_rate(10.0);
00575 
00576         while(ros::ok())
00577         {               
00578                         imdriver.CheckMotorCurrent();
00579                         imdriver.CheckTimeout();
00580                         pub.publish(imdriver.GetMotorVoltage());
00581 
00582                         updater.update();
00583                         ros::spinOnce();
00584                         loop_rate.sleep();
00585         }
00586   
00587   return 0;
00588 }


evarobot_driver
Author(s): Mehmet Akcakoca
autogenerated on Fri Feb 12 2016 01:15:19