sensor_map.cpp
Go to the documentation of this file.
1 
7 #include "sensor_map.hpp"
8 #include <chrono>
9 
10 namespace mitre_fast_layered_map
11 {
12 
13  // Static variable definition
14  // tf2_ros::Buffer tfBuffer;
15  // tf2_ros::TransformListener Map::tfListener_(Map::tfBuffer_);
16 
24  config_(config),
25  gridMap_({"ground", "nonground", "permanent", "vehicle_hitbox",
26  "current_probability", "occupancy", "elevation_min"}), // The layers should be parameterized at some point
27  staticMap_({"map"}),
28  obstacleFilterChain_("grid_map::GridMap"),
29  mapOperationsFilterChain_("grid_map::GridMap"),
31  {
32  }
33 
34  // // Don't use default constructor
36  obstacleFilterChain_("grid_map::GridMap&"),
37  mapOperationsFilterChain_("grid_map::GridMap&"),
39  {
40  }
41 
43  {
44  }
45 
52  {
55 
56  // We constantly fight nans with gridmap. Here we remove the nans
57  // it initializes with. In the moveMap function we remove any nans that
58  // appear as they can affect other functions and we don't want to handle
59  // them everywhere
60  gridMap_["ground"].setConstant(20.0);
61  gridMap_["nonground"].setConstant(0.0);
62  gridMap_["permanent"].setConstant(0.0);
63  gridMap_["vehicle_hitbox"].setConstant(0.0);
64  gridMap_["current_probability"].setConstant(0.5);
65  gridMap_["elevation_min"].setConstant(FLT_MAX);
66 
67  // Calculate vehicle corners given the length and width
68  // We calculate as a function of theta for ease when turning within map
69  // see movemap function
70  // Distance from center of vehicle to any corner
71  // inscribedRadius_ = sqrt(pow(config_.footPrintLen, 2) + pow(config_.footPrintWidth, 2));
72  // centToFrontLeftTheta_ = acos((config_.footPrintLen / 2) / inscribedRadius_);
73 
74  // Add corners in the vehicle's frame. We will transform these into the grid maps frame in MoveMap
75  geometry_msgs::Pose frontLeft;
76  frontLeft.position.x = config_.footPrintLen / 2;
77  frontLeft.position.y = config_.footPrintWidth / 2; // Remember FLU, so left is positive
78  geometry_msgs::Pose frontRight;
79  frontRight.position.x = config_.footPrintLen / 2;
80  frontRight.position.y = -(config_.footPrintWidth / 2);
81  geometry_msgs::Pose backLeft;
82  backLeft.position.x = -(config_.footPrintLen / 2);
83  backLeft.position.y = config_.footPrintWidth / 2;
84  geometry_msgs::Pose backRight;
85  backRight.position.x = -(config_.footPrintLen / 2);
86  backRight.position.y = -(config_.footPrintWidth / 2);
87  // Order turns out to be important due to how the polygon iterator follows the vertexes
88  corners_.push_back(frontLeft);
89  corners_.push_back(frontRight);
90  corners_.push_back(backRight);
91  corners_.push_back(backLeft);
92 
93  // Add the number of history layers that are configured
94  for (int i = 0; i < config_.numHistoryLayers; i++)
95  {
96  // Set to -1 to show now readings recorded
97  gridMap_.add(config_.historyLayerPrefix + std::to_string(i), -1);
98  }
99 
100  // Register the filter chains we want to use
102  {
103  ROS_ERROR("Unable to configure obstacle filter chain");
104  return -1;
105  }
106 
108  {
109  ROS_ERROR("Unable to configure map operations filter chain");
110  return -1;
111  }
112 
113  // Used to determine how often to update map position
117 
118  // Required topics
122 
123  // Optional topics
124  if (config_.staticMapSubTopic != "")
125  {
127  }
128 
129  if (config_.markerSubTopic != "")
130  {
132  }
133 
134  occPub_ = nh_.advertise<nav_msgs::OccupancyGrid>(config_.occupancyOutputTopic, 1);
135  gridMapPub_ = nh_.advertise<grid_map_msgs::GridMap>(config_.gridmapOutputTopic, 1);
136 
137  initialized_ = true;
138 
139  return 0;
140  }
141 
148  {
149  if (!initialized_)
150  {
151  ROS_ERROR("SensorMap %s has not yet been initialized successfully. Cannot run.", config_.mapName.c_str());
152  return -1;
153  }
154 
155  // All we need to do is publish!
156  publishMap();
157 
158  return 0;
159  }
160 
166  void SensorMap::odomCb(const nav_msgs::Odometry::ConstPtr odom)
167  {
168 
169  // Update at most every 1/10 of a second
170  // TODO: Add update time as configurable variable
171  if (odomLastUpdate_.toNSec() - ros::Time::now().toNSec() < 100000000)
172  {
173  ROS_DEBUG("Not long enough since last odom update. Ignoring.");
174  return;
175  }
176 
177  geometry_msgs::Pose pose = odom->pose.pose;
178  ROS_DEBUG_THROTTLE(1, "Moving local map to postion: %f, %f", pose.position.x, pose.position.y);
179 
180  odomLastUpdate_ = ros::Time::now(); // Record time of udpate
181  if (moveMap(pose.position.x, pose.position.y) > 0)
182  {
183  ROS_WARN("Map Jumped!");
184  }
185  }
186 
195  int SensorMap::moveMap(double _posX, double _posY)
196  {
197  // PROFILE: ~<1ms with 10 history layers
198  ROS_DEBUG("Setting uncovered cells.");
199 
200  // We have had errors before due to our map "jumping", usuall
201  // at the very beginning when we start 0,0 then jump. Just a way
202  // to notify that this has occured
203  int mapInCurrentBounds = 0;
204  if (!gridMap_.isInside(grid_map::Position(_posX, _posY)))
205  {
206  mapInCurrentBounds = 1;
207  }
208 
209  gridMap_.move(grid_map::Position(_posX, _posY));
210 
211  // Cells that may have been uncovered due to the move will be set to nans
212  // which can cause unforseen errors, thus we remove all nans and put in appropriate values
213 
214  grid_map::Matrix &ground = gridMap_["ground"];
215  grid_map::Matrix &elevationMin = gridMap_["elevation_min"];
216  grid_map::Matrix &nonground = gridMap_["nonground"];
217  grid_map::Matrix &permanent = gridMap_["permanent"];
218  grid_map::Matrix &currentProb = gridMap_["current_probability"];
219 
220  // TODO: Faster to use select or to do a loop over gridmap and set each cell?
221 
222  // For any unfamiliar, this is equivalent to if isnan ? set num : keep value
223  ground = (ground.array().isNaN()).select(-1, ground); // 20 is unknown
224  elevationMin = (elevationMin.array().isNaN()).select(FLT_MAX, elevationMin); // Set max if no min recorded
225  nonground = (nonground.array().isNaN()).select(0, nonground); // 0 is clear
226  permanent = (permanent.array().isNaN()).select(0, permanent); // 0 is clear
227  currentProb = (currentProb.array().isNaN()).select(0.5, currentProb); // 0.5 for don't know
228 
229  // New history cells set to -1 for no readings
230  for (int i = 0; i < config_.numHistoryLayers; i++)
231  {
232  grid_map::Matrix &layer = gridMap_[config_.historyLayerPrefix + std::to_string(i)];
233  layer = (layer.array().isNaN()).select(-1, layer);
234  }
235 
236  // Calculate the current hitbox for the vehicle given its current position and orientation
237  grid_map::Matrix &vehicleHitBox = gridMap_["vehicle_hitbox"];
238  vehicleHitBox.setConstant(0);
239 
240  try
241  {
242  geometry_msgs::TransformStamped transform = tfBuffer_.lookupTransform(config_.mapFrameId, config_.vehicleFrameId, ros::Time(0));
243 
244  // Convert vehicle corners into grid map frame and then draw a polygone
245  grid_map::Polygon poly;
247 
248  geometry_msgs::Pose tempPose;
249  for(geometry_msgs::Pose pose : corners_)
250  {
251  tf2::doTransform(pose, tempPose, transform);
252  poly.addVertex(grid_map::Position(tempPose.position.x, tempPose.position.y));
253  }
254 
255  // Iterate on polygon to set hitbox
256  for(grid_map::PolygonIterator it(gridMap_, poly); !it.isPastEnd(); ++it)
257  {
258  const grid_map::Index index(*it);
259  vehicleHitBox(index(0), index(1)) = 100; // Set as collision
260  }
261 
262  }
263  catch (const std::exception &e)
264  {
265  ROS_WARN("Unable to find transform: %s. Disabling bounding box filter for this iteration.", e.what());
266  }
267 
268  return mapInCurrentBounds;
269  }
270 
276  void SensorMap::groundPointCb(const sensor_msgs::PointCloud2 &_cloud)
277  {
278  // Check if it has been long enough since the last update
279  if (nongroundLastUpdate_.toNSec() - ros::Time::now().toNSec() < 100000000)
280  {
281  ROS_DEBUG("Not long enough since last nonground point update. Ignoring.");
282  return;
283  }
284 
285  // Check if the transform is possible
286  if (!tfBuffer_.canTransform(config_.mapFrameId, _cloud.header.frame_id, ros::Time(0), ros::Duration(0.2)))
287  {
288  ROS_WARN("Unable to find transform from %s to %s.", config_.mapFrameId.c_str(), _cloud.header.frame_id.c_str());
289  return;
290  }
291 
292  // Convert the pcl point cloud into a ros point cloud and transform
293  sensor_msgs::PointCloud2 tfCloud;
294  tfTransformCloud(_cloud, tfCloud, config_.mapFrameId);
295 
296  // Convert back to pcl cloud
297  PointCloud conCloud;
298  pcl::fromROSMsg(tfCloud, conCloud);
299 
300  updateGroundPts(conCloud);
302  }
303 
311  int SensorMap::updateGroundPts(const PointCloud &_pointCloud)
312  {
313  grid_map::Matrix &ground = gridMap_["ground"];
314  ground.setConstant(0.0);
315  grid_map::Matrix &elevation_min = gridMap_["elevation_min"];
316  grid_map::Index index;
317 
318  // Update ground cells with
319  for (auto it = _pointCloud.begin(); it < _pointCloud.end(); it++)
320  {
321 
322  // May be able to use isInside and atPosition function instead
323  if (gridMap_.getIndex(grid_map::Position(it->x, it->y), index))
324  {
325  // Record as ground point
326  ground(index(0), index(1)) += 1;
327 
328  // Record minimum elevation within the cell
329  if (std::isnan(elevation_min(index(0), index(1))) || it->z < elevation_min(index(0), index(1)))
330  {
331  elevation_min(index(0), index(1)) = it->z;
332  }
333  }
334  }
335 
336  return 0;
337  }
338 
344  void SensorMap::nonGroundPointCb(const sensor_msgs::PointCloud2 &_cloud)
345  {
346 
347  // Determine if the transform is possible
348  if (!tfBuffer_.canTransform(config_.mapFrameId, _cloud.header.frame_id, ros::Time(0), ros::Duration(0.2)))
349  {
350  ROS_WARN("Unable to find transform from %s to %s.", config_.mapFrameId.c_str(), _cloud.header.frame_id.c_str());
351  return;
352  }
353 
354  sensor_msgs::PointCloud2 tfCloud;
355  tfTransformCloud(_cloud, tfCloud, config_.mapFrameId);
356 
357  PointCloud conCloud;
358  pcl::fromROSMsg(tfCloud, conCloud);
359 
360  updateNongroundPts(conCloud);
361 
362  }
363 
372  {
373 
374  // PROFILING: ~5ms to add lidar points
375  // Determine if the height filter can and should run
376  // Lets find transform between the grid map frame and the robot/vehicle frame
377  double vehicleHeight = 0;
378  bool runHeightFilter = config_.enablePointHeightFilter;
379 
380  if (runHeightFilter)
381  {
382  try
383  {
384  geometry_msgs::TransformStamped transform = tfBuffer_.lookupTransform(config_.mapFrameId, config_.vehicleFrameId, ros::Time(0));
385  vehicleHeight = transform.transform.translation.z;
386  // ROS_INFO("Transform Z: %f", vehicleHeight);
387  }
388  catch (const std::exception &e)
389  {
390  ROS_WARN("Unable to find transform: %s. Disabling height filter for this iteration.", e.what());
391  runHeightFilter = false;
392  }
393  }
394 
395  grid_map::Index index;
396  // Determine history layer to use for this reading. Cycles through all history layers
397  std::string historyLayerStr = config_.historyLayerPrefix + std::to_string(readingsReceived_ % config_.numHistoryLayers);
398  grid_map::Matrix& historyLayer = gridMap_[historyLayerStr];
399  // Layer is being overwritten, so set to all 0's
400  historyLayer.setConstant(0);
401 
402  // Point cloud will be in map frame
403  for (auto it = _pointCloud.begin(); it < _pointCloud.end(); it++)
404  {
405  // Don't consider points outside of the map
406  if (!gridMap_.getIndex(grid_map::Position(it->x, it->y), index))
407  {
408  continue;
409  }
410 
411  // Determine if the point is too high above the vehicle to be considered an obstacle
412  if (runHeightFilter && pointHeightFilter(*it, vehicleHeight))
413  {
414  continue; // Ignore the point and continue
415  }
416  else if (config_.enableBoundingBoxFilter && pointBoundingBoxFilter(*it)) // Check if the point may be hitting the vehicle
417  {
418  continue;
419  }
420 
421  // Point in bounds and not filtered out, record it!
422  historyLayer(index(0), index(1)) += 1;
423  }
424 
425  if (runFilter() != 0)
426  {
427  return 1;
428  }
429 
431  {
432  // Add objects to permanent layer
433  grid_map::Matrix tempMat = gridMap_["current_probability"].unaryExpr([this](const float x) {
434  if (x >= config_.permanentFilterProb)
435  {
436  return (float)100;
437  }
438  return (float)0.0;
439  });
440  gridMap_["permanent"] = gridMap_["permanent"] + tempMat;
441  }
442 
443  // Only count readings that we succesfully filtered
445  return 0;
446  }
447 
448  bool SensorMap::pointHeightFilter(const pcl::PointXYZ _point, double _vehicleHeight)
449  {
450  /*
451  * Determine if the point is too high for consideration. This often catches objects such as
452  * bridges or tree branches that may register as obstacles but be safely above the vehicle.
453  */
454  if (_point.z > (config_.maxPointHeight + _vehicleHeight))
455  {
456  // ROS_INFO("Height Filter Point: %f, max height allowed: %f", point.z, (config_.maxPointHeight + transform.transform.translation.z));
457  return true;
458  }
459 
460  return false;
461  }
462 
463  bool SensorMap::pointBoundingBoxFilter(const pcl::PointXYZ point)
464  {
465  // Check if point is in cell of our vehicle bounding box
466  if (gridMap_.atPosition("vehicle_hitbox", grid_map::Position(point.x, point.y)) == 100)
467  {
468  return true;
469  }
470 
471  return false;
472  }
473 
481  {
482  // Reset nonground layer to empty, the filters will build obstacles based off past history
483  gridMap_["nonground"].setConstant(0);
484 
485  // Currently taking ~25ms for local map
487  {
488  ROS_ERROR("Unable to run obstacle filter chain.");
489  return -1;
490  }
491 
492  // Add any obstacles that have been determined to be permanent
493  if (config_.staticMapSubTopic != "")
494  {
495  integrateStaticMap(); // Will add obstacles in static map to gridMap
496  }
497 
498  gridMap_["nonground"] = gridMap_["nonground"] + gridMap_["permanent"];
499  // nonground, permanent, and static map may all share obstacles, adding them together
500  // will result in cells >100, set them to 0
501  gridMap_["nonground"] = (gridMap_["nonground"].array() > 100).select(100, gridMap_["nonground"]);
502 
503  // Runs in ~3ms
504  // Run any operations such as inflation or ray tracing on obstacle map
505  if (!mapOperationsFilterChain_.update(gridMap_, gridMap_))
506  {
507  ROS_ERROR("Unable to run map operations filter chain.");
508  return -1;
509  }
510 
511  return 0;
512  }
513 
520  {
521  if (!recStaticMap_)
522  {
523  return 1; // Haven't received a map so nothing to do
524  }
525 
526  ROS_DEBUG_THROTTLE(1, "Integrating static map.");
527 
528  // Run the map server and add mark any cells that should be occupied
529  geometry_msgs::TransformStamped tfStamp;
530 
531  // Need to wait for the tf buffer to fill up.
532  try
533  {
534  // ROS_DEBUG_THROTTLE(1, "Trying to transform from: %s to %s", _inCloud.header.frame_id.c_str(), _outFrame.c_str());
536  }
537  catch (const std::exception &e)
538  {
539  ROS_WARN("Unable to perform transform: %s", e.what());
540  return 2; // No error, but just not able to add the static map
541  }
542 
543  // grid_map::Matrix& staticMapLayer = staticMap_["map"];
544  grid_map::Matrix &gridMapLayer = gridMap_["permanent"];
545 
546  geometry_msgs::PoseStamped gridMapStamped;
547  gridMapStamped.header.frame_id = gridMap_.getFrameId();
548  gridMapStamped.header.stamp = ros::Time::now();
549 
550  geometry_msgs::PoseStamped staticMapStamped;
551 
552  for (grid_map::GridMapIterator it(gridMap_); !it.isPastEnd(); ++it)
553  {
554  const grid_map::Index index(*it);
555 
556  // Get the position of the current cell in grid map
557  grid_map::Position pos;
558  gridMap_.getPosition(index, pos);
559 
560  gridMapStamped.pose.position.x = pos.x();
561  gridMapStamped.pose.position.y = pos.y();
562 
563  // Transform the position into the static map frame
564  tf2::doTransform(gridMapStamped, staticMapStamped, tfStamp);
565 
566  grid_map::Position staticMapPos(staticMapStamped.pose.position.x, staticMapStamped.pose.position.y);
567 
568  // Check if the position is in the map and the map has registered it as an obstacle
569  if (staticMap_.isInside(staticMapPos) && staticMap_.atPosition("map", staticMapPos) == 100)
570  {
571  gridMapLayer(index(0), index(1)) = 100;
572  }
573  }
574 
575  return 0;
576  }
577 
583  void SensorMap::markerCb(const visualization_msgs::Marker &marker)
584  {
585  ROS_INFO("Recieved marker!");
586 
587  // TODO: If published in the ned frame we should switch the x and y before we look at it in utm_enu frame
588  // If we have a ned frame published then we might be okay.
589 
590  // Make sure the point is inside the map
591  grid_map::Position pos(marker.pose.position.x, marker.pose.position.y);
592  if (!gridMap_.isInside(pos))
593  {
594  ROS_WARN("Recieved Marker not inside of map.");
595  return;
596  }
597 
598  // ASSUMPTION: Obstacle is a circle/sphere
599  double radius = marker.scale.x;
600  for (grid_map::CircleIterator it(gridMap_, pos, radius); !it.isPastEnd(); ++it)
601  {
602  gridMap_.at("permanent", *it) = 100;
603  }
604  }
605 
611  void SensorMap::staticMapCb(const nav_msgs::OccupancyGrid &_map)
612  {
613  if (recStaticMap_) // Only getting the map once for now
614  {
615  return;
616  }
617 
618  // Turn the occupancy grid into a grid map message
620 
621  // Grid map seems to be using nans as obstacles, so we make all nans 100
622  staticMap_["map"] = (staticMap_["map"].array().isNaN()).select(100, staticMap_["map"]);
623 
626 
627  // DEBUG Stuff
628  ROS_INFO("Recieved static map.");
629  ROS_INFO("Map Size: %d, %d", size(0, 0), size(1, 0));
630  ROS_INFO("Resolution: %f", staticMap_.getResolution());
631  ROS_INFO("Position: %f, %f", pos(0), pos(1));
632 
633  recStaticMap_ = true; // Nofity we have received the map
634  }
635 
643  int SensorMap::getOccupancyGrid(nav_msgs::OccupancyGrid &_mapOut)
644  {
645  gridMap_["occupancy"] = gridMap_["nonground"];
646  grid_map::GridMapRosConverter::toOccupancyGrid(gridMap_, "occupancy", 0, 100, _mapOut);
647 
648  return 0;
649  }
650 
658  {
659  // PROFILE: ~2ms with 10 history layers
660  ROS_DEBUG_THROTTLE(1, "Publishing map.");
661 
662  // Publish basic occupancy map
663  nav_msgs::OccupancyGrid message;
664  getOccupancyGrid(message);
665 
666  message.header.frame_id = config_.mapFrameId;
667  message.header.stamp = ros::Time::now();
668 
669  occPub_.publish(message);
670 
671  // Publish the whole gridmap if anyone wants it
672  ROS_DEBUG_THROTTLE(1, "Publishing grid map message");
674  grid_map_msgs::GridMap gridMapMessage;
676  gridMapPub_.publish(gridMapMessage);
677 
678  return 0;
679  }
680 
690  int SensorMap::tfTransformCloud(const sensor_msgs::PointCloud2 &_inCloud, sensor_msgs::PointCloud2 &_outCloud, std::string _outFrame)
691  {
692  // Important to catch exception, since this call usually fails the first couple of times for some reason
693  // I would guess the tfBuffer is still getting updated before we call this and doesn't contain the transform
694  // geometry_msgs::TransformStamped tfStamped;
695  try
696  {
697  ROS_DEBUG_THROTTLE(1, "Trying to transform from: %s to %s", _inCloud.header.frame_id.c_str(), _outFrame.c_str());
698  tfBuffer_.transform(_inCloud, _outCloud, _outFrame, ros::Duration(0.3));
699  }
700  catch (const std::exception &e)
701  {
702  std::cerr << e.what() << '\n';
703  return -1;
704  }
705 
706  return 0;
707  }
708 
709 } // namespace mitre_fast_layered_map
SensorMap()
Constructor to initialize mapping.
Definition: sensor_map.cpp:35
Eigen::Array2i Index
void setGeometry(const Length &length, const double resolution, const Position &position=Position::Zero())
ros::Subscriber markerSub_
Subscriber for marker topic to add points to map.
Definition: sensor_map.hpp:156
ros::Subscriber groundPointsSub_
Receives point cloud of ground points.
Definition: sensor_map.hpp:159
float & atPosition(const std::string &layer, const Position &position)
grid_map::GridMap staticMap_
Storage for static map. For optimization we only want to receive it once.
Definition: sensor_map.hpp:165
std::string obstacleFilterNs
Filter chain for filtering sensor data into obstacles.
Definition: sensor_map.hpp:65
void publish(const boost::shared_ptr< M > &message) const
void odomCb(const nav_msgs::Odometry::ConstPtr)
Odometry callback function to update map position.
Definition: sensor_map.cpp:166
bool getPosition(const Index &index, Position &position) const
#define ROS_DEBUG_THROTTLE(rate,...)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void staticMapCb(const nav_msgs::OccupancyGrid &)
Definition: sensor_map.cpp:611
Eigen::Array2i Size
const std::string & getFrameId() const
Eigen::MatrixXf Matrix
std::string staticMapSubTopic
Sub topic for static maps that should be integrated with our dynamic map.
Definition: sensor_map.hpp:44
double permanentFilterProb
Probability required to declare a cell as a permanent obstacle.
Definition: sensor_map.hpp:73
ros::Publisher gridMapPub_
Publisher for the whole grid map using grid map msgs.
Definition: sensor_map.hpp:162
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
std::string nonGroundPointSubTopic
Ros topic with nonground (obstacle) points.
Definition: sensor_map.hpp:40
void markerCb(const visualization_msgs::Marker &)
Definition: sensor_map.cpp:583
static void toMessage(const grid_map::GridMap &gridMap, grid_map_msgs::GridMap &message)
bool enablePermanentObstacles
Whether to try and save permanent obstacles.
Definition: sensor_map.hpp:72
std::string mapFrameId
TF frame that the map should use.
Definition: sensor_map.hpp:50
std::string gridmapOutputTopic
Topic to output the full grid map on.
Definition: sensor_map.hpp:46
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
grid_map::Length len
Size of the map, assumed to be square.
Definition: sensor_map.hpp:51
static bool fromOccupancyGrid(const nav_msgs::OccupancyGrid &occupancyGrid, const std::string &layer, grid_map::GridMap &gridMap)
int tfTransformCloud(const sensor_msgs::PointCloud2 &, sensor_msgs::PointCloud2 &, std::string)
Definition: sensor_map.cpp:690
void doTransform(const T &data_in, T &data_out, const geometry_msgs::TransformStamped &transform)
ros::Time odomLastUpdate_
Keeps track of last time we updated position of map.
Definition: sensor_map.hpp:173
static void toOccupancyGrid(const grid_map::GridMap &gridMap, const std::string &layer, float dataMin, float dataMax, nav_msgs::OccupancyGrid &occupancyGrid)
#define ROS_WARN(...)
bool move(const Position &position, std::vector< BufferRegion > &newRegions)
int getOccupancyGrid(nav_msgs::OccupancyGrid &)
Compiles the ground and nonground layers to create an occupancy grid.
Definition: sensor_map.cpp:643
int runFilter()
Run the grid map through the filter chain.
Definition: sensor_map.cpp:480
bool enablePointHeightFilter
Whether to filter points by height.
Definition: sensor_map.hpp:67
std::string odomSubTopic
Ros topic holding odometry information.
Definition: sensor_map.hpp:42
grid_map::GridMap gridMap_
Mapping data storage container.
Definition: sensor_map.hpp:164
double getResolution() const
int updateNongroundPts(const PointCloud &)
Updates cells in the map that may have nonground (obstacle) points.
Definition: sensor_map.cpp:371
bool isInside(const Position &position) const
double footPrintLen
Length of robot.
Definition: sensor_map.hpp:61
Eigen::Vector2d Position
double resolution
Cell size of map.
Definition: sensor_map.hpp:52
#define ROS_INFO(...)
std::string occupancyOutputTopic
Topic the occupancy map should be output on.
Definition: sensor_map.hpp:45
bool recStaticMap_
Stateful variable for receiving static map.
Definition: sensor_map.hpp:172
uint64_t toNSec() const
int updateGroundPts(const PointCloud &)
Records cells in the gridmap where the ground points landed.
Definition: sensor_map.cpp:311
TFSIMD_FORCE_INLINE const tfScalar & x() const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool enableBoundingBoxFilter
Whether to filter lidar points if they are inside the hitbox of the vehicle.
Definition: sensor_map.hpp:68
std::string historyLayerPrefix
Prefix to use for history layers.
Definition: sensor_map.hpp:53
double footPrintWidth
Width of robot.
Definition: sensor_map.hpp:62
int numHistoryLayers
Number of layers to hold for history.
Definition: sensor_map.hpp:54
ros::NodeHandle nh_
Passed in node handle for namespace.
Definition: sensor_map.hpp:155
void addVertex(const Position &vertex)
filters::FilterChain< grid_map::GridMap > mapOperationsFilterChain_
after updating points
Definition: sensor_map.hpp:167
uint64_t readingsReceived_
Records how many readings we have received.
Definition: sensor_map.hpp:169
double maxPointHeight
If height filter is enabled, filter points more than this height above vehicle.
Definition: sensor_map.hpp:69
float & at(const std::string &layer, const Index &index)
ros::Time groundLastUpdate_
Keeps track of the last time we updated ground points.
Definition: sensor_map.hpp:174
filters::FilterChain< grid_map::GridMap > obstacleFilterChain_
Filters to modify obstacle state of map.
Definition: sensor_map.hpp:166
bool pointBoundingBoxFilter(const pcl::PointXYZ)
Definition: sensor_map.cpp:463
tf2_ros::TransformListener tfListener_
Used in tfBuffer_.
Definition: sensor_map.hpp:150
void add(const std::string &layer, const double value=NAN)
ros::Time nongroundLastUpdate_
Keeps track of the last time we updated non ground points.
Definition: sensor_map.hpp:175
std::vector< geometry_msgs::Pose > corners_
Holds corner of vehicle which will create polygon bounding box.
Definition: sensor_map.hpp:171
ros::Subscriber nonGroundPointsSub_
Receives point cloud of nonground points.
Definition: sensor_map.hpp:158
bool pointHeightFilter(const pcl::PointXYZ, double _vehicleHeight=0)
Definition: sensor_map.cpp:448
void setFrameId(const std::string &frameId)
bool update(const T &data_in, T &data_out)
bool configure(std::string param_name, ros::NodeHandle node=ros::NodeHandle())
std::string vehicleFrameId
Frame id of the robot.
Definition: sensor_map.hpp:60
static Time now()
virtual bool canTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &target_time, const ros::Duration timeout, std::string *errstr=NULL) const
T & transform(const T &in, T &out, const std::string &target_frame, ros::Duration timeout=ros::Duration(0.0)) const
void nonGroundPointCb(const sensor_msgs::PointCloud2 &)
Callback function for nonground points.
Definition: sensor_map.cpp:344
std::string groundPointSubTopic
Ros topic with ground points.
Definition: sensor_map.hpp:41
void setFrameId(const std::string &frameId)
ros::Subscriber odomSub_
Subscribes to odom topic to position map within frame.
Definition: sensor_map.hpp:157
int moveMap(double, double)
Move the center of the map to follow ego.
Definition: sensor_map.cpp:195
std::string mapOperationsFilterNs
Filter chain for map operations after obstacles have been determined.
Definition: sensor_map.hpp:66
void setTimestamp(const Time timestamp)
bool getIndex(const Position &position, Index &index) const
std::string markerSubTopic
Ros topic to recieve obstacles from other sources.
Definition: sensor_map.hpp:43
#define ROS_ERROR(...)
ros::Subscriber staticMapSub_
Will subscripe to the static map topic. ASSUMPTION: Only one static map.
Definition: sensor_map.hpp:160
tf2_ros::Buffer tfBuffer_
Holds transformations from tf tree.
Definition: sensor_map.hpp:149
const Size & getSize() const
void groundPointCb(const sensor_msgs::PointCloud2 &)
Callback function for ground points.
Definition: sensor_map.cpp:276
ros::Publisher occPub_
Publisher of occupancy grid.
Definition: sensor_map.hpp:161
std::string mapName
Name that will refer to this instance of map.
Definition: sensor_map.hpp:49
#define ROS_DEBUG(...)
pcl::PointCloud< pcl::PointXYZ > PointCloud
Definition: sensor_map.hpp:102


mitre_fast_layered_map
Author(s):
autogenerated on Thu Mar 11 2021 03:06:49