40#include <moveit_msgs/srv/load_map.hpp>
41#include <moveit_msgs/srv/save_map.hpp>
42#include <rclcpp/clock.hpp>
43#include <rclcpp/logger.hpp>
44#include <rclcpp/logging.hpp>
45#include <rclcpp/node.hpp>
61 const std::shared_ptr<tf2_ros::Buffer>& tf_buffer,
62 const std::string& map_frame,
double map_resolution)
69 const std::shared_ptr<tf2_ros::Buffer>& tf_buffer)
70 : middleware_handle_{ std::move(middleware_handle) }
71 , tf_buffer_{ tf_buffer }
72 , parameters_{ 0.0,
"", {} }
73 , debug_info_{
false }
74 , mesh_handle_count_{ 0 }
78 if (middleware_handle_ ==
nullptr)
80 throw std::invalid_argument(
"OccupancyMapMonitor cannot be constructed with nullptr MiddlewareHandle");
84 parameters_ = middleware_handle_->getParameters();
86 RCLCPP_DEBUG(logger_,
"Using resolution = %lf m for building octomap", parameters_.map_resolution);
88 if (tf_buffer_ !=
nullptr && parameters_.map_frame.empty())
90 RCLCPP_WARN(logger_,
"No target frame specified for Octomap. No transforms will be applied to received data.");
92 if (tf_buffer_ ==
nullptr && !parameters_.map_frame.empty())
94 RCLCPP_WARN(logger_,
"Target frame specified but no TF instance (buffer) specified."
95 "No transforms will be applied to received data.");
98 tree_ = std::make_shared<collision_detection::OccMapTree>(parameters_.map_resolution);
101 for (
const auto& [sensor_name, sensor_type] : parameters_.sensor_plugins)
103 auto occupancy_map_updater = middleware_handle_->loadOccupancyMapUpdater(sensor_type);
106 if (occupancy_map_updater ==
nullptr)
108 RCLCPP_ERROR_STREAM(logger_,
"Failed to load sensor: `" << sensor_name <<
"` of type: `" << sensor_type <<
'`');
113 occupancy_map_updater->setMonitor(
this);
116 middleware_handle_->initializeOccupancyMapUpdater(occupancy_map_updater);
119 if (!occupancy_map_updater->setParams(sensor_name))
121 RCLCPP_ERROR_STREAM(logger_,
"Failed to configure updater of type " << occupancy_map_updater->getType());
126 addUpdater(occupancy_map_updater);
130 auto save_map_service_callback = [
this](
const std::shared_ptr<rmw_request_id_t>& request_header,
131 const std::shared_ptr<moveit_msgs::srv::SaveMap::Request>& request,
132 const std::shared_ptr<moveit_msgs::srv::SaveMap::Response>& response) ->
bool {
133 return saveMapCallback(request_header, request, response);
136 auto load_map_service_callback = [
this](
const std::shared_ptr<rmw_request_id_t>& request_header,
137 const std::shared_ptr<moveit_msgs::srv::LoadMap::Request>& request,
138 const std::shared_ptr<moveit_msgs::srv::LoadMap::Response>& response) ->
bool {
139 return loadMapCallback(request_header, request, response);
142 middleware_handle_->createSaveMapService(save_map_service_callback);
143 middleware_handle_->createLoadMapService(load_map_service_callback);
150 map_updaters_.push_back(updater);
151 updater->publishDebugInformation(debug_info_);
152 if (map_updaters_.size() > 1)
154 mesh_handles_.resize(map_updaters_.size());
156 if (map_updaters_.size() == 2)
158 map_updaters_[0]->setTransformCacheCallback(
160 return getShapeTransformCache(0, frame, stamp, cache);
162 map_updaters_[1]->setTransformCacheCallback(
164 return getShapeTransformCache(1, frame, stamp, cache);
169 map_updaters_.back()->setTransformCacheCallback(
170 [
this, i = map_updaters_.size() - 1](
const std::string& frame,
const rclcpp::Time& stamp,
172 return getShapeTransformCache(i, frame, stamp, cache);
178 updater->setTransformCacheCallback(transform_cache_callback_);
183 RCLCPP_ERROR(logger_,
"nullptr updater was specified");
190 for (OccupancyMapUpdaterPtr& map_updater : map_updaters_)
191 map_updater->publishDebugInformation(debug_info_);
196 std::lock_guard<std::mutex> _(parameters_lock_);
197 parameters_.map_frame = frame;
203 if (map_updaters_.size() == 1)
204 return map_updaters_[0]->excludeShape(shape);
207 for (std::size_t i = 0; i < map_updaters_.size(); ++i)
209 ShapeHandle mh = map_updaters_[i]->excludeShape(shape);
213 h = ++mesh_handle_count_;
214 mesh_handles_[i][h] = mh;
223 if (map_updaters_.size() == 1)
225 map_updaters_[0]->forgetShape(handle);
229 for (std::size_t i = 0; i < map_updaters_.size(); ++i)
231 std::map<ShapeHandle, ShapeHandle>::const_iterator it = mesh_handles_[i].find(handle);
232 if (it == mesh_handles_[i].end())
234 map_updaters_[i]->forgetShape(it->second);
241 if (map_updaters_.size() == 1)
243 map_updaters_[0]->setTransformCacheCallback(transform_callback);
247 transform_cache_callback_ = transform_callback;
251bool OccupancyMapMonitor::getShapeTransformCache(std::size_t index,
const std::string& target_frame,
254 if (transform_cache_callback_)
257 if (transform_cache_callback_(target_frame, target_time, temp_cache))
259 for (std::pair<const ShapeHandle, Eigen::Isometry3d>& it : temp_cache)
261 std::map<ShapeHandle, ShapeHandle>::const_iterator jt = mesh_handles_[index].find(it.first);
262 if (jt == mesh_handles_[index].end())
264 rclcpp::Clock steady_clock(RCL_STEADY_TIME);
265#pragma GCC diagnostic push
266#pragma GCC diagnostic ignored "-Wold-style-cast"
267 RCLCPP_ERROR_THROTTLE(logger_, steady_clock, 1000,
"Incorrect mapping of mesh handles");
268#pragma GCC diagnostic pop
273 cache[jt->second] = it.second;
289bool OccupancyMapMonitor::saveMapCallback(
const std::shared_ptr<rmw_request_id_t>& ,
290 const std::shared_ptr<moveit_msgs::srv::SaveMap::Request>& request,
291 const std::shared_ptr<moveit_msgs::srv::SaveMap::Response>& response)
293 RCLCPP_INFO(logger_,
"Writing map to %s", request->filename.c_str());
297 response->success = tree_->writeBinary(request->filename);
301 response->success =
false;
307bool OccupancyMapMonitor::loadMapCallback(
const std::shared_ptr<rmw_request_id_t>& ,
308 const std::shared_ptr<moveit_msgs::srv::LoadMap::Request>& request,
309 const std::shared_ptr<moveit_msgs::srv::LoadMap::Response>& response)
311 RCLCPP_INFO(logger_,
"Reading map from %s", request->filename.c_str());
317 response->success = tree_->readBinary(request->filename);
321 RCLCPP_ERROR(logger_,
"Failed to load map from file");
322 response->success =
false;
324 tree_->unlockWrite();
326 if (response->success)
327 tree_->triggerUpdateCallback();
336 for (OccupancyMapUpdaterPtr& map_updater : map_updaters_)
337 map_updater->start();
343 for (OccupancyMapUpdaterPtr& map_updater : map_updaters_)
This class contains the ros interfaces for OccupancyMapMontior.
~OccupancyMapMonitor()
Destroys the object.
void startMonitor()
start the monitor (will begin updating the octomap
void setTransformCacheCallback(const TransformCacheProvider &transform_cache_callback)
Sets the transform cache callback.
void publishDebugInformation(bool flag)
Set the debug flag on the updaters.
OccupancyMapMonitor(std::unique_ptr< MiddlewareHandle > middleware_handle, const std::shared_ptr< tf2_ros::Buffer > &tf_buffer)
Occupancy map monitor constructor with the MiddlewareHandle.
void stopMonitor()
Stops the monitor, this also stops the updaters.
ShapeHandle excludeShape(const shapes::ShapeConstPtr &shape)
Add this shape to the set of shapes to be filtered out from the octomap.
void addUpdater(const OccupancyMapUpdaterPtr &updater)
Adds an OccupancyMapUpdater to be monitored.
void setMapFrame(const std::string &frame)
Sets the map frame.
void forgetShape(ShapeHandle handle)
Forget about this shape handle and the shapes it corresponds to.
rclcpp::Logger getLogger(const std::string &name)
Creates a namespaced logger.
std::map< ShapeHandle, Eigen::Isometry3d, std::less< ShapeHandle >, Eigen::aligned_allocator< std::pair< const ShapeHandle, Eigen::Isometry3d > > > ShapeTransformCache
std::function< bool(const std::string &, const rclcpp::Time &, ShapeTransformCache &)> TransformCacheProvider