diff --git a/rtabmap_util/include/rtabmap_util/map_assembler.hpp b/rtabmap_util/include/rtabmap_util/map_assembler.hpp index 8c87adeb..3c874ee0 100644 --- a/rtabmap_util/include/rtabmap_util/map_assembler.hpp +++ b/rtabmap_util/include/rtabmap_util/map_assembler.hpp @@ -79,6 +79,7 @@ private: private: MapsManager mapsManager_; std::map nodes_; + int lastNodeAdded_; std::map optimizedPoses_; std::string mapFrameId_; std::string rtabmapNodeName_; diff --git a/rtabmap_util/src/MapsManager.cpp b/rtabmap_util/src/MapsManager.cpp index 827d43c1..19c1a9a2 100644 --- a/rtabmap_util/src/MapsManager.cpp +++ b/rtabmap_util/src/MapsManager.cpp @@ -381,7 +381,7 @@ std::map MapsManager::getFilteredPoses(const std::map(); + return poses; } std::map MapsManager::updateMapCaches( @@ -443,6 +443,12 @@ std::map MapsManager::updateMapCaches( return std::map(); } + if(posesIn.empty()) + { + UERROR("Poses are empty, cannot update map caches!"); + return std::map(); + } + // process only nodes (exclude landmarks) std::map poses; if(posesIn.begin()->first < 0) diff --git a/rtabmap_util/src/nodelets/map_assembler.cpp b/rtabmap_util/src/nodelets/map_assembler.cpp index f966533c..07e91ad7 100644 --- a/rtabmap_util/src/nodelets/map_assembler.cpp +++ b/rtabmap_util/src/nodelets/map_assembler.cpp @@ -52,6 +52,7 @@ namespace rtabmap_util { MapAssembler::MapAssembler(const rclcpp::NodeOptions & options) : Node("map_assembler", options), + lastNodeAdded_(-1), rtabmapNodeName_("rtabmap"), localGridsRegenerated_(false) { @@ -256,12 +257,28 @@ void MapAssembler::mapDataReceivedCallback(const rtabmap_msgs::msg::MapData::Con } void MapAssembler::processMapData(const rtabmap_msgs::msg::MapData & msg) { + if(msg.graph.poses.empty() && msg.nodes.empty()) + { + // empty map, nothing to update + return; + } + UTimer timer; std::map poses; std::multimap constraints; rtabmap::Transform mapOdom; rtabmap_conversions::mapGraphFromROS(msg.graph, poses, constraints, mapOdom); + + // If the last node added to the cache is not in the graph anymore, it has been + // discarded by rtabmap (e.g., too small motion), so remove it from the cache. + if(lastNodeAdded_>0 && poses.find(lastNodeAdded_) == poses.end()) + { + RCLCPP_DEBUG(get_logger(), "map_assembler: Removing node %d from cache (discarded by rtabmap)", lastNodeAdded_); + nodes_.erase(lastNodeAdded_); + } + lastNodeAdded_ = -1; + for(unsigned int i=0; i lastNodeAdded_) + { + lastNodeAdded_ = msg.nodes[i].id; + } } } - // create a tmp signature with latest sensory data - if(poses.size() && nodes_.find(poses.rbegin()->first) != nodes_.end()) - { - rtabmap::Signature tmpS = nodes_.at(poses.rbegin()->first); - rtabmap::SensorData tmpData = tmpS.sensorData(); - tmpData.setId(0); - uInsert(nodes_, std::make_pair(0, rtabmap::Signature(0, -1, 0, tmpS.getStamp(), "", tmpS.getPose(), rtabmap::Transform(), tmpData))); - poses.insert(std::make_pair(0, poses.rbegin()->second)); - } - // Update maps if(!nodes_.empty()) { @@ -297,6 +308,12 @@ void MapAssembler::processMapData(const rtabmap_msgs::msg::MapData & msg) false, nodes_); } + else + { + // No data cached, republish the maps already assembled, applying + // the same pose filtering than updateMapCaches() would do. + poses = mapsManager_.getFilteredPoses(poses); + } double updateTime = timer.ticks(); mapFrameId_ = msg.header.frame_id; @@ -313,6 +330,9 @@ void MapAssembler::reset(const std::shared_ptr, { RCLCPP_INFO(this->get_logger(), "map_assembler: reset!"); mapsManager_.clear(); + nodes_.clear(); + lastNodeAdded_ = -1; + optimizedPoses_.clear(); } #ifdef WITH_OCTOMAP_MSGS @@ -326,7 +346,10 @@ void MapAssembler::octomapBinaryCallback( res->map.header.frame_id = mapFrameId_; res->map.header.stamp = now(); - mapsManager_.updateMapCaches(optimizedPoses_, 0, false, true, nodes_); + if(!optimizedPoses_.empty() && !nodes_.empty()) + { + mapsManager_.updateMapCaches(optimizedPoses_, 0, false, true, nodes_); + } const rtabmap::OctoMap * octomap = mapsManager_.getOctomap(); if(octomap->octree()->size()) @@ -342,7 +365,10 @@ void MapAssembler::octomapFullCallback( res->map.header.frame_id = mapFrameId_; res->map.header.stamp = now(); - mapsManager_.updateMapCaches(optimizedPoses_, 0, false, true, nodes_); + if(!optimizedPoses_.empty() && !nodes_.empty()) + { + mapsManager_.updateMapCaches(optimizedPoses_, 0, false, true, nodes_); + } const rtabmap::OctoMap * octomap = mapsManager_.getOctomap(); if(octomap->octree()->size())