gmcl_node.cpp
Go to the documentation of this file.
1 //this package is based on amcl and has been modified to fit gmcl
2 /*
3  * Author: Mhd Ali Alshikh Khalil
4  * Date: 20 June 2021
5  *
6 */
7 
8 //amcl author clarification
9 /*
10  * Copyright (c) 2008, Willow Garage, Inc.
11  * All rights reserved.
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Lesser General Public
15  * License as published by the Free Software Foundation; either
16  * version 2.1 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  * Lesser General Public License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public
24  * License along with this library; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26  *
27  */
28 
29 /* Author: Brian Gerkey */
30 
31 #include <algorithm>
32 #include <vector>
33 #include <map>
34 #include <cmath>
35 #include <memory>
36 
37 #include <boost/bind.hpp>
38 #include <boost/thread/mutex.hpp>
39 
40 // Signal handling
41 #include <signal.h>
42 
43 #include "gmcl/map/map.h"
44 #include "gmcl/pf/pf.h"
45 #include "gmcl/sensors/gmcl_odom.h"
47 #include "portable_utils.hpp"
48 
49 #include "ros/assert.h"
50 
51 // roscpp
52 #include "ros/ros.h"
53 
54 // Messages that I need
55 #include "sensor_msgs/LaserScan.h"
56 #include "geometry_msgs/PoseWithCovarianceStamped.h"
57 #include "geometry_msgs/PoseArray.h"
58 #include "geometry_msgs/Pose.h"
59 #include "geometry_msgs/PoseStamped.h"
60 #include "nav_msgs/GetMap.h"
61 #include "nav_msgs/SetMap.h"
62 #include "std_srvs/Empty.h"
63 
64 // For transform support
66 #include "tf2/convert.h"
67 #include "tf2/utils.h"
69 #include "tf2_ros/buffer.h"
70 #include "tf2_ros/message_filter.h"
74 
75 // Dynamic_reconfigure
76 #include "dynamic_reconfigure/server.h"
77 #include "gmcl/GMCLConfig.h"
78 
79 // Allows AMCL to run from bag file
80 #include <rosbag/bag.h>
81 #include <rosbag/view.h>
82 #include <boost/foreach.hpp>
83 
84 // For monitoring the estimator
86 
87 #define NEW_UNIFORM_SAMPLING 1
88 
89 using namespace gmcl;
90 
91 // Pose hypothesis
92 typedef struct
93 {
94  // Total weight (weights sum to 1)
95  double weight;
96 
97  // Mean of pose esimate
99 
100  // Covariance of pose estimate
102 
103 } gmcl_hyp_t;
104 
105 static double
106 normalize(double z)
107 {
108  return atan2(sin(z),cos(z));
109 }
110 static double
111 angle_diff(double a, double b)
112 {
113  double d1, d2;
114  a = normalize(a);
115  b = normalize(b);
116  d1 = a-b;
117  d2 = 2*M_PI - fabs(d1);
118  if(d1 > 0)
119  d2 *= -1.0;
120  if(fabs(d1) < fabs(d2))
121  return(d1);
122  else
123  return(d2);
124 }
125 
126 static const std::string scan_topic_ = "scan" ;
127 
128 /* This function is only useful to have the whole code work
129  * with old rosbags that have trailing slashes for their frames
130  */
131 inline
132 std::string stripSlash(const std::string& in)
133 {
134  std::string out = in;
135  if ( ( !in.empty() ) && (in[0] == '/') )
136  out.erase(0,1);
137  return out;
138 }
139 
140 class GmclNode
141 {
142  public:
143  GmclNode();
144  ~GmclNode();
145 
152  void runFromBag(const std::string &in_bag_fn, bool trigger_global_localization = false);
153 
154  int process();
155  void savePoseToServer();
156 
157  private:
158  std::shared_ptr<tf2_ros::TransformBroadcaster> tfb_;
159  std::shared_ptr<tf2_ros::TransformListener> tfl_;
160  std::shared_ptr<tf2_ros::Buffer> tf_;
161 
163 
166 
167  // Pose-generating function used to uniformly distribute particles over
168  // the map
169  static pf_vector_t uniformPoseGenerator(pf_t *pf, void* arg , void* e_arg );
170 #if NEW_UNIFORM_SAMPLING
171  static std::vector<std::pair<int,int> > free_space_indices;
172 #endif
173  // Callbacks
174  bool globalLocalizationCallback(std_srvs::Empty::Request& req,
175  std_srvs::Empty::Response& res);
176  bool nomotionUpdateCallback(std_srvs::Empty::Request& req,
177  std_srvs::Empty::Response& res);
178  bool setMapCallback(nav_msgs::SetMap::Request& req,
179  nav_msgs::SetMap::Response& res);
180 
181 
182  void handelNewLaser(const sensor_msgs::LaserScanConstPtr& laser_scan);
183  void laserReceived(const sensor_msgs::LaserScanConstPtr& laser_scan);
184  void initialPoseReceived(const geometry_msgs::PoseWithCovarianceStampedConstPtr& msg);
185  void handleInitialPoseMessage(const geometry_msgs::PoseWithCovarianceStamped& msg);
186  void mapReceived(const nav_msgs::OccupancyGridConstPtr& msg);
187 
188  void handleMapMessage(const nav_msgs::OccupancyGrid& msg);
189  void freeMapDependentMemory();
190  map_t* convertMap( const nav_msgs::OccupancyGrid& map_msg );
191  void updatePoseFromServer();
192  void applyInitialPose();
193 
194  //parameter for what odom to use
195  std::string odom_frame_id_;
196 
197  //paramater to store latest odom pose
198  geometry_msgs::PoseStamped latest_odom_pose_;
199 
200  //parameter for what base to use
201  std::string base_frame_id_;
202  std::string global_frame_id_;
203 
206 
210 
211  geometry_msgs::PoseWithCovarianceStamped last_published_pose;
212 
214  char* mapdata;
215  int sx, sy;
216  double resolution;
217 
219  double resolution_x_ , resolution_y_;
222 
226  std::vector< GMCLLaser* > lasers_;
227  std::vector< GMCLLaserData* > ldata_;
228  std::vector< bool > lasers_update_;
229  std::map< std::string, int > frame_to_laser_;
230 
231  // Particle filter
233  double pf_err_, pf_z_;
234  bool pf_init_;
236  double d_thresh_, a_thresh_;
242 
243  //Nomotion update control
244  bool m_force_update; // used to temporarily let amcl update samples even when no motion occurs...
245 
249 
252 
253  // For slowing play-back when reading directly from a bag file
255 
256  void requestMap();
257 
258  // Helper to get odometric pose from transform system
259  bool getOdomPose(geometry_msgs::PoseStamped& pose,
260  double& x, double& y, double& yaw,
261  const ros::Time& t, const std::string& f);
262 
263  //time for tolerance on the published transform,
264  //basically defines how long a map->odom transform is good for
266 
273  ros::ServiceServer nomotion_update_srv_; //to let amcl update samples without requiring motion
277 
279  void standardDeviationDiagnostics(diagnostic_updater::DiagnosticStatusWrapper& diagnostic_status);
283 
287 
288  boost::recursive_mutex configuration_mutex_;
289  dynamic_reconfigure::Server<gmcl::GMCLConfig> *dsrv_;
290  gmcl::GMCLConfig default_config_;
292 
293  int max_beams_, min_particles_, max_particles_ , N_aux_particles_;
294  double alpha1_, alpha2_, alpha3_, alpha4_, alpha5_;
295  double alpha_slow_, alpha_fast_;
296  double crossover_alpha_, mutation_prob_;
297  double z_hit_, z_short_, z_max_, z_rand_, sigma_hit_, lambda_short_;
298  //beam skip related params
300  double beam_skip_distance_, beam_skip_threshold_, beam_skip_error_threshold_;
303  double init_pose_[3];
304  double init_cov_[3];
308 
309 
310  void reconfigureCB(gmcl::GMCLConfig &config, uint32_t level);
311 
314  void checkLaserReceived(const ros::TimerEvent& event);
315 };
316 #if NEW_UNIFORM_SAMPLING
317 std::vector<std::pair<int,int> > GmclNode::free_space_indices;
318 #endif
319 
320 #define USAGE "USAGE: gmcl"
321 
323 
324 void sigintHandler(int sig)
325 {
326  // Save latest pose as we're shutting down.
327  gmcl_node_ptr->savePoseToServer();
328  ros::shutdown();
329 }
330 
331 int
332 main(int argc, char** argv)
333 {
334  ros::init(argc, argv, "gmcl");
335  ros::NodeHandle nh;
336 
337  // Override default sigint handler
338  signal(SIGINT, sigintHandler);
339 
340  // Make our node available to sigintHandler
341  gmcl_node_ptr.reset(new GmclNode());
342 
343  if (argc == 1)
344  {
345  // run using ROS input
346  ros::spin();
347  }
348  else if ((argc >= 3) && (std::string(argv[1]) == "--run-from-bag"))
349  {
350  if (argc == 3)
351  {
352  gmcl_node_ptr->runFromBag(argv[2]);
353  }
354  else if ((argc == 4) && (std::string(argv[3]) == "--global-localization"))
355  {
356  gmcl_node_ptr->runFromBag(argv[2], true);
357  }
358  }
359 
360  // Without this, our boost locks are not shut down nicely
361  gmcl_node_ptr.reset();
362 
363  // To quote Morgan, Hooray!
364  return(0);
365 }
366 
368  sent_first_transform_(false),
369  latest_tf_valid_(false),
370  map_(NULL),
371  pf_(NULL),
372  resample_count_(0),
373  odom_(NULL),
374  laser_(NULL),
375  private_nh_("~"),
376  initial_pose_hyp_(NULL),
377  first_map_received_(false),
378  first_reconfigure_call_(true)
379 {
380  boost::recursive_mutex::scoped_lock l(configuration_mutex_);
381 
382  // Grab params off the param server
383  private_nh_.param("use_optimal_filter", pf_model_.use_optimal_filter, false);
384  private_nh_.param("use_intelligent_filter", pf_model_.use_crossover_mutation, false);
385  private_nh_.param("use_self_adaptive", pf_model_.use_self_adaptive, false);
386  private_nh_.param("use_kld_sampling", pf_model_.use_adaptive_sampling, true);
387 
388  private_nh_.param("use_map_topic", use_map_topic_, false);
389  private_nh_.param("first_map_only", first_map_only_, false);
390 
391  private_nh_.param("energy_map_resolution_x", resolution_x_, 0.2);
392  private_nh_.param("energy_map_resolution_y", resolution_y_, 0.2);
393  if( !resolution_x_ || !resolution_y_)
394  { ROS_ERROR("don't set either of energy map resolutions to zero");
395  ros::shutdown();
396  }
397  private_nh_.param("energy_threshold_value", threshold_val_, 0.05);
398  private_nh_.param("publish_ser", pub_energy_map_, false);
399 
400  double tmp;
401  private_nh_.param("gui_publish_rate", tmp, -1.0);
403  private_nh_.param("save_pose_rate", tmp, 0.5);
404  save_pose_period = ros::Duration(1.0/tmp);
405 
406  private_nh_.param("laser_min_range", laser_min_range_, -1.0);
407  private_nh_.param("laser_max_range", laser_max_range_, -1.0);
408  private_nh_.param("laser_max_beams", max_beams_, 30);
409  private_nh_.param("min_particles", min_particles_, 100);
410  private_nh_.param("max_particles", max_particles_, 5000);
411  private_nh_.param("N_aux_particles", N_aux_particles_, 10);
412  private_nh_.param("kld_err", pf_err_, 0.01);
413  private_nh_.param("kld_z", pf_z_, 0.99);
414  private_nh_.param("odom_alpha1", alpha1_, 0.2);
415  private_nh_.param("odom_alpha2", alpha2_, 0.2);
416  private_nh_.param("odom_alpha3", alpha3_, 0.2);
417  private_nh_.param("odom_alpha4", alpha4_, 0.2);
418  private_nh_.param("odom_alpha5", alpha5_, 0.2);
419 
420  private_nh_.param("do_beamskip", do_beamskip_, false);
421  private_nh_.param("beam_skip_distance", beam_skip_distance_, 0.5);
422  private_nh_.param("beam_skip_threshold", beam_skip_threshold_, 0.3);
423  if (private_nh_.hasParam("beam_skip_error_threshold_"))
424  {
425  private_nh_.param("beam_skip_error_threshold_", beam_skip_error_threshold_);
426  }
427  else
428  {
429  private_nh_.param("beam_skip_error_threshold", beam_skip_error_threshold_, 0.9);
430  }
431 
432  private_nh_.param("laser_z_hit", z_hit_, 0.95);
433  private_nh_.param("laser_z_short", z_short_, 0.1);
434  private_nh_.param("laser_z_max", z_max_, 0.05);
435  private_nh_.param("laser_z_rand", z_rand_, 0.05);
436  private_nh_.param("laser_sigma_hit", sigma_hit_, 0.2);
437  private_nh_.param("laser_lambda_short", lambda_short_, 0.1);
438  private_nh_.param("laser_likelihood_max_dist", laser_likelihood_max_dist_, 2.0);
439  std::string tmp_model_type;
440  private_nh_.param("laser_model_type", tmp_model_type, std::string("likelihood_field"));
441  if(tmp_model_type == "beam")
443  else if(tmp_model_type == "likelihood_field")
445  else if(tmp_model_type == "likelihood_field_prob"){
447  }
448  else
449  {
450  ROS_WARN("Unknown laser model type \"%s\"; defaulting to likelihood_field model",
451  tmp_model_type.c_str());
453  }
454 
455  private_nh_.param("odom_model_type", tmp_model_type, std::string("diff"));
456  if(tmp_model_type == "diff")
458  else if(tmp_model_type == "omni")
460  else if(tmp_model_type == "diff-corrected")
462  else if(tmp_model_type == "omni-corrected")
464  else
465  {
466  ROS_WARN("Unknown odom model type \"%s\"; defaulting to diff model",
467  tmp_model_type.c_str());
469  }
470 
471  private_nh_.param("update_min_d", d_thresh_, 0.2);
472  private_nh_.param("update_min_a", a_thresh_, M_PI/6.0);
473  private_nh_.param("odom_frame_id", odom_frame_id_, std::string("odom"));
474  private_nh_.param("base_frame_id", base_frame_id_, std::string("base_link"));
475  private_nh_.param("global_frame_id", global_frame_id_, std::string("map"));
476  private_nh_.param("resample_interval", resample_interval_, 2);
477  private_nh_.param("selective_resampling", selective_resampling_, false);
478  double tmp_tol;
479  private_nh_.param("transform_tolerance", tmp_tol, 0.1);
480  private_nh_.param("recovery_alpha_slow", alpha_slow_, 0.001);
481  private_nh_.param("recovery_alpha_fast", alpha_fast_, 0.1);
482  private_nh_.param("mutation_probability", mutation_prob_, 0.1);
483  private_nh_.param("crossover_alpha", crossover_alpha_, 0.5);
484  private_nh_.param("tf_broadcast", tf_broadcast_, true);
485 
486  // For diagnostics
487  private_nh_.param("std_warn_level_x", std_warn_level_x_, 0.2);
488  private_nh_.param("std_warn_level_y", std_warn_level_y_, 0.2);
489  private_nh_.param("std_warn_level_yaw", std_warn_level_yaw_, 0.1);
490 
491  transform_tolerance_.fromSec(tmp_tol);
492 
493  {
494  double bag_scan_period;
495  private_nh_.param("bag_scan_period", bag_scan_period, -1.0);
496  bag_scan_period_.fromSec(bag_scan_period);
497  }
498 
502 
504 
506  tfb_.reset(new tf2_ros::TransformBroadcaster());
507  tf_.reset(new tf2_ros::Buffer());
508  tfl_.reset(new tf2_ros::TransformListener(*tf_));
509 
510  pose_pub_ = nh_.advertise<geometry_msgs::PoseWithCovarianceStamped>("gmcl_pose", 2, true);
511  particlecloud_pub_ = nh_.advertise<geometry_msgs::PoseArray>("gmcl_particlecloud", 2, true);
512  energy_particlecloud_pub_ = nh_.advertise<geometry_msgs::PoseArray>("gmcl_SER", 2, true);
513  global_loc_srv_ = nh_.advertiseService("global_localization",
515  this);
518 
522  *tf_,
524  100,
525  nh_);
526  laser_scan_filter_->registerCallback(boost::bind(&GmclNode::laserReceived,
527  this, _1));
528  initial_pose_sub_ = nh_.subscribe("initialpose", 2, &GmclNode::initialPoseReceived, this);
529 
530  if(use_map_topic_) {
531  map_sub_ = nh_.subscribe("map", 1, &GmclNode::mapReceived, this);
532  ROS_INFO("Subscribed to map topic.");
533  } else {
534  requestMap();
535  }
536  m_force_update = false;
537 
538  dsrv_ = new dynamic_reconfigure::Server<gmcl::GMCLConfig>(ros::NodeHandle("~"));
539  dynamic_reconfigure::Server<gmcl::GMCLConfig>::CallbackType cb = boost::bind(&GmclNode::reconfigureCB, this, _1, _2);
540  dsrv_->setCallback(cb);
541 
542  // 15s timer to warn on lack of receipt of laser scans, #5209
545  boost::bind(&GmclNode::checkLaserReceived, this, _1));
546 
548  diagnosic_updater_.add("Standard deviation", this, &GmclNode::standardDeviationDiagnostics);
549 }
550 
551 void GmclNode::reconfigureCB(gmcl::GMCLConfig &config, uint32_t level)
552 {
553  boost::recursive_mutex::scoped_lock cfl(configuration_mutex_);
554 
555  //we don't want to do anything on the first call
556  //which corresponds to startup
558  {
559  first_reconfigure_call_ = false;
560  default_config_ = config;
561  return;
562  }
563 
564  if(config.restore_defaults) {
565  config = default_config_;
566  //avoid looping
567  config.restore_defaults = false;
568  }
569 
570  resolution_x_ = config.energy_map_resolution_x;
571  resolution_y_ = config.energy_map_resolution_y;
572  if( !resolution_x_ || !resolution_y_)
573  { ROS_ERROR("don't set either of energy map resolutions to zero");
574  ros::shutdown();
575  }
576  threshold_val_ = config.energy_threshold_value;
577  pub_energy_map_ = config.publish_ser;
578 
579  d_thresh_ = config.update_min_d;
580  a_thresh_ = config.update_min_a;
581 
582  resample_interval_ = config.resample_interval;
583 
584  laser_min_range_ = config.laser_min_range;
585  laser_max_range_ = config.laser_max_range;
586 
587  gui_publish_period = ros::Duration(1.0/config.gui_publish_rate);
588  save_pose_period = ros::Duration(1.0/config.save_pose_rate);
589 
590  transform_tolerance_.fromSec(config.transform_tolerance);
591 
592  max_beams_ = config.laser_max_beams;
593  alpha1_ = config.odom_alpha1;
594  alpha2_ = config.odom_alpha2;
595  alpha3_ = config.odom_alpha3;
596  alpha4_ = config.odom_alpha4;
597  alpha5_ = config.odom_alpha5;
598 
599  z_hit_ = config.laser_z_hit;
600  z_short_ = config.laser_z_short;
601  z_max_ = config.laser_z_max;
602  z_rand_ = config.laser_z_rand;
603  sigma_hit_ = config.laser_sigma_hit;
604  lambda_short_ = config.laser_lambda_short;
605  laser_likelihood_max_dist_ = config.laser_likelihood_max_dist;
606 
607  if(config.laser_model_type == "beam")
609  else if(config.laser_model_type == "likelihood_field")
611  else if(config.laser_model_type == "likelihood_field_prob")
613 
614  if(config.odom_model_type == "diff")
616  else if(config.odom_model_type == "omni")
618  else if(config.odom_model_type == "diff-corrected")
620  else if(config.odom_model_type == "omni-corrected")
622 
623  if(config.min_particles > config.max_particles)
624  {
625  ROS_WARN("You've set min_particles to be greater than max particles, this isn't allowed so they'll be set to be equal.");
626  config.max_particles = config.min_particles;
627  }
628 
629  pf_model_.use_optimal_filter = config.use_optimal_filter;
630  pf_model_.use_crossover_mutation = config.use_intelligent_filter;
631  pf_model_.use_self_adaptive = config.use_self_adaptive;
632  pf_model_.use_adaptive_sampling = config.use_kld_sampling;
633 
634  min_particles_ = config.min_particles;
635  max_particles_ = config.max_particles;
636  N_aux_particles_ = config.N_aux_particles;
637  alpha_slow_ = config.recovery_alpha_slow;
638  alpha_fast_ = config.recovery_alpha_fast;
639  crossover_alpha_ = config.crossover_alpha;
640  mutation_prob_ = config.mutation_probability;
641  tf_broadcast_ = config.tf_broadcast;
642 
643  do_beamskip_= config.do_beamskip;
644  beam_skip_distance_ = config.beam_skip_distance;
645  beam_skip_threshold_ = config.beam_skip_threshold;
646 
647  // Clear queued laser objects so that their parameters get updated
648  lasers_.clear();
649  ldata_.clear();
650  GMCLLaserData::sldata.clear();
651  lasers_update_.clear();
652  frame_to_laser_.clear();
653 
654  if( pf_ != NULL )
655  {
656  pf_free( pf_ );
657  pf_ = NULL;
658  }
662  (void *)map_, (void *)energy_map_);
664 
665  ROS_INFO("general particel filter initialized : ");
667  std::cout<<("\t\twith optimal filter on \n");
668  else
669  std::cout<<("\t\twith optimal filter off \n");
671  std::cout<<("\t\twith intelligent filter on \n");
672  else
673  std::cout<<("\t\twith intelligent filter off \n");
675  std::cout<<("\t\twith self adaptive on \n");
676  else
677  std::cout<<("\t\twith self adaptive off \n");
679  std::cout<<("\t\twith kld sampling on \n");
680  else
681  std::cout<<("\t\twith kld sampling off \n");
683  pf_err_ = config.kld_err;
684  pf_z_ = config.kld_z;
685  pf_->pop_err = pf_err_;
686  pf_->pop_z = pf_z_;
687 
688  // Initialize the filter
689  pf_vector_t pf_init_pose_mean = pf_vector_zero();
690  pf_init_pose_mean.v[0] = last_published_pose.pose.pose.position.x;
691  pf_init_pose_mean.v[1] = last_published_pose.pose.pose.position.y;
692  pf_init_pose_mean.v[2] = tf2::getYaw(last_published_pose.pose.pose.orientation);
693  pf_matrix_t pf_init_pose_cov = pf_matrix_zero();
694  pf_init_pose_cov.m[0][0] = last_published_pose.pose.covariance[6*0+0];
695  pf_init_pose_cov.m[1][1] = last_published_pose.pose.covariance[6*1+1];
696  pf_init_pose_cov.m[2][2] = last_published_pose.pose.covariance[6*5+5];
697  pf_init(pf_, pf_init_pose_mean, pf_init_pose_cov);
698  pf_init_ = false;
699 
700  // Instantiate the sensor objects
701  // Odometry
702  delete odom_;
703  odom_ = new GMCLOdom();
704  ROS_ASSERT(odom_);
706  // Laser
707  delete laser_;
712  sigma_hit_, lambda_short_, 0.0);
714  ROS_INFO("Initializing likelihood field model; this can take some time on large maps...");
719  ROS_INFO("Done initializing likelihood field model with probabilities.");
720  }
722  ROS_INFO("Initializing likelihood field model; this can take some time on large maps...");
725  ROS_INFO("Done initializing likelihood field model.");
726  }
727 
728  odom_frame_id_ = stripSlash(config.odom_frame_id);
729  base_frame_id_ = stripSlash(config.base_frame_id);
730  global_frame_id_ = stripSlash(config.global_frame_id);
731 
732  delete laser_scan_filter_;
735  *tf_,
737  100,
738  nh_);
739  laser_scan_filter_->registerCallback(boost::bind(&GmclNode::laserReceived,
740  this, _1));
741 
742  initial_pose_sub_ = nh_.subscribe("initialpose", 2, &GmclNode::initialPoseReceived, this);
743 }
744 
745 
746 void GmclNode::runFromBag(const std::string &in_bag_fn, bool trigger_global_localization)
747 {
748  rosbag::Bag bag;
749  bag.open(in_bag_fn, rosbag::bagmode::Read);
750  std::vector<std::string> topics;
751  topics.push_back(std::string("tf"));
752  std::string scan_topic_name = "base_scan"; // TODO determine what topic this actually is from ROS
753  topics.push_back(scan_topic_name);
754  rosbag::View view(bag, rosbag::TopicQuery(topics));
755 
756  ros::Publisher laser_pub = nh_.advertise<sensor_msgs::LaserScan>(scan_topic_name, 100);
757  ros::Publisher tf_pub = nh_.advertise<tf2_msgs::TFMessage>("/tf", 100);
758 
759  // Sleep for a second to let all subscribers connect
760  ros::WallDuration(1.0).sleep();
761 
763 
764  // Wait for map
765  while (ros::ok())
766  {
767  {
768  boost::recursive_mutex::scoped_lock cfl(configuration_mutex_);
769  if (map_)
770  {
771  ROS_INFO("Map is ready");
772  break;
773  }
774  }
775  ROS_INFO("Waiting for map...");
777  }
778 
779  if (trigger_global_localization)
780  {
781  std_srvs::Empty empty_srv;
782  globalLocalizationCallback(empty_srv.request, empty_srv.response);
783  }
784 
785  BOOST_FOREACH(rosbag::MessageInstance const msg, view)
786  {
787  if (!ros::ok())
788  {
789  break;
790  }
791 
792  // Process any ros messages or callbacks at this point
794 
795  tf2_msgs::TFMessage::ConstPtr tf_msg = msg.instantiate<tf2_msgs::TFMessage>();
796  if (tf_msg != NULL)
797  {
798  tf_pub.publish(msg);
799  for (size_t ii=0; ii<tf_msg->transforms.size(); ++ii)
800  {
801  tf_->setTransform(tf_msg->transforms[ii], "rosbag_authority");
802  }
803  continue;
804  }
805 
806  sensor_msgs::LaserScan::ConstPtr base_scan = msg.instantiate<sensor_msgs::LaserScan>();
807  if (base_scan != NULL)
808  {
809  laser_pub.publish(msg);
810  laser_scan_filter_->add(base_scan);
812  {
814  }
815  continue;
816  }
817 
818  ROS_WARN_STREAM("Unsupported message type" << msg.getTopic());
819  }
820 
821  bag.close();
822 
823  double runtime = (ros::WallTime::now() - start).toSec();
824  ROS_INFO("Bag complete, took %.1f seconds to process, shutting down", runtime);
825 
826  const geometry_msgs::Quaternion & q(last_published_pose.pose.pose.orientation);
827  double yaw, pitch, roll;
828  tf2::Matrix3x3(tf2::Quaternion(q.x, q.y, q.z, q.w)).getEulerYPR(yaw,pitch,roll);
829  ROS_INFO("Final location %.3f, %.3f, %.3f with stamp=%f",
830  last_published_pose.pose.pose.position.x,
831  last_published_pose.pose.pose.position.y,
832  yaw, last_published_pose.header.stamp.toSec()
833  );
834 
835  ros::shutdown();
836 }
837 
838 
840 {
841  // We need to apply the last transform to the latest odom pose to get
842  // the latest map pose to store. We'll take the covariance from
843  // last_published_pose.
844  tf2::Transform odom_pose_tf2;
845  tf2::convert(latest_odom_pose_.pose, odom_pose_tf2);
846  tf2::Transform map_pose = latest_tf_.inverse() * odom_pose_tf2;
847 
848  double yaw = tf2::getYaw(map_pose.getRotation());
849 
850  ROS_DEBUG("Saving pose to server. x: %.3f, y: %.3f", map_pose.getOrigin().x(), map_pose.getOrigin().y() );
851 
852  private_nh_.setParam("initial_pose_x", map_pose.getOrigin().x());
853  private_nh_.setParam("initial_pose_y", map_pose.getOrigin().y());
854  private_nh_.setParam("initial_pose_a", yaw);
855  private_nh_.setParam("initial_cov_xx",
856  last_published_pose.pose.covariance[6*0+0]);
857  private_nh_.setParam("initial_cov_yy",
858  last_published_pose.pose.covariance[6*1+1]);
859  private_nh_.setParam("initial_cov_aa",
860  last_published_pose.pose.covariance[6*5+5]);
861 }
862 
864 {
865  init_pose_[0] = 0.0;
866  init_pose_[1] = 0.0;
867  init_pose_[2] = 0.0;
868  init_cov_[0] = 0.5 * 0.5;
869  init_cov_[1] = 0.5 * 0.5;
870  init_cov_[2] = (M_PI/12.0) * (M_PI/12.0);
871  // Check for NAN on input from param server, #5239
872  double tmp_pos;
873  private_nh_.param("initial_pose_x", tmp_pos, init_pose_[0]);
874  if(!std::isnan(tmp_pos))
875  init_pose_[0] = tmp_pos;
876  else
877  ROS_WARN("ignoring NAN in initial pose X position");
878  private_nh_.param("initial_pose_y", tmp_pos, init_pose_[1]);
879  if(!std::isnan(tmp_pos))
880  init_pose_[1] = tmp_pos;
881  else
882  ROS_WARN("ignoring NAN in initial pose Y position");
883  private_nh_.param("initial_pose_a", tmp_pos, init_pose_[2]);
884  if(!std::isnan(tmp_pos))
885  init_pose_[2] = tmp_pos;
886  else
887  ROS_WARN("ignoring NAN in initial pose Yaw");
888  private_nh_.param("initial_cov_xx", tmp_pos, init_cov_[0]);
889  if(!std::isnan(tmp_pos))
890  init_cov_[0] =tmp_pos;
891  else
892  ROS_WARN("ignoring NAN in initial covariance XX");
893  private_nh_.param("initial_cov_yy", tmp_pos, init_cov_[1]);
894  if(!std::isnan(tmp_pos))
895  init_cov_[1] = tmp_pos;
896  else
897  ROS_WARN("ignoring NAN in initial covariance YY");
898  private_nh_.param("initial_cov_aa", tmp_pos, init_cov_[2]);
899  if(!std::isnan(tmp_pos))
900  init_cov_[2] = tmp_pos;
901  else
902  ROS_WARN("ignoring NAN in initial covariance AA");
903 }
904 
905 void
907 {
910  {
911  ROS_WARN("No laser scan received (and thus no pose updates have been published) for %f seconds. Verify that data is being published on the %s topic.",
912  d.toSec(),
914  }
915 }
916 
917 void
919 {
920  boost::recursive_mutex::scoped_lock ml(configuration_mutex_);
921 
922  // get map via RPC
923  nav_msgs::GetMap::Request req;
924  nav_msgs::GetMap::Response resp;
925  ROS_INFO("Requesting the map...");
926  while(!ros::service::call("static_map", req, resp))
927  {
928  ROS_WARN("Request for map failed; trying again...");
929  ros::Duration d(0.5);
930  d.sleep();
931  }
932  handleMapMessage( resp.map );
933 }
934 
935 void
936 GmclNode::mapReceived(const nav_msgs::OccupancyGridConstPtr& msg)
937 {
939  return;
940  }
941 
942  handleMapMessage( *msg );
943 
944  first_map_received_ = true;
945 }
946 
947 void
948 GmclNode::handleMapMessage(const nav_msgs::OccupancyGrid& msg)
949 {
950  boost::recursive_mutex::scoped_lock cfl(configuration_mutex_);
951 
952  ROS_INFO("Received a %d X %d map @ %.3f m/pix\n",
953  msg.info.width,
954  msg.info.height,
955  msg.info.resolution);
956 
957  if(msg.header.frame_id != global_frame_id_)
958  ROS_WARN("Frame_id of map received:'%s' doesn't match global_frame_id:'%s'. This could cause issues with reading published topics",
959  msg.header.frame_id.c_str(),
960  global_frame_id_.c_str());
961 
963  // Clear queued laser objects because they hold pointers to the existing
964  // map, #5202.
965  lasers_.clear();
966  ldata_.clear();
967  GMCLLaserData::sldata.clear();
968  lasers_update_.clear();
969  frame_to_laser_.clear();
970 
971  map_ = convertMap(msg);
973  {
976 
977  ROS_INFO("energy map has been created with a %d X %d \n energy cell @ resoultion_x %.2f m and resoultion_y %.2f m \n",
979  }
980 
981 #if NEW_UNIFORM_SAMPLING
982  // Index of free space
983  free_space_indices.resize(0);
984  for(int i = 0; i < map_->size_x; i++)
985  for(int j = 0; j < map_->size_y; j++)
986  if(map_->cells[MAP_INDEX(map_,i,j)].occ_state == -1)
987  free_space_indices.push_back(std::make_pair(i,j));
988 #endif
989  // Create the particle filter
993  (void *)map_, (void *)energy_map_);
995  ROS_INFO("general particle filter initialized : ");
997  std::cout<<("\t\twith optimal filter on \n");
998  else
999  std::cout<<("\t\twith optimal filter off \n");
1001  std::cout<<("\t\twith intelligent filter on \n");
1002  else
1003  std::cout<<("\t\twith intelligent filter off \n");
1005  std::cout<<("\t\twith self adaptive on \n");
1006  else
1007  std::cout<<("\t\twith self adaptive off \n");
1009  std::cout<<("\t\twith kld sampling on \n");
1010  else
1011  std::cout<<("\t\twith kld sampling off \n");
1012 
1014  pf_->pop_err = pf_err_;
1015  pf_->pop_z = pf_z_;
1016 
1017  // Initialize the filter
1019  pf_vector_t pf_init_pose_mean = pf_vector_zero();
1020  pf_init_pose_mean.v[0] = init_pose_[0];
1021  pf_init_pose_mean.v[1] = init_pose_[1];
1022  pf_init_pose_mean.v[2] = init_pose_[2];
1023  pf_matrix_t pf_init_pose_cov = pf_matrix_zero();
1024  pf_init_pose_cov.m[0][0] = init_cov_[0];
1025  pf_init_pose_cov.m[1][1] = init_cov_[1];
1026  pf_init_pose_cov.m[2][2] = init_cov_[2];
1027  pf_init(pf_, pf_init_pose_mean, pf_init_pose_cov);
1028  pf_init_ = false;
1029 
1030  // Instantiate the sensor objects
1031  // Odometry
1032  delete odom_;
1033  odom_ = new GMCLOdom();
1034  ROS_ASSERT(odom_);
1036  // Laser
1037  delete laser_;
1038  laser_ = new GMCLLaser(max_beams_, map_);
1039  ROS_ASSERT(laser_);
1042  sigma_hit_, lambda_short_, 0.0);
1044  ROS_INFO("Initializing likelihood field model; this can take some time on large maps...");
1049  ROS_INFO("Done initializing likelihood field model.");
1050  }
1051  else
1052  {
1053  ROS_INFO("Initializing likelihood field model; this can take some time on large maps...");
1056  ROS_INFO("Done initializing likelihood field model.");
1057  }
1058 
1059  // In case the initial pose message arrived before the first map,
1060  // try to apply the initial pose now that the map has arrived.
1061  applyInitialPose();
1062 
1063 }
1064 
1065 void
1067 {
1068  if( map_ != NULL ) {
1069  map_free( map_ );
1070  map_ = NULL;
1071  }
1072  if( energy_map_ != NULL ) {
1074  energy_map_ = NULL;
1075  }
1076  if( pf_ != NULL ) {
1077  pf_free( pf_ );
1078  pf_ = NULL;
1079  }
1080  delete odom_;
1081  odom_ = NULL;
1082  delete laser_;
1083  laser_ = NULL;
1084 }
1085 
1090 map_t*
1091 GmclNode::convertMap( const nav_msgs::OccupancyGrid& map_msg )
1092 {
1093  map_t* map = map_alloc();
1094  ROS_ASSERT(map);
1095 
1096  map->size_x = map_msg.info.width;
1097  map->size_y = map_msg.info.height;
1098  map->scale = map_msg.info.resolution;
1099  map->origin_x = map_msg.info.origin.position.x + (map->size_x / 2) * map->scale;
1100  map->origin_y = map_msg.info.origin.position.y + (map->size_y / 2) * map->scale;
1101  // Convert to player format
1102  map->cells = (map_cell_t*)malloc(sizeof(map_cell_t)*map->size_x*map->size_y);
1103  ROS_ASSERT(map->cells);
1104  for(int i=0;i<map->size_x * map->size_y;i++)
1105  {
1106  if(map_msg.data[i] == 0)
1107  map->cells[i].occ_state = -1;
1108  else if(map_msg.data[i] == 100)
1109  map->cells[i].occ_state = +1;
1110  else
1111  map->cells[i].occ_state = 0;
1112  }
1113 
1114  return map;
1115 }
1116 
1118 {
1119  delete dsrv_;
1121  delete laser_scan_filter_;
1122  delete laser_scan_sub_;
1123  // TODO: delete everything allocated in constructor
1124 }
1125 
1126 bool
1127 GmclNode::getOdomPose(geometry_msgs::PoseStamped& odom_pose,
1128  double& x, double& y, double& yaw,
1129  const ros::Time& t, const std::string& f)
1130 {
1131  // Get the robot's pose
1132  geometry_msgs::PoseStamped ident;
1133  ident.header.frame_id = stripSlash(f);
1134  ident.header.stamp = t;
1135  tf2::toMsg(tf2::Transform::getIdentity(), ident.pose);
1136  try
1137  {
1138  this->tf_->transform(ident, odom_pose, odom_frame_id_);
1139  }
1140  catch(tf2::TransformException e)
1141  {
1142  ROS_WARN("Failed to compute odom pose, skipping scan (%s)", e.what());
1143  return false;
1144  }
1145  x = odom_pose.pose.position.x;
1146  y = odom_pose.pose.position.y;
1147  yaw = tf2::getYaw(odom_pose.pose.orientation);
1148 
1149  return true;
1150 }
1151 
1152 
1154 GmclNode::uniformPoseGenerator(pf_t *pf, void* arg , void* e_arg )
1155 {
1156 if(pf->model.use_optimal_filter && GMCLLaserData::sldata.size()>0)
1157 {
1158  double max_weight = 0;
1159  pf_vector_t f_pose;
1160  pf_vector_t t_p[pf->N_aux_particles];
1161  GMCLLaser *self;
1162  if(pf->model.use_self_adaptive)
1163  { energy_map_t* energy_map = (energy_map_t*)e_arg;
1164  if(energy_map->accepted_count>0)
1165  {
1166  // ROS_INFO("size %d", AMCLLaserData::sldata.size());
1167  for ( int loop=0 ; loop < pf->N_aux_particles ; loop++)
1168  { int index = drand48()*energy_map->accepted_count;
1169  t_p[loop].v[0] = energy_map->poses[energy_map->accepted_index[index]].pose_x ;
1170  t_p[loop].v[1] = energy_map->poses[energy_map->accepted_index[index]].pose_y ;
1171  t_p[loop].v[2] = energy_map->poses[energy_map->accepted_index[index]].orientation_yaw;
1172  double pose_weight = 1.0 ;
1173 
1174  for ( int laser_index = 0 ; laser_index < GMCLLaserData::sldata.size() ; laser_index++ )
1175  {
1176  self = (GMCLLaser*) GMCLLaserData::sldata[laser_index]->sensor;
1177  pose_weight *= self->PoseWeight(t_p[loop] , GMCLLaserData::sldata[laser_index]);
1178  // ROS_INFO(" self adaptive aux weight%f", pose_weight);
1179 
1180  }
1181  if ( pose_weight > max_weight)
1182  {
1183  f_pose = t_p[loop];
1184  max_weight = pose_weight;
1185  }
1186 
1187  }
1188  // ROS_INFO(" self adaptive max weight %f", max_weight);
1189  return f_pose;
1190  }
1191  }
1192  map_t* map = (map_t*)arg;
1193 
1194 int loop ;
1195 
1196 #if NEW_UNIFORM_SAMPLING
1197 
1198  for ( loop=0 ; loop < pf->N_aux_particles ; loop++)
1199  {
1200  unsigned int rand_index = drand48() * free_space_indices.size();
1201  std::pair<int,int> free_point = free_space_indices[rand_index];
1202 
1203  t_p[loop].v[0] = MAP_WXGX(map, free_point.first);
1204  t_p[loop].v[1] = MAP_WYGY(map, free_point.second);
1205  t_p[loop].v[2] = drand48() * 2 * M_PI - M_PI;
1206 #else
1207  double min_x, max_x, min_y, max_y;
1208 
1209  min_x = (map->size_x * map->scale)/2.0 - map->origin_x;
1210  max_x = (map->size_x * map->scale)/2.0 + map->origin_x;
1211  min_y = (map->size_y * map->scale)/2.0 - map->origin_y;
1212  max_y = (map->size_y * map->scale)/2.0 + map->origin_y;
1213 
1214  for ( loop=0 ; loop < pf->N_aux_particles ; loop++)
1215  {
1216  ROS_DEBUG("Generating new uniform sample");
1217  for(;;)
1218  {
1219  t_p[loop].v[0] = min_x + drand48() * (max_x - min_x);
1220  t_p[loop].v[1] = min_y + drand48() * (max_y - min_y);
1221  t_p[loop].v[2] = drand48() * 2 * M_PI - M_PI;
1222  // Check that it's a free cell
1223  int i,j;
1224  i = MAP_GXWX(map, p.v[0]);
1225  j = MAP_GYWY(map, p.v[1]);
1226  if(MAP_VALID(map,i,j) && (map->cells[MAP_INDEX(map,i,j)].occ_state == -1))
1227  break;
1228  }
1229  #endif
1230 
1231  double pose_weight = 1.0 ;
1232  for ( int laser_index = 0 ; laser_index < GMCLLaserData::sldata.size() ; laser_index++ )
1233  {
1234  self = (GMCLLaser*) GMCLLaserData::sldata[laser_index]->sensor;
1235  pose_weight *= self->PoseWeight(t_p[loop] , GMCLLaserData::sldata[laser_index]);
1236 
1237  }
1238  if ( pose_weight > max_weight)
1239  {
1240  f_pose = t_p[loop];
1241  max_weight = pose_weight;
1242  }
1243  // ROS_INFO("Generating new uniform sample %d", loop);
1244  }
1245 
1246  return f_pose;
1247 
1248 }
1249 else
1250  { if(pf->model.use_self_adaptive)
1251  { energy_map_t* energy_map = (energy_map_t*)e_arg;
1252  if(energy_map->accepted_count>0)
1253  {
1254  pf_vector_t p;
1255  int index = drand48()*energy_map->accepted_count;
1256  p.v[0] = energy_map->poses[energy_map->accepted_index[index]].pose_x ;
1257  p.v[1] = energy_map->poses[energy_map->accepted_index[index]].pose_y ;
1258  p.v[2] = energy_map->poses[energy_map->accepted_index[index]].orientation_yaw;
1259 
1260  return p;
1261  }
1262  }
1263  map_t* map = (map_t*)arg;
1264 #if NEW_UNIFORM_SAMPLING
1265  unsigned int rand_index = drand48() * free_space_indices.size();
1266  std::pair<int,int> free_point = free_space_indices[rand_index];
1267  pf_vector_t p;
1268  p.v[0] = MAP_WXGX(map, free_point.first);
1269  p.v[1] = MAP_WYGY(map, free_point.second);
1270  p.v[2] = drand48() * 2 * M_PI - M_PI;
1271 #else
1272  double min_x, max_x, min_y, max_y;
1273 
1274  min_x = (map->size_x * map->scale)/2.0 - map->origin_x;
1275  max_x = (map->size_x * map->scale)/2.0 + map->origin_x;
1276  min_y = (map->size_y * map->scale)/2.0 - map->origin_y;
1277  max_y = (map->size_y * map->scale)/2.0 + map->origin_y;
1278 
1279  pf_vector_t p;
1280 
1281  ROS_DEBUG("Generating new uniform sample");
1282  for(;;)
1283  {
1284  p.v[0] = min_x + drand48() * (max_x - min_x);
1285  p.v[1] = min_y + drand48() * (max_y - min_y);
1286  p.v[2] = drand48() * 2 * M_PI - M_PI;
1287  // Check that it's a free cell
1288  int i,j;
1289  i = MAP_GXWX(map, p.v[0]);
1290  j = MAP_GYWY(map, p.v[1]);
1291  if(MAP_VALID(map,i,j) && (map->cells[MAP_INDEX(map,i,j)].occ_state == -1))
1292  break;
1293  }
1294 #endif
1295  return p;
1296 
1297  }
1298 }
1299 bool
1300 GmclNode::globalLocalizationCallback(std_srvs::Empty::Request& req,
1301  std_srvs::Empty::Response& res)
1302 {
1303  if( map_ == NULL ) {
1304  return true;
1305  }
1306 
1307  boost::recursive_mutex::scoped_lock gl(configuration_mutex_);
1308 
1310  {
1311  ROS_INFO("Initializing with uniform distribution");
1312  }
1313  else
1314  ROS_INFO("Initializing with uniform distribution in energy map");
1315 
1317  (void *)map_ , (void *)energy_map_ );
1318  ROS_INFO("Global initialisation done!");
1319  pf_init_ = false;
1320  return true;
1321 }
1322 
1323 // force nomotion updates (amcl updating without requiring motion)
1324 bool
1325 GmclNode::nomotionUpdateCallback(std_srvs::Empty::Request& req,
1326  std_srvs::Empty::Response& res)
1327 {
1328  m_force_update = true;
1329  //ROS_INFO("Requesting no-motion update");
1330  return true;
1331 }
1332 
1333 bool
1334 GmclNode::setMapCallback(nav_msgs::SetMap::Request& req,
1335  nav_msgs::SetMap::Response& res)
1336 {
1337  handleMapMessage(req.map);
1338  handleInitialPoseMessage(req.initial_pose);
1339  res.success = true;
1340  return true;
1341 }
1342 
1343 
1344 
1345 void
1346 GmclNode::handelNewLaser(const sensor_msgs::LaserScanConstPtr& laser_scan)
1347 {
1348  lasers_.push_back(new GMCLLaser(*laser_));
1349  ldata_.push_back(new GMCLLaserData);
1350  GMCLLaserData::sldata.push_back(new GMCLLaserData);
1351  lasers_update_.push_back(true);
1352  laser_index = frame_to_laser_.size();
1353  ldata_[laser_index]->sensor = lasers_[laser_index];
1354  lsensor_scan_t t_laser_scan;
1355 
1356  std::string laser_scan_frame_id = stripSlash(laser_scan->header.frame_id);
1357  geometry_msgs::PoseStamped ident;
1358  ident.header.frame_id = laser_scan_frame_id;
1359  ident.header.stamp = ros::Time();
1360  tf2::toMsg(tf2::Transform::getIdentity(), ident.pose);
1361  geometry_msgs::PoseStamped laser_pose;
1362  try
1363  {
1364  this->tf_->transform(ident, laser_pose, base_frame_id_);
1365  }
1366  catch(tf2::TransformException& e)
1367  {
1368  ROS_ERROR("Couldn't transform from %s to %s, "
1369  "even though the message notifier is in use",
1370  laser_scan_frame_id.c_str(),
1371  base_frame_id_.c_str());
1372  return;
1373  }
1374 
1375  pf_vector_t laser_pose_v;
1376  laser_pose_v.v[0] = laser_pose.pose.position.x;
1377  laser_pose_v.v[1] = laser_pose.pose.position.y;
1378  // laser mounting angle gets computed later -> set to 0 here!
1379  laser_pose_v.v[2] = 0;
1380 
1381  ROS_DEBUG("Received laser's pose wrt robot: %.3f %.3f %.3f",
1382  laser_pose_v.v[0],
1383  laser_pose_v.v[1],
1384  laser_pose_v.v[2]);
1385 
1386  t_laser_scan.laser_pose = laser_pose_v;
1387 
1388  frame_to_laser_[laser_scan_frame_id] = laser_index;
1389 
1390  tf2::Quaternion q;
1391  q.setRPY(0.0, 0.0, laser_scan->angle_min);
1392  geometry_msgs::QuaternionStamped min_q, inc_q;
1393  min_q.header.stamp = laser_scan->header.stamp;
1394  min_q.header.frame_id = stripSlash(laser_scan->header.frame_id);
1395  tf2::convert(q, min_q.quaternion);
1396 
1397  q.setRPY(0.0, 0.0, laser_scan->angle_min + laser_scan->angle_increment);
1398  inc_q.header = min_q.header;
1399  tf2::convert(q, inc_q.quaternion);
1400  try
1401  {
1402  tf_->transform(min_q, min_q, base_frame_id_);
1403  tf_->transform(inc_q, inc_q, base_frame_id_);
1404  }
1405  catch(tf2::TransformException& e)
1406  {
1407  ROS_WARN("Unable to transform min/max laser angles into base frame: %s",
1408  e.what());
1409  return;
1410  }
1411  double angle_min = tf2::getYaw(min_q.quaternion);
1412  double angle_increment = tf2::getYaw(inc_q.quaternion) - angle_min;
1413 
1414  // wrapping angle to [-pi .. pi]
1415  angle_increment = fmod(angle_increment + 5*M_PI, 2*M_PI) - M_PI; //angle wrt base
1416 
1417  // Apply range min/max thresholds, if the user supplied them
1418  double range_max , range_min ;
1419 
1420  if(laser_max_range_ > 0.0)
1421  range_max = std::min(laser_scan->range_max, (float)laser_max_range_);
1422  else
1423  range_max = laser_scan->range_max;
1424 
1425  if(laser_min_range_ > 0.0)
1426  range_min = std::max(laser_scan->range_min, (float)laser_min_range_);
1427  else
1428  range_min = laser_scan->range_min;
1429 
1430  t_laser_scan.range_max = range_max;
1431  t_laser_scan.range_min = range_min;
1432  t_laser_scan.range_count = laser_scan->ranges.size();
1433 
1434  // The AMCLLaserData destructor will free this memory
1435  ldata_[laser_index]->ranges = new double[laser_scan->ranges.size()][2];
1436  ROS_ASSERT(ldata_[laser_index]->ranges);
1437 
1438  for(int i=0; i<laser_scan->ranges.size(); i++)
1439 
1440  ldata_[laser_index]->ranges[i][1] = angle_min + (i * angle_increment);
1441 
1442  t_laser_scan.ranges = ldata_[laser_index]->ranges ;
1443 
1444  lasers_[laser_index]->SetLaserScan(t_laser_scan) ;
1445 
1446  ldata_[laser_index]->range_count = t_laser_scan.range_count;
1447 
1449  {
1451 
1452  ROS_INFO("adding Laser %d to energy map; this can take some time on large maps with high resolution...", laser_index);
1453 
1454  map_update_espace(energy_map_,map_, &t_laser_scan) ; // compute the espace for new laser
1455 
1456 
1457 
1458  ROS_INFO("Laser %d has been added to espace", laser_index);
1459  }
1460 
1461 }
1462 
1463 void
1464 GmclNode::laserReceived(const sensor_msgs::LaserScanConstPtr& laser_scan)
1465 {
1466  std::string laser_scan_frame_id = stripSlash(laser_scan->header.frame_id);
1468  if( map_ == NULL ) {
1469  return;
1470  }
1471  boost::recursive_mutex::scoped_lock lr(configuration_mutex_);
1472 
1473  // Do we have the base->base_laser Tx yet?
1474  if(frame_to_laser_.find(laser_scan_frame_id) == frame_to_laser_.end())
1475  {
1476  ROS_INFO("Setting up laser %d (frame_id=%s)\n", (int)frame_to_laser_.size(), laser_scan_frame_id.c_str());
1477 
1478  GmclNode::handelNewLaser(laser_scan) ;
1479 
1480  } else {
1481  // we have the laser pose, retrieve laser index
1482  laser_index = frame_to_laser_[laser_scan_frame_id];
1483  }
1484 
1485  // Where was the robot when this scan was taken?
1486  pf_vector_t pose;
1487  if(!getOdomPose(latest_odom_pose_, pose.v[0], pose.v[1], pose.v[2],
1488  laser_scan->header.stamp, base_frame_id_))
1489  {
1490  ROS_ERROR("Couldn't determine robot's pose associated with laser scan");
1491  return;
1492  }
1493 
1494 
1495  pf_vector_t delta = pf_vector_zero();
1496 
1497  if(pf_init_)
1498  {
1499  // Compute change in pose
1500  //delta = pf_vector_coord_sub(pose, pf_odom_pose_);
1501  delta.v[0] = pose.v[0] - pf_odom_pose_.v[0];
1502  delta.v[1] = pose.v[1] - pf_odom_pose_.v[1];
1503  delta.v[2] = angle_diff(pose.v[2], pf_odom_pose_.v[2]);
1504 
1505 if ( fabs (delta.v[0] )> 2.0 || fabs (delta.v[1] )> 2.0)
1506  { pf_odom_pose_.v[0] = pose.v[0] ;
1507  pf_odom_pose_.v[1] = pose.v[1] ;
1508  pf_odom_pose_.v[2] = pose.v[2] ;
1509  return;
1510  }
1511  // See if we should update the filter
1512  bool update = fabs(delta.v[0]) > d_thresh_ ||
1513  fabs(delta.v[1]) > d_thresh_ ||
1514  fabs(delta.v[2]) > a_thresh_;
1516  m_force_update=false;
1517 
1518  // Set the laser update flags
1519  if(update)
1520  for(unsigned int i=0; i < lasers_update_.size(); i++)
1521  lasers_update_[i] = true;
1522  }
1523 
1524  bool force_publication = false;
1525  if(!pf_init_)
1526  {
1527  // Pose at last filter update
1528  pf_odom_pose_ = pose;
1529 
1530  // Filter is now initialized
1531  pf_init_ = true;
1532 
1533  // Should update sensor data
1534  for(unsigned int i=0; i < lasers_update_.size(); i++)
1535  lasers_update_[i] = true;
1536 
1537  force_publication = true;
1538 
1539  resample_count_ = 0;
1540  }
1541  // If the robot has moved, update the filter
1542  else if(pf_init_ && lasers_update_[laser_index])
1543  {
1544  //printf("pose\n");
1545  //pf_vector_fprintf(pose, stdout, "%.3f");
1546 
1547  GMCLOdomData odata;
1548  odata.sensor = odom_;
1549  odata.pose = pose;
1550  // HACK
1551  // Modify the delta in the action data so the filter gets
1552  // updated correctly
1553  odata.delta = delta;
1554 
1555  // Use the action data to update the filter
1556  odom_->UpdateAction(pf_, (GMCLSensorData*)&odata);
1557 
1558  // Pose at last filter update
1559  //this->pf_odom_pose = pose;
1560  }
1561 
1562  bool resampled = false;
1563  // If the robot has moved, update the filter
1565  {
1566 
1567  // To account for lasers that are mounted upside-down, we determine the
1568  // min, max, and increment angles of the laser in the base frame.
1569  //
1570  // Construct min and max angles of laser, in the base_link frame.
1571 
1572  for(int i=0;i<laser_scan->ranges.size();i++)
1573  {
1574 
1575  // amcl doesn't (yet) have a concept of min range. So we'll map short
1576  // readings to max range.
1577  if(laser_scan->ranges[i] <= lasers_[laser_index]->range_min)
1578  ldata_[laser_index]->ranges[i][0] = lasers_[laser_index]->range_max;
1579 
1580  // else if (laser_scan->ranges[i] >= lasers_[laser_index]->range_max)
1581  // ldata_[laser_index]->ranges[i][0] = lasers_[laser_index]->range_max;
1582  else
1583  ldata_[laser_index]->ranges[i][0] = laser_scan->ranges[i];
1584 
1585  }
1586 
1587  GMCLLaserData::sldata[laser_index] = ldata_[laser_index] ;
1588  lasers_[laser_index]->UpdateSensor(pf_, (GMCLSensorData*) GMCLLaserData::sldata[laser_index]);
1589 
1590  lasers_update_[laser_index] = false;
1591 
1592  pf_odom_pose_ = pose;
1593 
1595  pf_update_crossover_mutation(pf_, (pf_reupdate_sensor_fn_t) GMCLLaser::ReUpdateSensor,
1598  {
1599  lsensor_scan_t* t_laser_scan = new lsensor_scan_t;
1600 
1601  t_laser_scan->ranges = ldata_[laser_index]->ranges;
1602  t_laser_scan->range_count = ldata_[laser_index]->range_count;
1603  t_laser_scan->range_max = lasers_[laser_index]->range_max;
1604 
1605  map_calc_SER(energy_map_ , t_laser_scan);
1606 
1607  delete t_laser_scan;
1608  if(!((resample_count_+1) % lasers_update_.size()))
1610  }
1611 
1612  // Resample the particles
1613  if(!(++resample_count_ % resample_interval_)) // must collect data from all laser data sensors
1614  { // before resampling
1616  resampled = true;
1617  }
1618 
1619 
1621  ROS_INFO("Num samples: %d\n", set->sample_count);
1622  // Publish the resulting cloud
1623  // TODO: set maximum rate for publishing
1624  if (!m_force_update)
1625  {
1627  { energy_pose_t* poses = energy_map_->poses;
1628  int* accepted_index = energy_map_->accepted_index;
1629  int accepted_count = energy_map_->accepted_count ;
1630  geometry_msgs::PoseArray energy_cloud_msg;
1631  energy_cloud_msg.header.stamp = ros::Time::now();
1632  energy_cloud_msg.header.frame_id = global_frame_id_;
1633  energy_cloud_msg.poses.resize(energy_map_->accepted_count);
1634 
1635  for (int i=0 ; i<accepted_count ; i++ )
1636  {
1637  energy_cloud_msg.poses[i].position.x = poses[accepted_index[i]].pose_x;
1638  energy_cloud_msg.poses[i].position.y = poses[accepted_index[i]].pose_y;
1639  energy_cloud_msg.poses[i].position.z = 0;
1640  tf2::Quaternion q;
1641  q.setRPY(0, 0,poses[accepted_index[i]].orientation_yaw);
1642  tf2::convert(q,energy_cloud_msg.poses[i].orientation);
1643  }
1644  energy_particlecloud_pub_.publish(energy_cloud_msg);
1645  }
1646 
1647  geometry_msgs::PoseArray cloud_msg;
1648  cloud_msg.header.stamp = ros::Time::now();
1649  cloud_msg.header.frame_id = global_frame_id_;
1650  cloud_msg.poses.resize(set->sample_count);
1651 
1652  for(int i=0;i<set->sample_count;i++)
1653  {
1654  cloud_msg.poses[i].position.x = set->samples[i].pose.v[0];
1655  cloud_msg.poses[i].position.y = set->samples[i].pose.v[1];
1656  cloud_msg.poses[i].position.z = 0;
1657  tf2::Quaternion q;
1658  q.setRPY(0, 0, set->samples[i].pose.v[2]);
1659  tf2::convert(q, cloud_msg.poses[i].orientation);
1660  }
1661  particlecloud_pub_.publish(cloud_msg);
1662 
1663 
1664  }
1665  }
1666  if(resampled || force_publication)
1667  {
1668  // Read out the current hypotheses
1669  double max_weight = 0.0;
1670  int max_weight_hyp = -1;
1671  std::vector<gmcl_hyp_t> hyps;
1672  hyps.resize(pf_->sets[pf_->current_set].cluster_count);
1673  for(int hyp_count = 0;
1674  hyp_count < pf_->sets[pf_->current_set].cluster_count; hyp_count++)
1675  {
1676  double weight;
1677  pf_vector_t pose_mean;
1678  pf_matrix_t pose_cov;
1679  if (!pf_get_cluster_stats(pf_, hyp_count, &weight, &pose_mean, &pose_cov))
1680  {
1681  ROS_ERROR("Couldn't get stats on cluster %d", hyp_count);
1682  break;
1683  }
1684  hyps[hyp_count].weight = weight;
1685  hyps[hyp_count].pf_pose_mean = pose_mean;
1686  hyps[hyp_count].pf_pose_cov = pose_cov;
1687 
1688  if(hyps[hyp_count].weight > max_weight)
1689  {
1690  max_weight = hyps[hyp_count].weight;
1691  max_weight_hyp = hyp_count;
1692  }
1693  }
1694 
1695  if(max_weight > 0.0)
1696  {
1697  ROS_DEBUG("Max weight pose: %.3f %.3f %.3f",
1698  hyps[max_weight_hyp].pf_pose_mean.v[0],
1699  hyps[max_weight_hyp].pf_pose_mean.v[1],
1700  hyps[max_weight_hyp].pf_pose_mean.v[2]);
1701 
1702  /*
1703  puts("");
1704  pf_matrix_fprintf(hyps[max_weight_hyp].pf_pose_cov, stdout, "%6.3f");
1705  puts("");
1706  */
1707 
1708  geometry_msgs::PoseWithCovarianceStamped p;
1709  // Fill in the header
1710  p.header.frame_id = global_frame_id_;
1711  p.header.stamp = laser_scan->header.stamp;
1712  // Copy in the pose
1713  p.pose.pose.position.x = hyps[max_weight_hyp].pf_pose_mean.v[0];
1714  p.pose.pose.position.y = hyps[max_weight_hyp].pf_pose_mean.v[1];
1715 
1716  tf2::Quaternion q;
1717  q.setRPY(0, 0, hyps[max_weight_hyp].pf_pose_mean.v[2]);
1718  tf2::convert(q, p.pose.pose.orientation);
1719  // Copy in the covariance, converting from 3-D to 6-D
1721  for(int i=0; i<2; i++)
1722  {
1723  for(int j=0; j<2; j++)
1724  {
1725  // Report the overall filter covariance, rather than the
1726  // covariance for the highest-weight cluster
1727  //p.covariance[6*i+j] = hyps[max_weight_hyp].pf_pose_cov.m[i][j];
1728  p.pose.covariance[6*i+j] = set->cov.m[i][j];
1729  }
1730  }
1731  p.pose.covariance[6*3] = set->cov.m[2][0];
1732  // Report the overall filter covariance, rather than the
1733  // covariance for the highest-weight cluster
1734  //p.covariance[6*5+5] = hyps[max_weight_hyp].pf_pose_cov.m[2][2];
1735  p.pose.covariance[6*5+5] = set->cov.m[2][2];
1736 
1737  /*
1738  printf("cov:\n");
1739  for(int i=0; i<6; i++)
1740  {
1741  for(int j=0; j<6; j++)
1742  printf("%6.3f ", p.covariance[6*i+j]);
1743  puts("");
1744  }
1745  */
1746 
1747  pose_pub_.publish(p);
1748  last_published_pose = p;
1749 
1750  ROS_DEBUG("New pose: %6.3f %6.3f %6.3f",
1751  hyps[max_weight_hyp].pf_pose_mean.v[0],
1752  hyps[max_weight_hyp].pf_pose_mean.v[1],
1753  hyps[max_weight_hyp].pf_pose_mean.v[2]);
1754 
1755  // subtracting base to odom from map to base and send map to odom instead
1756  geometry_msgs::PoseStamped odom_to_map;
1757  try
1758  {
1759  tf2::Quaternion q;
1760  q.setRPY(0, 0, hyps[max_weight_hyp].pf_pose_mean.v[2]);
1761  tf2::Transform tmp_tf(q, tf2::Vector3(hyps[max_weight_hyp].pf_pose_mean.v[0],
1762  hyps[max_weight_hyp].pf_pose_mean.v[1],
1763  0.0));
1764 
1765  geometry_msgs::PoseStamped tmp_tf_stamped;
1766  tmp_tf_stamped.header.frame_id = base_frame_id_;
1767  tmp_tf_stamped.header.stamp = laser_scan->header.stamp;
1768  tf2::toMsg(tmp_tf.inverse(), tmp_tf_stamped.pose);
1769 
1770  this->tf_->transform(tmp_tf_stamped, odom_to_map, odom_frame_id_);
1771  }
1773  {
1774  ROS_DEBUG("Failed to subtract base to odom transform");
1775  return;
1776  }
1777 
1778  tf2::convert(odom_to_map.pose, latest_tf_);
1779  latest_tf_valid_ = true;
1780 
1781  if (tf_broadcast_ == true)
1782  {
1783  // We want to send a transform that is good up until a
1784  // tolerance time so that odom can be used
1785  ros::Time transform_expiration = (laser_scan->header.stamp +
1787  geometry_msgs::TransformStamped tmp_tf_stamped;
1788  tmp_tf_stamped.header.frame_id = global_frame_id_;
1789  tmp_tf_stamped.header.stamp = transform_expiration;
1790  tmp_tf_stamped.child_frame_id = odom_frame_id_;
1791  tf2::convert(latest_tf_.inverse(), tmp_tf_stamped.transform);
1792 
1793  this->tfb_->sendTransform(tmp_tf_stamped);
1794  sent_first_transform_ = true;
1795  }
1796  }
1797  else
1798  {
1799  ROS_ERROR("No pose!");
1800  }
1801  }
1802  else if(latest_tf_valid_)
1803  {
1804  if (tf_broadcast_ == true)
1805  {
1806  // Nothing changed, so we'll just republish the last transform, to keep
1807  // everybody happy.
1808  ros::Time transform_expiration = (laser_scan->header.stamp +
1810  geometry_msgs::TransformStamped tmp_tf_stamped;
1811  tmp_tf_stamped.header.frame_id = global_frame_id_;
1812  tmp_tf_stamped.header.stamp = transform_expiration;
1813  tmp_tf_stamped.child_frame_id = odom_frame_id_;
1814  tf2::convert(latest_tf_.inverse(), tmp_tf_stamped.transform);
1815  this->tfb_->sendTransform(tmp_tf_stamped);
1816  }
1817 
1818  // Is it time to save our last pose to the param server
1819  ros::Time now = ros::Time::now();
1820  if((save_pose_period.toSec() > 0.0) &&
1822  {
1823  this->savePoseToServer();
1824  save_pose_last_time = now;
1825  }
1826  }
1827 
1829 }
1830 
1831 void
1832 GmclNode::initialPoseReceived(const geometry_msgs::PoseWithCovarianceStampedConstPtr& msg)
1833 {
1835 }
1836 
1837 void
1838 GmclNode::handleInitialPoseMessage(const geometry_msgs::PoseWithCovarianceStamped& msg)
1839 {
1840  boost::recursive_mutex::scoped_lock prl(configuration_mutex_);
1841  if(msg.header.frame_id == "")
1842  {
1843  // This should be removed at some point
1844  ROS_WARN("Received initial pose with empty frame_id. You should always supply a frame_id.");
1845  }
1846  // We only accept initial pose estimates in the global frame, #5148.
1847  else if(stripSlash(msg.header.frame_id) != global_frame_id_)
1848  {
1849  ROS_WARN("Ignoring initial pose in frame \"%s\"; initial poses must be in the global frame, \"%s\"",
1850  stripSlash(msg.header.frame_id).c_str(),
1851  global_frame_id_.c_str());
1852  return;
1853  }
1854 
1855  // In case the client sent us a pose estimate in the past, integrate the
1856  // intervening odometric change.
1857  geometry_msgs::TransformStamped tx_odom;
1858  try
1859  {
1860  ros::Time now = ros::Time::now();
1861  // wait a little for the latest tf to become available
1862  tx_odom = tf_->lookupTransform(base_frame_id_, msg.header.stamp,
1865  }
1866  catch(tf2::TransformException e)
1867  {
1868  // If we've never sent a transform, then this is normal, because the
1869  // global_frame_id_ frame doesn't exist. We only care about in-time
1870  // transformation for on-the-move pose-setting, so ignoring this
1871  // startup condition doesn't really cost us anything.
1873  ROS_WARN("Failed to transform initial pose in time (%s)", e.what());
1874  tf2::convert(tf2::Transform::getIdentity(), tx_odom.transform);
1875  }
1876 
1877  tf2::Transform tx_odom_tf2;
1878  tf2::convert(tx_odom.transform, tx_odom_tf2);
1879  tf2::Transform pose_old, pose_new;
1880  tf2::convert(msg.pose.pose, pose_old);
1881  pose_new = pose_old * tx_odom_tf2;
1882 
1883  // Transform into the global frame
1884 
1885  ROS_INFO("Setting pose (%.6f): %.3f %.3f %.3f",
1886  ros::Time::now().toSec(),
1887  pose_new.getOrigin().x(),
1888  pose_new.getOrigin().y(),
1889  tf2::getYaw(pose_new.getRotation()));
1890  // Re-initialize the filter
1891  pf_vector_t pf_init_pose_mean = pf_vector_zero();
1892  pf_init_pose_mean.v[0] = pose_new.getOrigin().x();
1893  pf_init_pose_mean.v[1] = pose_new.getOrigin().y();
1894  pf_init_pose_mean.v[2] = tf2::getYaw(pose_new.getRotation());
1895  pf_matrix_t pf_init_pose_cov = pf_matrix_zero();
1896  // Copy in the covariance, converting from 6-D to 3-D
1897  for(int i=0; i<2; i++)
1898  {
1899  for(int j=0; j<2; j++)
1900  {
1901  pf_init_pose_cov.m[i][j] = msg.pose.covariance[6*i+j];
1902  }
1903  }
1904  pf_init_pose_cov.m[2][2] = msg.pose.covariance[6*5+5];
1905 
1906  delete initial_pose_hyp_;
1907  initial_pose_hyp_ = new gmcl_hyp_t();
1908  initial_pose_hyp_->pf_pose_mean = pf_init_pose_mean;
1909  initial_pose_hyp_->pf_pose_cov = pf_init_pose_cov;
1910  applyInitialPose();
1911 }
1912 
1918 void
1920 {
1921  boost::recursive_mutex::scoped_lock cfl(configuration_mutex_);
1922  if( initial_pose_hyp_ != NULL && map_ != NULL ) {
1924  pf_init_ = false;
1925 
1926  delete initial_pose_hyp_;
1927  initial_pose_hyp_ = NULL;
1928  }
1929 }
1930 
1931 void
1933 {
1934  double std_x = sqrt(last_published_pose.pose.covariance[6*0+0]);
1935  double std_y = sqrt(last_published_pose.pose.covariance[6*1+1]);
1936  double std_yaw = sqrt(last_published_pose.pose.covariance[6*5+5]);
1937 
1938  diagnostic_status.add("std_x", std_x);
1939  diagnostic_status.add("std_y", std_y);
1940  diagnostic_status.add("std_yaw", std_yaw);
1941  diagnostic_status.add("std_warn_level_x", std_warn_level_x_);
1942  diagnostic_status.add("std_warn_level_y", std_warn_level_y_);
1943  diagnostic_status.add("std_warn_level_yaw", std_warn_level_yaw_);
1944 
1945  if (std_x > std_warn_level_x_ || std_y > std_warn_level_y_ || std_yaw > std_warn_level_yaw_)
1946  {
1947  diagnostic_status.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Too large");
1948  }
1949  else
1950  {
1951  diagnostic_status.summary(diagnostic_msgs::DiagnosticStatus::OK, "OK");
1952  }
1953 }
gmcl::LASER_MODEL_LIKELIHOOD_FIELD_PROB
@ LASER_MODEL_LIKELIHOOD_FIELD_PROB
Definition: gmcl_laser.h:50
GmclNode::last_cloud_pub_time
ros::Time last_cloud_pub_time
Definition: gmcl_node.cpp:251
gmcl::GMCLOdom
Definition: gmcl_odom.h:67
GmclNode::alpha1_
double alpha1_
Definition: gmcl_node.cpp:294
energy_map_t::size_y
int size_y
Definition: map.h:122
GmclNode::z_hit_
double z_hit_
Definition: gmcl_node.cpp:297
tf2::convert
void convert(const A &a, B &b)
GmclNode::sigma_hit_
double sigma_hit_
Definition: gmcl_node.cpp:297
GmclNode::std_warn_level_x_
double std_warn_level_x_
Definition: gmcl_node.cpp:280
lsensor_scan_t
Definition: map.h:88
ros::WallDuration::sleep
bool sleep() const
gmcl::odom_model_t
odom_model_t
Definition: gmcl_odom.h:46
tf2::Matrix3x3::getEulerYPR
void getEulerYPR(tf2Scalar &yaw, tf2Scalar &pitch, tf2Scalar &roll, unsigned int solution_number=1) const
GmclNode::pf_model_
pf_model_type pf_model_
Definition: gmcl_node.cpp:241
ros::NodeHandle::setParam
void setParam(const std::string &key, bool b) const
GmclNode::resample_interval_
int resample_interval_
Definition: gmcl_node.cpp:237
pf_matrix_zero
pf_matrix_t pf_matrix_zero()
Definition: pf_vector.c:142
energy_map_t::poses
energy_pose_t * poses
Definition: map.h:118
gmcl
Definition: gmcl_laser.h:43
GmclNode::sy
int sy
Definition: gmcl_node.cpp:215
GmclNode::handleMapMessage
void handleMapMessage(const nav_msgs::OccupancyGrid &msg)
Definition: gmcl_node.cpp:948
gmcl::GMCLOdom::UpdateAction
virtual bool UpdateAction(pf_t *pf, GMCLSensorData *data)
Definition: gmcl_odom.cpp:121
ros::service::call
bool call(const std::string &service_name, MReq &req, MRes &res)
rosbag::Bag
GmclNode::beam_skip_threshold_
double beam_skip_threshold_
Definition: gmcl_node.cpp:300
msg
msg
ros::Publisher
GmclNode::cloud_pub_interval
ros::Duration cloud_pub_interval
Definition: gmcl_node.cpp:250
DurationBase< Duration >::fromSec
Duration & fromSec(double t)
GmclNode::initial_pose_hyp_
gmcl_hyp_t * initial_pose_hyp_
Definition: gmcl_node.cpp:284
tf2_ros::MessageFilter< sensor_msgs::LaserScan >
pf.h
GmclNode::a_thresh_
double a_thresh_
Definition: gmcl_node.cpp:236
pf_vector_t
Definition: pf_vector.h:46
_pf_model_type::use_adaptive_sampling
bool use_adaptive_sampling
Definition: pf.h:146
GmclNode::resolution_x_
double resolution_x_
Definition: gmcl_node.cpp:219
GmclNode::diagnosic_updater_
diagnostic_updater::Updater diagnosic_updater_
Definition: gmcl_node.cpp:278
GmclNode::lambda_short_
double lambda_short_
Definition: gmcl_node.cpp:297
GmclNode::energy_particlecloud_pub_
ros::Publisher energy_particlecloud_pub_
Definition: gmcl_node.cpp:271
boost::shared_ptr
energy_map_t::accepted_count
int accepted_count
Definition: map.h:122
GmclNode::map_
map_t * map_
Definition: gmcl_node.cpp:213
tf2::Transform::inverse
Transform inverse() const
diagnostic_updater::DiagnosticStatusWrapper::add
void add(const std::string &key, const bool &b)
GmclNode::threshold_val_
double threshold_val_
Definition: gmcl_node.cpp:220
energy_pose_t::pose_y
double pose_y
Definition: map.h:106
gmcl::GMCLSensorData
Definition: gmcl_sensor.h:93
gmcl::GMCLOdom::SetModel
void SetModel(odom_model_t type, double alpha1, double alpha2, double alpha3, double alpha4, double alpha5=0)
Definition: gmcl_odom.cpp:104
gmcl::GMCLOdomData::delta
pf_vector_t delta
Definition: gmcl_odom.h:64
GmclNode::save_pose_last_time
ros::Time save_pose_last_time
Definition: gmcl_node.cpp:208
MAP_WYGY
#define MAP_WYGY(map, j)
Definition: map.h:197
ros::init
ROSCPP_DECL void init(const M_string &remappings, const std::string &name, uint32_t options=0)
energy_map_t::resoultion_x
double resoultion_x
Definition: map.h:120
GmclNode::z_rand_
double z_rand_
Definition: gmcl_node.cpp:297
map_calc_SER
void map_calc_SER(energy_map_t *energy_map, lsensor_scan_t *laser_scan)
Definition: map_espace.cpp:79
tf2::getYaw
double getYaw(const A &a)
rosbag::MessageInstance
GmclNode::handelNewLaser
void handelNewLaser(const sensor_msgs::LaserScanConstPtr &laser_scan)
Definition: gmcl_node.cpp:1346
utils.h
gmcl::GMCLLaser::SetModelLikelihoodFieldProb
void SetModelLikelihoodFieldProb(double z_hit, double z_rand, double sigma_hit, double max_occ_dist, bool do_beamskip, double beam_skip_distance, double beam_skip_threshold, double beam_skip_error_threshold)
Definition: gmcl_laser.cpp:108
energy_map_t::resoultion_y
double resoultion_y
Definition: map.h:120
ros.h
GmclNode::free_space_indices
static std::vector< std::pair< int, int > > free_space_indices
Definition: gmcl_node.cpp:171
pf_reupdate_sensor_fn_t
void(* pf_reupdate_sensor_fn_t)(struct _pf_t *pf, void *laser_data)
Definition: pf.h:67
GmclNode::private_nh_
ros::NodeHandle private_nh_
Definition: gmcl_node.cpp:268
GmclNode::tfb_
std::shared_ptr< tf2_ros::TransformBroadcaster > tfb_
Definition: gmcl_node.cpp:158
GmclNode::convertMap
map_t * convertMap(const nav_msgs::OccupancyGrid &map_msg)
Definition: gmcl_node.cpp:1091
GmclNode::base_frame_id_
std::string base_frame_id_
Definition: gmcl_node.cpp:201
tf2::Quaternion::setRPY
void setRPY(const tf2Scalar &roll, const tf2Scalar &pitch, const tf2Scalar &yaw)
GmclNode::max_particles_
int max_particles_
Definition: gmcl_node.cpp:293
energy_map_t::size_x
int size_x
Definition: map.h:122
GmclNode::GmclNode
GmclNode()
Definition: gmcl_node.cpp:367
diagnostic_updater::Updater
_pf_t::pop_err
double pop_err
Definition: pf.h:158
GmclNode::laser_index
int laser_index
Definition: gmcl_node.cpp:248
map_diff_SER
void map_diff_SER(energy_map_t *energy_map)
Definition: map_espace.cpp:110
pf_get_cluster_stats
int pf_get_cluster_stats(pf_t *pf, int cluster, double *weight, pf_vector_t *mean, pf_matrix_t *cov)
Definition: pf.c:1114
GmclNode::resolution
double resolution
Definition: gmcl_node.cpp:216
ros::shutdown
ROSCPP_DECL void shutdown()
ros::NodeHandle::advertiseService
ServiceServer advertiseService(AdvertiseServiceOptions &ops)
GmclNode
Definition: gmcl_node.cpp:140
buffer.h
tf2::Transform::getOrigin
TF2SIMD_FORCE_INLINE Vector3 & getOrigin()
gmcl_hyp_t::pf_pose_cov
pf_matrix_t pf_pose_cov
Definition: gmcl_node.cpp:101
_pf_model_type::use_self_adaptive
bool use_self_adaptive
Definition: pf.h:143
GmclNode::beam_skip_error_threshold_
double beam_skip_error_threshold_
Definition: gmcl_node.cpp:300
GmclNode::pf_init_
bool pf_init_
Definition: gmcl_node.cpp:234
energy_map_t
Definition: map.h:114
drand48
static double drand48(void)
Definition: portable_utils.hpp:13
GmclNode::pose_pub_
ros::Publisher pose_pub_
Definition: gmcl_node.cpp:269
_pf_sample_set_t
Definition: pf.h:107
GmclNode::global_loc_srv_
ros::ServiceServer global_loc_srv_
Definition: gmcl_node.cpp:272
GmclNode::max_beams_
int max_beams_
Definition: gmcl_node.cpp:293
GmclNode::d_thresh_
double d_thresh_
Definition: gmcl_node.cpp:236
rosbag::Bag::close
void close()
GmclNode::initial_pose_sub_
ros::Subscriber initial_pose_sub_
Definition: gmcl_node.cpp:225
MAP_WXGX
#define MAP_WXGX(map, i)
Definition: map.h:196
bag.h
GmclNode::laser_likelihood_max_dist_
double laser_likelihood_max_dist_
Definition: gmcl_node.cpp:301
GmclNode::pf_z_
double pf_z_
Definition: gmcl_node.cpp:233
GmclNode::applyInitialPose
void applyInitialPose()
Definition: gmcl_node.cpp:1919
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
gmcl_hyp_t
Definition: gmcl_node.cpp:92
ros::NodeHandle::advertise
Publisher advertise(AdvertiseOptions &ops)
gmcl::GMCLLaser::SetModelBeam
void SetModelBeam(double z_hit, double z_short, double z_max, double z_rand, double sigma_hit, double lambda_short, double chi_outlier)
Definition: gmcl_laser.cpp:75
GmclNode::requestMap
void requestMap()
Definition: gmcl_node.cpp:918
pf_init
void pf_init(pf_t *pf, pf_vector_t mean, pf_matrix_t cov)
Definition: pf.c:152
ros::ok
ROSCPP_DECL bool ok()
GmclNode::save_pose_period
ros::Duration save_pose_period
Definition: gmcl_node.cpp:209
rosbag::bagmode::Read
Read
transform_broadcaster.h
GmclNode::check_laser_timer_
ros::Timer check_laser_timer_
Definition: gmcl_node.cpp:291
normalize
static double normalize(double z)
Definition: gmcl_node.cpp:106
diagnostic_updater.h
ros::names::resolve
ROSCPP_DECL std::string resolve(const std::string &name, bool remap=true)
f
f
GmclNode::getOdomPose
bool getOdomPose(geometry_msgs::PoseStamped &pose, double &x, double &y, double &yaw, const ros::Time &t, const std::string &f)
Definition: gmcl_node.cpp:1127
GmclNode::transform_tolerance_
ros::Duration transform_tolerance_
Definition: gmcl_node.cpp:265
gmcl::LASER_MODEL_LIKELIHOOD_FIELD
@ LASER_MODEL_LIKELIHOOD_FIELD
Definition: gmcl_laser.h:49
message_filters::Subscriber< sensor_msgs::LaserScan >
ros::ServiceServer
GmclNode::bag_scan_period_
ros::WallDuration bag_scan_period_
Definition: gmcl_node.cpp:254
GmclNode::dsrv_
dynamic_reconfigure::Server< gmcl::GMCLConfig > * dsrv_
Definition: gmcl_node.cpp:289
GmclNode::alpha_fast_
double alpha_fast_
Definition: gmcl_node.cpp:295
GmclNode::laser_model_type_
laser_model_t laser_model_type_
Definition: gmcl_node.cpp:305
tf2_ros::TransformListener
GmclNode::particlecloud_pub_
ros::Publisher particlecloud_pub_
Definition: gmcl_node.cpp:270
map_t::origin_x
double origin_x
Definition: map.h:70
GmclNode::odom_model_type_
odom_model_t odom_model_type_
Definition: gmcl_node.cpp:302
pf_matrix_t::m
double m[3][3]
Definition: pf_vector.h:55
energy_pose_t::pose_x
double pose_x
Definition: map.h:106
gmcl::GMCLOdomData::pose
pf_vector_t pose
Definition: gmcl_odom.h:61
_pf_t
Definition: pf.h:150
GmclNode::~GmclNode
~GmclNode()
Definition: gmcl_node.cpp:1117
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
GmclNode::energy_map_
energy_map_t * energy_map_
Definition: gmcl_node.cpp:218
diagnostic_updater::DiagnosticStatusWrapper::summary
void summary(const diagnostic_msgs::DiagnosticStatus &src)
_pf_t::sets
pf_sample_set_t sets[2]
Definition: pf.h:166
GmclNode::map_sub_
ros::Subscriber map_sub_
Definition: gmcl_node.cpp:276
GmclNode::use_map_topic_
bool use_map_topic_
Definition: gmcl_node.cpp:204
tf2::Transform::getIdentity
static const Transform & getIdentity()
update
void update(const std::string &key, const XmlRpc::XmlRpcValue &v)
message_filter.h
map_t::cells
map_cell_t * cells
Definition: map.h:79
GmclNode::nh_
ros::NodeHandle nh_
Definition: gmcl_node.cpp:267
lsensor_scan_t::ranges
double(* ranges)[2]
Definition: map.h:98
ROS_DEBUG
#define ROS_DEBUG(...)
map_alloc
map_t * map_alloc(void)
Definition: map.c:46
GmclNode::odom_frame_id_
std::string odom_frame_id_
Definition: gmcl_node.cpp:195
GmclNode::first_map_received_
bool first_map_received_
Definition: gmcl_node.cpp:285
GmclNode::updatePoseFromServer
void updatePoseFromServer()
Definition: gmcl_node.cpp:863
GmclNode::gui_publish_period
ros::Duration gui_publish_period
Definition: gmcl_node.cpp:207
_pf_t::pop_z
double pop_z
Definition: pf.h:158
GmclNode::tf_
std::shared_ptr< tf2_ros::Buffer > tf_
Definition: gmcl_node.cpp:160
map_cell_t::occ_state
int occ_state
Definition: map.h:55
GmclNode::laserReceived
void laserReceived(const sensor_msgs::LaserScanConstPtr &laser_scan)
Definition: gmcl_node.cpp:1464
subscriber.h
MAP_INDEX
#define MAP_INDEX(map, i, j)
Definition: map.h:207
ros::WallTime::now
static WallTime now()
GmclNode::beam_skip_distance_
double beam_skip_distance_
Definition: gmcl_node.cpp:300
GmclNode::laser_
GMCLLaser * laser_
Definition: gmcl_node.cpp:247
map_free
void map_free(map_t *map)
Definition: map.c:122
GmclNode::resample_count_
int resample_count_
Definition: gmcl_node.cpp:238
GmclNode::laser_min_range_
double laser_min_range_
Definition: gmcl_node.cpp:239
GmclNode::std_warn_level_yaw_
double std_warn_level_yaw_
Definition: gmcl_node.cpp:282
GmclNode::first_reconfigure_call_
bool first_reconfigure_call_
Definition: gmcl_node.cpp:286
gmcl::ODOM_MODEL_DIFF
@ ODOM_MODEL_DIFF
Definition: gmcl_odom.h:48
GmclNode::init_pose_
double init_pose_[3]
Definition: gmcl_node.cpp:303
GmclNode::latest_tf_
tf2::Transform latest_tf_
Definition: gmcl_node.cpp:164
tf2::Transform
GmclNode::last_laser_received_ts_
ros::Time last_laser_received_ts_
Definition: gmcl_node.cpp:312
tf2::Transform::getRotation
Quaternion getRotation() const
stripSlash
std::string stripSlash(const std::string &in)
Definition: gmcl_node.cpp:132
ros::NodeHandle::hasParam
bool hasParam(const std::string &key) const
d
d
ROS_WARN
#define ROS_WARN(...)
GmclNode::handleInitialPoseMessage
void handleInitialPoseMessage(const geometry_msgs::PoseWithCovarianceStamped &msg)
Definition: gmcl_node.cpp:1838
tf2_ros::Buffer
GmclNode::z_max_
double z_max_
Definition: gmcl_node.cpp:297
energy_map_t::threshold_val
double threshold_val
Definition: map.h:126
_pf_t::model
pf_model_type model
Definition: pf.h:153
map.h
_pf_sample_set_t::cluster_count
int cluster_count
Definition: pf.h:117
pf_vector_zero
pf_vector_t pf_vector_zero()
Definition: pf_vector.c:46
ros::NodeHandle::subscribe
Subscriber subscribe(const std::string &topic, uint32_t queue_size, const boost::function< void(C)> &callback, const VoidConstPtr &tracked_object=VoidConstPtr(), const TransportHints &transport_hints=TransportHints())
gmcl::ODOM_MODEL_OMNI_CORRECTED
@ ODOM_MODEL_OMNI_CORRECTED
Definition: gmcl_odom.h:51
GmclNode::pf_
pf_t * pf_
Definition: gmcl_node.cpp:232
ros::TimerEvent
GmclNode::configuration_mutex_
boost::recursive_mutex configuration_mutex_
Definition: gmcl_node.cpp:288
GmclNode::laser_max_range_
double laser_max_range_
Definition: gmcl_node.cpp:240
ros::WallTime
map_t::scale
double scale
Definition: map.h:73
diagnostic_updater::Updater::setHardwareID
void setHardwareID(const std::string &hwid)
GmclNode::alpha3_
double alpha3_
Definition: gmcl_node.cpp:294
rosbag::TopicQuery
GmclNode::selective_resampling_
bool selective_resampling_
Definition: gmcl_node.cpp:307
GmclNode::setMapCallback
bool setMapCallback(nav_msgs::SetMap::Request &req, nav_msgs::SetMap::Response &res)
Definition: gmcl_node.cpp:1334
GmclNode::first_map_only_
bool first_map_only_
Definition: gmcl_node.cpp:205
pf_init_model_fn_t
pf_vector_t(* pf_init_model_fn_t)(struct _pf_t *pf, void *init_data, void *e_init_data)
Definition: pf.h:55
pf_set_model_type
void pf_set_model_type(pf_t *pf, pf_model_type *pf_model_)
Definition: pf.c:1043
GmclNode::uniformPoseGenerator
static pf_vector_t uniformPoseGenerator(pf_t *pf, void *arg, void *e_arg)
Definition: gmcl_node.cpp:1154
view.h
map_t::size_x
int size_x
Definition: map.h:76
set
ROSCPP_DECL void set(const std::string &key, bool b)
GmclNode::alpha4_
double alpha4_
Definition: gmcl_node.cpp:294
GmclNode::alpha2_
double alpha2_
Definition: gmcl_node.cpp:294
GmclNode::standardDeviationDiagnostics
void standardDeviationDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &diagnostic_status)
Definition: gmcl_node.cpp:1932
GmclNode::latest_tf_valid_
bool latest_tf_valid_
Definition: gmcl_node.cpp:165
transform_listener.h
start
ROSCPP_DECL void start()
gmcl::GMCLLaserData
Definition: gmcl_laser.h:54
_pf_model_type
Definition: pf.h:135
diagnostic_updater::Updater::update
void update()
gmcl_hyp_t::pf_pose_mean
pf_vector_t pf_pose_mean
Definition: gmcl_node.cpp:98
pf_update_resample
void pf_update_resample(pf_t *pf)
Definition: pf.c:482
rosbag::View
gmcl_laser.h
GmclNode::frame_to_laser_
std::map< std::string, int > frame_to_laser_
Definition: gmcl_node.cpp:229
GmclNode::crossover_alpha_
double crossover_alpha_
Definition: gmcl_node.cpp:296
GmclNode::sent_first_transform_
bool sent_first_transform_
Definition: gmcl_node.cpp:162
GmclNode::min_particles_
int min_particles_
Definition: gmcl_node.cpp:293
ros::Time
gmcl_node_ptr
boost::shared_ptr< GmclNode > gmcl_node_ptr
Definition: gmcl_node.cpp:322
GmclNode::mutation_prob_
double mutation_prob_
Definition: gmcl_node.cpp:296
GmclNode::global_frame_id_
std::string global_frame_id_
Definition: gmcl_node.cpp:202
GmclNode::z_short_
double z_short_
Definition: gmcl_node.cpp:297
gmcl::LASER_MODEL_BEAM
@ LASER_MODEL_BEAM
Definition: gmcl_laser.h:48
GmclNode::do_beamskip_
bool do_beamskip_
Definition: gmcl_node.cpp:299
map_t
Definition: map.h:67
gmcl::GMCLOdomData
Definition: gmcl_odom.h:57
map_t::size_y
int size_y
Definition: map.h:76
map_t::origin_y
double origin_y
Definition: map.h:70
main
int main(int argc, char **argv)
Definition: gmcl_node.cpp:332
gmcl_hyp_t::weight
double weight
Definition: gmcl_node.cpp:95
gmcl::laser_model_t
laser_model_t
Definition: gmcl_laser.h:46
gmcl_odom.h
angle_diff
static double angle_diff(double a, double b)
Definition: gmcl_node.cpp:111
lsensor_scan_t::range_count
int range_count
Definition: map.h:92
GmclNode::initial_pose_sub_old_
ros::Subscriber initial_pose_sub_old_
Definition: gmcl_node.cpp:275
scan_topic_
static const std::string scan_topic_
Definition: gmcl_node.cpp:126
GmclNode::pub_energy_map_
bool pub_energy_map_
Definition: gmcl_node.cpp:221
portable_utils.hpp
gmcl::GMCLLaser::SetModelLikelihoodField
void SetModelLikelihoodField(double z_hit, double z_rand, double sigma_hit, double max_occ_dist)
Definition: gmcl_laser.cpp:94
energy_map_t::accepted_index
int * accepted_index
Definition: map.h:124
GmclNode::init_cov_
double init_cov_[3]
Definition: gmcl_node.cpp:304
ROS_ERROR
#define ROS_ERROR(...)
GmclNode::laser_scan_filter_
tf2_ros::MessageFilter< sensor_msgs::LaserScan > * laser_scan_filter_
Definition: gmcl_node.cpp:224
energy_map_free
void energy_map_free(energy_map_t *energy_map)
Definition: map.c:129
GmclNode::odom_
GMCLOdom * odom_
Definition: gmcl_node.cpp:246
tf2_ros::MessageFilter::add
void add(const MConstPtr &message)
GmclNode::globalLocalizationCallback
bool globalLocalizationCallback(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res)
Definition: gmcl_node.cpp:1300
GmclNode::set_map_srv_
ros::ServiceServer set_map_srv_
Definition: gmcl_node.cpp:274
tf2_ros::TransformBroadcaster
pf_set_selective_resampling
void pf_set_selective_resampling(pf_t *pf, int selective_resampling)
Definition: pf.c:1072
GmclNode::mapdata
char * mapdata
Definition: gmcl_node.cpp:214
ros::NodeHandle::param
T param(const std::string &param_name, const T &default_val) const
tf2::Quaternion
GmclNode::nomotionUpdateCallback
bool nomotionUpdateCallback(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res)
Definition: gmcl_node.cpp:1325
MAP_GXWX
#define MAP_GXWX(map, x)
Definition: map.h:200
GmclNode::freeMapDependentMemory
void freeMapDependentMemory()
Definition: gmcl_node.cpp:1066
sigintHandler
void sigintHandler(int sig)
Definition: gmcl_node.cpp:324
GmclNode::m_force_update
bool m_force_update
Definition: gmcl_node.cpp:244
pf_matrix_t
Definition: pf_vector.h:53
diagnostic_updater::DiagnosticStatusWrapper
_pf_t::N_aux_particles
int N_aux_particles
Definition: pf.h:155
tf2_geometry_msgs.h
tf2::toMsg
B toMsg(const A &a)
GmclNode::std_warn_level_y_
double std_warn_level_y_
Definition: gmcl_node.cpp:281
GmclNode::reconfigureCB
void reconfigureCB(gmcl::GMCLConfig &config, uint32_t level)
Definition: gmcl_node.cpp:551
MAP_GYWY
#define MAP_GYWY(map, y)
Definition: map.h:201
ros::spin
ROSCPP_DECL void spin()
GmclNode::resolution_y_
double resolution_y_
Definition: gmcl_node.cpp:219
convert.h
GmclNode::pf_odom_pose_
pf_vector_t pf_odom_pose_
Definition: gmcl_node.cpp:235
GmclNode::latest_odom_pose_
geometry_msgs::PoseStamped latest_odom_pose_
Definition: gmcl_node.cpp:198
map_cell_t
Definition: map.h:52
GmclNode::tfl_
std::shared_ptr< tf2_ros::TransformListener > tfl_
Definition: gmcl_node.cpp:159
DurationBase< Duration >::toSec
double toSec() const
GmclNode::alpha5_
double alpha5_
Definition: gmcl_node.cpp:294
GmclNode::pf_err_
double pf_err_
Definition: gmcl_node.cpp:233
pf_init_model
void pf_init_model(pf_t *pf, pf_init_model_fn_t init_fn, void *init_data, void *e_init_data)
Definition: pf.c:214
ros::WallDuration
rosbag::Bag::open
void open(std::string const &filename, uint32_t mode=bagmode::Read)
tf2::Matrix3x3
GmclNode::N_aux_particles_
int N_aux_particles_
Definition: gmcl_node.cpp:293
lsensor_scan_t::range_max
float range_max
Definition: map.h:94
assert.h
tf2::TransformException
ROS_INFO
#define ROS_INFO(...)
GmclNode::runFromBag
void runFromBag(const std::string &in_bag_fn, bool trigger_global_localization=false)
Uses TF and LaserScan messages from bag file to drive AMCL instead.
Definition: gmcl_node.cpp:746
GmclNode::lasers_update_
std::vector< bool > lasers_update_
Definition: gmcl_node.cpp:228
GmclNode::alpha_slow_
double alpha_slow_
Definition: gmcl_node.cpp:295
lsensor_scan_t::range_min
float range_min
Definition: map.h:96
ROS_ASSERT
#define ROS_ASSERT(cond)
diagnostic_updater::DiagnosticTaskVector::add
void add(const std::string &name, TaskFunction f)
GmclNode::initialPoseReceived
void initialPoseReceived(const geometry_msgs::PoseWithCovarianceStampedConstPtr &msg)
Definition: gmcl_node.cpp:1832
pf_alloc
pf_t * pf_alloc(int min_samples, int max_samples, int N_aux_particles, double alpha_slow, double alpha_fast, double crossover_alpha, double mutation_prob, pf_init_model_fn_t random_pose_fn, void *random_pose_data, void *e_random_pose_data)
Definition: pf.c:54
GmclNode::ldata_
std::vector< GMCLLaserData * > ldata_
Definition: gmcl_node.cpp:227
ros::NodeHandle::createTimer
Timer createTimer(Duration period, const TimerCallback &callback, bool oneshot=false, bool autostart=true) const
gmcl::ODOM_MODEL_DIFF_CORRECTED
@ ODOM_MODEL_DIFF_CORRECTED
Definition: gmcl_odom.h:50
_pf_t::current_set
int current_set
Definition: pf.h:165
energy_pose_t::orientation_yaw
double orientation_yaw
Definition: map.h:106
_pf_model_type::use_optimal_filter
bool use_optimal_filter
Definition: pf.h:137
GmclNode::mapReceived
void mapReceived(const nav_msgs::OccupancyGridConstPtr &msg)
Definition: gmcl_node.cpp:936
GmclNode::checkLaserReceived
void checkLaserReceived(const ros::TimerEvent &event)
Definition: gmcl_node.cpp:906
ros::Duration
GmclNode::default_config_
gmcl::GMCLConfig default_config_
Definition: gmcl_node.cpp:290
energy_pose_t
Definition: map.h:103
pf_vector_t::v
double v[3]
Definition: pf_vector.h:53
ros::Timer
_pf_model_type::use_crossover_mutation
bool use_crossover_mutation
Definition: pf.h:140
ros::CallbackQueue::callAvailable
void callAvailable()
GmclNode::laser_scan_sub_
message_filters::Subscriber< sensor_msgs::LaserScan > * laser_scan_sub_
Definition: gmcl_node.cpp:223
t
geometry_msgs::TransformStamped t
gmcl::GMCLSensorData::sensor
GMCLSensor * sensor
Definition: gmcl_sensor.h:96
Transform.h
lsensor_scan_t::laser_pose
pf_vector_t laser_pose
Definition: map.h:90
GmclNode::lasers_
std::vector< GMCLLaser * > lasers_
Definition: gmcl_node.cpp:226
map_update_espace
void map_update_espace(energy_map_t *energy_map, map_t *map, lsensor_scan_t *laser_scan)
Definition: map_espace.cpp:36
GmclNode::nomotion_update_srv_
ros::ServiceServer nomotion_update_srv_
Definition: gmcl_node.cpp:273
ros::NodeHandle
ros::Subscriber
GmclNode::last_published_pose
geometry_msgs::PoseWithCovarianceStamped last_published_pose
Definition: gmcl_node.cpp:211
energy_map_alloc
energy_map_t * energy_map_alloc(map_t *map, double resoultion_x, double resoultion_y, size_t max_beams, double laser_min_range, double laser_max_range)
Definition: map.c:68
pf_update_crossover_mutation
void pf_update_crossover_mutation(pf_t *pf, pf_reupdate_sensor_fn_t laser_fn, void *laser_data)
Definition: pf.c:689
pf_free
void pf_free(pf_t *pf)
Definition: pf.c:131
ros::getGlobalCallbackQueue
ROSCPP_DECL CallbackQueue * getGlobalCallbackQueue()
GmclNode::savePoseToServer
void savePoseToServer()
Definition: gmcl_node.cpp:839
gmcl::GMCLLaser
Definition: gmcl_laser.h:71
gmcl::ODOM_MODEL_OMNI
@ ODOM_MODEL_OMNI
Definition: gmcl_odom.h:49
ros::Time::now
static Time now()
GmclNode::tf_broadcast_
bool tf_broadcast_
Definition: gmcl_node.cpp:306
MAP_VALID
#define MAP_VALID(map, i, j)
Definition: map.h:204
GmclNode::laser_check_interval_
ros::Duration laser_check_interval_
Definition: gmcl_node.cpp:313


gmcl
Author(s): Mhd Ali Alshikh Khalil, adler1994@gmail.com
autogenerated on Wed Mar 2 2022 00:20:14