Computing odometry from encoder ticks

In this section, we will see the C++ interpretation of the diff_tf.py node,
which subscribes the encoder data and computes the odometry, and publishes
the odometry and tf of the robot. We can see the C++ interpretation of this node, called diff_tf.cpp, which can be found in the src folder of a package named chefbot_navig_cpp.

Discussed next are the important code snippets of this code and their explanations. The following code snippet is the constructor of the class Odometry_calc. This class contains the definition of computing odometry. The following code declares the subscriber for the left and right wheel encoders along with the publisher for odom value:

Odometry_calc::Odometry_calc(){ 
 
  //Initialize variables used in the node 
   init_variables(); 
 
  ROS_INFO("Started odometry computing node"); 
 
  //Subscribing left and right wheel encoder values 
  l_wheel_sub = n.subscribe("/lwheel",10, &Odometry_calc::leftencoderCb, this); 
   
  r_wheel_sub = n.subscribe("/rwheel",10, &Odometry_calc::rightencoderCb, this); 
 
   //Creating a publisher for odom 
    odom_pub = n.advertise<nav_msgs::Odometry>("odom", 50);    
     
 
  //Retrieving parameters of this node 
  get_node_params(); 
}   

The following code is the update loop of computing odometry. It computes the delta distance moved and the angle rotated by the robot using the encoder values, base width of the robot, and ticks per meter of the encoder. After calculating the delta distance and the delta theta, we can compute the final x, y, and theta using the standard differential drive robot equations.

  if ( now > t_next) { 
 
    elapsed = now.toSec() - then.toSec();  
 
    if(enc_left == 0){ 
      d_left = 0; 
      d_right = 0; 
    } 
    else{ 
      d_left = (left - enc_left) / ( ticks_meter); 
      d_right = (right - enc_right) / ( ticks_meter); 
    } 
     
    enc_left = left; 
    enc_right = right; 
 
    d = (d_left + d_right ) / 2.0; 
 
    th = ( d_right - d_left ) / base_width; 
     
    dx = d /elapsed; 
 
    dr = th / elapsed; 
 
    if ( d != 0){ 
 
                  x = cos( th ) * d; 
                  y = -sin( th ) * d; 
 
                  // calculate the final position of the robot 
                  x_final = x_final + ( cos( theta_final ) * x - sin( theta_final ) * y ); 
                  y_final = y_final + ( sin( theta_final ) * x + cos( theta_final ) * y ); 
 
      } 
       if( th != 0) 
              theta_final = theta_final + th; 

After computing the robot position and the orientation from the preceding code snippet, we can feed the odom values to the odom message header and in the tf header, which will publish the topics in /odom and /tf.

        geometry_msgs::Quaternion odom_quat ; 
 
        odom_quat.x = 0.0; 
        odom_quat.y = 0.0; 
        odom_quat.z = 0.0; 
 
          odom_quat.z = sin( theta_final / 2 );   
          odom_quat.w = cos( theta_final / 2 ); 
 
        //first, we'll publish the transform over tf 
        geometry_msgs::TransformStamped odom_trans; 
        odom_trans.header.stamp = now; 
        odom_trans.header.frame_id = "odom"; 
        odom_trans.child_frame_id = "base_footprint"; 
 
        odom_trans.transform.translation.x = x_final; 
        odom_trans.transform.translation.y = y_final; 
        odom_trans.transform.translation.z = 0.0; 
        odom_trans.transform.rotation = odom_quat; 
 
        //send the transform 
        odom_broadcaster.sendTransform(odom_trans); 
 
         
        //next, we'll publish the odometry message over ROS 
        nav_msgs::Odometry odom; 
        odom.header.stamp = now; 
        odom.header.frame_id = "odom"; 
 
        //set the position 
        odom.pose.pose.position.x = x_final; 
        odom.pose.pose.position.y = y_final; 
        odom.pose.pose.position.z = 0.0; 
        odom.pose.pose.orientation = odom_quat; 
 
        //set the velocity 
        odom.child_frame_id = "base_footprint"; 
        odom.twist.twist.linear.x = dx; 
        odom.twist.twist.linear.y = 0; 
        odom.twist.twist.angular.z = dr; 
 
        //publish the message 
        odom_pub.publish(odom); 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.107.210