Node.cpp
Go to the documentation of this file.
1 
18 #include "Node.h"
19 
20 #include <pcl/filters/passthrough.h>
23 #include <visualization_msgs/Marker.h>
24 
25 namespace amcl3d
26 {
27 Node::Node() : grid3d_(parameters_.sensor_dev_), pf_(), nh_(ros::this_node::getName())
28 {
29  ROS_DEBUG("[%s] Node::Node()", ros::this_node::getName().data());
30 }
31 
33 {
34  ROS_DEBUG("[%s] Node::~Node()", ros::this_node::getName().data());
35 }
36 
37 void Node::spin()
38 {
39  ROS_DEBUG("[%s] Node::spin()", ros::this_node::getName().data());
40 
42  return;
43 
45  {
46  grid_slice_pub_ = nh_.advertise<nav_msgs::OccupancyGrid>("grid_slice", 1, true);
49  }
50 
52  {
53  map_point_cloud_pub_ = nh_.advertise<sensor_msgs::PointCloud2>("map_point_cloud", 1, true);
56  }
57 
59 
61  {
64  }
65 
66  point_sub_ = nh_.subscribe("/laser_sensor", 1, &Node::pointcloudCallback, this);
67  odom_sub_ = nh_.subscribe("/odometry", 1, &Node::odomCallback, this);
68  range_sub_ = nh_.subscribe("/radiorange_sensor", 1, &Node::rangeCallback, this);
69 
70  particles_pose_pub_ = nh_.advertise<geometry_msgs::PoseArray>("particle_cloud", 1, true);
71  range_markers_pub_ = nh_.advertise<visualization_msgs::Marker>("range", 0);
72  odom_base_pub_ = nh_.advertise<geometry_msgs::TransformStamped>("base_transform", 1);
73 
74  cloud_filter_pub_ = nh_.advertise<sensor_msgs::PointCloud2>("pointcloud_voxelfiltered", 0);
75 
76  while (ros::ok())
77  {
78  ros::spinOnce();
79  usleep(100);
80  }
81 
82  nh_.shutdown();
83 }
84 
86 {
87  ROS_DEBUG("[%s] Node::publishMapPointCloud()", ros::this_node::getName().data());
88 
89  map_point_cloud_msg_.header.stamp = ros::Time::now();
91 }
92 
94 {
95  ROS_DEBUG("[%s] Node::publishGridSlice()", ros::this_node::getName().data());
96 
97  grid_slice_msg_.header.stamp = ros::Time::now();
99 }
100 
102 {
103  ROS_DEBUG("[%s] Node::publishGridSlice()", ros::this_node::getName().data());
104 
106 
107  static tf::TransformBroadcaster tf_broadcaster;
108  tf_broadcaster.sendTransform(grid_to_world_tf_);
109 }
110 
112 {
114  if (!pf_.isInitialized())
115  return;
116 
117  geometry_msgs::Point32 grid3d;
118  grid3d_.getMinOctomap(grid3d.x, grid3d.y, grid3d.z);
119 
121  geometry_msgs::PoseArray msg;
122  pf_.buildParticlesPoseMsg(grid3d, msg);
123  msg.header.stamp = ros::Time::now();
124  msg.header.frame_id = parameters_.global_frame_id_;
125 
128 }
129 
130 void Node::pointcloudCallback(const sensor_msgs::PointCloud2ConstPtr& msg)
131 {
132  ROS_INFO("pointcloudCallback open");
133 
134  if (!is_odom_)
135  {
136  ROS_WARN("Odometry transform not received");
137  return;
138  }
139 
141  if (!checkUpdateThresholds())
142  return;
143 
144  static const ros::Duration update_interval(1.0 / parameters_.update_rate_);
145  nextupdate_time_ = ros::Time::now() + update_interval;
146 
148 
149  clock_t begin_filter = clock();
150 
151  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
152  pcl::fromROSMsg(*msg, *cloud);
153  pcl::PassThrough<pcl::PointXYZ> pass;
154  pass.setInputCloud(cloud);
155  pass.setFilterFieldName("x");
156  pass.setFilterLimits(-2, 2);
157  pass.setNegative(false);
158  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
159  pass.filter(*cloud_filtered);
160 
161  sensor_msgs::PointCloud2 passCloud;
162  pcl::toROSMsg(*cloud_filtered, passCloud);
163 
164  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud2(new pcl::PointCloud<pcl::PointXYZ>);
165  pcl::fromROSMsg(*msg, *cloud2);
166  pcl::PassThrough<pcl::PointXYZ> pass2;
167  pass2.setInputCloud(cloud2);
168  pass2.setFilterFieldName("y");
169  pass2.setFilterLimits(-2, 2);
170  pass2.setNegative(false);
171  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered2(new pcl::PointCloud<pcl::PointXYZ>);
172  pass2.filter(*cloud_filtered2);
173 
174  sensor_msgs::PointCloud2 passCloud2;
175  pcl::toROSMsg(*cloud_filtered2, passCloud2);
176 
178 
179  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered_total(new pcl::PointCloud<pcl::PointXYZ>);
180  sensor_msgs::PointCloud2 frustumCloudTotal;
181  *cloud_filtered_total = *cloud_filtered;
182  *cloud_filtered_total += *cloud_filtered2;
183  cloud_filtered_total->header = cloud->header;
184  pcl::toROSMsg(*cloud_filtered_total, frustumCloudTotal);
185  cloud_filter_pub_.publish(frustumCloudTotal);
186 
187  clock_t end_filter = clock();
188  double elapsed_secs = double(end_filter - begin_filter) / CLOCKS_PER_SEC;
189  ROS_INFO("Filter time: [%lf] sec", elapsed_secs);
190 
193  const double delta_x = odom_increment_tf.getOrigin().getX();
194  const double delta_y = odom_increment_tf.getOrigin().getY();
195  const double delta_z = odom_increment_tf.getOrigin().getZ();
196  const double delta_a = getYawFromTf(odom_increment_tf);
197 
198  clock_t begin_predict = clock();
200  delta_x, delta_y, delta_z, delta_a);
201  clock_t end_predict = clock();
202  elapsed_secs = double(end_predict - begin_predict) / CLOCKS_PER_SEC;
203  ROS_INFO("Predict time: [%lf] sec", elapsed_secs);
204 
206  const float sr = sin(0);
207  const float cr = cos(0);
208  const float sp = sin(0);
209  const float cp = cos(0);
210  float r00, r01, r02, r10, r11, r12, r20, r21, r22;
211  r00 = cp;
212  r01 = sp * sr;
213  r02 = cr * sp;
214  r10 = 0;
215  r11 = cr;
216  r12 = -sr;
217  r20 = -sp;
218  r21 = cp * sr;
219  r22 = cp * cr;
220  sensor_msgs::PointCloud2ConstIterator<float> iter_x(frustumCloudTotal, "x");
221  sensor_msgs::PointCloud2ConstIterator<float> iter_y(frustumCloudTotal, "y");
222  sensor_msgs::PointCloud2ConstIterator<float> iter_z(frustumCloudTotal, "z");
223  std::vector<pcl::PointXYZ> points;
224  points.resize(frustumCloudTotal.width);
225  for (uint32_t i = 0; i < frustumCloudTotal.width; ++i, ++iter_x, ++iter_y, ++iter_z)
226  {
227  points[i].x = *iter_x * r00 + *iter_y * r01 + *iter_z * r02;
228  points[i].y = *iter_x * r10 + *iter_y * r11 + *iter_z * r12;
229  points[i].z = *iter_x * r20 + *iter_y * r21 + *iter_z * r22;
230  }
231 
233  clock_t begin_update = clock();
235  clock_t end_update = clock();
236  elapsed_secs = double(end_update - begin_update) / CLOCKS_PER_SEC;
237  ROS_INFO("Update time: [%lf] sec", elapsed_secs);
238 
239  mean_p_ = pf_.getMean();
240 
242  range_data.clear();
243 
246 
248  clock_t begin_resample = clock();
249  static int n_updates = 0;
250  if (++n_updates > parameters_.resample_interval_)
251  {
252  n_updates = 0;
253  pf_.resample();
254  }
255  clock_t end_resample = clock();
256  elapsed_secs = double(end_resample - begin_resample) / CLOCKS_PER_SEC;
257  ROS_INFO("Resample time: [%lf] sec", elapsed_secs);
258 
261 
262  ROS_INFO("pointcloudCallback close");
263 }
264 
265 void Node::odomCallback(const geometry_msgs::TransformStampedConstPtr& msg)
266 {
267  ROS_INFO("odomCallback open");
268 
270  tf::Vector3(msg->transform.translation.x, msg->transform.translation.y, msg->transform.translation.z));
271  base_2_odom_tf_.setRotation(tf::Quaternion(msg->transform.rotation.x, msg->transform.rotation.y,
272  msg->transform.rotation.z, msg->transform.rotation.w));
273 
275  if (!pf_.isInitialized())
276  {
277  ROS_WARN("Filter not initialized yet, waiting for initial pose.");
279  {
280  tf::Transform init_pose;
282  init_pose.setRotation(tf::Quaternion(0.0, 0.0, sin(parameters_.init_a_ * 0.5), cos(parameters_.init_a_ * 0.5)));
285  }
286  return;
287  }
288 
290  double yaw;
292 
293  static tf::TransformBroadcaster tf_br;
294  tf_br.sendTransform(
296 
297  if (!is_odom_)
298  {
299  is_odom_ = true;
300 
303  }
304 
305  static bool has_takenoff = false;
306  if (!has_takenoff)
307  {
308  ROS_WARN("Not <<taken off>> yet");
309 
312 
315 
316  lastmean_p_ = mean_p_; // for not 'jumping' whenever has_takenoff is true
317  }
318  else
319  {
321  if (std::isnan(mean_p_.x) || std::isnan(mean_p_.y) || std::isnan(mean_p_.z) || std::isnan(mean_p_.a))
322  {
323  ROS_WARN("AMCL NaN detected");
324  amcl_out_ = true;
325  }
326  if (std::isinf(mean_p_.x) || std::isinf(mean_p_.y) || std::isinf(mean_p_.z) || std::isinf(mean_p_.a))
327  {
328  ROS_WARN("AMCL Inf detected");
329  amcl_out_ = true;
330  }
331 
333  if (fabs(mean_p_.x - lastmean_p_.x) > 1.)
334  {
335  ROS_WARN("AMCL Jump detected in X");
336  amcl_out_ = true;
337  }
338  if (fabs(mean_p_.y - lastmean_p_.y) > 1.)
339  {
340  ROS_WARN("AMCL Jump detected in Y");
341  amcl_out_ = true;
342  }
343  if (fabs(mean_p_.z - lastmean_p_.z) > 1.)
344  {
345  ROS_WARN("AMCL Jump detected in Z");
346  amcl_out_ = true;
347  }
348  if (fabs(mean_p_.a - lastmean_p_.a) > 1.)
349  {
350  ROS_WARN("AMCL Jump detected in Yaw");
351  amcl_out_ = true;
352  }
353 
354  if (!amcl_out_)
355  {
356  geometry_msgs::Point32 grid3d;
357  grid3d_.getMinOctomap(grid3d.x, grid3d.y, grid3d.z);
358 
359  tf::Transform base_2_world_tf;
360  base_2_world_tf.setOrigin(tf::Vector3(mean_p_.x + grid3d.x, mean_p_.y + grid3d.y, mean_p_.z + grid3d.z));
361  tf::Quaternion q;
362  q.setRPY(roll_, pitch_, mean_p_.a);
363  base_2_world_tf.setRotation(q);
364 
365  base_2_world_tf = base_2_world_tf * lastupdatebase_2_odom_tf_.inverse() * base_2_odom_tf_;
366 
368 
369  lastbase_2_world_tf_ = base_2_world_tf;
370  lastodom_2_world_tf_ = base_2_world_tf * base_2_odom_tf_.inverse();
371 
373  }
374  else
375  {
378  }
379  }
380 
382  geometry_msgs::TransformStamped odom_2_base_tf;
383  odom_2_base_tf.header.stamp = msg->header.stamp;
384  odom_2_base_tf.header.frame_id = parameters_.global_frame_id_;
385  odom_2_base_tf.child_frame_id = parameters_.base_frame_id_;
386  odom_2_base_tf.transform.translation.x = lastbase_2_world_tf_.getOrigin().getX();
387  odom_2_base_tf.transform.translation.y = lastbase_2_world_tf_.getOrigin().getY();
388  odom_2_base_tf.transform.translation.z = lastbase_2_world_tf_.getOrigin().getZ();
389  odom_2_base_tf.transform.rotation.x = lastbase_2_world_tf_.getRotation().getX();
390  odom_2_base_tf.transform.rotation.y = lastbase_2_world_tf_.getRotation().getY();
391  odom_2_base_tf.transform.rotation.z = lastbase_2_world_tf_.getRotation().getZ();
392  odom_2_base_tf.transform.rotation.w = lastbase_2_world_tf_.getRotation().getW();
393  odom_base_pub_.publish(odom_2_base_tf);
394 
397 
398  ROS_INFO("odomCallback close");
399 }
400 
401 void Node::rangeCallback(const rosinrange_msg::range_poseConstPtr& msg)
402 {
403  ROS_INFO("rangeCallback open");
404 
405  const int node = msg->destination_id;
406 
407  geometry_msgs::Point32 grid3d;
408  grid3d_.getMinOctomap(grid3d.x, grid3d.y, grid3d.z);
409 
410  geometry_msgs::Point anchor;
411  anchor.x = msg->position.x;
412  anchor.y = msg->position.y;
413  anchor.z = msg->position.z;
414 
415  float ax, ay, az;
416  ax = msg->position.x - grid3d.x;
417  ay = msg->position.y - grid3d.y;
418  az = msg->position.z - grid3d.z;
419 
420  range_data.push_back(Range(static_cast<float>(msg->range), ax, ay, az));
421 
422  geometry_msgs::Point uav;
423  uav.x = mean_p_.x + grid3d.x;
424  uav.y = mean_p_.y + grid3d.y;
425  uav.z = mean_p_.z + grid3d.z;
426 
427  rvizMarkerPublish(msg->destination_id, static_cast<float>(msg->range), uav, anchor);
428 
429  ROS_INFO("rangeCallback close");
430 }
431 
433 {
434  ROS_DEBUG("Checking for AMCL3D update");
435 
437  return false;
438 
440 
443  {
444  ROS_INFO("Translation update");
445  return true;
446  }
447 
449  double yaw, pitch, roll;
450  odom_increment_tf.getBasis().getRPY(roll, pitch, yaw);
451  if (fabs(yaw) > parameters_.a_th_)
452  {
453  ROS_INFO("Rotation update");
454  return true;
455  }
456 
457  return false;
458 }
459 
460 void Node::setInitialPose(const tf::Transform& init_pose, const float x_dev, const float y_dev, const float z_dev,
461  const float a_dev)
462 {
463  initodom_2_world_tf_ = init_pose;
464 
465  geometry_msgs::Point32 grid3d;
466  grid3d_.getMinOctomap(grid3d.x, grid3d.y, grid3d.z);
467 
468  const tf::Vector3 t = init_pose.getOrigin();
469 
470  const float x_init = t.x() - grid3d.x;
471  const float y_init = t.y() - grid3d.y;
472  const float z_init = t.z() - grid3d.z;
473  const float a_init = static_cast<float>(getYawFromTf(init_pose));
474 
475  pf_.init(parameters_.num_particles_, x_init, y_init, z_init, a_init, x_dev, y_dev, z_dev, a_dev);
476 
477  mean_p_ = pf_.getMean();
479 
483 
486 }
487 
489 {
490  double yaw, pitch, roll;
491  tf.getBasis().getRPY(roll, pitch, yaw);
492 
493  return yaw;
494 }
495 
496 void Node::rvizMarkerPublish(const uint32_t anchor_id, const float r, const geometry_msgs::Point& uav,
497  const geometry_msgs::Point& anchor)
498 {
499  visualization_msgs::Marker marker;
500  marker.header.frame_id = parameters_.global_frame_id_;
501  marker.header.stamp = ros::Time::now();
502  marker.ns = "amcl3d";
503  marker.id = anchor_id;
504  marker.type = visualization_msgs::Marker::LINE_STRIP;
505  marker.action = visualization_msgs::Marker::ADD;
506  marker.scale.x = 0.1;
507  marker.scale.y = r;
508  marker.scale.z = r;
509  marker.color.a = 0.5;
510  if (amcl_out_)
511  {
512  marker.color.r = 1.0;
513  marker.color.g = 1.0;
514  marker.color.b = 1.0;
515  }
516  else
517  {
518  switch (anchor_id)
519  {
520  case 0:
521  marker.color.r = 0.0;
522  marker.color.g = 1.0;
523  marker.color.b = 0.0;
524  break;
525  case 1:
526  marker.color.r = 1.0;
527  marker.color.g = 0.0;
528  marker.color.b = 0.0;
529  break;
530  case 2:
531  marker.color.r = 0.0;
532  marker.color.g = 0.0;
533  marker.color.b = 1.0;
534  break;
535  }
536  }
537  marker.points.clear();
538  marker.points.push_back(uav);
539  marker.points.push_back(anchor);
540 
542  range_markers_pub_.publish(marker);
543 }
544 
545 } // namespace amcl3d
void odomCallback(const geometry_msgs::TransformStampedConstPtr &msg)
Definition: Node.cpp:265
TFSIMD_FORCE_INLINE void setRotation(const Quaternion &q)
ros::Publisher odom_base_pub_
Definition: Node.h:86
Parameters parameters_
Definition: Node.h:61
tf::StampedTransform grid_to_world_tf_
Definition: Node.h:75
double publish_grid_slice_rate_
Definition: Parameters.h:40
void publish(const boost::shared_ptr< M > &message) const
double take_off_height_
Definition: Parameters.h:55
void spin()
Definition: Node.cpp:37
tf::Transform base_2_odom_tf_
Definition: Node.h:88
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
double publish_grid_tf_rate_
Definition: Parameters.h:41
TFSIMD_FORCE_INLINE Matrix3x3 & getBasis()
std::string base_frame_id_
Definition: Parameters.h:29
sensor_msgs::PointCloud2 map_point_cloud_msg_
Definition: Node.h:67
void publishParticles()
Definition: Node.cpp:111
double sensor_range_
Definition: Parameters.h:44
std::string odom_frame_id_
Definition: Parameters.h:30
bool open(const std::string &map_path)
Definition: Grid3d.cpp:33
std::string global_frame_id_
Definition: Parameters.h:31
bool amcl_out_
Definition: Node.h:79
std::string getName(void *handle)
ros::Timer grid_slice_pub_timer_
Definition: Node.h:73
ros::Subscriber point_sub_
Definition: Node.h:85
ROSCPP_DECL const std::string & getName()
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
TFSIMD_FORCE_INLINE const tfScalar & getY() const
TFSIMD_FORCE_INLINE const tfScalar & getW() const
void update(const Grid3d &grid3d, const std::vector< pcl::PointXYZ > &points, const std::vector< Range > &range_data, const double alpha, const double sigma)
Update Particles with a pointcloud update.
double getYawFromTf(const tf::Transform &tf)
Return yaw from a given TF.
Definition: Node.cpp:488
TFSIMD_FORCE_INLINE const tfScalar & getZ() const
#define ROS_WARN(...)
float a
Yaw angle.
Particle getMean() const
Get mean value from particles.
bool buildGridSliceMsg(const float z, nav_msgs::OccupancyGrid &msg) const
Definition: Grid3d.cpp:61
void publishGridSlice(const ros::TimerEvent &)
Definition: Node.cpp:93
ros::Publisher cloud_filter_pub_
Definition: Node.h:93
ros::Timer map_point_cloud_pub_timer_
Definition: Node.h:69
TFSIMD_FORCE_INLINE const tfScalar & x() const
bool checkUpdateThresholds()
Check motion and time thresholds for AMCL update.
Definition: Node.cpp:432
ros::Publisher particles_pose_pub_
Definition: Node.h:86
ros::NodeHandle nh_
Definition: Node.h:65
Include Grid.hpp.
Definition: Grid3d.cpp:23
double publish_point_cloud_rate_
Definition: Parameters.h:39
TFSIMD_FORCE_INLINE const tfScalar & z() const
double roll_
Definition: Node.h:80
void setRPY(const tfScalar &roll, const tfScalar &pitch, const tfScalar &yaw)
void getRPY(tfScalar &roll, tfScalar &pitch, tfScalar &yaw, unsigned int solution_number=1) const
#define ROS_INFO(...)
double pitch_
Definition: Node.h:80
ros::Subscriber range_sub_
Definition: Node.h:85
Grid3d grid3d_
Definition: Node.h:62
std::vector< Range > range_data
Definition: Node.h:82
ROSCPP_DECL bool ok()
TFSIMD_FORCE_INLINE const tfScalar & y() const
void sendTransform(const StampedTransform &transform)
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
void buildParticlesPoseMsg(const geometry_msgs::Point32 &offset, geometry_msgs::PoseArray &msg) const
bool is_odom_
Definition: Node.h:78
virtual ~Node()
Definition: Node.cpp:32
Transform inverse() const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
tf::Transform lastupdatebase_2_odom_tf_
Definition: Node.h:88
bool buildMapPointCloudMsg(sensor_msgs::PointCloud2 &msg) const
Definition: Grid3d.cpp:101
void predict(const double odom_x_mod, const double odom_y_mod, const double odom_z_mod, const double odom_a_mod, const double delta_x, const double delta_y, const double delta_z, const double delta_a)
tf::Transform lastbase_2_world_tf_
Definition: Node.h:88
tf::Transform amcl_out_lastbase_2_odom_tf_
Definition: Node.h:88
TFSIMD_FORCE_INLINE Vector3 & getOrigin()
tf::Transform lastodom_2_world_tf_
Definition: Node.h:88
void rvizMarkerPublish(const uint32_t anchor_id, const float r, const geometry_msgs::Point &uav, const geometry_msgs::Point &anchor)
To show range sensors in Rviz.
Definition: Node.cpp:496
Particle mean_p_
Definition: Node.h:83
void buildGrid3d2WorldTf(const std::string &global_frame_id, tf::StampedTransform &tf) const
Definition: Grid3d.cpp:113
ros::Publisher range_markers_pub_
Definition: Node.h:86
bool isInitialized() const
ros::Publisher map_point_cloud_pub_
Definition: Node.h:68
void setInitialPose(const tf::Transform &init_pose, const float x_dev, const float y_dev, const float z_dev, const float a_dev)
Set the initial pose of the particle filter.
Definition: Node.cpp:460
void publishGridTf(const ros::TimerEvent &)
Definition: Node.cpp:101
void getMinOctomap(float &x, float &y, float &z) const
Definition: Grid3d.cpp:159
Quaternion getRotation() const
ros::Time nextupdate_time_
Definition: Node.h:91
tf::Transform initodom_2_world_tf_
Definition: Node.h:88
void publishMapPointCloud(const ros::TimerEvent &)
Definition: Node.cpp:85
void init(const int num_particles, const float x_init, const float y_init, const float z_init, const float a_init, const float x_dev, const float y_dev, const float z_dev, const float a_dev)
Set the initial pose of the particle filter.
void toROSMsg(const sensor_msgs::PointCloud2 &cloud, sensor_msgs::Image &image)
void resample()
Resample the set of particles using low-variance sampling.
TFSIMD_FORCE_INLINE const tfScalar & getX() const
static Time now()
nav_msgs::OccupancyGrid grid_slice_msg_
Definition: Node.h:71
float x
Position.
tf::Transform odom_increment_tf
Definition: Node.h:88
ros::Subscriber odom_sub_
Definition: Node.h:85
ROSCPP_DECL void spinOnce()
Struct that contains the data concerning one range meaurement.
ParticleFilter pf_
Definition: Node.h:63
ros::Publisher grid_slice_pub_
Definition: Node.h:72
TFSIMD_FORCE_INLINE void setOrigin(const Vector3 &origin)
void pointcloudCallback(const sensor_msgs::PointCloud2ConstPtr &msg)
Definition: Node.cpp:130
void rangeCallback(const rosinrange_msg::range_poseConstPtr &msg)
Definition: Node.cpp:401
TFSIMD_FORCE_INLINE tfScalar length() const
ros::Timer grid_to_world_tf_timer_
Definition: Node.h:76
#define ROS_DEBUG(...)
Particle lastmean_p_
Definition: Node.h:83
std::string map_path_
Definition: Parameters.h:32


amcl3d
Author(s): Francisco J.Perez-Grau
autogenerated on Sun Sep 15 2019 04:08:05