CanListener.cpp
Go to the documentation of this file.
00001 
00020 #include <sys/socket.h>
00021 #include <linux/sockios.h>
00022 #include <linux/can.h>
00023 #include <linux/if.h>
00024 #include "CanListener.h"
00025 #include "ros/ros.h"
00026 #include "nav_msgs/Odometry.h"
00027 #include "OwnMath.h"
00028 #include <stdlib.h>
00029 
00030 
00031 
00032 
00033 void CanListener::initalize()
00034 {
00035     //Means 1:144 gearing.
00036     impulses_per_mm_left = -152.8;
00037     impulses_per_mm_right = 152.8;
00038     //distance between left and right wheel
00039     wheel_distance = 663.0;
00040 
00041     left_average = 0;
00042     right_average = 0;
00043 
00044     //Average over X succressive measures.
00045     average_size = 25;
00046     counter = 0;
00047 }
00048 
00049 geometry_msgs::TransformStamped CanListener::getOdomTF(ros::Time current_time)
00050 {
00051 
00052     //since all odometry is 6DOF we'll need a quaternion created from yaw
00053     geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(state->getTh());
00054 
00055     geometry_msgs::TransformStamped odom_trans;
00056 
00057     odom_trans.header.stamp = current_time;
00058     odom_trans.header.frame_id = "odom";
00059     odom_trans.child_frame_id = "base_link";
00060 
00061     odom_trans.transform.translation.x = state->getX()/1000.0;
00062     odom_trans.transform.translation.y = state->getY()/1000.0;
00063     odom_trans.transform.translation.z = 0.0;
00064     odom_trans.transform.rotation = odom_quat;
00065 
00066     return odom_trans;
00067 
00068 }
00069 
00070 nav_msgs::Odometry CanListener::getOdomMsg(ros::Time current_time)
00071 {
00072 
00073     //since all odometry is 6DOF we'll need a quaternion created from yaw
00074     geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(state->getTh());
00075 
00076     nav_msgs::Odometry odom;
00077 
00078     odom.header.stamp = current_time;
00079     odom.header.frame_id = "odom";
00080 
00081     //Set the position.
00082     odom.pose.pose.position.x = state->getX()/1000.0;
00083     odom.pose.pose.position.y = state->getY()/1000.0;
00084     odom.pose.pose.position.z = 0.0;
00085     odom.pose.pose.orientation = odom_quat;
00086 
00087     //Set the velocity.
00088     odom.child_frame_id = "base_link";
00089     odom.twist.twist.linear.x = state->getVX()/1000.0;
00090     odom.twist.twist.linear.y = state->getVY()/1000.0;
00091     odom.twist.twist.angular.z = state->getVTh();
00092 
00093     return odom;
00094 
00095 }
00096 
00097 bool CanListener::gettingData()
00098 {
00099     ssize_t nbytes;
00100     nbytes = recv(state->getSocket(), &frame, sizeof(struct can_frame), MSG_DONTWAIT);
00101     if (nbytes < 0)
00102     {
00103         if (errno != EAGAIN)
00104         {
00105             ROS_ERROR("CanListener: mild_base_driving raw socket read, status %zu (%i)", nbytes, errno);
00106             exit(1);
00107         }
00108     }
00109     else if (nbytes < (int)sizeof(struct can_frame))
00110     {
00111         ROS_ERROR("CanListener: read: incomplete CAN frame of size %zu",nbytes);
00112         exit(1);
00113     }
00114     return true;
00115 }
00116 
00117 int CanListener::overflowDetection(int ticks, int ticks_old)
00118 {
00119     int max_encoder = 0xffff;
00120     if (fabs(ticks - ticks_old) > 0.5*max_encoder)
00121     {
00122         //Overflow detected left.
00123         ROS_DEBUG("CanListener: Overflow left. Old ticks_old = %i", ticks_old);
00124         if (ticks > ticks_old)
00125         {
00126             ticks_old = ticks_old + max_encoder;
00127         }
00128         else ticks_old = ticks_old - max_encoder;
00129         ROS_DEBUG("CanListener: Overflow left. New ticks_old = %i", ticks_old);
00130     }
00131     return ticks_old;
00132 }
00133 
00134 void CanListener::movingForward(double d, double d_time)
00135 {
00136     double velocity = d / d_time;
00137     double tx = state->getX()+velocity*cos(state->getTh())*d_time;
00138     double ty = state->getY()+velocity*sin(state->getTh())*d_time;
00139 
00140     state->setVX((tx-state->getX())/d_time);
00141     state->setVY((ty-state->getY())/d_time);
00142     state->setVTh(0);
00143     state->setX(tx);
00144     state->setY(ty);
00145 
00146     ROS_DEBUG("CanListener: Moving forward. velocity = %f", velocity);
00147 }
00148 
00149 void CanListener::turningInPlace(double t, double d_time)
00150 {
00151     state->setVX(0);
00152     state->setVY(0);
00153     double tth = state->getTh() + t ;
00154     state->setVTh((tth-state->getTh())/d_time);
00155     state->setTh(tth);
00156 }
00157 
00158 void CanListener::otherMovement(double d, double t, double d_time)
00159 {
00160     double radius = d / t;
00161     double iccx = state->getX() - radius*sin(state->getTh());
00162     double iccy = state->getY() + radius*cos(state->getTh());
00163 
00164     double tx =
00165         cos(t)*(state->getX()-iccx)
00166         -sin(t)*(state->getY()-iccy) + iccx;
00167     double ty =
00168         sin(t)*(state->getX()-iccx)
00169         +cos(t)*(state->getY()-iccy) + iccy;
00170     double tth =
00171         state->getTh() + t;
00172 
00173     state->setVX((tx-state->getX())/d_time);
00174     state->setVY((ty-state->getY())/d_time);
00175     state->setVTh((tth-state->getTh())/d_time);
00176     state->setX(tx);
00177     state->setY(ty);
00178     state->setTh(tth);
00179 
00180     ROS_DEBUG("CanListener: Other movement. radius = %f", radius);
00181 }
00182 
00183 double CanListener::calculateAverage(double velocity_average[], double velocity)
00184 {
00185     //Calculate average velocity
00186     velocity_average[counter]= velocity;
00187 
00188     counter++;
00189     if(counter >= average_size)
00190     {
00191         counter = 0;
00192     }
00193 
00194     double sum = 0;
00195 
00196     for(int i = 0; i < average_size; i++)
00197     {
00198         sum += velocity_average[i];
00199     }
00200 
00201     return sum/average_size;
00202 }
00203 
00204 void CanListener::run()
00205 {
00206     //********************************************************************************//
00207     // Initialisation.
00208     //********************************************************************************//
00209     initalize();
00210     //d=drived distance, d_left = drived distance wheel left, t = changing of the orientation.
00211     double d = 0, d_left = 0, d_right = 0, t =0 ;
00212     // velocity of left/right wheel
00213     double velocity_left = 0, velocity_right = 0;
00214     int ticks_left = 0, ticks_right = 0, ticks_left_old = 0, ticks_right_old = 0;
00215     bool first = true;
00216 
00217     ros::Rate rate(300);
00218     ros::Time current_time, last_time, start_time;
00219     current_time = last_time = start_time = ros::Time::now();
00220 
00221     //Loop until node is stopped.
00222     while( ros::ok() )
00223     {
00224         current_time = ros::Time::now();
00225         //Time between two loops.
00226         double d_time = (current_time - last_time).toNSec();
00227         //********************************************************************************//
00228         // Receiving data from CAN-Bus
00229         //********************************************************************************//
00230         if(gettingData())
00231         {
00232             ticks_left = (frame.data[3]<<8)+frame.data[2];
00233             ticks_right = (frame.data[1]<<8)+frame.data[0];
00234 
00235             ROS_DEBUG("CanListener: ticks_left: %i, ticks_right: %i", ticks_left,ticks_right);
00236             if(first)
00237             {
00238                 ROS_INFO("CanListener: Started successfully.\n");
00239                 ticks_left_old = ticks_left;
00240                 ticks_right_old = ticks_right;
00241                 first = false;
00242             }
00243 
00244             //********************************************************************************//
00245             // Overflow detection.
00246             //********************************************************************************//
00247             ticks_left_old = overflowDetection(ticks_left, ticks_left_old);
00248             ticks_right_old = overflowDetection(ticks_right, ticks_right_old);
00249 
00250             //********************************************************************************//
00251             // Calculation the estimated velocities from the ticks
00252             //********************************************************************************//
00253             if ((current_time - last_time) > ros::Duration(0,0))
00254             {
00255                 d_left  =  (ticks_left  - ticks_left_old) / impulses_per_mm_left ;
00256                 d_right =  (ticks_right - ticks_right_old) / impulses_per_mm_right ;
00257 
00258                 velocity_left = d_left / d_time;
00259                 velocity_right = d_right / d_time;
00260             }
00261 
00262             ticks_left_old = ticks_left;
00263             ticks_right_old = ticks_right;
00264 
00265             left_average = calculateAverage(left_velocity_average, velocity_left);
00266             right_average = calculateAverage(right_velocity_average, velocity_right);
00267 
00268             d = ( d_left + d_right ) / 2 ;
00269             ROS_DEBUG("CanListener: Driven dinstance =  %f", d);
00270 
00271             t = ( d_right - d_left ) / wheel_distance;
00272             ROS_DEBUG("CanListener: Orientation change =  %f", t);
00273 
00274             //********************************************************************************//
00275             // Calculating the Odometry.
00276             //********************************************************************************//
00277 
00278             //Moving forward.
00279             if(velocity_left == velocity_right)
00280             {
00281                 movingForward(d, d_time);
00282             }
00283             else
00284             {
00285                 //Turning in place.
00286                 if(velocity_left == -velocity_right)
00287                 {
00288                     turningInPlace(t, d_time);
00289                 }
00290                 else
00291                 {
00292                     otherMovement(d,t,d_time);
00293                 }
00294             }
00295         }
00296 
00297         //********************************************************************************//
00298         // Publishing.
00299         //********************************************************************************//
00300 
00301 
00302         //First, we'll publish the transform over tf.
00303         state->sendTransformOdomTF(getOdomTF(current_time));
00304 
00305         //Next, we'll publish the odometry message over ROS.
00306         state->odom_pub.publish(getOdomMsg(current_time));
00307 
00308         last_time = current_time;
00309 
00310         rate.sleep();
00311     }
00312 }
00313 
00314 double CanListener::get_velocity_right()
00315 {
00316     return right_average*10000000;
00317 }
00318 double CanListener::get_velocity_left()
00319 {
00320     return left_average*10000000;
00321 }


asr_mild_base_driving
Author(s): Aumann Florian, Borella Jocelyn, Dehmani Souheil, Marek Felix, Meißner Pascal, Reckling Reno
autogenerated on Thu Jun 6 2019 22:02:58