evarobot_odometry.cpp
Go to the documentation of this file.
00001 #include "evarobot_odometry/evarobot_odometry.h"
00002 
00003 #include <dynamic_reconfigure/server.h>
00004 #include <evarobot_odometry/ParamsConfig.h>
00005 
00006 bool b_is_received_params = false;
00007 
00008 bool b_reset_odom = false;
00009 double d_wheel_separation;
00010 double d_height;
00011 int i_gear_ratio;
00012 int i_cpr;
00013 double d_wheel_diameter;
00014 
00015 int i_error_code = 0;
00016         
00017 void CallbackReconfigure(evarobot_odometry::ParamsConfig &config, uint32_t level)
00018 {
00019    b_is_received_params = true;        
00020    
00021    d_wheel_separation = config.wheelSeparation;
00022    d_height = config.height;
00023    i_gear_ratio = config.gearRatio;
00024    i_cpr = config.CPR;
00025    d_wheel_diameter = config.wheelDiameter;
00026 }
00027 
00028 bool CallbackResetOdom(std_srvs::Empty::Request& request, std_srvs::Empty::Response& response)
00029 {
00030         ROS_DEBUG("EvarobotOdometry: Reset Odometry");
00031         b_reset_odom = true;
00032         return true;
00033 }
00034 
00035 
00036 
00037 void ProduceDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00038 {
00039     if(i_error_code<0)
00040     {
00041         stat.summaryf(diagnostic_msgs::DiagnosticStatus::ERROR, "%s", GetErrorDescription(i_error_code).c_str());
00042         i_error_code = 0;
00043     }
00044     else
00045     {
00046                 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "EvarobotOdometry: No problem.");
00047     }
00048 }
00049 
00050 int main(int argc, char **argv)
00051 {
00052         int i_fd;
00053         double d_frequency;
00054         double d_min_freq, d_max_freq;
00055     stringstream ss;
00056         
00057         string str_device_path;
00058         
00059         ros::init(argc, argv, "/evarobot_odometry");
00060         ros::NodeHandle n;
00061 
00062         n.param<string>("evarobot_odometry/devicePath", str_device_path, "/dev/evarobotEncoder");
00063         n.param("evarobot_odometry/minFreq", d_min_freq, 0.2);
00064         n.param("evarobot_odometry/maxFreq", d_max_freq, 10.0);
00065         
00066         if(!n.getParam("evarobot_odometry/wheelSeparation", d_wheel_separation))
00067         {
00068           ROS_INFO(GetErrorDescription(-108).c_str());
00069         i_error_code = -108;
00070         }
00071         
00072         if(!n.getParam("evarobot_odometry/height", d_height))
00073         {
00074           ROS_INFO(GetErrorDescription(-109).c_str());
00075         i_error_code = -109;
00076         }       
00077         
00078         if(!n.getParam("evarobot_odometry/frequency", d_frequency))
00079         {
00080           ROS_INFO(GetErrorDescription(-110).c_str());
00081         i_error_code = -110;
00082         }       
00083         
00084         if(!n.getParam("evarobot_odometry/gearRatio", i_gear_ratio))
00085         {
00086           ROS_INFO(GetErrorDescription(-111).c_str());
00087         i_error_code = -111;
00088         }       
00089         
00090         if(!n.getParam("evarobot_odometry/CPR", i_cpr))
00091         {
00092           ROS_INFO(GetErrorDescription(-112).c_str());
00093         i_error_code = -112;
00094         }       
00095         
00096         if(!n.getParam("evarobot_odometry/wheelDiameter", d_wheel_diameter))
00097         {
00098           ROS_INFO(GetErrorDescription(-113).c_str());
00099         i_error_code = -113;
00100         }
00101                 
00102         
00103   realtime_tools::RealtimePublisher<nav_msgs::Odometry> * pose_pub = new realtime_tools::RealtimePublisher<nav_msgs::Odometry>(n, "odom", 10);
00104   realtime_tools::RealtimePublisher<im_msgs::WheelVel> * vel_pub = new realtime_tools::RealtimePublisher<im_msgs::WheelVel>(n, "wheel_vel", 10);
00105 
00106 
00107         
00108         ros::ServiceServer service = n.advertiseService("evarobot_odometry/reset_odom", CallbackResetOdom);
00109         
00110         ros::Rate loop_rate(d_frequency);
00111 
00112         ros::Time read_time = ros::Time::now();
00113         ros::Duration dur_time;
00114 
00115   // Dynamic Reconfigure
00116   dynamic_reconfigure::Server<evarobot_odometry::ParamsConfig> srv;
00117   dynamic_reconfigure::Server<evarobot_odometry::ParamsConfig>::CallbackType f;
00118   f = boost::bind(&CallbackReconfigure, _1, _2);
00119   srv.setCallback(f);
00121   
00122   // Diagnostics
00123         diagnostic_updater::Updater updater;
00124         updater.setHardwareID("none");
00125         updater.add("evarobot_odometry", &ProduceDiagnostics);
00126                 
00127         diagnostic_updater::HeaderlessTopicDiagnostic pub_freq("odom", updater,
00128                                                                                         diagnostic_updater::FrequencyStatusParam(&d_min_freq, &d_max_freq, 0.1, 10));
00129     
00130         char c_read_buf[31], c_write_buf[100];
00131         
00132 
00133         geometry_msgs::Pose2D odom_pose;
00134         geometry_msgs::Pose2D delta_odom_pose;
00135 
00136         string str_data;
00137 
00138         float f_left_read = 0.0, f_right_read = 0.0;
00139         float f_left_read_last = 0.0, f_right_read_last = 0.0; 
00140 
00141                                                                                 
00142         float covariance[36] =  {1, 0, 0, 0, 0, 0,  // covariance on gps_x
00143                                                                                 0, 1, 0, 0, 0, 0,  // covariance on gps_y
00144                                                                                 0, 0, 1, 0, 0, 0,  // covariance on gps_z
00145                                                                                 0, 0, 0, 1, 0, 0,  // large covariance on rot x
00146                                                                                 0, 0, 0, 0, 1, 0,  // large covariance on rot y
00147                                                                                 0, 0, 0, 0, 0, 1};  // large covariance on rot z        
00148         for(int i = 0; i < 36; i++)
00149         {
00150                 pose_pub->msg_.pose.covariance[i] = covariance[i];
00151         }               
00152         
00153         // Opening the encoder.
00154         i_fd = open(str_device_path.c_str(), O_RDWR);
00155         
00156         // Cleaning the encoder.
00157         //    write(fd, write_buf, sizeof(write_buf));
00158         write(i_fd, "clean", 5);
00159         
00160         
00161         if(i_fd < 0)
00162         {
00163                 ROS_INFO(GetErrorDescription(-114).c_str());
00164         i_error_code = -114;
00165                 exit(-1);
00166         }
00167 
00168         while (ros::ok())
00169         {
00170                 if(b_is_received_params)
00171                 {
00172                         ROS_DEBUG("EvarobotOdometry: Updating Odometry Params...");
00173                         b_is_received_params = false;
00174                 }
00175                 
00176                 if(b_reset_odom)
00177                 {
00178                         ROS_DEBUG("EvarobotOdometry: Resetting Odometry");
00179                         
00180                         write(i_fd, "clean", 5);
00181                         
00182                         f_left_read = 0.0;
00183                         f_right_read = 0.0;
00184                         f_left_read_last = 0.0;
00185                         f_right_read_last = 0.0;
00186                         
00187                         odom_pose.x = 0.0;
00188                         odom_pose.y = 0.0;
00189                         odom_pose.theta = 0.0;
00190                         
00191                         delta_odom_pose.x = 0.0;
00192                         delta_odom_pose.y = 0.0;
00193                         delta_odom_pose.theta = 0.0;
00194                         
00195                         b_reset_odom = false;
00196                 }
00197                 
00198                 // Reading encoder.
00199                 read(i_fd, c_read_buf, sizeof(c_read_buf));
00200                 str_data = c_read_buf; 
00201 
00202                 dur_time = ros::Time::now() - read_time;
00203 
00204                 read_time = ros::Time::now();
00205 
00206                 // Parse left and right rpms.
00207                 std::size_t found = str_data.find("_");
00208                 if (found != std::string::npos)
00209                 {
00210                         f_left_read = atof(str_data.substr(0, found).c_str());
00211                         f_right_read = atof(str_data.substr(found+1).c_str());
00212                         str_data = "";
00213                 }       
00214 
00215                 float f_delta_sr = 0.0, f_delta_sl = 0.0, f_delta_s = 0.0; 
00216 
00217                 // Dönüş sayısı değişimi hesaplanıyor.
00218                 f_delta_sr =  PI * d_wheel_diameter * (f_right_read - f_right_read_last) / (i_gear_ratio * i_cpr);
00219                 f_delta_sl =  PI * d_wheel_diameter * (f_left_read - f_left_read_last) / (i_gear_ratio * i_cpr);
00220 
00221                 // Oryantasyondaki değişim hesaplanıyor.
00222                 delta_odom_pose.theta = (f_delta_sr - f_delta_sl) / d_wheel_separation;
00223                 f_delta_s = (f_delta_sr + f_delta_sl) / 2;
00224 
00225                 // x ve y eksenlerindeki yer değiştirme hesaplanıyor.
00226                 delta_odom_pose.x = f_delta_s * cos(odom_pose.theta + delta_odom_pose.theta * 0.5);
00227                 delta_odom_pose.y = f_delta_s * sin(odom_pose.theta + delta_odom_pose.theta * 0.5);
00228 
00229                 // Calculate new positions.
00230                 odom_pose.x += delta_odom_pose.x;
00231                 odom_pose.y += delta_odom_pose.y;
00232                 odom_pose.theta += delta_odom_pose.theta;
00233 
00234                 // Yeni dönüş değerleri son okunan olarak atanıyor.
00235                 f_right_read_last = f_right_read;
00236                 f_left_read_last = f_left_read;
00237 
00238                         
00239                 // Yayınlanacak Posizyon Verisi dolduruluyor.
00240                 pose_pub->msg_.pose.pose.position.x = odom_pose.x;
00241                 pose_pub->msg_.pose.pose.position.y = odom_pose.y;
00242                 pose_pub->msg_.pose.pose.position.z = (float)d_height;
00243 
00244                 pose_pub->msg_.pose.pose.orientation.x = 0.0;
00245                 pose_pub->msg_.pose.pose.orientation.y = 0.0;
00246                 pose_pub->msg_.pose.pose.orientation.z = sin(0.5 * odom_pose.theta); 
00247                 pose_pub->msg_.pose.pose.orientation.w = cos(0.5 * odom_pose.theta);
00248 
00249                 float f_lin_vel = 0, f_ang_vel = 0;
00250                 float f_lin_vel_right = 0, f_lin_vel_left = 0;
00251 
00252                 ROS_DEBUG_STREAM("EvarobotOdometry: dur_time: " << dur_time.toSec());
00253 
00254                 if(dur_time.toSec() > 0)
00255                 {               
00256                         f_lin_vel_right = f_delta_sr / dur_time.toSec();
00257                         f_lin_vel_left = f_delta_sl / dur_time.toSec();
00258                         
00259                         ROS_DEBUG_STREAM("EvarobotOdometry: VEl_LEFT: " << f_lin_vel_left << "  Vel_right: " << f_lin_vel_right << " dur: " << dur_time.toSec());
00260 
00261                         
00262                         f_lin_vel = (f_lin_vel_right + f_lin_vel_left) / 2.0;
00263                         f_ang_vel = (f_lin_vel_right - f_lin_vel_left) / d_wheel_separation;
00264                 }
00265                 else
00266                 {
00267                         ROS_INFO(GetErrorDescription(-115).c_str());
00268                         i_error_code = -115;
00269                 }
00270                 
00271                 ss.str("");
00272                 ss << n.resolveName(n.getNamespace(), true) << "/wheel_link";
00273                 
00274                 vel_pub->msg_.header.frame_id = ss.str();
00275                 vel_pub->msg_.header.stamp = ros::Time::now();
00276                 vel_pub->msg_.left_vel = f_lin_vel_left;
00277                 vel_pub->msg_.right_vel = f_lin_vel_right;
00278 
00279                 if (vel_pub->trylock())
00280                 {
00281                         vel_pub->unlockAndPublish();
00282                 }                       
00283                 
00284                 // Yayınlacak Hız Verisi dolduruluyor.
00285                 pose_pub->msg_.twist.twist.linear.x = f_lin_vel;
00286                 pose_pub->msg_.twist.twist.linear.y = 0.0;
00287                 pose_pub->msg_.twist.twist.linear.z = 0.0;
00288 
00289                 pose_pub->msg_.twist.twist.angular.x = 0.0;
00290                 pose_pub->msg_.twist.twist.angular.y = 0.0;
00291                 pose_pub->msg_.twist.twist.angular.z = f_ang_vel;
00292 
00293                 //uint32
00294                 //msg.header.seq
00295                 // ROS Zaman etiketi topiğe basılıyor. (time)
00296                 pose_pub->msg_.header.stamp = ros::Time::now();
00297 
00298                 // Odometry verisinin frame id'si yazılıyor. (string)
00299                 ss.str("");
00300                 ss << n.resolveName(n.getNamespace(), true) << "/odom";
00301                 pose_pub->msg_.header.frame_id = ss.str();
00302                 
00303                 ss.str("");
00304                 ss << n.resolveName(n.getNamespace(), true) << "/base_link";
00305                 pose_pub->msg_.child_frame_id = ss.str();
00306                 
00307                 // Veri topikten basılıyor.
00308                 if (pose_pub->trylock())
00309                 {
00310                         pose_pub->unlockAndPublish();
00311                 }                       
00312                 pub_freq.tick();
00313 
00314                 ros::spinOnce();
00315                 updater.update();
00316                 // Frekansı tutturmak için uyutuluyor.
00317                 loop_rate.sleep();
00318         }
00319 
00320         // Enkoder sürücü dosyası kapatılıyor.
00321         close(i_fd);
00322 
00323         return 0;
00324 }


evarobot_odometry
Author(s): Mehmet Akcakoca
autogenerated on Fri Feb 12 2016 01:15:27