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
00036 impulses_per_mm_left = -152.8;
00037 impulses_per_mm_right = 152.8;
00038
00039 wheel_distance = 663.0;
00040
00041 left_average = 0;
00042 right_average = 0;
00043
00044
00045 average_size = 25;
00046 counter = 0;
00047 }
00048
00049 geometry_msgs::TransformStamped CanListener::getOdomTF(ros::Time current_time)
00050 {
00051
00052
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
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
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
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
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
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
00208
00209 initalize();
00210
00211 double d = 0, d_left = 0, d_right = 0, t =0 ;
00212
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
00222 while( ros::ok() )
00223 {
00224 current_time = ros::Time::now();
00225
00226 double d_time = (current_time - last_time).toNSec();
00227
00228
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
00246
00247 ticks_left_old = overflowDetection(ticks_left, ticks_left_old);
00248 ticks_right_old = overflowDetection(ticks_right, ticks_right_old);
00249
00250
00251
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
00276
00277
00278
00279 if(velocity_left == velocity_right)
00280 {
00281 movingForward(d, d_time);
00282 }
00283 else
00284 {
00285
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
00299
00300
00301
00302
00303 state->sendTransformOdomTF(getOdomTF(current_time));
00304
00305
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