HectorMappingRos.cpp
Go to the documentation of this file.
1 //=================================================================================================
2 // Copyright (c) 2011, Stefan Kohlbrecher, TU Darmstadt
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 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright
10 // notice, this list of conditions and the following disclaimer in the
11 // documentation and/or other materials provided with the distribution.
12 // * Neither the name of the Simulation, Systems Optimization and Robotics
13 // group, TU Darmstadt nor the names of its contributors may be used to
14 // endorse or promote products derived from this software without
15 // specific prior written permission.
16 
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //=================================================================================================
28 
29 #include "HectorMappingRos.h"
30 
31 #include "map/GridMap.h"
32 
33 #include <geometry_msgs/PoseWithCovarianceStamped.h>
34 #include <nav_msgs/Odometry.h>
35 
36 #include "sensor_msgs/PointCloud2.h"
37 
38 #include "HectorDrawings.h"
40 #include "HectorMapMutex.h"
41 
42 #ifndef TF_SCALAR_H
43  typedef btScalar tfScalar;
44 #endif
45 
47  : debugInfoProvider(0)
48  , hectorDrawings(0)
49  , lastGetMapUpdateIndex(-100)
50  , tfB_(0)
51  , map__publish_thread_(0)
52  , initial_pose_set_(false)
53  , pause_scan_processing_(false)
54 {
55  ros::NodeHandle private_nh_("~");
56 
57  std::string mapTopic_ = "map";
58 
59  private_nh_.param("pub_drawings", p_pub_drawings, false);
60  private_nh_.param("pub_debug_output", p_pub_debug_output_, false);
61  private_nh_.param("pub_map_odom_transform", p_pub_map_odom_transform_,true);
62  private_nh_.param("pub_odometry", p_pub_odometry_,false);
63  private_nh_.param("advertise_map_service", p_advertise_map_service_,true);
64  private_nh_.param("scan_subscriber_queue_size", p_scan_subscriber_queue_size_, 5);
65 
66  private_nh_.param("map_resolution", p_map_resolution_, 0.025);
67  private_nh_.param("map_size", p_map_size_, 1024);
68  private_nh_.param("map_start_x", p_map_start_x_, 0.5);
69  private_nh_.param("map_start_y", p_map_start_y_, 0.5);
70  private_nh_.param("map_multi_res_levels", p_map_multi_res_levels_, 3);
71 
72  private_nh_.param("update_factor_free", p_update_factor_free_, 0.4);
73  private_nh_.param("update_factor_occupied", p_update_factor_occupied_, 0.9);
74 
75  private_nh_.param("map_update_distance_thresh", p_map_update_distance_threshold_, 0.4);
76  private_nh_.param("map_update_angle_thresh", p_map_update_angle_threshold_, 0.9);
77 
78  private_nh_.param("scan_topic", p_scan_topic_, std::string("scan"));
79  private_nh_.param("sys_msg_topic", p_sys_msg_topic_, std::string("syscommand"));
80  private_nh_.param("pose_update_topic", p_pose_update_topic_, std::string("poseupdate"));
81 
82  private_nh_.param("use_tf_scan_transformation", p_use_tf_scan_transformation_,true);
83  private_nh_.param("use_tf_pose_start_estimate", p_use_tf_pose_start_estimate_,false);
84  private_nh_.param("map_with_known_poses", p_map_with_known_poses_, false);
85 
86  private_nh_.param("base_frame", p_base_frame_, std::string("base_link"));
87  private_nh_.param("map_frame", p_map_frame_, std::string("map"));
88  private_nh_.param("odom_frame", p_odom_frame_, std::string("odom"));
89 
90  private_nh_.param("pub_map_scanmatch_transform", p_pub_map_scanmatch_transform_,true);
91  private_nh_.param("tf_map_scanmatch_transform_frame_name", p_tf_map_scanmatch_transform_frame_name_, std::string("scanmatcher_frame"));
92 
93  private_nh_.param("output_timing", p_timing_output_,false);
94 
95  private_nh_.param("map_pub_period", p_map_pub_period_, 2.0);
96 
97  double tmp = 0.0;
98  private_nh_.param("laser_min_dist", tmp, 0.4);
99  p_sqr_laser_min_dist_ = static_cast<float>(tmp*tmp);
100 
101  private_nh_.param("laser_max_dist", tmp, 30.0);
102  p_sqr_laser_max_dist_ = static_cast<float>(tmp*tmp);
103 
104  private_nh_.param("laser_z_min_value", tmp, -1.0);
105  p_laser_z_min_value_ = static_cast<float>(tmp);
106 
107  private_nh_.param("laser_z_max_value", tmp, 1.0);
108  p_laser_z_max_value_ = static_cast<float>(tmp);
109 
110  if (p_pub_drawings)
111  {
112  ROS_INFO("HectorSM publishing debug drawings");
114  }
115 
117  {
118  ROS_INFO("HectorSM publishing debug info");
120  }
121 
122  if(p_pub_odometry_)
123  {
124  odometryPublisher_ = node_.advertise<nav_msgs::Odometry>("scanmatch_odom", 50);
125  }
126 
128  slamProcessor->setUpdateFactorFree(p_update_factor_free_);
129  slamProcessor->setUpdateFactorOccupied(p_update_factor_occupied_);
130  slamProcessor->setMapUpdateMinDistDiff(p_map_update_distance_threshold_);
131  slamProcessor->setMapUpdateMinAngleDiff(p_map_update_angle_threshold_);
132 
133  int mapLevels = slamProcessor->getMapLevels();
134  mapLevels = 1;
135 
136  for (int i = 0; i < mapLevels; ++i)
137  {
139  slamProcessor->addMapMutex(i, new HectorMapMutex());
140 
141  std::string mapTopicStr(mapTopic_);
142 
143  if (i != 0)
144  {
145  mapTopicStr.append("_" + boost::lexical_cast<std::string>(i));
146  }
147 
148  std::string mapMetaTopicStr(mapTopicStr);
149  mapMetaTopicStr.append("_metadata");
150 
152  tmp.mapPublisher_ = node_.advertise<nav_msgs::OccupancyGrid>(mapTopicStr, 1, true);
153  tmp.mapMetadataPublisher_ = node_.advertise<nav_msgs::MapMetaData>(mapMetaTopicStr, 1, true);
154 
155  if ( (i == 0) && p_advertise_map_service_)
156  {
158  }
159 
160  setServiceGetMapData(tmp.map_, slamProcessor->getGridMap(i));
161 
162  if ( i== 0){
163  mapPubContainer[i].mapMetadataPublisher_.publish(mapPubContainer[i].map_.map.info);
164  }
165  }
166 
167  // Initialize services
171 
172  ROS_INFO("HectorSM p_base_frame_: %s", p_base_frame_.c_str());
173  ROS_INFO("HectorSM p_map_frame_: %s", p_map_frame_.c_str());
174  ROS_INFO("HectorSM p_odom_frame_: %s", p_odom_frame_.c_str());
175  ROS_INFO("HectorSM p_scan_topic_: %s", p_scan_topic_.c_str());
176  ROS_INFO("HectorSM p_use_tf_scan_transformation_: %s", p_use_tf_scan_transformation_ ? ("true") : ("false"));
177  ROS_INFO("HectorSM p_pub_map_odom_transform_: %s", p_pub_map_odom_transform_ ? ("true") : ("false"));
178  ROS_INFO("HectorSM p_scan_subscriber_queue_size_: %d", p_scan_subscriber_queue_size_);
179  ROS_INFO("HectorSM p_map_pub_period_: %f", p_map_pub_period_);
180  ROS_INFO("HectorSM p_update_factor_free_: %f", p_update_factor_free_);
181  ROS_INFO("HectorSM p_update_factor_occupied_: %f", p_update_factor_occupied_);
182  ROS_INFO("HectorSM p_map_update_distance_threshold_: %f ", p_map_update_distance_threshold_);
183  ROS_INFO("HectorSM p_map_update_angle_threshold_: %f", p_map_update_angle_threshold_);
184  ROS_INFO("HectorSM p_laser_z_min_value_: %f", p_laser_z_min_value_);
185  ROS_INFO("HectorSM p_laser_z_max_value_: %f", p_laser_z_max_value_);
186 
189 
190  poseUpdatePublisher_ = node_.advertise<geometry_msgs::PoseWithCovarianceStamped>(p_pose_update_topic_, 1, false);
191  posePublisher_ = node_.advertise<geometry_msgs::PoseStamped>("slam_out_pose", 1, false);
192 
193  scan_point_cloud_publisher_ = node_.advertise<sensor_msgs::PointCloud>("slam_cloud",1,false);
194 
196  ROS_ASSERT(tfB_);
197 
198  /*
199  bool p_use_static_map_ = false;
200 
201  if (p_use_static_map_){
202  mapSubscriber_ = node_.subscribe(mapTopic_, 1, &HectorMappingRos::staticMapCallback, this);
203  }
204  */
205 
208  initial_pose_filter_->registerCallback(boost::bind(&HectorMappingRos::initialPoseCallback, this, _1));
209 
210 
211  map__publish_thread_ = new boost::thread(boost::bind(&HectorMappingRos::publishMapLoop, this, p_map_pub_period_));
212 
214 
216 }
217 
219 {
220  delete slamProcessor;
221 
222  if (hectorDrawings)
223  delete hectorDrawings;
224 
225  if (debugInfoProvider)
226  delete debugInfoProvider;
227 
228  if (tfB_)
229  delete tfB_;
230 
232  delete map__publish_thread_;
233 }
234 
235 void HectorMappingRos::scanCallback(const sensor_msgs::LaserScan& scan)
236 {
238  {
239  return;
240  }
241 
242  if (hectorDrawings)
243  {
244  hectorDrawings->setTime(scan.header.stamp);
245  }
246 
247  ros::WallTime start_time = ros::WallTime::now();
249  {
250  // If we are not using the tf tree to find the transform between the base frame and laser frame,
251  // then just convert the laser scan to our data container and process the update based on our last
252  // pose estimate
255  }
256  else
257  {
258  // If we are using the tf tree to find the transform between the base frame and laser frame,
259  // let's get that transform
260  const ros::Duration dur(0.5);
261  tf::StampedTransform laser_transform;
262  if (tf_.waitForTransform(p_base_frame_, scan.header.frame_id, scan.header.stamp, dur))
263  {
264  tf_.lookupTransform(p_base_frame_, scan.header.frame_id, scan.header.stamp, laser_transform);
265  }
266  else
267  {
268  ROS_INFO("lookupTransform %s to %s timed out. Could not transform laser scan into base_frame.", p_base_frame_.c_str(), scan.header.frame_id.c_str());
269  return;
270  }
271 
272  // Convert the laser scan to point cloud
274 
275  // Publish the point cloud if there are any subscribers
277  {
279  }
280 
281  // Convert the point cloud to our data container
283 
284  // Now let's choose the initial pose estimate for our slam process update
285  Eigen::Vector3f start_estimate(Eigen::Vector3f::Zero());
286  if (initial_pose_set_)
287  {
288  // User has requested a pose reset
289  initial_pose_set_ = false;
290  start_estimate = initial_pose_;
291  }
293  {
294  // Initial pose estimate comes from the tf tree
295  try
296  {
297  tf::StampedTransform stamped_pose;
298 
299  tf_.waitForTransform(p_map_frame_, p_base_frame_, scan.header.stamp, ros::Duration(0.5));
300  tf_.lookupTransform(p_map_frame_, p_base_frame_, scan.header.stamp, stamped_pose);
301 
302  const double yaw = tf::getYaw(stamped_pose.getRotation());
303  start_estimate = Eigen::Vector3f(stamped_pose.getOrigin().getX(), stamped_pose.getOrigin().getY(), yaw);
304  }
305  catch(tf::TransformException e)
306  {
307  ROS_ERROR("Transform from %s to %s failed\n", p_map_frame_.c_str(), p_base_frame_.c_str());
308  start_estimate = slamProcessor->getLastScanMatchPose();
309  }
310  }
311  else
312  {
313  // If none of the above, the initial pose is simply the last estimated pose
314  start_estimate = slamProcessor->getLastScanMatchPose();
315  }
316 
317  // If "p_map_with_known_poses_" is enabled, we assume that start_estimate is precise and doesn't need to be refined
319  {
320  slamProcessor->update(laserScanContainer, start_estimate, true);
321  }
322  else
323  {
324  slamProcessor->update(laserScanContainer, start_estimate);
325  }
326  }
327 
328  // If the debug flag "p_timing_output_" is enabled, print how long this last iteration took
329  if (p_timing_output_)
330  {
331  ros::WallDuration duration = ros::WallTime::now() - start_time;
332  ROS_INFO("HectorSLAM Iter took: %f milliseconds", duration.toSec()*1000.0f );
333  }
334 
335  // If we're just building a map with known poses, we're finished now. Code below this point publishes the localization results.
337  {
338  return;
339  }
340 
342 
343  // Publish pose with and without covariances
346 
347  // Publish odometry if enabled
348  if(p_pub_odometry_)
349  {
350  nav_msgs::Odometry tmp;
352 
353  tmp.header = poseInfoContainer_.getPoseWithCovarianceStamped().header;
354  tmp.child_frame_id = p_base_frame_;
356  }
357 
358  // Publish the map->odom transform if enabled
360  {
361  tf::StampedTransform odom_to_base;
362  try
363  {
364  tf_.waitForTransform(p_odom_frame_, p_base_frame_, scan.header.stamp, ros::Duration(0.5));
365  tf_.lookupTransform(p_odom_frame_, p_base_frame_, scan.header.stamp, odom_to_base);
366  }
367  catch(tf::TransformException e)
368  {
369  ROS_ERROR("Transform failed during publishing of map_odom transform: %s",e.what());
370  odom_to_base.setIdentity();
371  }
374  }
375 
376  // Publish the transform from map to estimated pose (if enabled)
378  {
380  }
381 }
382 
383 void HectorMappingRos::sysMsgCallback(const std_msgs::String& string)
384 {
385  ROS_INFO("HectorSM sysMsgCallback, msg contents: %s", string.data.c_str());
386 
387  if (string.data == "reset")
388  {
389  ROS_INFO("HectorSM reset");
390  slamProcessor->reset();
391  }
392 }
393 
394 bool HectorMappingRos::mapCallback(nav_msgs::GetMap::Request &req,
395  nav_msgs::GetMap::Response &res)
396 {
397  ROS_INFO("HectorSM Map service called");
398  res = mapPubContainer[0].map_;
399  return true;
400 }
401 
402 bool HectorMappingRos::resetMapCallback(std_srvs::Trigger::Request &req,
403  std_srvs::Trigger::Response &res)
404 {
405  ROS_INFO("HectorSM Reset map service called");
406  slamProcessor->reset();
407  return true;
408 }
409 
410 bool HectorMappingRos::restartHectorCallback(hector_mapping::ResetMapping::Request &req,
411  hector_mapping::ResetMapping::Response &res)
412 {
413  // Reset map
414  ROS_INFO("HectorSM Reset map");
415  slamProcessor->reset();
416 
417  // Reset pose
418  this->resetPose(req.initial_pose);
419 
420  // Unpause node (in case it is paused)
421  this->toggleMappingPause(false);
422 
423  // Return success
424  return true;
425 }
426 
427 bool HectorMappingRos::pauseMapCallback(std_srvs::SetBool::Request &req,
428  std_srvs::SetBool::Response &res)
429 {
430  this->toggleMappingPause(req.data);
431  res.success = true;
432  return true;
433 }
434 
436 {
437  nav_msgs::GetMap::Response& map_ (mapPublisher.map_);
438 
439  //only update map if it changed
440  if (lastGetMapUpdateIndex != gridMap.getUpdateIndex())
441  {
442 
443  int sizeX = gridMap.getSizeX();
444  int sizeY = gridMap.getSizeY();
445 
446  int size = sizeX * sizeY;
447 
448  std::vector<int8_t>& data = map_.map.data;
449 
450  //std::vector contents are guaranteed to be contiguous, use memset to set all to unknown to save time in loop
451  memset(&data[0], -1, sizeof(int8_t) * size);
452 
453  if (mapMutex)
454  {
455  mapMutex->lockMap();
456  }
457 
458  for(int i=0; i < size; ++i)
459  {
460  if(gridMap.isFree(i))
461  {
462  data[i] = 0;
463  }
464  else if (gridMap.isOccupied(i))
465  {
466  data[i] = 100;
467  }
468  }
469 
471 
472  if (mapMutex)
473  {
474  mapMutex->unlockMap();
475  }
476  }
477 
478  map_.map.header.stamp = timestamp;
479 
480  mapPublisher.mapPublisher_.publish(map_.map);
481 }
482 
483 void HectorMappingRos::rosLaserScanToDataContainer(const sensor_msgs::LaserScan& scan, hectorslam::DataContainer& dataContainer, float scaleToMap)
484 {
485  size_t size = scan.ranges.size();
486 
487  float angle = scan.angle_min;
488 
489  dataContainer.clear();
490 
491  dataContainer.setOrigo(Eigen::Vector2f::Zero());
492 
493  float maxRangeForContainer = scan.range_max - 0.1f;
494 
495  for (size_t i = 0; i < size; ++i)
496  {
497  float dist = scan.ranges[i];
498 
499  if ( (dist > scan.range_min) && (dist < maxRangeForContainer))
500  {
501  dist *= scaleToMap;
502  dataContainer.add(Eigen::Vector2f(cos(angle) * dist, sin(angle) * dist));
503  }
504 
505  angle += scan.angle_increment;
506  }
507 }
508 
509 void HectorMappingRos::rosPointCloudToDataContainer(const sensor_msgs::PointCloud& pointCloud, const tf::StampedTransform& laserTransform, hectorslam::DataContainer& dataContainer, float scaleToMap)
510 {
511  size_t size = pointCloud.points.size();
512  //ROS_INFO("size: %d", size);
513 
514  dataContainer.clear();
515 
516  tf::Vector3 laserPos (laserTransform.getOrigin());
517  dataContainer.setOrigo(Eigen::Vector2f(laserPos.x(), laserPos.y())*scaleToMap);
518 
519  for (size_t i = 0; i < size; ++i)
520  {
521 
522  const geometry_msgs::Point32& currPoint(pointCloud.points[i]);
523 
524  float dist_sqr = currPoint.x*currPoint.x + currPoint.y* currPoint.y;
525 
526  if ( (dist_sqr > p_sqr_laser_min_dist_) && (dist_sqr < p_sqr_laser_max_dist_) ){
527 
528  if ( (currPoint.x < 0.0f) && (dist_sqr < 0.50f)){
529  continue;
530  }
531 
532  tf::Vector3 pointPosBaseFrame(laserTransform * tf::Vector3(currPoint.x, currPoint.y, currPoint.z));
533 
534  float pointPosLaserFrameZ = pointPosBaseFrame.z() - laserPos.z();
535 
536  if (pointPosLaserFrameZ > p_laser_z_min_value_ && pointPosLaserFrameZ < p_laser_z_max_value_)
537  {
538  dataContainer.add(Eigen::Vector2f(pointPosBaseFrame.x(),pointPosBaseFrame.y())*scaleToMap);
539  }
540  }
541  }
542 }
543 
544 void HectorMappingRos::setServiceGetMapData(nav_msgs::GetMap::Response& map_, const hectorslam::GridMap& gridMap)
545 {
546  Eigen::Vector2f mapOrigin (gridMap.getWorldCoords(Eigen::Vector2f::Zero()));
547  mapOrigin.array() -= gridMap.getCellLength()*0.5f;
548 
549  map_.map.info.origin.position.x = mapOrigin.x();
550  map_.map.info.origin.position.y = mapOrigin.y();
551  map_.map.info.origin.orientation.w = 1.0;
552 
553  map_.map.info.resolution = gridMap.getCellLength();
554 
555  map_.map.info.width = gridMap.getSizeX();
556  map_.map.info.height = gridMap.getSizeY();
557 
558  map_.map.header.frame_id = p_map_frame_;
559  map_.map.data.resize(map_.map.info.width * map_.map.info.height);
560 }
561 
562 /*
563 void HectorMappingRos::setStaticMapData(const nav_msgs::OccupancyGrid& map)
564 {
565  float cell_length = map.info.resolution;
566  Eigen::Vector2f mapOrigin (map.info.origin.position.x + cell_length*0.5f,
567  map.info.origin.position.y + cell_length*0.5f);
568 
569  int map_size_x = map.info.width;
570  int map_size_y = map.info.height;
571 
572  slamProcessor = new hectorslam::HectorSlamProcessor(cell_length, map_size_x, map_size_y, Eigen::Vector2f(0.0f, 0.0f), 1, hectorDrawings, debugInfoProvider);
573 }
574 */
575 
576 
577 void HectorMappingRos::publishMapLoop(double map_pub_period)
578 {
579  ros::Rate r(1.0 / map_pub_period);
580  while(ros::ok())
581  {
582  //ros::WallTime t1 = ros::WallTime::now();
583  ros::Time mapTime (ros::Time::now());
584  //publishMap(mapPubContainer[2],slamProcessor->getGridMap(2), mapTime);
585  //publishMap(mapPubContainer[1],slamProcessor->getGridMap(1), mapTime);
587 
588  //ros::WallDuration t2 = ros::WallTime::now() - t1;
589 
590  //std::cout << "time s: " << t2.toSec();
591  //ROS_INFO("HectorSM ms: %4.2f", t2.toSec()*1000.0f);
592 
593  r.sleep();
594  }
595 }
596 
597 void HectorMappingRos::staticMapCallback(const nav_msgs::OccupancyGrid& map)
598 {
599 
600 }
601 
602 void HectorMappingRos::initialPoseCallback(const geometry_msgs::PoseWithCovarianceStampedConstPtr& msg)
603 {
604  this->resetPose(msg->pose.pose);
605 }
606 
608 {
609  // Pause/unpause
610  if (pause && !pause_scan_processing_)
611  {
612  ROS_INFO("[HectorSM]: Mapping paused");
613  }
614  else if (!pause && pause_scan_processing_)
615  {
616  ROS_INFO("[HectorSM]: Mapping no longer paused");
617  }
618  pause_scan_processing_ = pause;
619 }
620 
621 void HectorMappingRos::resetPose(const geometry_msgs::Pose &pose)
622 {
623  initial_pose_set_ = true;
624  initial_pose_ = Eigen::Vector3f(pose.position.x, pose.position.y, util::getYawFromQuat(pose.orientation));
625  ROS_INFO("[HectorSM]: Setting initial pose with world coords x: %f y: %f yaw: %f",
627 }
void projectLaser(const sensor_msgs::LaserScan &scan_in, sensor_msgs::PointCloud &cloud_out, double range_cutoff=-1.0, int channel_options=channel_option::Default)
tf::TransformBroadcaster * tfB_
const GridMap & getGridMap(int mapLevel=0) const
ros::Publisher odometryPublisher_
bool p_pub_map_scanmatch_transform_
tf::MessageFilter< geometry_msgs::PoseWithCovarianceStamped > * initial_pose_filter_
HectorDebugInfoProvider * debugInfoProvider
void publishMap(MapPublisherContainer &map_, const hectorslam::GridMap &gridMap, ros::Time timestamp, MapLockerInterface *mapMutex=0)
const Eigen::Vector3f & getLastScanMatchPose() const
Transform inverse() const
void resetPose(const geometry_msgs::Pose &pose)
Quaternion getRotation() const
laser_geometry::LaserProjection projector_
void staticMapCallback(const nav_msgs::OccupancyGrid &map)
const geometry_msgs::PoseStamped & getPoseStamped()
boost::thread * map__publish_thread_
ros::Time lastMapPublishTime
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void rosLaserScanToDataContainer(const sensor_msgs::LaserScan &scan, hectorslam::DataContainer &dataContainer, float scaleToMap)
std::vector< MapPublisherContainer > mapPubContainer
static double getYaw(const Quaternion &bt_q)
const geometry_msgs::PoseWithCovarianceStamped & getPoseWithCovarianceStamped()
void update(const Eigen::Vector3f &slamPose, const Eigen::Matrix3f &slamCov, const ros::Time &stamp, const std::string &frame_id)
bool mapCallback(nav_msgs::GetMap::Request &req, nav_msgs::GetMap::Response &res)
bool waitForTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration &timeout, const ros::Duration &polling_sleep_duration=ros::Duration(0.01), std::string *error_msg=NULL) const
void setOrigo(const DataPointType &origoIn)
static double getYawFromQuat(const geometry_msgs::Quaternion &quat)
Definition: UtilFunctions.h:94
bool isOccupied(int xMap, int yMap) const
ros::Publisher mapPublisher_
bool restartHectorCallback(hector_mapping::ResetMapping::Request &req, hector_mapping::ResetMapping::Response &res)
ros::ServiceServer reset_map_service_
double p_map_update_distance_threshold_
PoseInfoContainer poseInfoContainer_
std::string p_scan_topic_
ros::Subscriber scanSubscriber_
const Eigen::Matrix3f & getLastScanMatchCovariance() const
float getCellLength() const
Definition: GridMapBase.h:296
const tf::Transform & getTfTransform()
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
bool p_use_tf_pose_start_estimate_
nav_msgs::GetMap::Response map_
MapLockerInterface * getMapMutex(int i)
hectorslam::HectorSlamProcessor * slamProcessor
Eigen::Vector3f initial_pose_
ros::ServiceServer dynamicMapServiceServer_
void sysMsgCallback(const std_msgs::String &string)
ros::NodeHandle node_
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
HectorDrawings * hectorDrawings
void setIdentity()
Eigen::Vector2f getWorldCoords(const Eigen::Vector2f &mapCoords) const
Definition: GridMapBase.h:210
ros::Publisher scan_point_cloud_publisher_
std::string p_tf_map_scanmatch_transform_frame_name_
sensor_msgs::PointCloud laser_point_cloud_
ros::Subscriber sysMsgSubscriber_
bool param(const std::string &param_name, T &param_val, const T &default_val) const
void publish(const boost::shared_ptr< M > &message) const
ros::Publisher posePublisher_
bool isFree(int xMap, int yMap) const
void scanCallback(const sensor_msgs::LaserScan &scan)
#define ROS_INFO(...)
double p_map_update_angle_threshold_
virtual void lockMap()=0
std::string p_odom_frame_
ROSCPP_DECL bool ok()
void sendTransform(const StampedTransform &transform)
std::string p_map_frame_
btScalar tfScalar
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
std::string p_pose_update_topic_
ros::Publisher mapMetadataPublisher_
bool p_use_tf_scan_transformation_
TFSIMD_FORCE_INLINE Vector3 & getOrigin()
bool sleep()
void toggleMappingPause(bool pause)
double p_update_factor_occupied_
static WallTime now()
void publishMapLoop(double p_map_pub_period_)
void lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, StampedTransform &transform) const
hectorslam::DataContainer laserScanContainer
std::string p_sys_msg_topic_
ros::ServiceServer restart_hector_service_
ros::Publisher poseUpdatePublisher_
static Time now()
void setTime(const ros::Time &time)
void initialPoseCallback(const geometry_msgs::PoseWithCovarianceStampedConstPtr &msg)
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
virtual void unlockMap()=0
ros::ServiceServer toggle_scan_processing_service_
#define ROS_ASSERT(cond)
void update(const DataContainer &dataContainer, const Eigen::Vector3f &poseHintWorld, bool map_without_matching=false)
uint32_t getNumSubscribers() const
void rosPointCloudToDataContainer(const sensor_msgs::PointCloud &pointCloud, const tf::StampedTransform &laserTransform, hectorslam::DataContainer &dataContainer, float scaleToMap)
void setServiceGetMapData(nav_msgs::GetMap::Response &map_, const hectorslam::GridMap &gridMap)
void add(const DataPointType &dataPoint)
std::string p_base_frame_
#define ROS_ERROR(...)
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
bool resetMapCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
tf::Transform map_to_odom_
tf::TransformListener tf_
int getUpdateIndex() const
Definition: GridMapBase.h:329
message_filters::Subscriber< geometry_msgs::PoseWithCovarianceStamped > * initial_pose_sub_
bool pauseMapCallback(std_srvs::SetBool::Request &req, std_srvs::SetBool::Response &res)
Connection registerCallback(const C &callback)


hector_mapping
Author(s): Stefan Kohlbrecher
autogenerated on Sat Mar 12 2022 03:57:50