occupancy_xyz.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2008, Willow Garage, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34 #include <ros/ros.h>
35 #include <nodelet/nodelet.h>
39 #include <boost/thread.hpp>
41 #include <sensor_msgs/Image.h>
42 
44 #include <sensor_msgs/PointField.h>
45 #include <nav_msgs/OccupancyGrid.h>
46 
48 
49 //#include <cstdint> //int8_t
50 #include <math.h> //fmod
51 #include<cstring>
52 
53 //line function class,uesed to calculate a point position according to the line,
54 class LineFunc
55 {
56 public:
57  LineFunc(double p1[],double p2[])
58  {
59  if(std::fabs(p1[0]-p2[0])<0.000001)
60  {
61  A_=0;
62  B_=1;
63  C_=-p1[0];
64  }
65  else
66  {
67  A_=1;
68  B_=(p2[1]-p1[1])/(p2[0]-p1[0]);
69  C_=p1[1]-B_*p1[0];
70  }
71  }
72  //return value>0 meaning point is locating at left or down side of line ,
73  // return value==0 meaning point is in the line
74  //return value<0 meaning point is locating at right or top side of line
75  double getPointPos(double p[])
76  {
77  return A_*p[1]-B_*p[0]-C_;
78  }
79 private:
80  double A_;
81  double B_;
82  double C_;
83 };
84 
86 
88 
90 {
91  // Subscriptions
95 
96  // Publications
97  boost::mutex connect_mutex_;
98  typedef sensor_msgs::PointCloud2 PointCloud;
99 
100 
102 
103  virtual void onInit();
104 
105  void connectCb();
106 
107  void depthCb(const sensor_msgs::ImageConstPtr& depth_msg,
108  const sensor_msgs::CameraInfoConstPtr& info_msg);
109  void convert2(const sensor_msgs::ImageConstPtr& depth_msg,PointCloud::Ptr& cloud_msg,const image_geometry::PinholeCameraModel& model,double range_max = 0.0);
110 
111 private:
112  double resolution_; // The map grid resolution [m/cell] ,default 0.1
113  std::vector<double> lowerLeftPos_;// the position of the lower left border [x,y] ,default [0.4,1.5]
114  double gridHeight_; // the height of map grid ,default 2.0,the width of grid map=2*LowerLeftPos_.y
115  double usingWidth_;// the Width length of lower left border that kinect can seen,default 0.3
116  double usingHeight_down_;//the start height length of kinect must seen area
117  double usingHeight_up_;//the end height length of kinect must seen area
118  int8_t* mapGrid_;// the output occupancy map grid
119  int8_t* unkown_mapGrid_;// the init output occupancy map grid
120  int8_t* filter_mapGrid_;// the output occupancy map grid filter
121  std::vector<int> seenGrid_indexs_;
122  std::vector<int> mustseenGrid_indexs_;
125  int ANN_num_ ; //number of ANNpoint
126  int ANN_k_ ; // number of nearest neighbors
127  int ANN_dim_ ; // dimension
128  double ANN_eps_ ; // error bound
129  bool ANN_ready_ ;
130  std::vector<double> R_;
131  std::vector<double> T_;
139  int point_mode_; //0 完整点云、1 除去地板后的所有可视点云
140  std::string frame_id_;
141  nav_msgs::OccupancyGrid occupancygrid_msg_;
142  double height_temp_;
143  double width_temp_;
144  unsigned int num_frame_;
147 };
148 void OccupancyXyzNodelet::convert2(const sensor_msgs::ImageConstPtr& depth_msg,PointCloud::Ptr& cloud_msg,const image_geometry::PinholeCameraModel& model,double range_max)
149 {
150 
151  //static last_mapGrid =new int8_t[2*height_temp_*width_temp_];
152  // Use correct principal point from calibration
153  float center_x = model.cx();
154  float center_y = model.cy();
155 
156  // Combine unit conversion (if necessary) with scaling by focal length for computing (X,Y)
157  float unit_scaling = DepthTraits<uint16_t>::toMeters( uint16_t(1) );
158  float constant_x = unit_scaling / model.fx();
159  float constant_y = unit_scaling / model.fy();
160  float bad_point = std::numeric_limits<float>::quiet_NaN();
161 
162  sensor_msgs::PointCloud2Iterator<float> iter_x(*cloud_msg, "x");
163  sensor_msgs::PointCloud2Iterator<float> iter_y(*cloud_msg, "y");
164  sensor_msgs::PointCloud2Iterator<float> iter_z(*cloud_msg, "z");
165  const uint16_t* depth_row = reinterpret_cast<const uint16_t*>(&depth_msg->data[0]);
166  int row_step = depth_msg->step / sizeof(uint16_t);
167  float x,y,z;
168  ANNpoint p;
169  ANNpoint queryPt=annAllocPt(ANN_dim_); // allocate query point;
170  ANNidxArray nnIdx; // near neighbor indices
171  ANNdistArray dists; // near neighbor distances
172  nnIdx = new ANNidx[ANN_k_]; // allocate near neigh indices
173  dists = new ANNdist[ANN_k_]; // allocate near neighbor dists
174  float resolution_square=resolution_*resolution_;
175  int index_temp1,index_temp2;
176  //boost::lock_guard<boost::mutex> lock(connect_mutex_);
177  // for(std::vector<int>::iterator it = seenGrid_indexs_.begin() ; it !=seenGrid_indexs_.end() ; ++it)
178  // {
179  //
180  // index_temp1=*it;
181  // mapGrid_[index_temp1]=-1;
182  // }
183  int x_num,y_num;
184  float float_temp;
185  ANNpoint PP;
186  for (int v = 0; v < (int)cloud_msg->height; ++v, depth_row += row_step)
187  {
188  for (int u = 0; u < (int)cloud_msg->width; u+=2, ++iter_x, ++iter_y, ++iter_z)
189  {
190  uint16_t depth = depth_row[u];
191 
192  // Missing points denoted by NaNs
193  if (!DepthTraits<uint16_t>::valid(depth))
194  {
195  if (range_max != 0.0)
196  {
197  depth = DepthTraits<uint16_t>::fromMeters(range_max);
198  }
199  else
200  {
201  *iter_x = *iter_y = *iter_z = bad_point;
202  continue;
203  }
204  }
205 
206  // Fill in XYZ
207  x = (u - center_x) * depth * constant_x;
208  y = (v - center_y) * depth * constant_y;
210 
211  *iter_x = R_[0]*x+R_[1]*y+R_[2]*z;
212  *iter_y = R_[3]*x+R_[4]*y+R_[5]*z;
213  *iter_z = R_[6]*x+R_[7]*y+R_[8]*z+kinectHeight_;
214 
215  x=*iter_x;
216  y=*iter_y;
217  z=*iter_z;
218 
219  //地板扣除 障碍物识别
220  if(z< barHeight_max_)
221  {
222  if(z< barHeight_min_)
223  {
224  //地板
225  if(point_mode_==1)
226  {
227  //ROS_INFO("get the floor\n");
228  *iter_x = *iter_y = *iter_z = bad_point;
229  }
230  //除去不感兴趣区域
231  if(!((x<(gridHeight_+lowerLeftPos_[0]) &&x>lowerLeftPos_[0])&&(y<lowerLeftPos_[1] && y> -lowerLeftPos_[1]))) continue;
232  float_temp=(x-lowerLeftPos_[0])/resolution_;
233  x_num=static_cast<int>(float_temp);
234  float_temp=y/resolution_+width_temp_;
235  y_num=static_cast<int>(float_temp);
236  index_temp1=x_num+y_num*height_temp_;
237  if(mapGrid_[index_temp1]<0) mapGrid_[index_temp1]=0;
238  }
239  else
240  {
241  //障碍物
242  //除去不感兴趣区域
243  if(!((x<(gridHeight_+lowerLeftPos_[0]) &&x>lowerLeftPos_[0])&&(y<lowerLeftPos_[1] && y> -lowerLeftPos_[1]))) continue;
244  float_temp=(x-lowerLeftPos_[0])/resolution_;
245  x_num=static_cast<int>(float_temp);
246  float_temp=y/resolution_+width_temp_;
247  y_num=static_cast<int>(float_temp);
248  index_temp1=x_num+y_num*height_temp_;
249  mapGrid_[index_temp1]+=single_score_;
250  if(mapGrid_[index_temp1]>100) mapGrid_[index_temp1]=100;
251  // queryPt[0]=*iter_x;
252  // queryPt[1]=*iter_y;
253  // kdTree_->annkSearch( // search
254  // queryPt, // query point
255  // ANN_k_, // number of near neighbors
256  // nnIdx, // nearest neighbors (returned)
257  // dists, // distance (returned)
258  // 0.0); // error bound
259  // if(dists[0]<=(resolution_square))
260  // {
261  // index_temp1=seenGrid_indexs_[nnIdx[0]];
262  // mapGrid_[index_temp1]+=10;
263  // if(mapGrid_[index_temp1]>100) mapGrid_[index_temp1]=100;
264  // }
265 
266 
267  }
268  }
269  }
270  }
271  //更新必须看见区域
272 
273  for(std::vector<int>::iterator it = mustseenGrid_indexs_.begin() ; it !=mustseenGrid_indexs_.end() ; it++)
274  {
275  index_temp1=*it;
276  if(mapGrid_[index_temp1]<0) //mapGrid_[index_temp1]=100;
277  {
278  filter_mapGrid_[index_temp1]-=1;
279  if(filter_mapGrid_[index_temp1]<-10) filter_mapGrid_[index_temp1]=-10;
280  }
281  else
282  {
283  filter_mapGrid_[index_temp1]+=1;
284  if(filter_mapGrid_[index_temp1]>0) filter_mapGrid_[index_temp1]=0;
285  }
286  if(filter_mapGrid_[index_temp1]<-9)
287  {
288  mapGrid_[index_temp1]=100;
289  }
290  }
291  //将可见区域分成可移动区和雷区
292  std::vector<int> clearArea,barArea;
293  index_temp2=0;
294  for(std::vector<int>::iterator it = seenGrid_indexs_.begin() ; it !=seenGrid_indexs_.end() ; it++)
295  {
296  index_temp1=*it;
297  if(mapGrid_[index_temp1]<bar_threshold_&&mapGrid_[index_temp1]>=0)//被遮挡区域不发布
298  {
299  clearArea.push_back(index_temp2);
300  }
301  else if(mapGrid_[index_temp1]>=bar_threshold_)
302  {
303  barArea.push_back(index_temp2);
304  }
305  index_temp2++;
306  }
307 
308  if(barArea.size()>1||(barArea.size()==1&&num_frame_%4==0))
309  {
310  //发布雷区
311  PointCloud::Ptr barcloud_msg(new PointCloud);
312  barcloud_msg->header = depth_msg->header;
313  barcloud_msg->height = 1;
314  barcloud_msg->width = barArea.size();
315  barcloud_msg->is_dense = true;
316  barcloud_msg->is_bigendian = false;
317  barcloud_msg->header.frame_id=frame_id_;
318  sensor_msgs::PointCloud2Modifier pcd_modifier1(*barcloud_msg);
319  pcd_modifier1.setPointCloud2FieldsByString(1,"xyz");
320  sensor_msgs::PointCloud2Iterator<float> bariter_x(*barcloud_msg, "x");
321  sensor_msgs::PointCloud2Iterator<float> bariter_y(*barcloud_msg, "y");
322  sensor_msgs::PointCloud2Iterator<float> bariter_z(*barcloud_msg, "z");
323  for(std::vector<int>::iterator it = barArea.begin() ; it !=barArea.end() ; ++bariter_x, ++bariter_y,++bariter_z,it++)
324  {
325  index_temp1=*it;
326  PP=gridCenters_[index_temp1];
327  *bariter_x=PP[0];
328  *bariter_y=PP[1];
329  *bariter_z=0.15;
330  }
331  pub_barpoint_cloud_.publish(barcloud_msg);
332  }
333  // else
334  // {
335  // //发布空雷区
336  // PointCloud::Ptr barcloud_msg(new PointCloud);
337  // barcloud_msg->header = depth_msg->header;
338  // barcloud_msg->height = 1;
339  // barcloud_msg->width = 1;
340  // barcloud_msg->is_dense = true;
341  // barcloud_msg->is_bigendian = false;
342  // barcloud_msg->header.frame_id=frame_id_;
343  // sensor_msgs::PointCloud2Modifier pcd_modifier1(*barcloud_msg);
344  // pcd_modifier1.setPointCloud2FieldsByString(1,"xyz");
345  // sensor_msgs::PointCloud2Iterator<float> bariter_x(*barcloud_msg, "x");
346  // sensor_msgs::PointCloud2Iterator<float> bariter_y(*barcloud_msg, "y");
347  // sensor_msgs::PointCloud2Iterator<float> bariter_z(*barcloud_msg, "z");
348  // *bariter_x=-1.0;
349  // *bariter_y=-1.0;
350  // *bariter_z=-1.0;
351  // pub_barpoint_cloud_.publish(barcloud_msg);
352  // }
353  if(clearArea.size()>0)
354  {
355  //发布可移动区域
356  PointCloud::Ptr clearcloud_msg(new PointCloud);
357  clearcloud_msg->header = depth_msg->header;
358  clearcloud_msg->height = 1;
359  clearcloud_msg->width = clearArea.size();
360  clearcloud_msg->is_dense = true;
361  clearcloud_msg->is_bigendian = false;
362  clearcloud_msg->header.frame_id=frame_id_;
363  sensor_msgs::PointCloud2Modifier pcd_modifier2(*clearcloud_msg);
364  pcd_modifier2.setPointCloud2FieldsByString(1, "xyz");
365  sensor_msgs::PointCloud2Iterator<float> cleariter_x(*clearcloud_msg, "x");
366  sensor_msgs::PointCloud2Iterator<float> cleariter_y(*clearcloud_msg, "y");
367  sensor_msgs::PointCloud2Iterator<float> cleariter_z(*clearcloud_msg, "z");
368  for(std::vector<int>::iterator it = clearArea.begin() ; it !=clearArea.end() ; ++cleariter_x, ++cleariter_y,it++)
369  {
370  index_temp1=*it;
371  PP=gridCenters_[index_temp1];
372  *cleariter_x=PP[0];
373  *cleariter_y=PP[1];
374  *cleariter_z=mapGrid_[seenGrid_indexs_[index_temp1]];
375  }
376  pub_clearpoint_cloud_.publish(clearcloud_msg);
377  }
378 
379 }
380 
381 void OccupancyXyzNodelet::onInit()
382 {
383  ros::NodeHandle& nh = getNodeHandle();
384  ros::NodeHandle& private_nh = getPrivateNodeHandle();
385  it_.reset(new image_transport::ImageTransport(nh));
386  num_frame_=1;
387  // Read parameters
388  private_nh.getParam("lowerLeftPos", lowerLeftPos_);
389  private_nh.getParam("R", R_);
390  private_nh.getParam("T", T_);
391  private_nh.param("resolution", resolution_, 0.1);
392  private_nh.param("gridHeight", gridHeight_, 2.0);
393  private_nh.param("usingWidth", usingWidth_, 0.3);
394  nh.param("usingHeight_down",usingHeight_down_, 0.10);
395  nh.param("usingHeight_up",usingHeight_up_, 0.25);
396  private_nh.param("frame_id",frame_id_,std::string("kinect_link_new"));
397  private_nh.param("kinectHeight", kinectHeight_, 0.3769);
398  private_nh.param("barHeight_max", barHeight_max_, 0.50);
399  private_nh.param("barHeight_min", barHeight_min_, 0.05);
400  private_nh.param("point_mode", point_mode_, 0);
401  private_nh.param("bar_threshold", bar_threshold_, 10.0);
402  private_nh.param("single_score", single_score_, 2.0);
403  // Monitor whether anyone is subscribed to the output
404  ros::SubscriberStatusCallback connect_cb = boost::bind(&OccupancyXyzNodelet::connectCb, this);
405 
406  //init map grid
407  ANN_k_ =1 ; // number of nearest neighbors
408  ANN_dim_ =2 ; // dimension
409  ANN_eps_ =0.0 ; // error bound
410  ANN_ready_ =false ;
411 
412  //计算网格大小
413  int width_temp,height_temp;
414 
415  if(fmod(lowerLeftPos_[1],resolution_)>0.001)
416  {
417  width_temp=lowerLeftPos_[1]/resolution_+1;
418  }
419  else
420  {
421  width_temp=lowerLeftPos_[1]/resolution_;
422  }
423  if(fmod(gridHeight_,resolution_)>0.001)
424  {
425  height_temp=gridHeight_/resolution_+1;
426  }
427  else
428  {
429  height_temp=gridHeight_/resolution_;
430  }
431  width_temp =std::max(width_temp,1);
432  height_temp =std::max(height_temp,1);
433  mapGrid_=new int8_t[2*height_temp*width_temp];
434  unkown_mapGrid_=new int8_t[2*height_temp*width_temp];
435  filter_mapGrid_=new int8_t[2*height_temp*width_temp];
436  int x_num,y_num;
437  float x,y; //格子中心点坐标
438  double p1[2]={lowerLeftPos_[0],usingWidth_},p2[2]={lowerLeftPos_[0]+gridHeight_,lowerLeftPos_[1]};
439  double p3[2]={lowerLeftPos_[0],-usingWidth_},p4[2]={lowerLeftPos_[0]+gridHeight_,-lowerLeftPos_[1]};
440  //设置视野边界线
441  LineFunc leftborder= LineFunc(p1,p2);
442  LineFunc rightborder= LineFunc(p3,p4);
443  //初始化网格和视野内网格
444  double p[2]={0.0,0.0};
445  for(int i=0;i<(2*height_temp*width_temp);i++)
446  {
447  mapGrid_[i]=-1;//init as Unknown area
448  unkown_mapGrid_[i]=-1;
449  filter_mapGrid_[i]=-1;
450  y_num=i/(height_temp);
451  x_num=i%(height_temp);
452  x=(x_num+0.5)*resolution_+lowerLeftPos_[0];
453  y=(-width_temp+y_num+0.5)*resolution_;
454  p[0]=x;
455  p[1]=y;
456  if((leftborder.getPointPos(p)*rightborder.getPointPos(p))>0.000001)
457  {
458  continue;
459  }
460  else
461  {
462  //NODELET_INFO("height_temp: %d width_temp: %d p1:%f %f p2:%f %f p:%f %f i:%d x_num:%d y_num:%d\n",height_temp,width_temp,p1[0],p1[1],p2[0],p2[1],p[0],p[1],i,x_num,y_num);
463  seenGrid_indexs_.push_back(i);
464  if(x<(usingHeight_up_+lowerLeftPos_[0]) && x>(usingHeight_down_+lowerLeftPos_[0]) ) mustseenGrid_indexs_.push_back(i);
465  }
466  }
467  //将视野内的网格中心点存入ANN,加速后续算法
468  ANN_num_=seenGrid_indexs_.size();
469  gridCenters_= annAllocPts(ANN_num_, ANN_dim_); // allocate data points
470  ANNpoint pp;
471  int num=0;
472  for(std::vector<int>::iterator it = seenGrid_indexs_.begin() ; it !=seenGrid_indexs_.end() ; it++)
473  {
474  int i=*it;
475  pp=gridCenters_[num];
476  y_num=i/(height_temp);
477  x_num=i%(height_temp);
478  pp[0]=(x_num+0.5)*resolution_+lowerLeftPos_[0];
479  pp[1]=(-width_temp+y_num+0.5)*resolution_;
480  //NODELET_INFO("num: %d index: %d x_num: %d y_num: %d\n",num,i,x_num,y_num);
481  num++;
482  }
483  kdTree_ = new ANNkd_tree( // build search structure
484  gridCenters_, // the data points
485  ANN_num_, // number of points
486  ANN_dim_); // dimension of space
487  ANN_ready_=true;
488 
489  occupancygrid_msg_.info.resolution=resolution_;
490  occupancygrid_msg_.info.height=2*width_temp;
491  occupancygrid_msg_.info.width=height_temp;
492  occupancygrid_msg_.info.origin.position.x=lowerLeftPos_[0];
493  occupancygrid_msg_.info.origin.position.y=-width_temp*resolution_;
494  occupancygrid_msg_.info.origin.position.z=0;
495 
496 
497  height_temp_=height_temp;
498  width_temp_=width_temp;
499  // Make sure we don't enter connectCb() between advertising and assigning to pub_point_cloud_
500  boost::lock_guard<boost::mutex> lock(connect_mutex_);
501  pub_point_cloud_ = nh.advertise<PointCloud>("points", 1, connect_cb, connect_cb);
502  pub_occupancy_grid_ = nh.advertise<nav_msgs::OccupancyGrid>("occupancygrid", 1,connect_cb, connect_cb);
503  pub_barpoint_cloud_ = nh.advertise<PointCloud>("barpoints", 1, connect_cb, connect_cb);
504  pub_clearpoint_cloud_ = nh.advertise<PointCloud>("clearpoints", 1, connect_cb, connect_cb);
505 
506 
507 }
508 
509 // Handles (un)subscribing when clients (un)subscribe
510 void OccupancyXyzNodelet::connectCb()
511 {
512  boost::lock_guard<boost::mutex> lock(connect_mutex_);
513  if ((pub_point_cloud_.getNumSubscribers() == 0 )&& (pub_barpoint_cloud_.getNumSubscribers() ==0) && (pub_clearpoint_cloud_.getNumSubscribers() ==0) && (pub_occupancy_grid_.getNumSubscribers()==0))
514  {
515  sub_depth_.shutdown();
516  }
517  else if (!sub_depth_)
518  {
519  image_transport::TransportHints hints("raw", ros::TransportHints(), getPrivateNodeHandle());
520  sub_depth_ = it_->subscribeCamera("image_rect", queue_size_, &OccupancyXyzNodelet::depthCb, this, hints);
521  }
522 }
523 
524 void OccupancyXyzNodelet::depthCb(const sensor_msgs::ImageConstPtr& depth_msg,
525  const sensor_msgs::CameraInfoConstPtr& info_msg)
526 {
527 
528  if (!ANN_ready_) return;
529  PointCloud::Ptr cloud_msg(new PointCloud);
530  cloud_msg->header = depth_msg->header;
531  cloud_msg->height = depth_msg->height;
532  cloud_msg->width = depth_msg->width;
533  cloud_msg->is_dense = false;
534  cloud_msg->is_bigendian = false;
535  cloud_msg->header.frame_id=frame_id_;
536 
537  sensor_msgs::PointCloud2Modifier pcd_modifier(*cloud_msg);
538  pcd_modifier.setPointCloud2FieldsByString(1, "xyz");
539 
540  std::vector<int8_t> a(height_temp_*2*width_temp_,-1);
541  occupancygrid_msg_.data = a;
542  memcpy(mapGrid_,unkown_mapGrid_,sizeof(int8_t)*(occupancygrid_msg_.info.height*occupancygrid_msg_.info.width));
543  // Update camera model
544  model_.fromCameraInfo(info_msg);
545 
546  if (depth_msg->encoding == enc::TYPE_16UC1)
547  {
548  this->convert2(depth_msg, cloud_msg, model_);
549  }
550  else
551  {
552  NODELET_ERROR_THROTTLE(5, "Depth image has unsupported encoding [%s]", depth_msg->encoding.c_str());
553  return;
554  }
555  // Time
556  ros::Time current_time = ros::Time::now();
557  if((num_frame_%2==0))
558  {
559  num_frame_++;
560  return;//10hz
561  }
562  num_frame_++;
563  occupancygrid_msg_.header = depth_msg->header;
564  occupancygrid_msg_.header.frame_id=frame_id_;
565  occupancygrid_msg_.info.map_load_time=current_time;
566  memcpy(&occupancygrid_msg_.data[0],mapGrid_,sizeof(int8_t)*(occupancygrid_msg_.info.height*occupancygrid_msg_.info.width));
567  pub_point_cloud_.publish (cloud_msg);
568  pub_occupancy_grid_.publish(occupancygrid_msg_);
569 }
570 
571 } // namespace xiaoqiang_depth_image_proc
572 
573 // Register as nodelet
boost::function< void(const SingleSubscriberPublisher &)> SubscriberStatusCallback
image_transport::CameraSubscriber sub_depth_
ANNdist * ANNdistArray
Definition: ANN.h:377
#define NODELET_ERROR_THROTTLE(rate,...)
PLUGINLIB_EXPORT_CLASS(xiaoqiang_depth_image_proc::OccupancyXyzNodelet, nodelet::Nodelet)
image_geometry::PinholeCameraModel model_
DLL_API ANNpointArray annAllocPts(int n, int dim)
Definition: ANN.cpp:117
LineFunc(double p1[], double p2[])
boost::shared_ptr< image_transport::ImageTransport > it_
ANNpoint * ANNpointArray
Definition: ANN.h:376
bool param(const std::string &param_name, T &param_val, const T &default_val) const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
DLL_API ANNpoint annAllocPt(int dim, ANNcoord c=0)
Definition: ANN.cpp:110
int ANNidx
Definition: ANN.h:175
ANNidx * ANNidxArray
Definition: ANN.h:378
bool getParam(const std::string &key, std::string &s) const
static Time now()
#define PP(i)
Definition: kd_util.cpp:44
void setPointCloud2FieldsByString(int n_fields,...)
ANNcoord * ANNpoint
Definition: ANN.h:375
double ANNdist
Definition: ANN.h:159
double getPointPos(double p[])


xiaoqiang_depth_image_proc
Author(s): Xie fusheng
autogenerated on Mon Jun 10 2019 15:53:04