StatusPublisher.cpp
Go to the documentation of this file.
1 /******************************************************************************
2 *
3 * The MIT License (MIT)
4 *
5 * Copyright (c) 2018 Bluewhale Robot
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Author: Xie fusheng
26 * Randoms
27 *******************************************************************************/
28 
29 #include <memory.h>
30 #include <math.h>
31 #include <stdlib.h>
34 
35 #define DISABLE 0
36 #define ENABLE 1
37 
38 namespace xiaoqiang_driver
39 {
40 typedef sensor_msgs::PointCloud2 PointCloud;
41 
43 {
44  mbUpdated = false;
45  wheel_separation = 0.37;
46  wheel_radius = 0.06;
47 
48  CarPos2D.x = 0.0;
49  CarPos2D.y = 0.0;
50  CarPos2D.theta = 0.0;
51 
52  CarTwist.linear.x = 0.0;
53  CarTwist.linear.y = 0.0;
54  CarTwist.linear.z = 0.0;
55  CarTwist.angular.x = 0.0;
56  CarTwist.angular.y = 0.0;
57  CarTwist.angular.z = 0.0;
58 
59  CarPower.data = 0.0;
60 
61  int i = 0;
62  int* status;
63  status = (int*)&car_status;
64  for (i = 0; i < 23; i++)
65  {
66  status[i] = 0;
67  }
68  car_status.encoder_ppr = 4 * 12 * 64;
69 
70  mPose2DPub = mNH.advertise<geometry_msgs::Pose2D>("pose2d", 1, true);
71  mStatusFlagPub = mNH.advertise<std_msgs::Int32>("status_flag", 1, true);
72  mTwistPub = mNH.advertise<geometry_msgs::Twist>("twist", 1, true);
73  mPowerPub = mNH.advertise<std_msgs::Float64>("power", 1, true);
74  mOdomPub = mNH.advertise<nav_msgs::Odometry>("odom", 1, true);
75  pub_barpoint_cloud_ = mNH.advertise<PointCloud>("bar_points", 1, true);
76  pub_clearpoint_cloud_ = mNH.advertise<PointCloud>("clear_points", 1, true);
77 }
78 
79 StatusPublisher::StatusPublisher(double separation, double radius)
80 {
81  new (this) StatusPublisher();
82  wheel_separation = separation;
83  wheel_radius = radius;
84 }
85 
86 void StatusPublisher::Update(const char data[], unsigned int len)
87 {
88  boost::mutex::scoped_lock lock(mMutex);
89 
90  int i = 0, j = 0;
91  int* receive_byte;
92  static unsigned char last_str[2] = { 0x00, 0x00 };
93  static unsigned char new_packed_ctr = DISABLE; // ENABLE表示新包开始,DISABLE 表示上一个包还未处理完;
94  static int new_packed_ok_len = 0; //包的理论长度
95  static int new_packed_len = 0; //包的实际长度
96  static unsigned char cmd_string_buf[512];
97  unsigned char current_str = 0x00;
98  const int cmd_string_max_size = 512;
99  receive_byte = (int*)&car_status;
100  // int ii=0;
101  // boost::mutex::scoped_lock lock(mMutex);
102 
103  // if(len<119)
104  // {
105  // std::cout<<"len0:"<<len<<std::endl;
106  // current_str=data[0];
107  // std::cout<<(unsigned int)current_str<<std::endl;
108  // }
109  for (i = 0; i < len; i++)
110  {
111  current_str = data[i];
112  // unsigned int temp=(unsigned int)current_str;
113  // std::cout<<temp<<std::endl;
114  //判断是否有新包头
115  if (last_str[0] == 205 && last_str[1] == 235 && current_str == 215) //包头 205 235 215
116  {
117  // std::cout<<"runup1 "<<std::endl;
118  new_packed_ctr = ENABLE;
119  new_packed_ok_len = 0;
120  new_packed_len = new_packed_ok_len;
121  last_str[0] = last_str[1]; //保存最后两个字符,用来确定包头
122  last_str[1] = current_str;
123  continue;
124  }
125  last_str[0] = last_str[1]; //保存最后两个字符,用来确定包头
126  last_str[1] = current_str;
127  if (new_packed_ctr == ENABLE)
128  {
129  //获取包长度
130  new_packed_ok_len = current_str;
131  if (new_packed_ok_len > cmd_string_max_size)
132  new_packed_ok_len = cmd_string_max_size; //包内容最大长度有限制
133  new_packed_ctr = DISABLE;
134  // std::cout<<"runup2 "<< new_packed_len<< new_packed_ok_len<<std::endl;
135  }
136  else
137  {
138  //判断包当前大小
139  if (new_packed_ok_len <= new_packed_len)
140  {
141  // std::cout<<"runup3 "<< new_packed_len<< new_packed_ok_len<<std::endl;
142  //包长度已经大于等于理论长度,后续内容无效
143  continue;
144  }
145  else
146  {
147  //获取包内容
148  new_packed_len++;
149  cmd_string_buf[new_packed_len - 1] = current_str;
150  if (new_packed_ok_len == new_packed_len && new_packed_ok_len > 0)
151  {
152  // std::cout<<"runup4 "<<std::endl;
153  //当前包已经处理完成,开始处理
154  if (new_packed_ok_len == 115)
155  {
156  for (j = 0; j < 23; j++)
157  {
158  memcpy(&receive_byte[j], &cmd_string_buf[5 * j], 4);
159  }
160  mbUpdated = true;
161  }
162  else if (new_packed_ok_len == 95)
163  {
164  for (j = 0; j < 19; j++)
165  {
166  memcpy(&receive_byte[j], &cmd_string_buf[5 * j], 4);
167  }
168  mbUpdated = true;
169  }
170  if (mbUpdated)
171  {
172  for (j = 0; j < 7; j++)
173  {
174  if (cmd_string_buf[5 * j + 4] != 32)
175  {
176  // std::cout<<"len:"<< len <<std::endl;
177  // std::cout<<"delta_encoder_car:"<< car_status.encoder_delta_car <<std::endl;
178  // for(j=0;j<115;j++)
179  // {
180  // current_str=cmd_string_buf[j];
181  // std::cout<<(unsigned int)current_str<<std::endl;
182  // }
183  mbUpdated = false;
184  car_status.encoder_ppr = 4 * 12 * 64;
185  break;
186  }
187  }
188  }
189  // if(mbUpdated&&(car_status.encoder_delta_car>3000||car_status.encoder_delta_car<-3000))
190  // {
191  // std::cout<<"len:"<< len <<std::endl;
192  // std::cout<<"delta_encoder_car:"<< car_status.encoder_delta_car <<std::endl;
193  // for(j=0;j<115;j++)
194  // {
195  // current_str=cmd_string_buf[j];
196  // std::cout<<(unsigned int)current_str<<std::endl;
197  // }
198  // std::cout<<"last len:"<<len2<<std::endl;
199  // for(j=0;j<len2;j++)
200  // {
201  // current_str=data2[j];
202  // std::cout<<(unsigned int)current_str<<std::endl;
203  // }
204  // std::cout<<"current:"<<std::endl;
205  // for(j=0;j<len;j++)
206  // {
207  // current_str=data[j];
208  // std::cout<<(unsigned int)current_str<<std::endl;
209  // }
210  // }
211 
212  // ii++;
213  // std::cout << ii << std::endl;
214  new_packed_ok_len = 0;
215  new_packed_len = 0;
216  }
217  }
218  }
219  }
220  // for(j=0;j<len;j++)
221  // {
222  // len2++;
223  // if(len2==1024) len2=1;
224  // data2[len2-1]=data[j];
225  // }
226 
227  return;
228 }
229 
231 {
232  boost::mutex::scoped_lock lock(mMutex);
233  static double theta_last = 0.0;
234  static unsigned int ii = 0;
235  static bool theta_updateflag = false;
236  ii++;
237  // std::cout<<"runR"<< mbUpdated<<std::endl;
238  if (mbUpdated)
239  {
240  // Time
241  ros::Time current_time = ros::Time::now();
242 
243  if (car_status.status == 0)
244  {
245  theta_updateflag = false;
246  }
247  else
248  {
249  theta_updateflag = true;
250  }
251  // pose
252  double delta_car, delta_x, delta_y, delta_theta, var_len, var_angle;
253 
254  var_len = (50.0f / car_status.encoder_ppr * 2.0f * PI * wheel_radius) *
255  (50.0f / car_status.encoder_ppr * 2.0f * PI * wheel_radius);
256  var_angle = (0.01f / 180.0f * PI) * (0.01f / 180.0f * PI);
257 
259  2.0f * PI * wheel_radius;
260  if (delta_car > 0.05 || delta_car < -0.05)
261  {
262  // std::cout<<"get you!"<<std::endl;
263  delta_car = 0;
264  }
265  // if(ii%50==0||car_status.encoder_delta_car>3000||car_status.encoder_delta_car<-3000)
266  // {
267  // std::cout<<"delta_encoder_car:"<< car_status.encoder_delta_car <<std::endl;
268  // std::cout<<"delta_encoder_r:"<< car_status.encoder_delta_r <<std::endl;
269  // std::cout<<"delta_encoder_l:"<< car_status.encoder_delta_l <<std::endl;
270  // std::cout<<"ppr:"<< car_status.encoder_ppr <<std::endl;
271  // std::cout<<"delta_car:"<< delta_car <<std::endl;
272  // }
273  delta_x = delta_car * cos(CarPos2D.theta * PI / 180.0f);
274  delta_y = delta_car * sin(CarPos2D.theta * PI / 180.0f);
275 
276  delta_theta = car_status.theta - theta_last;
277  theta_last = car_status.theta;
278  if (delta_theta > 270)
279  delta_theta -= 360;
280  if (delta_theta < -270)
281  delta_theta += 360;
282 
283  if ((!theta_updateflag) || delta_theta > 20 || delta_theta < -20)
284  {
285  delta_theta = 0;
286  }
287  CarPos2D.x += delta_x;
288  CarPos2D.y += delta_y;
289  CarPos2D.theta += delta_theta;
290 
291  if (CarPos2D.theta > 360.0)
292  CarPos2D.theta -= 360;
293  if (CarPos2D.theta < 0.0)
294  CarPos2D.theta += 360;
295 
297 
298  // flag
299  std_msgs::Int32 flag;
300  flag.data = car_status.status;
301  //底层障碍物信息
304  {
305  //有障碍物
306  flag.data = 2;
307  }
308  mStatusFlagPub.publish(flag);
309 
310  int barArea_nums = 0;
311  int clearArea_nums = 0;
312  if (car_status.distance1 > 0.1)
313  {
314  barArea_nums += 3;
315  }
316  else
317  {
318  clearArea_nums += 6;
319  }
320  if (car_status.distance2 > 0.1)
321  {
322  barArea_nums += 3;
323  }
324  else
325  {
326  clearArea_nums += 6;
327  }
328  if (car_status.distance4 > 0.1)
329  {
330  barArea_nums += 3;
331  }
332  else
333  {
334  clearArea_nums += 6;
335  }
336 
337  if (barArea_nums > 0)
338  {
339  //发布雷区
340  PointCloud::Ptr barcloud_msg(new PointCloud);
341  barcloud_msg->header.stamp = current_time;
342  barcloud_msg->height = 1;
343  barcloud_msg->width = barArea_nums;
344  barcloud_msg->is_dense = true;
345  barcloud_msg->is_bigendian = false;
346  barcloud_msg->header.frame_id = "kinect_link_new";
347  sensor_msgs::PointCloud2Modifier pcd_modifier1(*barcloud_msg);
348  pcd_modifier1.setPointCloud2FieldsByString(1, "xyz");
349  sensor_msgs::PointCloud2Iterator<float> bariter_x(*barcloud_msg, "x");
350  sensor_msgs::PointCloud2Iterator<float> bariter_y(*barcloud_msg, "y");
351  sensor_msgs::PointCloud2Iterator<float> bariter_z(*barcloud_msg, "z");
352  if (car_status.distance2 > 0.1)
353  {
354  for (int k = 0; k < 3; k++, ++bariter_x, ++bariter_y, ++bariter_z)
355  {
356  *bariter_x = 0.2;
357  *bariter_y = -0.10 - k * 0.05;
358  *bariter_z = 0.15;
359  }
360  }
361  if (car_status.distance4 > 0.1)
362  {
363  for (int k = 0; k < 3; k++, ++bariter_x, ++bariter_y, ++bariter_z)
364  {
365  *bariter_x = 0.2;
366  *bariter_y = -0.1 + k * 0.05;
367  *bariter_z = 0.15;
368  }
369  }
370  if (car_status.distance1 > 0.1)
371  {
372  for (int k = 0; k < 3; k++, ++bariter_x, ++bariter_y, ++bariter_z)
373  {
374  *bariter_x = 0.2;
375  *bariter_y = 0.05 + k * 0.05;
376  *bariter_z = 0.15;
377  }
378  }
379  if (ii % 5 == 0)
380  {
381  pub_barpoint_cloud_.publish(barcloud_msg);
382  }
383  }
384  if (clearArea_nums > 0)
385  {
386  //发布雷区
387  PointCloud::Ptr clearcloud_msg(new PointCloud);
388  clearcloud_msg->header.stamp = current_time;
389  clearcloud_msg->height = 1;
390  clearcloud_msg->width = clearArea_nums;
391  clearcloud_msg->is_dense = true;
392  clearcloud_msg->is_bigendian = false;
393  clearcloud_msg->header.frame_id = "kinect_link_new";
394  sensor_msgs::PointCloud2Modifier pcd_modifier1(*clearcloud_msg);
395  pcd_modifier1.setPointCloud2FieldsByString(1, "xyz");
396  sensor_msgs::PointCloud2Iterator<float> cleariter_x(*clearcloud_msg, "x");
397  sensor_msgs::PointCloud2Iterator<float> cleariter_y(*clearcloud_msg, "y");
398  sensor_msgs::PointCloud2Iterator<float> cleariter_z(*clearcloud_msg, "z");
399  if (car_status.distance2 < 0.1)
400  {
401  for (int k = 0; k < 3; k++, ++cleariter_x, ++cleariter_y, ++cleariter_z)
402  {
403  *cleariter_x = 0.2;
404  *cleariter_y = -0.1 - k * 0.05;
405  *cleariter_z = 0.0;
406  }
407  for (int k = 0; k < 3; k++, ++cleariter_x, ++cleariter_y, ++cleariter_z)
408  {
409  *cleariter_x = 0.15;
410  *cleariter_y = -0.1 - k * 0.05;
411  *cleariter_z = 0.0;
412  }
413  }
414  if (car_status.distance4 < 0.1)
415  {
416  for (int k = 0; k < 3; k++, ++cleariter_x, ++cleariter_y, ++cleariter_z)
417  {
418  *cleariter_x = 0.2;
419  *cleariter_y = -0.1 + k * 0.05;
420  *cleariter_z = 0.0;
421  }
422  for (int k = 0; k < 3; k++, ++cleariter_x, ++cleariter_y, ++cleariter_z)
423  {
424  *cleariter_x = 0.15;
425  *cleariter_y = -0.1 + k * 0.05;
426  *cleariter_z = 0.0;
427  }
428  }
429  if (car_status.distance1 < 0.1)
430  {
431  for (int k = 0; k < 3; k++, ++cleariter_x, ++cleariter_y, ++cleariter_z)
432  {
433  *cleariter_x = 0.2;
434  *cleariter_y = 0.05 + k * 0.05;
435  *cleariter_z = 0.0;
436  }
437  for (int k = 0; k < 3; k++, ++cleariter_x, ++cleariter_y, ++cleariter_z)
438  {
439  *cleariter_x = 0.15;
440  *cleariter_y = 0.05 + k * 0.05;
441  *cleariter_z = 0.0;
442  }
443  }
444  if (ii % 5 == 0)
445  {
446  pub_clearpoint_cloud_.publish(clearcloud_msg);
447  }
448  }
449 
450  // Twist
451  double angle_speed;
452  CarTwist.linear.x = delta_car * 50.0f;
453  angle_speed = -car_status.IMU[5];
454  CarTwist.angular.z = angle_speed * PI / 180.0f;
456 
457  CarPower.data = car_status.power;
459 
460  CarOdom.header.stamp = current_time;
461  CarOdom.header.frame_id = "odom";
462  CarOdom.pose.pose.position.x = CarPos2D.x;
463  CarOdom.pose.pose.position.y = CarPos2D.y;
464  CarOdom.pose.pose.position.z = 0.0f;
465  geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(CarPos2D.theta / 180.0f * PI);
466  CarOdom.pose.pose.orientation = odom_quat;
467  CarOdom.pose.covariance = boost::assign::list_of(var_len)(0)(0)(0)(0)(0)(0)(var_len)(0)(0)(0)(0)(0)(0)(999)(0)(0)(
468  0)(0)(0)(0)(999)(0)(0)(0)(0)(0)(0)(999)(0)(0)(0)(0)(0)(0)(var_angle);
469  CarOdom.child_frame_id = "base_footprint";
470  CarOdom.twist.twist.linear.x = CarTwist.linear.x; // * cos(CarPos2D.theta* PI / 180.0f);
471  CarOdom.twist.twist.linear.y = CarTwist.linear.y; // * sin(CarPos2D.theta* PI / 180.0f);
472  CarOdom.twist.twist.angular.z = CarTwist.angular.z;
473  CarOdom.twist.covariance = boost::assign::list_of(var_len)(0)(0)(0)(0)(0)(0)(var_len)(0)(0)(0)(0)(0)(0)(999)(0)(0)(
474  0)(0)(0)(0)(999)(0)(0)(0)(0)(0)(0)(999)(0)(0)(0)(0)(0)(0)(var_angle);
476 
477  // pub transform
478 
479  static tf::TransformBroadcaster br;
480  tf::Quaternion q;
481  tf::Transform transform;
482  transform.setOrigin(tf::Vector3(CarPos2D.x, CarPos2D.y, 0.0));
483  q.setRPY(0, 0, CarPos2D.theta / 180 * PI);
484  transform.setRotation(q);
485  br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "odom", "base_footprint"));
486 
487  ros::spinOnce();
488 
489  mbUpdated = false;
490  }
491 }
492 
494 {
495  return wheel_separation;
496 }
497 
499 {
500  return wheel_radius;
501 }
502 
504 {
505  return car_status.encoder_ppr;
506 }
507 
508 void StatusPublisher::get_wheel_speed(double speed[2])
509 {
510  //右一左二
511  speed[0] = car_status.omga_r / car_status.encoder_ppr * 2.0 * PI * wheel_radius;
512  speed[1] = car_status.omga_l / car_status.encoder_ppr * 2.0 * PI * wheel_radius;
513 }
514 
515 geometry_msgs::Pose2D StatusPublisher::get_CarPos2D()
516 {
517  return CarPos2D;
518 }
519 
520 geometry_msgs::Twist StatusPublisher::get_CarTwist()
521 {
522  return CarTwist;
523 }
524 
525 std_msgs::Float64 StatusPublisher::get_power()
526 {
527  return CarPower;
528 }
529 
530 nav_msgs::Odometry StatusPublisher::get_odom()
531 {
532  return CarOdom;
533 }
535 {
536  return car_status.status;
537 }
538 
539 } // namespace xiaoqiang_driver
TFSIMD_FORCE_INLINE void setRotation(const Quaternion &q)
#define ENABLE
void publish(const boost::shared_ptr< M > &message) const
f
sensor_msgs::PointCloud2 PointCloud
void setRPY(const tfScalar &roll, const tfScalar &pitch, const tfScalar &yaw)
geometry_msgs::Pose2D get_CarPos2D()
void sendTransform(const StampedTransform &transform)
#define DISABLE
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
#define PI
static geometry_msgs::Quaternion createQuaternionMsgFromYaw(double yaw)
static Time now()
geometry_msgs::Pose2D CarPos2D
geometry_msgs::Twist get_CarTwist()
void get_wheel_speed(double speed[2])
ROSCPP_DECL void spinOnce()
void setPointCloud2FieldsByString(int n_fields,...)
void Update(const char *data, unsigned int len)
TFSIMD_FORCE_INLINE void setOrigin(const Vector3 &origin)


xiaoqiang_driver
Author(s): Xie fusheng
autogenerated on Mon Jun 10 2019 15:53:12