CanListener.cpp
Go to the documentation of this file.
1 
20 #include <sys/socket.h>
21 #include <linux/sockios.h>
22 #include <linux/can.h>
23 #include <linux/if.h>
24 #include "CanListener.h"
25 #include "ros/ros.h"
26 #include "nav_msgs/Odometry.h"
27 #include "OwnMath.h"
28 #include <stdlib.h>
29 
30 
31 
32 
34 {
35  //Means 1:144 gearing.
36  impulses_per_mm_left = -152.8;
37  impulses_per_mm_right = 152.8;
38  //distance between left and right wheel
39  wheel_distance = 663.0;
40 
41  left_average = 0;
42  right_average = 0;
43 
44  //Average over X succressive measures.
45  average_size = 25;
46  counter = 0;
47 }
48 
49 geometry_msgs::TransformStamped CanListener::getOdomTF(ros::Time current_time)
50 {
51 
52  //since all odometry is 6DOF we'll need a quaternion created from yaw
53  geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(state->getTh());
54 
55  geometry_msgs::TransformStamped odom_trans;
56 
57  odom_trans.header.stamp = current_time;
58  odom_trans.header.frame_id = "odom";
59  odom_trans.child_frame_id = "base_link";
60 
61  odom_trans.transform.translation.x = state->getX()/1000.0;
62  odom_trans.transform.translation.y = state->getY()/1000.0;
63  odom_trans.transform.translation.z = 0.0;
64  odom_trans.transform.rotation = odom_quat;
65 
66  return odom_trans;
67 
68 }
69 
70 nav_msgs::Odometry CanListener::getOdomMsg(ros::Time current_time)
71 {
72 
73  //since all odometry is 6DOF we'll need a quaternion created from yaw
74  geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(state->getTh());
75 
76  nav_msgs::Odometry odom;
77 
78  odom.header.stamp = current_time;
79  odom.header.frame_id = "odom";
80 
81  //Set the position.
82  odom.pose.pose.position.x = state->getX()/1000.0;
83  odom.pose.pose.position.y = state->getY()/1000.0;
84  odom.pose.pose.position.z = 0.0;
85  odom.pose.pose.orientation = odom_quat;
86 
87  //Set the velocity.
88  odom.child_frame_id = "base_link";
89  odom.twist.twist.linear.x = state->getVX()/1000.0;
90  odom.twist.twist.linear.y = state->getVY()/1000.0;
91  odom.twist.twist.angular.z = state->getVTh();
92 
93  return odom;
94 
95 }
96 
98 {
99  ssize_t nbytes;
100  nbytes = recv(state->getSocket(), &frame, sizeof(struct can_frame), MSG_DONTWAIT);
101  if (nbytes < 0)
102  {
103  if (errno != EAGAIN)
104  {
105  ROS_ERROR("CanListener: mild_base_driving raw socket read, status %zu (%i)", nbytes, errno);
106  exit(1);
107  }
108  }
109  else if (nbytes < (int)sizeof(struct can_frame))
110  {
111  ROS_ERROR("CanListener: read: incomplete CAN frame of size %zu",nbytes);
112  exit(1);
113  }
114  return true;
115 }
116 
117 int CanListener::overflowDetection(int ticks, int ticks_old)
118 {
119  int max_encoder = 0xffff;
120  if (fabs(ticks - ticks_old) > 0.5*max_encoder)
121  {
122  //Overflow detected left.
123  ROS_DEBUG("CanListener: Overflow left. Old ticks_old = %i", ticks_old);
124  if (ticks > ticks_old)
125  {
126  ticks_old = ticks_old + max_encoder;
127  }
128  else ticks_old = ticks_old - max_encoder;
129  ROS_DEBUG("CanListener: Overflow left. New ticks_old = %i", ticks_old);
130  }
131  return ticks_old;
132 }
133 
134 void CanListener::movingForward(double d, double d_time)
135 {
136  double velocity = d / d_time;
137  double tx = state->getX()+velocity*cos(state->getTh())*d_time;
138  double ty = state->getY()+velocity*sin(state->getTh())*d_time;
139 
140  state->setVX((tx-state->getX())/d_time);
141  state->setVY((ty-state->getY())/d_time);
142  state->setVTh(0);
143  state->setX(tx);
144  state->setY(ty);
145 
146  ROS_DEBUG("CanListener: Moving forward. velocity = %f", velocity);
147 }
148 
149 void CanListener::turningInPlace(double t, double d_time)
150 {
151  state->setVX(0);
152  state->setVY(0);
153  double tth = state->getTh() + t ;
154  state->setVTh((tth-state->getTh())/d_time);
155  state->setTh(tth);
156 }
157 
158 void CanListener::otherMovement(double d, double t, double d_time)
159 {
160  double radius = d / t;
161  double iccx = state->getX() - radius*sin(state->getTh());
162  double iccy = state->getY() + radius*cos(state->getTh());
163 
164  double tx =
165  cos(t)*(state->getX()-iccx)
166  -sin(t)*(state->getY()-iccy) + iccx;
167  double ty =
168  sin(t)*(state->getX()-iccx)
169  +cos(t)*(state->getY()-iccy) + iccy;
170  double tth =
171  state->getTh() + t;
172 
173  state->setVX((tx-state->getX())/d_time);
174  state->setVY((ty-state->getY())/d_time);
175  state->setVTh((tth-state->getTh())/d_time);
176  state->setX(tx);
177  state->setY(ty);
178  state->setTh(tth);
179 
180  ROS_DEBUG("CanListener: Other movement. radius = %f", radius);
181 }
182 
183 double CanListener::calculateAverage(double velocity_average[], double velocity)
184 {
185  //Calculate average velocity
186  velocity_average[counter]= velocity;
187 
188  counter++;
189  if(counter >= average_size)
190  {
191  counter = 0;
192  }
193 
194  double sum = 0;
195 
196  for(int i = 0; i < average_size; i++)
197  {
198  sum += velocity_average[i];
199  }
200 
201  return sum/average_size;
202 }
203 
205 {
206  //********************************************************************************//
207  // Initialisation.
208  //********************************************************************************//
209  initalize();
210  //d=drived distance, d_left = drived distance wheel left, t = changing of the orientation.
211  double d = 0, d_left = 0, d_right = 0, t =0 ;
212  // velocity of left/right wheel
213  double velocity_left = 0, velocity_right = 0;
214  int ticks_left = 0, ticks_right = 0, ticks_left_old = 0, ticks_right_old = 0;
215  bool first = true;
216 
217  ros::Rate rate(300);
218  ros::Time current_time, last_time, start_time;
219  current_time = last_time = start_time = ros::Time::now();
220 
221  //Loop until node is stopped.
222  while( ros::ok() )
223  {
224  current_time = ros::Time::now();
225  //Time between two loops.
226  double d_time = (current_time - last_time).toNSec();
227  //********************************************************************************//
228  // Receiving data from CAN-Bus
229  //********************************************************************************//
230  if(gettingData())
231  {
232  ticks_left = (frame.data[3]<<8)+frame.data[2];
233  ticks_right = (frame.data[1]<<8)+frame.data[0];
234 
235  ROS_DEBUG("CanListener: ticks_left: %i, ticks_right: %i", ticks_left,ticks_right);
236  if(first)
237  {
238  ROS_INFO("CanListener: Started successfully.\n");
239  ticks_left_old = ticks_left;
240  ticks_right_old = ticks_right;
241  first = false;
242  }
243 
244  //********************************************************************************//
245  // Overflow detection.
246  //********************************************************************************//
247  ticks_left_old = overflowDetection(ticks_left, ticks_left_old);
248  ticks_right_old = overflowDetection(ticks_right, ticks_right_old);
249 
250  //********************************************************************************//
251  // Calculation the estimated velocities from the ticks
252  //********************************************************************************//
253  if ((current_time - last_time) > ros::Duration(0,0))
254  {
255  d_left = (ticks_left - ticks_left_old) / impulses_per_mm_left ;
256  d_right = (ticks_right - ticks_right_old) / impulses_per_mm_right ;
257 
258  velocity_left = d_left / d_time;
259  velocity_right = d_right / d_time;
260  }
261 
262  ticks_left_old = ticks_left;
263  ticks_right_old = ticks_right;
264 
267 
268  d = ( d_left + d_right ) / 2 ;
269  ROS_DEBUG("CanListener: Driven dinstance = %f", d);
270 
271  t = ( d_right - d_left ) / wheel_distance;
272  ROS_DEBUG("CanListener: Orientation change = %f", t);
273 
274  //********************************************************************************//
275  // Calculating the Odometry.
276  //********************************************************************************//
277 
278  //Moving forward.
279  if(velocity_left == velocity_right)
280  {
281  movingForward(d, d_time);
282  }
283  else
284  {
285  //Turning in place.
286  if(velocity_left == -velocity_right)
287  {
288  turningInPlace(t, d_time);
289  }
290  else
291  {
292  otherMovement(d,t,d_time);
293  }
294  }
295  }
296 
297  //********************************************************************************//
298  // Publishing.
299  //********************************************************************************//
300 
301 
302  //First, we'll publish the transform over tf.
303  state->sendTransformOdomTF(getOdomTF(current_time));
304 
305  //Next, we'll publish the odometry message over ROS.
306  state->odom_pub.publish(getOdomMsg(current_time));
307 
308  last_time = current_time;
309 
310  rate.sleep();
311  }
312 }
313 
315 {
316  return right_average*10000000;
317 }
319 {
320  return left_average*10000000;
321 }
d
int getSocket()
Definition: RobotState.h:109
void sendTransformOdomTF(geometry_msgs::TransformStamped odom_trans)
Definition: RobotState.h:67
void setTh(double th)
Definition: RobotState.h:126
double left_average
Definition: CanListener.h:38
void setX(double x)
Definition: RobotState.h:114
void publish(const boost::shared_ptr< M > &message) const
void otherMovement(double d, double t, double d_time)
void setVTh(double vth)
Definition: RobotState.h:144
void setY(double y)
Definition: RobotState.h:120
double getX()
Definition: RobotState.h:73
int average_size
Definition: CanListener.h:41
Mathematical functions.
double right_velocity_average[50]
Definition: CanListener.h:43
int overflowDetection(int ticks, int ticks_old)
double impulses_per_mm_left
Definition: CanListener.h:35
double getTh()
Definition: RobotState.h:85
void turningInPlace(double t, double d_time)
void initalize()
Definition: CanListener.cpp:33
double getVY()
Definition: RobotState.h:97
nav_msgs::Odometry getOdomMsg(ros::Time current_time)
Definition: CanListener.cpp:70
bool gettingData()
Definition: CanListener.cpp:97
double get_velocity_left()
#define ROS_INFO(...)
void setVX(double vx)
Definition: RobotState.h:132
ROSCPP_DECL bool ok()
double calculateAverage(double velocity_average[], double velocity)
RobotState * state
Definition: CanListener.h:34
bool sleep()
double getVTh()
Definition: RobotState.h:103
double impulses_per_mm_right
Definition: CanListener.h:36
double right_average
Definition: CanListener.h:39
ros::Publisher odom_pub
Definition: RobotState.h:54
static geometry_msgs::Quaternion createQuaternionMsgFromYaw(double yaw)
double getVX()
Definition: RobotState.h:91
void movingForward(double d, double d_time)
static Time now()
geometry_msgs::TransformStamped getOdomTF(ros::Time current_time)
Definition: CanListener.cpp:49
void setVY(double vy)
Definition: RobotState.h:138
double wheel_distance
Definition: CanListener.h:37
double left_velocity_average[50]
Definition: CanListener.h:42
double getY()
Definition: RobotState.h:79
struct can_frame frame
Definition: CanListener.h:96
double get_velocity_right()
#define ROS_ERROR(...)
#define ROS_DEBUG(...)


asr_mild_base_driving
Author(s): Aumann Florian, Borella Jocelyn, Dehmani Souheil, Marek Felix, Meißner Pascal, Reckling Reno
autogenerated on Mon Jun 10 2019 12:43:40