mcl_3dl.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2020, the mcl_3dl authors
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <algorithm>
31 #include <cassert>
32 #include <cmath>
33 #include <limits>
34 #include <map>
35 #include <memory>
36 #include <string>
37 #include <utility>
38 #include <vector>
39 
40 #include <Eigen/Core>
41 
42 #include <boost/chrono.hpp>
43 #include <boost/shared_ptr.hpp>
44 
45 #include <ros/ros.h>
46 
47 #include <sensor_msgs/PointCloud2.h>
49 #include <nav_msgs/Odometry.h>
50 #include <sensor_msgs/Imu.h>
51 #include <geometry_msgs/PoseArray.h>
52 #include <geometry_msgs/PoseWithCovarianceStamped.h>
53 #include <geometry_msgs/TransformStamped.h>
54 #include <visualization_msgs/MarkerArray.h>
55 #include <mcl_3dl_msgs/ResizeParticle.h>
56 #include <mcl_3dl_msgs/Status.h>
57 #include <mcl_3dl_msgs/LoadPCD.h>
58 #include <std_srvs/Trigger.h>
60 
65 
67 #include <pcl/point_types.h>
68 #include <pcl_ros/point_cloud.h>
69 #include <pcl_ros/transforms.h>
70 #include <pcl/conversions.h>
71 #include <pcl/filters/voxel_grid.h>
72 #include <pcl/kdtree/kdtree.h>
73 #include <pcl/kdtree/kdtree_flann.h>
74 
75 #include <mcl_3dl/chunked_kdtree.h>
76 #include <mcl_3dl/cloud_accum.h>
77 #include <mcl_3dl/filter.h>
78 #include <mcl_3dl/filter_vec3.h>
86 #include <mcl_3dl/nd.h>
88 #include <mcl_3dl/parameters.h>
89 #include <mcl_3dl/pf.h>
93 #include <mcl_3dl/point_types.h>
94 #include <mcl_3dl/quat.h>
95 #include <mcl_3dl/raycast.h>
96 #include <mcl_3dl/state_6dof.h>
97 #include <mcl_3dl/vec3.h>
98 
100 
101 namespace mcl_3dl
102 {
104 {
105 protected:
107  std::shared_ptr<pf::ParticleFilter<State6DOF, float, ParticleWeightedMeanQuat, std::default_random_engine>> pf_;
108 
109  class MyPointRepresentation : public pcl::PointRepresentation<PointType>
110  {
111  using pcl::PointRepresentation<PointType>::nr_dimensions_;
112 
113  public:
115  {
116  nr_dimensions_ = 3;
117  trivial_ = true;
118  }
119 
120  virtual void copyToFloatArray(const PointType& p, float* out) const
121  {
122  out[0] = p.x;
123  out[1] = p.y;
124  out[2] = p.z;
125  }
126  };
127  void cbMapcloud(const sensor_msgs::PointCloud2::ConstPtr& msg)
128  {
129  ROS_INFO("map received");
130  pcl::PointCloud<PointType>::Ptr pc_tmp(new pcl::PointCloud<PointType>);
131  if (!mcl_3dl::fromROSMsg(*msg, *pc_tmp))
132  {
133  has_map_ = false;
134  return;
135  }
136  const ros::Time map_stamp = (msg->header.stamp != ros::Time()) ? msg->header.stamp : ros::Time::now();
137  pcl_conversions::toPCL(map_stamp, pc_tmp->header.stamp);
138 
139  loadMapCloud(pc_tmp);
140  }
141  void cbMapcloudUpdate(const sensor_msgs::PointCloud2::ConstPtr& msg)
142  {
143  ROS_INFO("map_update received");
144  pcl::PointCloud<PointType>::Ptr pc_tmp(new pcl::PointCloud<PointType>);
145  if (!mcl_3dl::fromROSMsg(*msg, *pc_tmp))
146  return;
147 
148  pc_update_.reset(new pcl::PointCloud<PointType>);
149  pcl::VoxelGrid<PointType> ds;
150  ds.setInputCloud(pc_tmp);
152  ds.filter(*pc_update_);
153  }
154 
155  void cbPosition(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& msg)
156  {
157  const double len2 =
158  msg->pose.pose.orientation.x * msg->pose.pose.orientation.x +
159  msg->pose.pose.orientation.y * msg->pose.pose.orientation.y +
160  msg->pose.pose.orientation.z * msg->pose.pose.orientation.z +
161  msg->pose.pose.orientation.w * msg->pose.pose.orientation.w;
162  if (std::abs(len2 - 1.0) > 0.1)
163  {
164  ROS_ERROR("Discarded invalid initialpose. The orientation must be unit quaternion.");
165  return;
166  }
167 
168  geometry_msgs::PoseStamped pose_in, pose;
169  pose_in.header = msg->header;
170  pose_in.pose = msg->pose.pose;
171  try
172  {
173  const geometry_msgs::TransformStamped trans = tfbuf_.lookupTransform(
174  params_.frame_ids_["map"], pose_in.header.frame_id, pose_in.header.stamp, ros::Duration(1.0));
175  tf2::doTransform(pose_in, pose, trans);
176  }
177  catch (tf2::TransformException& e)
178  {
179  return;
180  }
181  const State6DOF mean(Vec3(pose.pose.position.x, pose.pose.position.y, pose.pose.position.z),
182  Quat(pose.pose.orientation.x,
183  pose.pose.orientation.y,
184  pose.pose.orientation.z,
185  pose.pose.orientation.w));
186  const MultivariateNoiseGenerator<float> noise_gen(mean, msg->pose.covariance);
187  pf_->initUsingNoiseGenerator(noise_gen);
188 
189  pc_update_.reset();
190  auto integ_reset_func = [](State6DOF& s)
191  {
192  s.odom_err_integ_lin_ = Vec3();
193  s.odom_err_integ_ang_ = Vec3();
194  };
195  pf_->predict(integ_reset_func);
196 
198  }
199 
200  void cbOdom(const nav_msgs::Odometry::ConstPtr& msg)
201  {
202  odom_ =
203  State6DOF(
204  Vec3(msg->pose.pose.position.x,
205  msg->pose.pose.position.y,
206  msg->pose.pose.position.z),
207  Quat(msg->pose.pose.orientation.x,
208  msg->pose.pose.orientation.y,
209  msg->pose.pose.orientation.z,
210  msg->pose.pose.orientation.w));
211  if (!has_odom_)
212  {
213  odom_prev_ = odom_;
214  odom_last_ = msg->header.stamp;
215  has_odom_ = true;
216  return;
217  }
218  const float dt = (msg->header.stamp - odom_last_).toSec();
219  if (dt < 0.0 || dt > 5.0)
220  {
221  ROS_WARN("Detected time jump in odometry. Resetting.");
222  has_odom_ = false;
223  return;
224  }
225  else if (dt > 0.05)
226  {
227  motion_prediction_model_->setOdoms(odom_prev_, odom_, dt);
228  auto prediction_func = [this](State6DOF& s)
229  {
230  motion_prediction_model_->predict(s);
231  };
232  pf_->predict(prediction_func);
233  odom_last_ = msg->header.stamp;
234  odom_prev_ = odom_;
235  }
236  if (params_.fake_imu_)
237  {
238  const Vec3 accel = odom_.rot_ * Vec3(0.0, 0.0, 1.0);
239  sensor_msgs::Imu::Ptr imu(new sensor_msgs::Imu);
240  imu->header = msg->header;
241  imu->linear_acceleration.x = accel.x_;
242  imu->linear_acceleration.y = accel.y_;
243  imu->linear_acceleration.z = accel.z_;
244  imu->orientation = msg->pose.pose.orientation;
245  cbImu(imu);
246  }
247  }
248  void cbCloud(const sensor_msgs::PointCloud2::ConstPtr& msg)
249  {
250  status_ = mcl_3dl_msgs::Status();
251  status_.header.stamp = ros::Time::now();
252  status_.status = mcl_3dl_msgs::Status::NORMAL;
253  status_.error = mcl_3dl_msgs::Status::ERROR_NORMAL;
254  status_.convergence_status = mcl_3dl_msgs::Status::CONVERGENCE_STATUS_NORMAL;
255 
256  if (!has_map_)
257  return;
258 
259  accum_->push(
260  msg->header.frame_id,
261  msg,
262  std::bind(&MCL3dlNode::measure, this),
263  std::bind(&MCL3dlNode::accumCloud, this, std::placeholders::_1),
264  std::bind(&MCL3dlNode::accumClear, this));
265  }
266 
267  void accumClear()
268  {
269  pc_local_accum_.reset(new pcl::PointCloud<PointType>);
270  pc_local_accum_->header.frame_id = params_.frame_ids_["odom"];
271  pc_accum_header_.clear();
272  }
273 
274  bool accumCloud(const sensor_msgs::PointCloud2::ConstPtr& msg)
275  {
276  sensor_msgs::PointCloud2 pc_bl;
277  try
278  {
279  const geometry_msgs::TransformStamped trans = tfbuf_.lookupTransform(
280  params_.frame_ids_["odom"], msg->header.frame_id, msg->header.stamp, ros::Duration(0.1));
281  tf2::doTransform(*msg, pc_bl, trans);
282  }
283  catch (tf2::TransformException& e)
284  {
285  ROS_INFO("Failed to transform pointcloud: %s", e.what());
286  return false;
287  }
288  pcl::PointCloud<PointType>::Ptr pc_tmp(new pcl::PointCloud<PointType>);
289  if (!mcl_3dl::fromROSMsg(pc_bl, *pc_tmp))
290  {
291  ROS_INFO("Failed to convert pointcloud");
292  return false;
293  }
294 
295  for (auto& p : pc_tmp->points)
296  {
297  p.label = pc_accum_header_.size();
298  }
299  *pc_local_accum_ += *pc_tmp;
300  pc_accum_header_.push_back(msg->header);
301  return true;
302  }
303 
304  void measure()
305  {
306  cnt_measure_++;
307  if (cnt_measure_ % static_cast<size_t>(params_.skip_measure_) != 0)
308  {
309  return;
310  }
311 
312  if (pc_accum_header_.empty())
313  {
314  ROS_ERROR("MCL measure function is called without available pointcloud");
315  return;
316  }
317  const std_msgs::Header& header = pc_accum_header_.back();
318 
319  try
320  {
321  const geometry_msgs::TransformStamped trans = tfbuf_.lookupTransform(
322  params_.frame_ids_["base_link"],
323  pc_local_accum_->header.frame_id,
324  header.stamp, ros::Duration(0.1));
325 
326  const Eigen::Affine3f trans_eigen =
327  Eigen::Translation3f(
328  trans.transform.translation.x,
329  trans.transform.translation.y,
330  trans.transform.translation.z) *
331  Eigen::Quaternionf(
332  trans.transform.rotation.w,
333  trans.transform.rotation.x,
334  trans.transform.rotation.y,
335  trans.transform.rotation.z);
336  pcl::transformPointCloud(*pc_local_accum_, *pc_local_accum_, trans_eigen);
337  }
338  catch (tf2::TransformException& e)
339  {
340  ROS_INFO("Failed to transform pointcloud: %s", e.what());
341  return;
342  }
343  std::vector<Vec3> origins;
344  for (auto& h : pc_accum_header_)
345  {
346  try
347  {
348  const geometry_msgs::TransformStamped trans = tfbuf_.lookupTransform(
349  params_.frame_ids_["base_link"], header.stamp, h.frame_id, h.stamp, params_.frame_ids_["odom"]);
350  origins.push_back(Vec3(trans.transform.translation.x,
351  trans.transform.translation.y,
352  trans.transform.translation.z));
353  }
354  catch (tf2::TransformException& e)
355  {
356  ROS_INFO("Failed to transform pointcloud: %s", e.what());
357  return;
358  }
359  }
360 
361  const auto ts = boost::chrono::high_resolution_clock::now();
362 
363  pcl::PointCloud<PointType>::Ptr pc_local_full(new pcl::PointCloud<PointType>);
364  pcl::VoxelGrid<PointType> ds;
365  ds.setInputCloud(pc_local_accum_);
367  ds.filter(*pc_local_full);
368 
369  std::map<std::string, pcl::PointCloud<PointType>::Ptr> pc_locals;
370  for (auto& lm : lidar_measurements_)
371  {
372  lm.second->setGlobalLocalizationStatus(
373  params_.num_particles_, pf_->getParticleSize());
374 
376  {
377  const State6DOF prev_mean = pf_->expectation();
378  const float cov_ratio = std::max(0.1f, static_cast<float>(params_.num_particles_) / pf_->getParticleSize());
379  const std::vector<State6DOF> prev_cov = pf_->covariance(1.0, cov_ratio);
380  auto sampler = std::dynamic_pointer_cast<PointCloudSamplerWithNormal<PointType>>(lm.second->getRandomSampler());
381  sampler->setParticleStatistics(prev_mean, prev_cov);
382  }
383  pc_locals[lm.first] = lm.second->filter(pc_local_full);
384  }
385 
386  if (pc_locals["likelihood"]->size() == 0)
387  {
388  ROS_ERROR("All points are filtered out. Failed to localize.");
389  status_.error = mcl_3dl_msgs::Status::ERROR_POINTS_NOT_FOUND;
391  return;
392  }
393 
394  if (pc_locals["beam"] && pc_locals["beam"]->size() == 0)
395  {
396  ROS_DEBUG("All beam points are filtered out. Skipping beam model.");
397  }
398 
399  float match_ratio_min = 1.0;
400  float match_ratio_max = 0.0;
403  auto measure_func = [this, &pc_locals,
404  &origins,
405  &odom_error_lin_nd,
406  &match_ratio_min, &match_ratio_max](const State6DOF& s) -> float
407  {
408  float likelihood = 1;
409  std::map<std::string, float> qualities;
410  for (auto& lm : lidar_measurements_)
411  {
412  const LidarMeasurementResult result = lm.second->measure(
413  kdtree_, pc_locals[lm.first], origins, s);
414  likelihood *= result.likelihood;
415  qualities[lm.first] = result.quality;
416  }
417  if (match_ratio_min > qualities["likelihood"])
418  match_ratio_min = qualities["likelihood"];
419  if (match_ratio_max < qualities["likelihood"])
420  match_ratio_max = qualities["likelihood"];
421 
422  // odometry error integration
423  const float odom_error =
424  odom_error_lin_nd(s.odom_err_integ_lin_.norm());
425  return likelihood * odom_error;
426  };
427  pf_->measure(measure_func);
428 
429  if (static_cast<int>(pf_->getParticleSize()) > params_.num_particles_)
430  {
431  auto bias_func = [](const State6DOF& s, float& p_bias) -> void
432  {
433  p_bias = 1.0;
434  };
435  pf_->bias(bias_func);
436  }
437  else
438  {
441  auto bias_func = [this, &nl_lin, &nl_ang](const State6DOF& s, float& p_bias) -> void
442  {
443  const float lin_diff = (s.pos_ - state_prev_.pos_).norm();
444  Vec3 axis;
445  float ang_diff;
446  (s.rot_ * state_prev_.rot_.inv()).getAxisAng(axis, ang_diff);
447  p_bias = nl_lin(lin_diff) * nl_ang(ang_diff) + 1e-6;
448  assert(std::isfinite(p_bias));
449  };
450  pf_->bias(bias_func);
451  }
452  auto e = pf_->expectationBiased();
453  const auto e_max = pf_->max();
454 
455  assert(std::isfinite(e.pos_.x_));
456  assert(std::isfinite(e.pos_.y_));
457  assert(std::isfinite(e.pos_.z_));
458  assert(std::isfinite(e.rot_.x_));
459  assert(std::isfinite(e.rot_.y_));
460  assert(std::isfinite(e.rot_.z_));
461  assert(std::isfinite(e.rot_.w_));
462 
463  e.rot_.normalize();
464 
465  if (lidar_measurements_["beam"])
466  {
467  visualization_msgs::MarkerArray markers;
468 
469  pcl::PointCloud<PointType>::Ptr pc_particle_beam(new pcl::PointCloud<PointType>);
470  *pc_particle_beam = *pc_locals["beam"];
471  e.transform(*pc_particle_beam);
472  const auto beam_model = std::dynamic_pointer_cast<LidarMeasurementModelBeam>(lidar_measurements_["beam"]);
473  for (auto& p : pc_particle_beam->points)
474  {
475  const int beam_header_id = p.label;
476  const Vec3 pos = e.pos_ + e.rot_ * origins[beam_header_id];
477  const Vec3 end(p.x, p.y, p.z);
479  const LidarMeasurementModelBeam::BeamStatus beam_status = beam_model->getBeamStatus(kdtree_, pos, end, point);
480 
482  {
483  visualization_msgs::Marker marker;
484  marker.header.frame_id = params_.frame_ids_["map"];
485  marker.header.stamp = header.stamp;
486  marker.ns = "Ray collisions";
487  marker.id = markers.markers.size();
488  marker.type = visualization_msgs::Marker::CUBE;
489  marker.action = 0;
490  marker.pose.position.x = point.pos_.x_;
491  marker.pose.position.y = point.pos_.y_;
492  marker.pose.position.z = point.pos_.z_;
493  marker.pose.orientation.x = 0.0;
494  marker.pose.orientation.y = 0.0;
495  marker.pose.orientation.z = 0.0;
496  marker.pose.orientation.w = 1.0;
497  marker.scale.x = marker.scale.y = marker.scale.z = 0.2;
498  marker.lifetime = ros::Duration(0.2);
499  marker.frame_locked = true;
500  switch (beam_status)
501  {
503  marker.color.a = 0.8;
504  marker.color.r = 0.0;
505  marker.color.g = 1.0;
506  marker.color.b = 0.0;
507  break;
509  marker.color.a = 0.8;
510  marker.color.r = 1.0;
511  marker.color.g = 0.0;
512  marker.color.b = 0.0;
513  break;
515  marker.color.a = 0.2;
516  marker.color.r = 0.0;
517  marker.color.g = 1.0;
518  marker.color.b = 0.0;
519  break;
520  default:
521  break;
522  }
523  markers.markers.push_back(marker);
524  }
525 
526  visualization_msgs::Marker marker;
527  marker.header.frame_id = params_.frame_ids_["map"];
528  marker.header.stamp = header.stamp;
529  marker.ns = "Rays";
530  marker.id = markers.markers.size();
531  marker.type = visualization_msgs::Marker::LINE_STRIP;
532  marker.action = 0;
533  marker.pose.position.x = 0.0;
534  marker.pose.position.y = 0.0;
535  marker.pose.position.z = 0.0;
536  marker.pose.orientation.x = 0.0;
537  marker.pose.orientation.y = 0.0;
538  marker.pose.orientation.z = 0.0;
539  marker.pose.orientation.w = 1.0;
540  marker.scale.x = marker.scale.y = marker.scale.z = 0.04;
541  marker.lifetime = ros::Duration(0.2);
542  marker.frame_locked = true;
543  marker.points.resize(2);
544  marker.points[0].x = pos.x_;
545  marker.points[0].y = pos.y_;
546  marker.points[0].z = pos.z_;
547  marker.points[1].x = end.x_;
548  marker.points[1].y = end.y_;
549  marker.points[1].z = end.z_;
550  marker.colors.resize(2);
551 
552  switch (beam_status)
553  {
555  marker.colors[0].a = 0.5;
556  marker.colors[0].r = 0.0;
557  marker.colors[0].g = 1.0;
558  marker.colors[0].b = 0.0;
559  marker.colors[1].a = 0.8;
560  marker.colors[1].r = 0.0;
561  marker.colors[1].g = 1.0;
562  marker.colors[1].b = 0.0;
563  break;
565  marker.colors[0].a = 0.5;
566  marker.colors[0].r = 1.0;
567  marker.colors[0].g = 0.0;
568  marker.colors[0].b = 0.0;
569  marker.colors[1].a = 0.8;
570  marker.colors[1].r = 1.0;
571  marker.colors[1].g = 0.0;
572  marker.colors[1].b = 0.0;
573  break;
575  marker.colors[0].a = 0.5;
576  marker.colors[0].r = 0.0;
577  marker.colors[0].g = 0.0;
578  marker.colors[0].b = 1.0;
579  marker.colors[1].a = 0.8;
580  marker.colors[1].r = 0.0;
581  marker.colors[1].g = 0.0;
582  marker.colors[1].b = 1.0;
583  break;
585  marker.colors[0].a = 0.2;
586  marker.colors[0].r = 0.0;
587  marker.colors[0].g = 1.0;
588  marker.colors[0].b = 0.0;
589  marker.colors[1].a = 0.2;
590  marker.colors[1].r = 0.0;
591  marker.colors[1].g = 1.0;
592  marker.colors[1].b = 0.0;
593  break;
594  }
595  markers.markers.push_back(marker);
596  }
597 
598  pcl::PointCloud<PointType>::Ptr pc_particle(new pcl::PointCloud<PointType>);
599  *pc_particle = *pc_locals["likelihood"];
600  e.transform(*pc_particle);
601  for (auto& p : pc_particle->points)
602  {
603  visualization_msgs::Marker marker;
604  marker.header.frame_id = params_.frame_ids_["map"];
605  marker.header.stamp = header.stamp;
606  marker.ns = "Sample points";
607  marker.id = markers.markers.size();
608  marker.type = visualization_msgs::Marker::SPHERE;
609  marker.action = 0;
610  marker.pose.position.x = p.x;
611  marker.pose.position.y = p.y;
612  marker.pose.position.z = p.z;
613  marker.pose.orientation.x = 0.0;
614  marker.pose.orientation.y = 0.0;
615  marker.pose.orientation.z = 0.0;
616  marker.pose.orientation.w = 1.0;
617  marker.scale.x = marker.scale.y = marker.scale.z = 0.2;
618  marker.lifetime = ros::Duration(0.2);
619  marker.frame_locked = true;
620  marker.color.a = 1.0;
621  marker.color.r = 1.0;
622  marker.color.g = 0.0;
623  marker.color.b = 1.0;
624 
625  markers.markers.push_back(marker);
626  }
627 
628  pub_debug_marker_.publish(markers);
629  }
630 
631  Vec3 map_pos;
632  Quat map_rot;
633  map_pos = e.pos_ - e.rot_ * odom_.rot_.inv() * odom_.pos_;
634  map_rot = e.rot_ * odom_.rot_.inv();
635 
636  bool jump = false;
637  if (static_cast<int>(pf_->getParticleSize()) > params_.num_particles_)
638  {
639  jump = true;
640  state_prev_ = e;
641  }
642  else
643  {
644  Vec3 jump_axis;
645  float jump_ang;
646  float jump_dist = (e.pos_ - state_prev_.pos_).norm();
647  (e.rot_.inv() * state_prev_.rot_).getAxisAng(jump_axis, jump_ang);
648  if (jump_dist > params_.jump_dist_ ||
649  fabs(jump_ang) > params_.jump_ang_)
650  {
651  ROS_INFO("Pose jumped pos:%0.3f, ang:%0.3f", jump_dist, jump_ang);
652  jump = true;
653 
654  auto integ_reset_func = [](State6DOF& s)
655  {
656  s.odom_err_integ_lin_ = Vec3();
657  s.odom_err_integ_ang_ = Vec3();
658  };
659  pf_->predict(integ_reset_func);
660  }
661  state_prev_ = e;
662  }
663  geometry_msgs::TransformStamped trans;
664  if (has_odom_)
665  trans.header.stamp = odom_last_ + tf_tolerance_base_ + *params_.tf_tolerance_;
666  else
667  trans.header.stamp = ros::Time::now() + tf_tolerance_base_ + *params_.tf_tolerance_;
668  trans.header.frame_id = params_.frame_ids_["map"];
669  trans.child_frame_id = params_.frame_ids_["odom"];
670  const auto rpy = map_rot.getRPY();
671  if (jump)
672  {
673  f_ang_->set(rpy);
674  f_pos_->set(map_pos);
675  }
676  map_rot.setRPY(f_ang_->in(rpy));
677  map_pos = f_pos_->in(map_pos);
678  trans.transform.translation = tf2::toMsg(tf2::Vector3(map_pos.x_, map_pos.y_, map_pos.z_));
679  trans.transform.rotation = tf2::toMsg(tf2::Quaternion(map_rot.x_, map_rot.y_, map_rot.z_, map_rot.w_));
680 
681  std::vector<geometry_msgs::TransformStamped> transforms;
682  transforms.push_back(trans);
683 
684  e.rot_ = map_rot * odom_.rot_;
685  e.pos_ = map_pos + map_rot * odom_.pos_;
686 
687  assert(std::isfinite(e.pos_.x_));
688  assert(std::isfinite(e.pos_.y_));
689  assert(std::isfinite(e.pos_.z_));
690  assert(std::isfinite(e.rot_.x_));
691  assert(std::isfinite(e.rot_.y_));
692  assert(std::isfinite(e.rot_.z_));
693  assert(std::isfinite(e.rot_.w_));
694 
695  trans.header.frame_id = params_.frame_ids_["map"];
696  trans.child_frame_id = params_.frame_ids_["floor"];
697  trans.transform.translation = tf2::toMsg(tf2::Vector3(0.0, 0.0, e.pos_.z_));
698  trans.transform.rotation = tf2::toMsg(tf2::Quaternion(0.0, 0.0, 0.0, 1.0));
699 
700  transforms.push_back(trans);
701 
702  if (params_.publish_tf_)
703  tfb_.sendTransform(transforms);
704 
705  // Calculate covariance from sampled particles to reduce calculation cost on global localization.
706  // Use the number of original particles or at least 10% of full particles.
707  const auto cov = pf_->covariance(
708  1.0,
709  std::max(
710  0.1f, static_cast<float>(params_.num_particles_) / pf_->getParticleSize()));
711 
712  geometry_msgs::PoseWithCovarianceStamped pose;
713  pose.header.stamp = header.stamp;
714  pose.header.frame_id = trans.header.frame_id;
715  pose.pose.pose.position.x = e.pos_.x_;
716  pose.pose.pose.position.y = e.pos_.y_;
717  pose.pose.pose.position.z = e.pos_.z_;
718  pose.pose.pose.orientation.x = e.rot_.x_;
719  pose.pose.pose.orientation.y = e.rot_.y_;
720  pose.pose.pose.orientation.z = e.rot_.z_;
721  pose.pose.pose.orientation.w = e.rot_.w_;
722  for (size_t i = 0; i < 36; i++)
723  {
724  pose.pose.covariance[i] = cov[i / 6][i % 6];
725  }
726  pub_pose_.publish(pose);
727 
729  {
730  if (std::sqrt(pose.pose.covariance[0] + pose.pose.covariance[1 * 6 + 1]) > params_.std_warn_thresh_[0] ||
731  std::sqrt(pose.pose.covariance[2 * 6 + 2]) > params_.std_warn_thresh_[1] ||
732  std::sqrt(pose.pose.covariance[5 * 6 + 5]) > params_.std_warn_thresh_[2])
733  {
734  status_.convergence_status = mcl_3dl_msgs::Status::CONVERGENCE_STATUS_LARGE_STD_VALUE;
735  }
736  }
737 
738  if (status_.convergence_status != mcl_3dl_msgs::Status::CONVERGENCE_STATUS_LARGE_STD_VALUE)
739  {
740  Vec3 fix_axis;
741  const float fix_ang = std::sqrt(
742  pose.pose.covariance[3 * 6 + 3] + pose.pose.covariance[4 * 6 + 4] + pose.pose.covariance[5 * 6 + 5]);
743  const float fix_dist = std::sqrt(
744  pose.pose.covariance[0] + pose.pose.covariance[1 * 6 + 1] + pose.pose.covariance[2 * 6 + 2]);
745  ROS_DEBUG("cov: lin %0.3f ang %0.3f", fix_dist, fix_ang);
746  if (fix_dist < params_.fix_dist_ &&
747  fabs(fix_ang) < params_.fix_ang_)
748  {
749  ROS_DEBUG("Localization fixed");
750  status_.convergence_status = mcl_3dl_msgs::Status::CONVERGENCE_STATUS_CONVERGED;
751  }
752  }
753 
754  if (params_.output_pcd_)
755  {
756  pcl::PointCloud<PointType>::Ptr pc_particle(new pcl::PointCloud<PointType>);
757  *pc_particle = *pc_locals["likelihood"];
758  e.transform(*pc_particle);
759  *pc_all_accum_ += *pc_particle;
760  }
761 
763  header.stamp + ros::Duration(1.0) < match_output_last_) &&
765  {
766  match_output_last_ = header.stamp;
767 
768  pcl::PointCloud<pcl::PointXYZ>::Ptr pc_match(new pcl::PointCloud<pcl::PointXYZ>);
769  pcl::PointCloud<pcl::PointXYZ>::Ptr pc_unmatch(new pcl::PointCloud<pcl::PointXYZ>);
770 
771  pcl::PointCloud<PointType>::Ptr pc_local(new pcl::PointCloud<PointType>);
772  *pc_local = *pc_local_full;
773 
774  e.transform(*pc_local);
775 
776  std::vector<int> id(1);
777  std::vector<float> sqdist(1);
778  const double match_dist_sq = params_.match_output_dist_ * params_.match_output_dist_;
779  for (auto& p : pc_local->points)
780  {
781  if (!kdtree_->radiusSearch(p, params_.unmatch_output_dist_, id, sqdist, 1))
782  {
783  pc_unmatch->points.emplace_back(p.x, p.y, p.z);
784  }
785  else if (sqdist[0] < match_dist_sq)
786  {
787  pc_match->points.emplace_back(p.x, p.y, p.z);
788  }
789  }
791  {
792  sensor_msgs::PointCloud2 pc2;
793  pcl::toROSMsg(*pc_match, pc2);
794  pc2.header.stamp = header.stamp;
795  pc2.header.frame_id = params_.frame_ids_["map"];
796  pub_matched_.publish(pc2);
797  }
799  {
800  sensor_msgs::PointCloud2 pc2;
801  pcl::toROSMsg(*pc_unmatch, pc2);
802  pc2.header.stamp = header.stamp;
803  pc2.header.frame_id = params_.frame_ids_["map"];
804  pub_unmatched_.publish(pc2);
805  }
806  }
807 
809 
810  pf_->resample(State6DOF(
817 
818  std::normal_distribution<float> noise(0.0, 1.0);
819  auto update_noise_func = [this, &noise](State6DOF& s)
820  {
821  s.noise_ll_ = noise(engine_) * params_.odom_err_lin_lin_;
822  s.noise_la_ = noise(engine_) * params_.odom_err_lin_ang_;
823  s.noise_aa_ = noise(engine_) * params_.odom_err_ang_ang_;
824  s.noise_al_ = noise(engine_) * params_.odom_err_ang_lin_;
825  };
826  pf_->predict(update_noise_func);
827 
828  const auto tnow = boost::chrono::high_resolution_clock::now();
829  ROS_DEBUG("MCL (%0.3f sec.)",
830  boost::chrono::duration<float>(tnow - ts).count());
831  const auto err_integ_map = e_max.rot_ * e_max.odom_err_integ_lin_;
832  ROS_DEBUG("odom error integral lin: %0.3f, %0.3f, %0.3f, "
833  "ang: %0.3f, %0.3f, %0.3f, "
834  "pos: %0.3f, %0.3f, %0.3f, "
835  "err on map: %0.3f, %0.3f, %0.3f",
836  e_max.odom_err_integ_lin_.x_,
837  e_max.odom_err_integ_lin_.y_,
838  e_max.odom_err_integ_lin_.z_,
839  e_max.odom_err_integ_ang_.x_,
840  e_max.odom_err_integ_ang_.y_,
841  e_max.odom_err_integ_ang_.z_,
842  e_max.pos_.x_,
843  e_max.pos_.y_,
844  e_max.pos_.z_,
845  err_integ_map.x_,
846  err_integ_map.y_,
847  err_integ_map.z_);
848  ROS_DEBUG("match ratio min: %0.3f, max: %0.3f, pos: %0.3f, %0.3f, %0.3f",
849  match_ratio_min,
850  match_ratio_max,
851  e.pos_.x_,
852  e.pos_.y_,
853  e.pos_.z_);
854  if (match_ratio_max < params_.match_ratio_thresh_)
855  {
856  ROS_WARN_THROTTLE(3.0, "Low match_ratio. Expansion resetting.");
857  pf_->noise(State6DOF(
864  status_.status = mcl_3dl_msgs::Status::EXPANSION_RESETTING;
865  }
866 
867  ros::Time localized_current = ros::Time::now();
868  float dt = (localized_current - localized_last_).toSec();
869  if (dt > 1.0)
870  dt = 1.0;
871  else if (dt < 0.0)
872  dt = 0.0;
874  localized_last_ = localized_current;
875 
876  if (static_cast<int>(pf_->getParticleSize()) > params_.num_particles_)
877  {
878  const int reduced = pf_->getParticleSize() * 0.75;
879  if (reduced > params_.num_particles_)
880  {
881  pf_->resizeParticle(reduced);
882  }
883  else
884  {
885  pf_->resizeParticle(params_.num_particles_);
886  }
887  // wait 99.7% fix (three-sigma)
888  global_localization_fix_cnt_ = 1 + std::ceil(params_.lpf_step_) * 3.0;
889  }
891  {
893  status_.status = mcl_3dl_msgs::Status::GLOBAL_LOCALIZATION;
894  }
895 
896  status_.match_ratio = match_ratio_max;
897  status_.particle_size = pf_->getParticleSize();
899  }
900  void cbLandmark(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& msg)
901  {
903  Eigen::Matrix<double, 6, 6>(
904  msg->pose.covariance.data())
905  .cast<float>());
906  const State6DOF measured(
907  Vec3(msg->pose.pose.position.x,
908  msg->pose.pose.position.y,
909  msg->pose.pose.position.z),
910  Quat(msg->pose.pose.orientation.x,
911  msg->pose.pose.orientation.y,
912  msg->pose.pose.orientation.z,
913  msg->pose.pose.orientation.w));
914  auto measure_func = [this, &measured, &nd](const State6DOF& s) -> float
915  {
916  State6DOF diff = s - measured;
917  const Vec3 rot_rpy = diff.rot_.getRPY();
918  const Eigen::Matrix<float, 6, 1> diff_vec =
919  (Eigen::MatrixXf(6, 1) << diff.pos_.x_,
920  diff.pos_.y_,
921  diff.pos_.z_,
922  rot_rpy.x_,
923  rot_rpy.y_,
924  rot_rpy.z_)
925  .finished();
926 
927  const auto n = nd(diff_vec);
928  return n;
929  };
930  pf_->measure(measure_func);
931 
932  pf_->resample(State6DOF(
939 
941  }
942  void cbImu(const sensor_msgs::Imu::ConstPtr& msg)
943  {
944  const Vec3 acc = f_acc_->in(Vec3(
945  msg->linear_acceleration.x,
946  msg->linear_acceleration.y,
947  msg->linear_acceleration.z));
948 
949  if (!has_imu_)
950  {
951  f_acc_->set(Vec3());
952  imu_last_ = msg->header.stamp;
953  has_imu_ = true;
954  return;
955  }
956 
957  float dt = (msg->header.stamp - imu_last_).toSec();
958  if (dt < 0.0 || dt > 5.0)
959  {
960  ROS_WARN("Detected time jump in imu. Resetting.");
961  has_imu_ = false;
962  return;
963  }
964  else if (dt > 0.05)
965  {
966  Vec3 acc_measure = acc.normalized();
967  try
968  {
969  geometry_msgs::Vector3 in, out;
970  in.x = acc_measure.x_;
971  in.y = acc_measure.y_;
972  in.z = acc_measure.z_;
973  // assuming imu frame is regit on base_link
974  const geometry_msgs::TransformStamped trans = tfbuf_.lookupTransform(
975  params_.frame_ids_["base_link"], msg->header.frame_id, ros::Time(0));
976  tf2::doTransform(in, out, trans);
977  acc_measure = Vec3(out.x, out.y, out.z);
978 
979  imu_quat_.x_ = msg->orientation.x;
980  imu_quat_.y_ = msg->orientation.y;
981  imu_quat_.z_ = msg->orientation.z;
982  imu_quat_.w_ = msg->orientation.w;
983  Vec3 axis;
984  float angle;
985  imu_quat_.getAxisAng(axis, angle);
986  axis = Quat(trans.transform.rotation.x,
987  trans.transform.rotation.y,
988  trans.transform.rotation.z,
989  trans.transform.rotation.w) *
990  axis;
991  imu_quat_.setAxisAng(axis, angle);
992  }
993  catch (tf2::TransformException& e)
994  {
995  return;
996  }
997 
998  imu_measurement_model_->setAccMeasure(acc_measure);
999  auto imu_measure_func = [this](const State6DOF& s) -> float
1000  {
1001  return imu_measurement_model_->measure(s);
1002  };
1003  pf_->measure(imu_measure_func);
1004 
1005  imu_last_ = msg->header.stamp;
1006 
1007  if (params_.fake_odom_)
1008  {
1009  nav_msgs::Odometry::Ptr odom(new nav_msgs::Odometry);
1010  odom->header.frame_id = params_.frame_ids_["base_link"];
1011  odom->header.stamp = msg->header.stamp;
1012  odom->pose.pose.orientation.x = imu_quat_.x_;
1013  odom->pose.pose.orientation.y = imu_quat_.y_;
1014  odom->pose.pose.orientation.z = imu_quat_.z_;
1015  odom->pose.pose.orientation.w = imu_quat_.w_;
1016  cbOdom(odom);
1017  }
1018  }
1019  }
1020  bool cbResizeParticle(mcl_3dl_msgs::ResizeParticleRequest& request,
1021  mcl_3dl_msgs::ResizeParticleResponse& response)
1022  {
1023  pf_->resizeParticle(request.size);
1024  publishParticles();
1025  return true;
1026  }
1027  bool cbExpansionReset(std_srvs::TriggerRequest& request,
1028  std_srvs::TriggerResponse& response)
1029  {
1030  pf_->noise(State6DOF(
1037  publishParticles();
1038  return true;
1039  }
1040  bool cbGlobalLocalization(std_srvs::TriggerRequest& request,
1041  std_srvs::TriggerResponse& response)
1042  {
1043  if (!has_map_)
1044  {
1045  response.success = false;
1046  response.message = "No map received.";
1047  return true;
1048  }
1049  pcl::PointCloud<PointType>::Ptr points(new pcl::PointCloud<PointType>);
1050 
1051  pcl::VoxelGrid<PointType> ds;
1052  ds.setInputCloud(pc_map_);
1053  ds.setLeafSize(
1057  ds.filter(*points);
1058 
1059  pcl::KdTreeFLANN<PointType>::Ptr kdtree(new pcl::KdTreeFLANN<PointType>);
1060  kdtree->setPointRepresentation(point_rep_);
1061  kdtree->setInputCloud(points);
1062 
1063  auto pc_filter = [this, kdtree](const PointType& p)
1064  {
1065  std::vector<int> id(1);
1066  std::vector<float> sqdist(1);
1067  auto p2 = p;
1068  p2.z += 0.01 + params_.global_localization_grid_;
1069 
1070  return kdtree->radiusSearch(
1071  p2, params_.global_localization_grid_, id, sqdist, 1);
1072  };
1073  points->erase(
1074  std::remove_if(points->begin(), points->end(), pc_filter),
1075  points->end());
1076 
1077  const int dir = params_.global_localization_div_yaw_;
1078  pf_->resizeParticle(points->size() * dir);
1079  auto pit = points->begin();
1080 
1081  const float prob = 1.0 / static_cast<float>(points->size());
1082  int cnt = 0;
1083  for (auto& particle : *pf_)
1084  {
1085  assert(pit != points->end());
1086  particle.probability_ = prob;
1087  particle.probability_bias_ = 1.0;
1088  particle.state_ = State6DOF(
1089  Vec3(pit->x, pit->y, pit->z),
1090  (Quat(Vec3(0.0, 0.0, 2.0 * M_PI * cnt / dir)) * imu_quat_).normalized());
1091  if (++cnt >= dir)
1092  {
1093  cnt = 0;
1094  ++pit;
1095  }
1096  }
1097  response.success = true;
1098  response.message = std::to_string(pf_->getParticleSize()) + " particles";
1099  return true;
1100  }
1101 
1103  {
1104  geometry_msgs::PoseArray pa;
1105  if (has_odom_)
1106  pa.header.stamp = odom_last_ + tf_tolerance_base_ + *params_.tf_tolerance_;
1107  else
1108  pa.header.stamp = ros::Time::now() + tf_tolerance_base_ + *params_.tf_tolerance_;
1109  pa.header.frame_id = params_.frame_ids_["map"];
1110  for (size_t i = 0; i < pf_->getParticleSize(); i++)
1111  {
1112  geometry_msgs::Pose pm;
1113  auto p = pf_->getParticle(i);
1114  p.rot_.normalize();
1115  pm.position.x = p.pos_.x_;
1116  pm.position.y = p.pos_.y_;
1117  pm.position.z = p.pos_.z_;
1118  pm.orientation.x = p.rot_.x_;
1119  pm.orientation.y = p.rot_.y_;
1120  pm.orientation.z = p.rot_.z_;
1121  pm.orientation.w = p.rot_.w_;
1122  pa.poses.push_back(pm);
1123  }
1124 
1125  pub_particle_.publish(pa);
1126  }
1127 
1129  {
1130  if (status_.error == mcl_3dl_msgs::Status::ERROR_POINTS_NOT_FOUND)
1131  {
1132  stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Valid points does not found.");
1133  }
1134  else if (status_.convergence_status == mcl_3dl_msgs::Status::CONVERGENCE_STATUS_LARGE_STD_VALUE)
1135  {
1136  stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Too Large Standard Deviation.");
1137  }
1138  else
1139  {
1140  stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "OK");
1141  }
1142 
1143  stat.add("Map Availability", has_map_ ? "true" : "false");
1144  stat.add("Odometry Availability", has_odom_ ? "true" : "false");
1145  stat.add("IMU Availability", has_imu_ ? "true" : "false");
1146 
1147  status_.entropy = pf_->getEntropy();
1149  }
1150 
1151  void loadMapCloud(const pcl::PointCloud<PointType>::Ptr& map_cloud)
1152  {
1153  pc_map_.reset(new pcl::PointCloud<PointType>);
1154  pc_map2_.reset();
1155  pc_update_.reset();
1156  pcl::VoxelGrid<PointType> ds;
1157  ds.setInputCloud(map_cloud);
1159  ds.filter(*pc_map_);
1160  pc_all_accum_.reset(new pcl::PointCloud<PointType>);
1161  has_map_ = true;
1162 
1163  accumClear();
1164  accum_->reset();
1165 
1166  ROS_INFO("map original: %d points", static_cast<int>(map_cloud->points.size()));
1167  ROS_INFO("map reduced: %d points", static_cast<int>(pc_map_->points.size()));
1168 
1169  // output map for visualization purposes:
1171  }
1172 
1173  bool cbLoadPCD(mcl_3dl_msgs::LoadPCD::Request& req, mcl_3dl_msgs::LoadPCD::Response& resp)
1174  {
1175  ROS_INFO("map received");
1176 
1177  pcl::PointCloud<PointType>::Ptr pc_tmp(new pcl::PointCloud<PointType>);
1178  if (pcl::io::loadPCDFile<PointType>(req.pcd_path, *pc_tmp) == -1)
1179  {
1180  ROS_ERROR_STREAM("Couldn't read file " << req.pcd_path);
1181  has_map_ = false;
1182  resp.success = false;
1183  return true;
1184  }
1185 
1186  pcl_conversions::toPCL(ros::Time::now(), pc_tmp->header.stamp);
1187  pc_tmp->header.frame_id = params_.frame_ids_["map"];
1188 
1189  loadMapCloud(pc_tmp);
1190 
1191  resp.success = true;
1192  return true;
1193  }
1194 
1195 public:
1197  : pnh_("~")
1198  , tfl_(tfbuf_)
1199  , cnt_measure_(0)
1202  , engine_(seed_gen_())
1203  {
1204  }
1205  bool configure()
1206  {
1208 
1209  if (!params_.load(pnh_))
1210  {
1211  ROS_ERROR("Failed to load parameters");
1212  return false;
1213  }
1214 
1215  if (!params_.fake_odom_)
1216  {
1217  int odom_queue_size;
1218  pnh_.param("odom_queue_size", odom_queue_size, 200);
1220  nh_, "odom",
1221  pnh_, "odom", odom_queue_size, &MCL3dlNode::cbOdom, this);
1222  }
1223  if (!params_.fake_imu_)
1224  {
1225  int imu_queue_size;
1226  pnh_.param("imu_queue_size", imu_queue_size, 200);
1228  nh_, "imu/data",
1229  pnh_, "imu", imu_queue_size, &MCL3dlNode::cbImu, this);
1230  }
1231 
1232  int cloud_queue_size;
1233  pnh_.param("cloud_queue_size", cloud_queue_size, 100);
1235  nh_, "cloud",
1236  pnh_, "cloud", cloud_queue_size, &MCL3dlNode::cbCloud, this);
1238  nh_, "mapcloud",
1239  pnh_, "mapcloud", 1, &MCL3dlNode::cbMapcloud, this);
1241  nh_, "mapcloud_update",
1242  pnh_, "mapcloud_update", 1, &MCL3dlNode::cbMapcloudUpdate, this);
1244  nh_, "initialpose",
1245  pnh_, "initialpose", 1, &MCL3dlNode::cbPosition, this);
1247  nh_, "mcl_measurement",
1248  pnh_, "landmark", 1, &MCL3dlNode::cbLandmark, this);
1249 
1250  pub_pose_ = nh_.advertise<geometry_msgs::PoseWithCovarianceStamped>("amcl_pose", 5, false);
1251  pub_particle_ = pnh_.advertise<geometry_msgs::PoseArray>("particles", 1, true);
1252  pub_mapcloud_ = pnh_.advertise<sensor_msgs::PointCloud2>("updated_map", 1, true);
1253  pub_debug_marker_ = pnh_.advertise<visualization_msgs::MarkerArray>("debug_marker", 1, true);
1254  pub_status_ = pnh_.advertise<mcl_3dl_msgs::Status>("status", 1, true);
1255  pub_matched_ = pnh_.advertise<sensor_msgs::PointCloud2>("matched", 2, true);
1256  pub_unmatched_ = pnh_.advertise<sensor_msgs::PointCloud2>("unmatched", 2, true);
1257 
1259  nh_, "resize_mcl_particle",
1260  pnh_, "resize_particle", &MCL3dlNode::cbResizeParticle, this);
1262  nh_, "global_localization",
1263  pnh_, "global_localization", &MCL3dlNode::cbGlobalLocalization, this);
1265  nh_, "expansion_resetting",
1266  pnh_, "expansion_resetting", &MCL3dlNode::cbExpansionReset, this);
1268 
1269  point_rep_->setRescaleValues(params_.dist_weight_.data());
1270 
1271  pf_.reset(new pf::ParticleFilter<State6DOF,
1272  float,
1274  std::default_random_engine>(params_.num_particles_));
1276 
1277  f_pos_.reset(new FilterVec3(
1280  Vec3()));
1281  f_ang_.reset(new FilterVec3(
1284  Vec3(), true));
1285  f_acc_.reset(new FilterVec3(
1288  Vec3()));
1289 
1290  if (params_.accum_cloud_ == 0)
1292  else
1293  accum_.reset(
1295 
1296  imu_quat_ = Quat(0.0, 0.0, 0.0, 1.0);
1297 
1298  has_odom_ = has_map_ = has_imu_ = false;
1299  localize_rate_.reset(new Filter(Filter::FILTER_LPF, 5.0, 0.0));
1300 
1301  lidar_measurements_["likelihood"] =
1304  lidar_measurements_["beam"] =
1312 
1313  float max_search_radius = 0;
1314  for (auto& lm : lidar_measurements_)
1315  {
1316  lm.second->loadConfig(pnh_, lm.first);
1317  max_search_radius = std::max(max_search_radius, lm.second->getMaxSearchRange());
1318 
1320  {
1321  auto sampler = std::make_shared<PointCloudSamplerWithNormal<PointType>>();
1322  sampler->loadConfig(pnh_);
1323  lm.second->setRandomSampler(sampler);
1324  }
1325  else
1326  {
1327  auto sampler = std::make_shared<PointCloudUniformSampler<PointType>>();
1328  lm.second->setRandomSampler(sampler);
1329  }
1330  }
1331 
1332  ROS_DEBUG("max_search_radius: %0.3f", max_search_radius);
1333  kdtree_.reset(new ChunkedKdtree<PointType>(params_.map_chunk_, max_search_radius));
1334  kdtree_->setEpsilon(params_.map_grid_min_ / 16);
1335  kdtree_->setPointRepresentation(point_rep_);
1336 
1340 
1341  diag_updater_.setHardwareID("none");
1342  diag_updater_.add("Status", this, &MCL3dlNode::diagnoseStatus);
1343 
1344  return true;
1345  }
1347  {
1349  {
1350  std::cerr << "mcl_3dl: saving pcd file.";
1351  std::cerr << " (" << pc_all_accum_->points.size() << " points)" << std::endl;
1352  pcl::io::savePCDFileBinary("mcl_3dl.pcd", *pc_all_accum_);
1353  }
1354  }
1355 
1357  {
1358  if (has_map_)
1359  {
1360  const auto ts = boost::chrono::high_resolution_clock::now();
1361  if (pc_update_)
1362  {
1363  if (!pc_map2_)
1364  pc_map2_.reset(new pcl::PointCloud<PointType>);
1365  *pc_map2_ = *pc_map_ + *pc_update_;
1366  pc_update_.reset();
1368  }
1369  else
1370  {
1371  if (pc_map2_)
1372  return;
1373  pc_map2_ = pc_map_;
1374  }
1375  kdtree_->setInputCloud(pc_map2_);
1376 
1377  sensor_msgs::PointCloud2 out;
1378  pcl::toROSMsg(*pc_map2_, out);
1379  pub_mapcloud_.publish(out);
1380  const auto tnow = boost::chrono::high_resolution_clock::now();
1381  ROS_DEBUG("Map update (%0.3f sec.)",
1382  boost::chrono::duration<float>(tnow - ts).count());
1383  }
1384  }
1385 
1386 protected:
1389 
1409 
1413 
1414  std::shared_ptr<FilterVec3> f_pos_;
1415  std::shared_ptr<FilterVec3> f_ang_;
1416  std::shared_ptr<FilterVec3> f_acc_;
1417  std::shared_ptr<Filter> localize_rate_;
1420 
1422 
1425  bool has_map_;
1427  bool has_imu_;
1436  mcl_3dl_msgs::Status status_;
1437 
1438  MyPointRepresentation::Ptr point_rep_;
1439 
1440  pcl::PointCloud<PointType>::Ptr pc_map_;
1441  pcl::PointCloud<PointType>::Ptr pc_map2_;
1442  pcl::PointCloud<PointType>::Ptr pc_update_;
1443  pcl::PointCloud<PointType>::Ptr pc_all_accum_;
1445 
1447  pcl::PointCloud<PointType>::Ptr pc_local_accum_;
1448  std::vector<std_msgs::Header> pc_accum_header_;
1449 
1450  std::map<
1451  std::string,
1456 
1457  std::random_device seed_gen_;
1458  std::default_random_engine engine_;
1459 };
1460 } // namespace mcl_3dl
1461 
1462 int main(int argc, char* argv[])
1463 {
1464  ros::init(argc, argv, "mcl_3dl");
1465 
1466  mcl_3dl::MCL3dlNode mcl;
1467  if (!mcl.configure())
1468  {
1469  return 1;
1470  }
1471  ros::spin();
1472 
1473  return 0;
1474 }
mcl_3dl::Filter
Definition: filter.h:38
response
const std::string response
mcl_3dl::MCL3dlNode::sub_cloud_
ros::Subscriber sub_cloud_
Definition: mcl_3dl.cpp:1390
mcl_3dl::MCL3dlNode::pub_particle_
ros::Publisher pub_particle_
Definition: mcl_3dl.cpp:1397
mcl_3dl::Parameters::bias_var_ang_
double bias_var_ang_
Definition: parameters.h:92
mcl_3dl::CloudAccumulationLogic
Definition: cloud_accum.h:72
mcl_3dl::Parameters::expansion_var_yaw_
double expansion_var_yaw_
Definition: parameters.h:74
mcl_3dl::MCL3dlNode::MyPointRepresentation::copyToFloatArray
virtual void copyToFloatArray(const PointType &p, float *out) const
Definition: mcl_3dl.cpp:120
mcl_3dl::MCL3dlNode::motion_prediction_model_
MotionPredictionModelBase::Ptr motion_prediction_model_
Definition: mcl_3dl.cpp:1455
filter.h
mcl_3dl::LidarMeasurementModelBeam::BeamStatus::HIT
@ HIT
mcl_3dl::Parameters::fake_odom_
bool fake_odom_
Definition: parameters.h:49
mcl_3dl::fromROSMsg
bool fromROSMsg(const sensor_msgs::PointCloud2 &msg, pcl::PointCloud< PointT > &pc)
Definition: point_conversion.h:65
mcl_3dl::MCL3dlNode::state_prev_
State6DOF state_prev_
Definition: mcl_3dl.cpp:1430
mcl_3dl::MCL3dlNode::~MCL3dlNode
~MCL3dlNode()
Definition: mcl_3dl.cpp:1346
mcl_3dl::MCL3dlNode::configure
bool configure()
Definition: mcl_3dl.cpp:1205
mcl_3dl::Quat::setRPY
void setRPY(const Vec3 &rpy)
Definition: quat.h:202
mcl_3dl::Parameters
Definition: parameters.h:44
msg
msg
mcl_3dl::Parameters::acc_var_
double acc_var_
Definition: parameters.h:93
ros::Publisher
raycast.h
mcl_3dl::MCL3dlNode::tfb_
tf2_ros::TransformBroadcaster tfb_
Definition: mcl_3dl.cpp:1412
mcl_3dl::Parameters::expansion_var_z_
double expansion_var_z_
Definition: parameters.h:71
compatibility.h
pf.h
cloud_accum.h
mcl_3dl::Parameters::fix_dist_
double fix_dist_
Definition: parameters.h:78
mcl_3dl::Parameters::global_localization_grid_
double global_localization_grid_
Definition: parameters.h:58
mcl_3dl::Parameters::update_downsample_y_
double update_downsample_y_
Definition: parameters.h:54
mcl_3dl::MCL3dlNode::pc_accum_header_
std::vector< std_msgs::Header > pc_accum_header_
Definition: mcl_3dl.cpp:1448
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(args)
mcl_3dl::Parameters::update_downsample_x_
double update_downsample_x_
Definition: parameters.h:53
angle
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
mcl_3dl::ChunkedKdtree::Ptr
std::shared_ptr< ChunkedKdtree > Ptr
Definition: chunked_kdtree.h:49
diagnostic_updater::DiagnosticStatusWrapper::add
void add(const std::string &key, const bool &b)
mcl_3dl::Parameters::downsample_y_
double downsample_y_
Definition: parameters.h:61
mcl_3dl::MCL3dlNode::sub_mapcloud_update_
ros::Subscriber sub_mapcloud_update_
Definition: mcl_3dl.cpp:1392
mcl_3dl::Parameters::downsample_x_
double downsample_x_
Definition: parameters.h:60
mcl_3dl::Parameters::resample_var_pitch_
double resample_var_pitch_
Definition: parameters.h:67
mcl_3dl::LidarMeasurementModelLikelihood
Definition: lidar_measurement_model_likelihood.h:50
ros::init
ROSCPP_DECL void init(const M_string &remappings, const std::string &name, uint32_t options=0)
diagnostic_updater::Updater::force_update
void force_update()
mcl_3dl::Vec3::x_
float x_
Definition: vec3.h:40
mcl_3dl::Parameters::publish_tf_
bool publish_tf_
Definition: parameters.h:104
mcl_3dl::LidarMeasurementModelBeam::BeamStatus::LONG
@ LONG
mcl_3dl::Parameters::skip_measure_
int skip_measure_
Definition: parameters.h:86
mcl_3dl::Parameters::dist_weight_
std::array< float, 4 > dist_weight_
Definition: parameters.h:102
s
XmlRpcServer s
mcl_3dl::Quat::setAxisAng
void setAxisAng(const Vec3 &axis, const float &ang)
Definition: quat.h:216
ROS_WARN_THROTTLE
#define ROS_WARN_THROTTLE(period,...)
ros.h
mcl_3dl::Parameters::total_accum_cloud_max_
int total_accum_cloud_max_
Definition: parameters.h:88
mcl_3dl::MCL3dlNode::loadMapCloud
void loadMapCloud(const pcl::PointCloud< PointType >::Ptr &map_cloud)
Definition: mcl_3dl.cpp:1151
mcl_3dl_compat::subscribe
ros::Subscriber subscribe(ros::NodeHandle &nh_new, const std::string &topic_new, ros::NodeHandle &nh_old, const std::string &topic_old, uint32_t queue_size, void(T::*fp)(M) const, T *obj, const ros::TransportHints &transport_hints=ros::TransportHints())
Definition: compatibility.h:100
pcl_conversions::toPCL
void toPCL(const pcl_msgs::ModelCoefficients &mc, pcl::ModelCoefficients &pcl_mc)
mcl_3dl::Parameters::jump_ang_
double jump_ang_
Definition: parameters.h:77
filter_vec3.h
tf2_sensor_msgs.h
mcl_3dl::Parameters::resample_var_roll_
double resample_var_roll_
Definition: parameters.h:66
mcl_3dl::CloudAccumulationLogicPassThrough
Definition: cloud_accum.h:57
mcl_3dl::MCL3dlNode::imu_quat_
Quat imu_quat_
Definition: mcl_3dl.cpp:1433
mcl_3dl::MCL3dlNode::MCL3dlNode
MCL3dlNode()
Definition: mcl_3dl.cpp:1196
mcl_3dl::pf::ParticleFilter
Definition: pf.h:160
mcl_3dl::Parameters::map_chunk_
double map_chunk_
Definition: parameters.h:105
diagnostic_updater::Updater
mcl_3dl::Vec3::normalized
Vec3 normalized() const
Definition: vec3.h:157
mcl_3dl::MCL3dlNode::diagnoseStatus
void diagnoseStatus(diagnostic_updater::DiagnosticStatusWrapper &stat)
Definition: mcl_3dl.cpp:1128
mcl_3dl::Filter::FILTER_LPF
@ FILTER_LPF
Definition: filter.h:44
mcl_3dl::Parameters::fix_ang_
double fix_ang_
Definition: parameters.h:79
mcl_3dl::Quat::inv
constexpr Quat inv() const
Definition: quat.h:187
mcl_3dl::Quat::y_
float y_
Definition: quat.h:44
ros::NodeHandle::advertiseService
ServiceServer advertiseService(AdvertiseServiceOptions &ops)
mcl_3dl_compat::checkCompatMode
void checkCompatMode()
Definition: compatibility.h:62
imu_measurement_model_base.h
lidar_measurement_model_beam.h
mcl_3dl::MCL3dlNode::f_ang_
std::shared_ptr< FilterVec3 > f_ang_
Definition: mcl_3dl.cpp:1415
mcl_3dl::MCL3dlNode::MyPointRepresentation
Definition: mcl_3dl.cpp:109
mcl_3dl::MCL3dlNode::pub_status_
ros::Publisher pub_status_
Definition: mcl_3dl.cpp:1403
mcl_3dl::MCL3dlNode::accumCloud
bool accumCloud(const sensor_msgs::PointCloud2::ConstPtr &msg)
Definition: mcl_3dl.cpp:274
mcl_3dl::LidarMeasurementResult
Definition: lidar_measurement_model_base.h:52
point_types.h
mcl_3dl::Parameters::map_downsample_z_
double map_downsample_z_
Definition: parameters.h:52
mcl_3dl::FilterVec3
Definition: filter_vec3.h:40
mcl_3dl::Parameters::update_downsample_z_
double update_downsample_z_
Definition: parameters.h:55
mcl_3dl::Parameters::expansion_var_y_
double expansion_var_y_
Definition: parameters.h:70
mcl_3dl::MCL3dlNode::match_output_last_
ros::Time match_output_last_
Definition: mcl_3dl.cpp:1423
mcl_3dl::MCL3dlNode::cbExpansionReset
bool cbExpansionReset(std_srvs::TriggerRequest &request, std_srvs::TriggerResponse &response)
Definition: mcl_3dl.cpp:1027
mcl_3dl::MCL3dlNode::imu_measurement_model_
ImuMeasurementModelBase::Ptr imu_measurement_model_
Definition: mcl_3dl.cpp:1454
mcl_3dl::ImuMeasurementModelBase::Ptr
std::shared_ptr< ImuMeasurementModelBase > Ptr
Definition: imu_measurement_model_base.h:42
mcl_3dl::MCL3dlNode::accum_
CloudAccumulationLogicBase::Ptr accum_
Definition: mcl_3dl.cpp:1446
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
mcl_3dl::MCL3dlNode::nh_
ros::NodeHandle nh_
Definition: mcl_3dl.cpp:1387
mcl_3dl::Parameters::map_downsample_x_
double map_downsample_x_
Definition: parameters.h:50
ros::NodeHandle::advertise
Publisher advertise(AdvertiseOptions &ops)
mcl_3dl::MCL3dlNode::has_imu_
bool has_imu_
Definition: mcl_3dl.cpp:1427
mcl_3dl::Parameters::num_particles_
int num_particles_
Definition: parameters.h:85
vec3.h
transform_broadcaster.h
transforms.h
multivariate_noise_generator.h
mcl_3dl::MCL3dlNode::cbLandmark
void cbLandmark(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr &msg)
Definition: mcl_3dl.cpp:900
point_cloud.h
diagnostic_updater.h
f
f
mcl_3dl::MCL3dlNode::pub_pose_
ros::Publisher pub_pose_
Definition: mcl_3dl.cpp:1399
mcl_3dl::Quat::getRPY
constexpr Vec3 getRPY() const
Definition: quat.h:191
mcl_3dl::MCL3dlNode::status_
mcl_3dl_msgs::Status status_
Definition: mcl_3dl.cpp:1436
ros::ServiceServer
mcl_3dl::MCL3dlNode::engine_
std::default_random_engine engine_
Definition: mcl_3dl.cpp:1458
point_cloud_uniform_sampler.h
mcl_3dl::MCL3dlNode::tfbuf_
tf2_ros::Buffer tfbuf_
Definition: mcl_3dl.cpp:1410
mcl_3dl::Vec3::z_
float z_
Definition: vec3.h:42
state_6dof.h
tf2_ros::TransformListener
mcl_3dl::PointXYZIL
Definition: point_types.h:40
lidar_measurement_model_likelihood.h
mcl_3dl::MCL3dlNode::diag_updater_
diagnostic_updater::Updater diag_updater_
Definition: mcl_3dl.cpp:1435
mcl_3dl::Parameters::match_output_dist_
double match_output_dist_
Definition: parameters.h:89
mcl_3dl::MCL3dlNode::f_acc_
std::shared_ptr< FilterVec3 > f_acc_
Definition: mcl_3dl.cpp:1416
mcl_3dl::Parameters::map_update_interval_
std::shared_ptr< ros::Duration > map_update_interval_
Definition: parameters.h:84
mcl_3dl::Parameters::bias_var_dist_
double bias_var_dist_
Definition: parameters.h:91
mcl_3dl::MotionPredictionModelBase::Ptr
std::shared_ptr< MotionPredictionModelBase > Ptr
Definition: motion_prediction_model_base.h:42
mcl_3dl::MCL3dlNode::localize_rate_
std::shared_ptr< Filter > localize_rate_
Definition: mcl_3dl.cpp:1417
diagnostic_updater::DiagnosticStatusWrapper::summary
void summary(const diagnostic_msgs::DiagnosticStatus &src)
mcl_3dl::MCL3dlNode::has_odom_
bool has_odom_
Definition: mcl_3dl.cpp:1426
mcl_3dl::MCL3dlNode::srv_load_pcd_
ros::ServiceServer srv_load_pcd_
Definition: mcl_3dl.cpp:1408
mcl_3dl::Parameters::unmatch_output_dist_
double unmatch_output_dist_
Definition: parameters.h:90
mcl_3dl::Parameters::map_grid_min_
double map_grid_min_
Definition: parameters.h:56
tf2_ros::TransformBroadcaster::sendTransform
void sendTransform(const geometry_msgs::TransformStamped &transform)
mcl_3dl::Quat
Definition: quat.h:40
mcl_3dl::Quat::w_
float w_
Definition: quat.h:46
mcl_3dl::MCL3dlNode::pc_map2_
pcl::PointCloud< PointType >::Ptr pc_map2_
Definition: mcl_3dl.cpp:1441
mcl_3dl::MCL3dlNode::odom_prev_
State6DOF odom_prev_
Definition: mcl_3dl.cpp:1429
motion_prediction_model_base.h
mcl_3dl::Parameters::map_downsample_y_
double map_downsample_y_
Definition: parameters.h:51
ROS_DEBUG
#define ROS_DEBUG(...)
mcl_3dl_compat::advertiseService
ros::ServiceServer advertiseService(ros::NodeHandle &nh_new, const std::string &service_new, ros::NodeHandle &nh_old, const std::string &service_old, bool(T::*srv_func)(MReq &, MRes &), T *obj)
Definition: compatibility.h:176
mcl_3dl::MCL3dlNode::sub_imu_
ros::Subscriber sub_imu_
Definition: mcl_3dl.cpp:1394
mcl_3dl::MCL3dlNode::kdtree_
ChunkedKdtree< PointType >::Ptr kdtree_
Definition: mcl_3dl.cpp:1444
mcl_3dl::MCL3dlNode::odom_last_
ros::Time odom_last_
Definition: mcl_3dl.cpp:1424
mcl_3dl::ImuMeasurementModelGravity
Definition: imu_measurement_model_gravity.h:40
point_conversion.h
mcl_3dl::MCL3dlNode::srv_global_localization_
ros::ServiceServer srv_global_localization_
Definition: mcl_3dl.cpp:1406
mcl_3dl::Vec3::y_
float y_
Definition: vec3.h:41
mcl_3dl::MCL3dlNode::pub_matched_
ros::Publisher pub_matched_
Definition: mcl_3dl.cpp:1400
mcl_3dl::MCL3dlNode
Definition: mcl_3dl.cpp:103
mcl_3dl::MCL3dlNode::odom_
State6DOF odom_
Definition: mcl_3dl.cpp:1428
mcl_3dl::Parameters::expansion_var_x_
double expansion_var_x_
Definition: parameters.h:69
mcl_3dl::MCL3dlNode::cbLoadPCD
bool cbLoadPCD(mcl_3dl_msgs::LoadPCD::Request &req, mcl_3dl_msgs::LoadPCD::Response &resp)
Definition: mcl_3dl.cpp:1173
mcl_3dl::MCL3dlNode::srv_expansion_reset_
ros::ServiceServer srv_expansion_reset_
Definition: mcl_3dl.cpp:1407
main
int main(int argc, char *argv[])
Definition: mcl_3dl.cpp:1462
mcl_3dl::CloudAccumulationLogicBase::Ptr
std::shared_ptr< CloudAccumulationLogicBase > Ptr
Definition: cloud_accum.h:45
mcl_3dl::Parameters::odom_err_ang_ang_
double odom_err_ang_ang_
Definition: parameters.h:83
lidar_measurement_model_base.h
mcl_3dl::MCL3dlNode::imu_last_
ros::Time imu_last_
Definition: mcl_3dl.cpp:1431
mcl_3dl::Parameters::use_random_sampler_with_normal_
bool use_random_sampler_with_normal_
Definition: parameters.h:110
mcl_3dl::Parameters::resample_var_z_
double resample_var_z_
Definition: parameters.h:65
ROS_WARN
#define ROS_WARN(...)
mcl_3dl::MCL3dlNode::global_localization_fix_cnt_
size_t global_localization_fix_cnt_
Definition: mcl_3dl.cpp:1434
tf2_ros::Buffer
mcl_3dl::MCL3dlNode::measure
void measure()
Definition: mcl_3dl.cpp:304
mcl_3dl::MCL3dlNode::pc_local_accum_
pcl::PointCloud< PointType >::Ptr pc_local_accum_
Definition: mcl_3dl.cpp:1447
quat.h
mcl_3dl::MCL3dlNode::publishParticles
void publishParticles()
Definition: mcl_3dl.cpp:1102
mcl_3dl::Parameters::global_localization_div_yaw_
int global_localization_div_yaw_
Definition: parameters.h:59
mcl_3dl::MCL3dlNode::seed_gen_
std::random_device seed_gen_
Definition: mcl_3dl.cpp:1457
ros::TimerEvent
mcl_3dl::MCL3dlNode::localized_last_
ros::Time localized_last_
Definition: mcl_3dl.cpp:1418
mcl_3dl::LidarMeasurementModelBeam::BeamStatus::TOTAL_REFLECTION
@ TOTAL_REFLECTION
mcl_3dl::MCL3dlNode::cbMapUpdateTimer
void cbMapUpdateTimer(const ros::TimerEvent &event)
Definition: mcl_3dl.cpp:1356
diagnostic_updater::Updater::setHardwareID
void setHardwareID(const std::string &hwid)
mcl_3dl::Parameters::odom_err_integ_lin_tc_
double odom_err_integ_lin_tc_
Definition: parameters.h:94
motion_prediction_model_differential_drive.h
mcl_3dl::Parameters::odom_err_lin_lin_
double odom_err_lin_lin_
Definition: parameters.h:80
mcl_3dl::Quat::getAxisAng
void getAxisAng(Vec3 &axis, float &ang) const
Definition: quat.h:226
parameters.h
mcl_3dl::MCL3dlNode::accumClear
void accumClear()
Definition: mcl_3dl.cpp:267
mcl_3dl
Definition: chunked_kdtree.h:43
mcl_3dl::MotionPredictionModelDifferentialDrive
Definition: motion_prediction_model_differential_drive.h:37
mcl_3dl::Parameters::tf_tolerance_
std::shared_ptr< ros::Duration > tf_tolerance_
Definition: parameters.h:99
mcl_3dl::MCL3dlNode::cbOdom
void cbOdom(const nav_msgs::Odometry::ConstPtr &msg)
Definition: mcl_3dl.cpp:200
mcl_3dl::Parameters::acc_lpf_step_
double acc_lpf_step_
Definition: parameters.h:101
transform_listener.h
point_cloud_conversion.h
mcl_3dl::Parameters::std_warn_thresh_
std::array< float, 3 > std_warn_thresh_
Definition: parameters.h:107
mcl_3dl::NormalLikelihood< float >
mcl_3dl::NormalLikelihoodNd
Definition: nd.h:61
mcl_3dl::MCL3dlNode::cbImu
void cbImu(const sensor_msgs::Imu::ConstPtr &msg)
Definition: mcl_3dl.cpp:942
mcl_3dl::MCL3dlNode::cbPosition
void cbPosition(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr &msg)
Definition: mcl_3dl.cpp:155
mcl_3dl::Parameters::resample_var_y_
double resample_var_y_
Definition: parameters.h:64
mcl_3dl::MCL3dlNode::pub_mapcloud_
ros::Publisher pub_mapcloud_
Definition: mcl_3dl.cpp:1398
mcl_3dl::MCL3dlNode::srv_particle_size_
ros::ServiceServer srv_particle_size_
Definition: mcl_3dl.cpp:1405
mcl_3dl::MCL3dlNode::cbResizeParticle
bool cbResizeParticle(mcl_3dl_msgs::ResizeParticleRequest &request, mcl_3dl_msgs::ResizeParticleResponse &response)
Definition: mcl_3dl.cpp:1020
mcl_3dl::Parameters::odom_err_ang_lin_
double odom_err_ang_lin_
Definition: parameters.h:82
ros::Time
tf2::doTransform
void doTransform(const T &data_in, T &data_out, const geometry_msgs::TransformStamped &transform)
mcl_3dl::Parameters::jump_dist_
double jump_dist_
Definition: parameters.h:76
mcl_3dl::MultivariateNoiseGenerator
Definition: multivariate_noise_generator.h:44
mcl_3dl::LidarMeasurementResult::likelihood
float likelihood
Definition: lidar_measurement_model_base.h:54
mcl_3dl::MCL3dlNode::pnh_
ros::NodeHandle pnh_
Definition: mcl_3dl.cpp:1388
mcl_3dl::Parameters::expansion_var_pitch_
double expansion_var_pitch_
Definition: parameters.h:73
mcl_3dl::MCL3dlNode::pub_unmatched_
ros::Publisher pub_unmatched_
Definition: mcl_3dl.cpp:1401
mcl_3dl::ChunkedKdtree
Definition: chunked_kdtree.h:46
mcl_3dl::Parameters::resample_var_yaw_
double resample_var_yaw_
Definition: parameters.h:68
mcl_3dl::MCL3dlNode::MyPointRepresentation::MyPointRepresentation
MyPointRepresentation()
Definition: mcl_3dl.cpp:114
mcl_3dl::Parameters::frame_ids_
std::map< std::string, std::string > frame_ids_
Definition: parameters.h:106
nd.h
point_cloud_sampler_with_normal.h
mcl_3dl::MCL3dlNode::pc_map_
pcl::PointCloud< PointType >::Ptr pc_map_
Definition: mcl_3dl.cpp:1440
mcl_3dl::ParticleWeightedMeanQuat
Definition: state_6dof.h:316
mcl_3dl::Parameters::match_ratio_thresh_
double match_ratio_thresh_
Definition: parameters.h:75
mcl_3dl::MCL3dlNode::f_pos_
std::shared_ptr< FilterVec3 > f_pos_
Definition: mcl_3dl.cpp:1414
ROS_ERROR
#define ROS_ERROR(...)
mcl_3dl::State6DOF::rot_
mcl_3dl::Quat rot_
Definition: state_6dof.h:53
mcl_3dl::MCL3dlNode::pf_
std::shared_ptr< pf::ParticleFilter< State6DOF, float, ParticleWeightedMeanQuat, std::default_random_engine > > pf_
Definition: mcl_3dl.cpp:107
tf2_ros::TransformBroadcaster
ros::NodeHandle::param
T param(const std::string &param_name, const T &default_val) const
tf2::Quaternion
mcl_3dl::Parameters::load
bool load(ros::NodeHandle &nh)
Definition: parameters.cpp:43
diagnostic_updater::DiagnosticStatusWrapper
mcl_3dl::Parameters::odom_err_lin_ang_
double odom_err_lin_ang_
Definition: parameters.h:81
tf2_geometry_msgs.h
pcl::toROSMsg
void toROSMsg(const pcl::PointCloud< T > &cloud, sensor_msgs::Image &msg)
tf2::toMsg
B toMsg(const A &a)
mcl_3dl::MCL3dlNode::map_update_timer_
ros::Timer map_update_timer_
Definition: mcl_3dl.cpp:1404
mcl_3dl::LidarMeasurementResult::quality
float quality
Definition: lidar_measurement_model_base.h:55
mcl_3dl::MCL3dlNode::sub_position_
ros::Subscriber sub_position_
Definition: mcl_3dl.cpp:1395
mcl_3dl::MCL3dlNode::pc_all_accum_
pcl::PointCloud< PointType >::Ptr pc_all_accum_
Definition: mcl_3dl.cpp:1443
mcl_3dl::LidarMeasurementModelBeam::BeamStatus
BeamStatus
Definition: lidar_measurement_model_beam.h:75
ros::spin
ROSCPP_DECL void spin()
imu_measurement_model_gravity.h
mcl_3dl::MCL3dlNode::sub_odom_
ros::Subscriber sub_odom_
Definition: mcl_3dl.cpp:1393
mcl_3dl::LidarMeasurementModelBase::Ptr
std::shared_ptr< LidarMeasurementModelBase > Ptr
Definition: lidar_measurement_model_base.h:67
ros::Publisher::getNumSubscribers
uint32_t getNumSubscribers() const
mcl_3dl::Parameters::output_pcd_
bool output_pcd_
Definition: parameters.h:103
mcl_3dl::Raycast::CastResult
Definition: raycast.h:45
mcl_3dl::MCL3dlNode::tf_tolerance_base_
ros::Duration tf_tolerance_base_
Definition: mcl_3dl.cpp:1419
mcl_3dl::State6DOF::pos_
mcl_3dl::Vec3 pos_
Definition: state_6dof.h:52
mcl_3dl::Raycast::CastResult::pos_
Vec3 pos_
Definition: raycast.h:48
mcl_3dl::Parameters::initial_pose_std_
State6DOF initial_pose_std_
Definition: parameters.h:109
header
const std::string header
mcl_3dl::MCL3dlNode::cbMapcloud
void cbMapcloud(const sensor_msgs::PointCloud2::ConstPtr &msg)
Definition: mcl_3dl.cpp:127
mcl_3dl::Vec3
Definition: vec3.h:37
mcl_3dl::MCL3dlNode::pc_update_
pcl::PointCloud< PointType >::Ptr pc_update_
Definition: mcl_3dl.cpp:1442
tf2::TransformException
ROS_INFO
#define ROS_INFO(...)
chunked_kdtree.h
mcl_3dl::MCL3dlNode::params_
Parameters params_
Definition: mcl_3dl.cpp:1421
mcl_3dl::MCL3dlNode::point_rep_
MyPointRepresentation::Ptr point_rep_
Definition: mcl_3dl.cpp:1438
diagnostic_updater::DiagnosticTaskVector::add
void add(const std::string &name, TaskFunction f)
mcl_3dl::Parameters::odom_err_integ_lin_sigma_
double odom_err_integ_lin_sigma_
Definition: parameters.h:95
mcl_3dl::MCL3dlNode::cbMapcloudUpdate
void cbMapcloudUpdate(const sensor_msgs::PointCloud2::ConstPtr &msg)
Definition: mcl_3dl.cpp:141
mcl_3dl::MCL3dlNode::sub_mapcloud_
ros::Subscriber sub_mapcloud_
Definition: mcl_3dl.cpp:1391
mcl_3dl::Parameters::lpf_step_
double lpf_step_
Definition: parameters.h:100
ros::NodeHandle::createTimer
Timer createTimer(Duration period, const TimerCallback &callback, bool oneshot=false, bool autostart=true) const
mcl_3dl::LidarMeasurementModelBeam::BeamStatus::SHORT
@ SHORT
mcl_3dl::Parameters::expansion_var_roll_
double expansion_var_roll_
Definition: parameters.h:72
mcl_3dl::Quat::z_
float z_
Definition: quat.h:45
mcl_3dl::MCL3dlNode::cbCloud
void cbCloud(const sensor_msgs::PointCloud2::ConstPtr &msg)
Definition: mcl_3dl.cpp:248
mcl_3dl::MCL3dlNode::sub_landmark_
ros::Subscriber sub_landmark_
Definition: mcl_3dl.cpp:1396
mcl_3dl::MCL3dlNode::has_map_
bool has_map_
Definition: mcl_3dl.cpp:1425
mcl_3dl::State6DOF
Definition: state_6dof.h:49
mcl_3dl::MCL3dlNode::tfl_
tf2_ros::TransformListener tfl_
Definition: mcl_3dl.cpp:1411
ros::Duration
ros::Timer
mcl_3dl::MCL3dlNode::lidar_measurements_
std::map< std::string, LidarMeasurementModelBase::Ptr > lidar_measurements_
Definition: mcl_3dl.cpp:1453
mcl_3dl::Parameters::accum_cloud_
int accum_cloud_
Definition: parameters.h:87
mcl_3dl::Parameters::fake_imu_
bool fake_imu_
Definition: parameters.h:49
mcl_3dl::MCL3dlNode::cnt_measure_
size_t cnt_measure_
Definition: mcl_3dl.cpp:1432
mcl_3dl::LidarMeasurementModelBeam
Definition: lidar_measurement_model_beam.h:51
mcl_3dl::Parameters::odom_err_integ_ang_tc_
double odom_err_integ_ang_tc_
Definition: parameters.h:96
mcl_3dl::Parameters::match_output_interval_
std::shared_ptr< ros::Duration > match_output_interval_
Definition: parameters.h:98
mcl_3dl::Parameters::downsample_z_
double downsample_z_
Definition: parameters.h:62
tf2_ros::Buffer::lookupTransform
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const ros::Time &target_time, const std::string &source_frame, const ros::Time &source_time, const std::string &fixed_frame, const ros::Duration timeout) const
mcl_3dl::MCL3dlNode::pub_debug_marker_
ros::Publisher pub_debug_marker_
Definition: mcl_3dl.cpp:1402
mcl_3dl::Parameters::resample_var_x_
double resample_var_x_
Definition: parameters.h:63
ros::NodeHandle
ros::Subscriber
mcl_3dl::Parameters::odom_err_integ_ang_sigma_
double odom_err_integ_ang_sigma_
Definition: parameters.h:97
mcl_3dl::Parameters::initial_pose_
State6DOF initial_pose_
Definition: parameters.h:108
ros::Time::now
static Time now()
mcl_3dl::Quat::x_
float x_
Definition: quat.h:43
mcl_3dl::MCL3dlNode::cbGlobalLocalization
bool cbGlobalLocalization(std_srvs::TriggerRequest &request, std_srvs::TriggerResponse &response)
Definition: mcl_3dl.cpp:1040
pcl_conversions.h


mcl_3dl
Author(s): Atsushi Watanabe
autogenerated on Thu Oct 17 2024 02:18:04