0.11.10: Updated LaserScanInfo interface. Updated NodeData msg with occupancy grids and laser scan local transform. MapsManager is now using directly the occupancy grids saved in nodes for 3D cloud, octomap and grid map.

This commit is contained in:
matlabbe
2016-08-31 12:45:54 -04:00
parent 7e8738685c
commit 2f6f874542
13 changed files with 800 additions and 912 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ find_package(rviz)
## System dependencies are found with CMake's conventions ## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system) # find_package(Boost REQUIRED COMPONENTS system)
find_package(RTABMap 0.11.9 REQUIRED) find_package(RTABMap 0.11.10 REQUIRED)
find_package(OpenCV REQUIRED) find_package(OpenCV REQUIRED)
+9 -2
View File
@@ -77,6 +77,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <actionlib_msgs/GoalStatusArray.h> #include <actionlib_msgs/GoalStatusArray.h>
typedef actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> MoveBaseClient; typedef actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> MoveBaseClient;
namespace rtabmap {
class StereoDense;
}
class CoreWrapper class CoreWrapper
{ {
public: public:
@@ -226,7 +230,8 @@ private:
bool setLogInfo(std_srvs::Empty::Request&, std_srvs::Empty::Response&); bool setLogInfo(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool setLogWarn(std_srvs::Empty::Request&, std_srvs::Empty::Response&); bool setLogWarn(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool setLogError(std_srvs::Empty::Request&, std_srvs::Empty::Response&); bool setLogError(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool getMapCallback(rtabmap_ros::GetMap::Request& req, rtabmap_ros::GetMap::Response& res); bool getMapDataCallback(rtabmap_ros::GetMap::Request& req, rtabmap_ros::GetMap::Response& res);
bool getMapCallback(nav_msgs::GetMap::Request &req, nav_msgs::GetMap::Response &res);
bool getProjMapCallback(nav_msgs::GetMap::Request &req, nav_msgs::GetMap::Response &res); bool getProjMapCallback(nav_msgs::GetMap::Request &req, nav_msgs::GetMap::Response &res);
bool getGridMapCallback(nav_msgs::GetMap::Request &req, nav_msgs::GetMap::Response &res); bool getGridMapCallback(nav_msgs::GetMap::Request &req, nav_msgs::GetMap::Response &res);
bool publishMapCallback(rtabmap_ros::PublishMap::Request&, rtabmap_ros::PublishMap::Response&); bool publishMapCallback(rtabmap_ros::PublishMap::Request&, rtabmap_ros::PublishMap::Response&);
@@ -239,7 +244,7 @@ private:
bool octomapFullCallback(octomap_msgs::GetOctomap::Request &req, octomap_msgs::GetOctomap::Response &res); bool octomapFullCallback(octomap_msgs::GetOctomap::Request &req, octomap_msgs::GetOctomap::Response &res);
#endif #endif
rtabmap::ParametersMap loadParameters(const std::string & configFile); void loadParameters(const std::string & configFile, rtabmap::ParametersMap & parameters);
void saveParameters(const std::string & configFile); void saveParameters(const std::string & configFile);
void publishLoop(double tfDelay, double tfTolerance); void publishLoop(double tfDelay, double tfTolerance);
@@ -489,6 +494,7 @@ private:
ros::ServiceServer setLogErrorSrv_; ros::ServiceServer setLogErrorSrv_;
ros::ServiceServer getMapDataSrv_; ros::ServiceServer getMapDataSrv_;
ros::ServiceServer getProjMapSrv_; ros::ServiceServer getProjMapSrv_;
ros::ServiceServer getMapSrv_;
ros::ServiceServer getGridMapSrv_; ros::ServiceServer getGridMapSrv_;
ros::ServiceServer publishMapDataSrv_; ros::ServiceServer publishMapDataSrv_;
ros::ServiceServer setGoalSrv_; ros::ServiceServer setGoalSrv_;
@@ -504,6 +510,7 @@ private:
boost::thread* transformThread_; boost::thread* transformThread_;
bool stereoToDepth_;
float rate_; float rate_;
bool createIntermediateNodes_; bool createIntermediateNodes_;
ros::Time time_; ros::Time time_;
+19 -34
View File
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define MAPSMANAGER_H_ #define MAPSMANAGER_H_
#include <rtabmap/core/Signature.h> #include <rtabmap/core/Signature.h>
#include <rtabmap/core/Parameters.h>
#include <pcl/point_cloud.h> #include <pcl/point_cloud.h>
#include <pcl/point_types.h> #include <pcl/point_types.h>
#include <ros/time.h> #include <ros/time.h>
@@ -37,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace rtabmap { namespace rtabmap {
class OctoMap; class OctoMap;
class Memory; class Memory;
class OccupancyGrid;
} // namespace rtabmap } // namespace rtabmap
@@ -46,6 +48,8 @@ public:
virtual ~MapsManager(); virtual ~MapsManager();
void clear(); void clear();
bool hasSubscribers() const; bool hasSubscribers() const;
void backwardCompatibilityParameters(rtabmap::ParametersMap & parameters) const;
void setParameters(const rtabmap::ParametersMap & parameters);
std::map<int, rtabmap::Transform> getFilteredPoses( std::map<int, rtabmap::Transform> getFilteredPoses(
const std::map<int, rtabmap::Transform> & poses); const std::map<int, rtabmap::Transform> & poses);
@@ -53,10 +57,7 @@ public:
std::map<int, rtabmap::Transform> updateMapCaches( std::map<int, rtabmap::Transform> updateMapCaches(
const std::map<int, rtabmap::Transform> & poses, const std::map<int, rtabmap::Transform> & poses,
const rtabmap::Memory * memory, const rtabmap::Memory * memory,
bool updateCloud,
bool updateProj,
bool updateGrid, bool updateGrid,
bool updateScan,
bool updateOctomap, bool updateOctomap,
const std::map<int, rtabmap::Signature> & signatures = std::map<int, rtabmap::Signature>()); const std::map<int, rtabmap::Signature> & signatures = std::map<int, rtabmap::Signature>());
@@ -65,12 +66,6 @@ public:
const ros::Time & stamp, const ros::Time & stamp,
const std::string & mapFrameId); const std::string & mapFrameId);
cv::Mat generateProjMap(
const std::map<int, rtabmap::Transform> & filteredPoses,
float & xMin,
float & yMin,
float & gridCellSize);
cv::Mat generateGridMap( cv::Mat generateGridMap(
const std::map<int, rtabmap::Transform> & filteredPoses, const std::map<int, rtabmap::Transform> & filteredPoses,
float & xMin, float & xMin,
@@ -81,37 +76,20 @@ public:
private: private:
// mapping stuff // mapping stuff
int cloudDecimation_;
double cloudMaxDepth_;
double cloudMinDepth_;
double cloudVoxelSize_;
double cloudFloorCullingHeight_;
double cloudCeilingCullingHeight_;
bool cloudOutputVoxelized_; bool cloudOutputVoxelized_;
bool cloudFrustumCulling_;
double cloudNoiseFilteringRadius_;
int cloudNoiseFilteringMinNeighbors_;
int scanDecimation_;
double scanVoxelSize_;
bool scanOutputVoxelized_;
double projMaxGroundAngle_;
int projMinClusterSize_;
double projMaxObstaclesHeight_;
double projMaxGroundHeight_;
bool projDetectFlatObstacles_;
bool projMapFrame_;
double gridCellSize_; double gridCellSize_;
bool gridIncremental_;
double gridSize_; double gridSize_;
bool gridEroded_; bool gridEroded_;
double footprintRadius_; double footprintRadius_;
bool gridUnknownSpaceFilled_;
double gridMaxUnknownSpaceFilledRange_;
double mapFilterRadius_; double mapFilterRadius_;
double mapFilterAngle_; double mapFilterAngle_;
bool mapCacheCleanup_; bool mapCacheCleanup_;
bool negativePosesIgnored_; bool negativePosesIgnored_;
ros::Publisher cloudMapPub_; ros::Publisher cloudMapPub_;
ros::Publisher cloudGroundPub_;
ros::Publisher cloudObstaclesPub_;
ros::Publisher projMapPub_; ros::Publisher projMapPub_;
ros::Publisher gridMapPub_; ros::Publisher gridMapPub_;
ros::Publisher scanMapPub_; ros::Publisher scanMapPub_;
@@ -121,15 +99,22 @@ private:
ros::Publisher octoMapEmptySpace_; ros::Publisher octoMapEmptySpace_;
ros::Publisher octoMapProj_; ros::Publisher octoMapProj_;
std::map<int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr > clouds_; std::map<int, rtabmap::Transform> assembledGroundPoses_;
std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr > scans_; std::map<int, rtabmap::Transform> assembledObstaclePoses_;
std::map<int, std::vector<rtabmap::CameraModel> > cameraModels_; pcl::PointCloud<pcl::PointXYZRGB>::Ptr assembledObstacles_;
std::map<int, std::pair<cv::Mat, cv::Mat> > projMaps_; // <ground, obstacles> pcl::PointCloud<pcl::PointXYZRGB>::Ptr assembledGround_;
std::map<int, rtabmap::Transform> gridPoses_;
cv::Mat gridMap_;
std::map<int, std::pair<cv::Mat, cv::Mat> > gridMaps_; // <ground, obstacles> std::map<int, std::pair<cv::Mat, cv::Mat> > gridMaps_; // <ground, obstacles>
std::map<int, cv::Point3f> gridMapsViewpoints_;
rtabmap::OccupancyGrid * occupancyGrid_;
rtabmap::OctoMap * octomap_; rtabmap::OctoMap * octomap_;
int octomapTreeDepth_; int octomapTreeDepth_;
bool octomapGroundIsObstacle_;
rtabmap::ParametersMap parameters_;
}; };
#endif /* MAPSMANAGER_H_ */ #endif /* MAPSMANAGER_H_ */
+8
View File
@@ -33,11 +33,19 @@ geometry_msgs/Transform[] localTransform
uint8[] laserScan uint8[] laserScan
int32 laserScanMaxPts int32 laserScanMaxPts
float32 laserScanMaxRange float32 laserScanMaxRange
geometry_msgs/Transform laserScanLocalTransform
# compressed user data # compressed user data
# use rtabmap::util3d::uncompressData() from "rtabmap/core/util3d.h" # use rtabmap::util3d::uncompressData() from "rtabmap/core/util3d.h"
uint8[] userData uint8[] userData
# compressed occupancy grid
# use rtabmap::util3d::uncompressData() from "rtabmap/core/util3d.h"
uint8[] grid_ground
uint8[] grid_obstacles
float32 grid_cell_size
Point3f grid_view_point
# std::multimap<wordId, cv::Keypoint> # std::multimap<wordId, cv::Keypoint>
# std::multimap<wordId, pcl::PointXYZ> # std::multimap<wordId, pcl::PointXYZ>
int32[] wordIds int32[] wordIds
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<package> <package>
<name>rtabmap_ros</name> <name>rtabmap_ros</name>
<version>0.11.9</version> <version>0.11.10</version>
<description>RTAB-Map's ros-pkg. RTAB-Map is a RGB-D SLAM approach with real-time constraints.</description> <description>RTAB-Map's ros-pkg. RTAB-Map is a RGB-D SLAM approach with real-time constraints.</description>
<maintainer email="matlabbe@gmail.com">Mathieu Labbe</maintainer> <maintainer email="matlabbe@gmail.com">Mathieu Labbe</maintainer>
<author>Mathieu Labbe</author> <author>Mathieu Labbe</author>
+2 -3
View File
@@ -51,9 +51,8 @@ int main(int argc, char** argv)
else if(strcmp(argv[i], "--params") == 0 || strcmp(argv[i], "--params-all") == 0) else if(strcmp(argv[i], "--params") == 0 || strcmp(argv[i], "--params-all") == 0)
{ {
rtabmap::ParametersMap parameters = rtabmap::Parameters::getDefaultParameters(); rtabmap::ParametersMap parameters = rtabmap::Parameters::getDefaultParameters();
uInsert(parameters, uInsert(parameters, rtabmap::ParametersPair(rtabmap::Parameters::kRGBDCreateOccupancyGrid(), "true")); // default true in ROS
std::make_pair(rtabmap::Parameters::kRtabmapWorkingDirectory(), uInsert(parameters, rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapWorkingDirectory(), UDirectory::homeDir()+"/.ros")); // change default to ~/.ros
UDirectory::homeDir()+"/.ros")); // change default to ~/.ros
if(strcmp(argv[i], "--params") == 0) if(strcmp(argv[i], "--params") == 0)
{ {
+167 -146
View File
@@ -52,6 +52,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/Memory.h> #include <rtabmap/core/Memory.h>
#include <rtabmap/core/OdometryEvent.h> #include <rtabmap/core/OdometryEvent.h>
#include <rtabmap/core/Version.h> #include <rtabmap/core/Version.h>
#include <rtabmap/core/StereoDense.h>
#include <pcl_conversions/pcl_conversions.h> #include <pcl_conversions/pcl_conversions.h>
@@ -124,6 +125,7 @@ CoreWrapper::CoreWrapper(bool deleteDbOnStart, const ParametersMap & parameters)
stereoApproxTFSync_(0), stereoApproxTFSync_(0),
stereoExactTFSync_(0), stereoExactTFSync_(0),
transformThread_(0), transformThread_(0),
stereoToDepth_(false),
rate_(Parameters::defaultRtabmapDetectionRate()), rate_(Parameters::defaultRtabmapDetectionRate()),
createIntermediateNodes_(Parameters::defaultRtabmapCreateIntermediateNodes()), createIntermediateNodes_(Parameters::defaultRtabmapCreateIntermediateNodes()),
time_(ros::Time::now()), time_(ros::Time::now()),
@@ -208,6 +210,7 @@ CoreWrapper::CoreWrapper(bool deleteDbOnStart, const ParametersMap & parameters)
pnh.param("scan_cloud_max_points", scanCloudMaxPoints_, scanCloudMaxPoints_); pnh.param("scan_cloud_max_points", scanCloudMaxPoints_, scanCloudMaxPoints_);
pnh.param("scan_cloud_normal_k", scanCloudNormalK_, scanCloudNormalK_); pnh.param("scan_cloud_normal_k", scanCloudNormalK_, scanCloudNormalK_);
pnh.param("flip_scan", flipScan_, flipScan_); pnh.param("flip_scan", flipScan_, flipScan_);
pnh.param("stereo_to_depth", stereoToDepth_, stereoToDepth_);
if(!tfPrefix.empty()) if(!tfPrefix.empty())
{ {
@@ -285,12 +288,15 @@ CoreWrapper::CoreWrapper(bool deleteDbOnStart, const ParametersMap & parameters)
databasePath_ = UDirectory::currentDir(true) + databasePath_; databasePath_ = UDirectory::currentDir(true) + databasePath_;
} }
ParametersMap allParameters = Parameters::getDefaultParameters();
uInsert(allParameters, ParametersPair(Parameters::kRGBDCreateOccupancyGrid(), "true")); // default true in ROS
uInsert(allParameters, ParametersPair(Parameters::kRtabmapWorkingDirectory(), UDirectory::homeDir()+"/.ros")); // change default to ~/.ros
// load parameters // load parameters
parameters_ = loadParameters(configPath_); loadParameters(configPath_, parameters_);
// update parameters with user input parameters (private) // update parameters with user input parameters (private)
uInsert(parameters_, std::make_pair(Parameters::kRtabmapWorkingDirectory(), UDirectory::homeDir()+"/.ros")); // change default to ~/.ros for(ParametersMap::iterator iter=allParameters.begin(); iter!=allParameters.end(); ++iter)
for(ParametersMap::iterator iter=parameters_.begin(); iter!=parameters_.end(); ++iter)
{ {
std::string vStr; std::string vStr;
bool vBool; bool vBool;
@@ -299,31 +305,31 @@ CoreWrapper::CoreWrapper(bool deleteDbOnStart, const ParametersMap & parameters)
if(pnh.getParam(iter->first, vStr)) if(pnh.getParam(iter->first, vStr))
{ {
ROS_INFO("Setting RTAB-Map parameter \"%s\"=\"%s\"", iter->first.c_str(), vStr.c_str()); ROS_INFO("Setting RTAB-Map parameter \"%s\"=\"%s\"", iter->first.c_str(), vStr.c_str());
iter->second = vStr;
if(iter->first.compare(Parameters::kRtabmapWorkingDirectory()) == 0) if(iter->first.compare(Parameters::kRtabmapWorkingDirectory()) == 0)
{ {
iter->second = uReplaceChar(iter->second, '~', UDirectory::homeDir()); vStr = uReplaceChar(vStr, '~', UDirectory::homeDir());
} }
else if(iter->first.compare(Parameters::kKpDictionaryPath()) == 0) else if(iter->first.compare(Parameters::kKpDictionaryPath()) == 0)
{ {
iter->second = uReplaceChar(iter->second, '~', UDirectory::homeDir()); vStr = uReplaceChar(vStr, '~', UDirectory::homeDir());
} }
uInsert(parameters_, ParametersPair(iter->first, vStr));
} }
else if(pnh.getParam(iter->first, vBool)) else if(pnh.getParam(iter->first, vBool))
{ {
ROS_INFO("Setting RTAB-Map parameter \"%s\"=\"%s\"", iter->first.c_str(), uBool2Str(vBool).c_str()); ROS_INFO("Setting RTAB-Map parameter \"%s\"=\"%s\"", iter->first.c_str(), uBool2Str(vBool).c_str());
iter->second = uBool2Str(vBool); uInsert(parameters_, ParametersPair(iter->first, uBool2Str(vBool)));
} }
else if(pnh.getParam(iter->first, vDouble)) else if(pnh.getParam(iter->first, vDouble))
{ {
ROS_INFO("Setting RTAB-Map parameter \"%s\"=\"%s\"", iter->first.c_str(), uNumber2Str(vDouble).c_str()); ROS_INFO("Setting RTAB-Map parameter \"%s\"=\"%s\"", iter->first.c_str(), uNumber2Str(vDouble).c_str());
iter->second = uNumber2Str(vDouble); uInsert(parameters_, ParametersPair(iter->first, uNumber2Str(vDouble)));
} }
else if(pnh.getParam(iter->first, vInt)) else if(pnh.getParam(iter->first, vInt))
{ {
ROS_INFO("Setting RTAB-Map parameter \"%s\"=\"%s\"", iter->first.c_str(), uNumber2Str(vInt).c_str()); ROS_INFO("Setting RTAB-Map parameter \"%s\"=\"%s\"", iter->first.c_str(), uNumber2Str(vInt).c_str());
iter->second = uNumber2Str(vInt); uInsert(parameters_, ParametersPair(iter->first, uNumber2Str(vInt)));
} }
} }
@@ -345,7 +351,7 @@ CoreWrapper::CoreWrapper(bool deleteDbOnStart, const ParametersMap & parameters)
if(iter->second.first) if(iter->second.first)
{ {
// can be migrated // can be migrated
parameters_.at(iter->second.second)= vStr; uInsert(parameters_, ParametersPair(iter->second.second, vStr));
ROS_WARN("Rtabmap: Parameter name changed: \"%s\" -> \"%s\". Please update your launch file accordingly. Value \"%s\" is still set to the new parameter name.", ROS_WARN("Rtabmap: Parameter name changed: \"%s\" -> \"%s\". Please update your launch file accordingly. Value \"%s\" is still set to the new parameter name.",
iter->first.c_str(), iter->second.second.c_str(), vStr.c_str()); iter->first.c_str(), iter->second.second.c_str(), vStr.c_str());
} }
@@ -365,6 +371,25 @@ CoreWrapper::CoreWrapper(bool deleteDbOnStart, const ParametersMap & parameters)
} }
} }
// Backward compatibility (MapsManager)
mapsManager_.backwardCompatibilityParameters(parameters_);
if((subscribeScan2d || subscribeScan3d) && parameters_.find(Parameters::kGridFromDepth()) == parameters_.end())
{
ROS_WARN("Setting \"%s\" parameter to false (default true) as \"subscribe_scan\" or \"subscribe_scan_cloud\" is "
"true. The occupancy grid map will be constructed from "
"laser scans. To get occupancy grid map from cloud projection, set \"%s\" "
"to true. To suppress this warning, "
"add <param name=\"%s\" type=\"string\" value=\"false\"/>",
Parameters::kGridFromDepth().c_str(),
Parameters::kGridFromDepth().c_str(),
Parameters::kGridFromDepth().c_str());
parameters_.insert(ParametersPair(Parameters::kGridFromDepth(), "false"));
}
// Add all other parameters (not copied if already exists)
parameters_.insert(allParameters.begin(), allParameters.end());
// set public parameters // set public parameters
nh.setParam("is_rtabmap_paused", paused_); nh.setParam("is_rtabmap_paused", paused_);
for(ParametersMap::iterator iter=parameters_.begin(); iter!=parameters_.end(); ++iter) for(ParametersMap::iterator iter=parameters_.begin(); iter!=parameters_.end(); ++iter)
@@ -391,9 +416,9 @@ CoreWrapper::CoreWrapper(bool deleteDbOnStart, const ParametersMap & parameters)
if(!subscribeDepth && !subscribeStereo) if(!subscribeDepth && !subscribeStereo)
{ {
ROS_WARN("ROS param subscribe_depth and subscribe_stereo are false, but RTAB-Map " ROS_WARN("ROS param subscribe_depth and subscribe_stereo are false, but RTAB-Map "
"parameter \"RGBD/Enabled\" is true! Please set subscribe_depth or subscribe_stereo " "parameter \"%s\" is true! Please set subscribe_depth or subscribe_stereo "
"to true to use rtabmap node for RGB-D SLAM, or set \"RGBD/Enabled\" to false for loop closure " "to true to use rtabmap node for RGB-D SLAM, or set \"%s\" to false for loop closure "
"detection on images-only."); "detection on images-only.", Parameters::kRGBDEnabled().c_str(), Parameters::kRGBDEnabled().c_str());
} }
} }
@@ -419,6 +444,12 @@ CoreWrapper::CoreWrapper(bool deleteDbOnStart, const ParametersMap & parameters)
ROS_INFO("rtabmap: database_path parameter not set, the map will not be saved."); ROS_INFO("rtabmap: database_path parameter not set, the map will not be saved.");
} }
mapsManager_.setParameters(parameters_);
if(subscribeStereo)
{
ROS_INFO("rtabmap: stereo_to_depth = %s", stereoToDepth_?"true":"false");
}
// Init RTAB-Map // Init RTAB-Map
rtabmap_.init(parameters_, databasePath_); rtabmap_.init(parameters_, databasePath_);
@@ -436,7 +467,8 @@ CoreWrapper::CoreWrapper(bool deleteDbOnStart, const ParametersMap & parameters)
backupDatabase_ = nh.advertiseService("backup", &CoreWrapper::backupDatabaseCallback, this); backupDatabase_ = nh.advertiseService("backup", &CoreWrapper::backupDatabaseCallback, this);
setModeLocalizationSrv_ = nh.advertiseService("set_mode_localization", &CoreWrapper::setModeLocalizationCallback, this); setModeLocalizationSrv_ = nh.advertiseService("set_mode_localization", &CoreWrapper::setModeLocalizationCallback, this);
setModeMappingSrv_ = nh.advertiseService("set_mode_mapping", &CoreWrapper::setModeMappingCallback, this); setModeMappingSrv_ = nh.advertiseService("set_mode_mapping", &CoreWrapper::setModeMappingCallback, this);
getMapDataSrv_ = nh.advertiseService("get_map", &CoreWrapper::getMapCallback, this); getMapDataSrv_ = nh.advertiseService("get_map_data", &CoreWrapper::getMapDataCallback, this);
getMapSrv_ = nh.advertiseService("get_map", &CoreWrapper::getMapCallback, this);
getGridMapSrv_ = nh.advertiseService("get_grid_map", &CoreWrapper::getGridMapCallback, this); getGridMapSrv_ = nh.advertiseService("get_grid_map", &CoreWrapper::getGridMapCallback, this);
getProjMapSrv_ = nh.advertiseService("get_proj_map", &CoreWrapper::getProjMapCallback, this); getProjMapSrv_ = nh.advertiseService("get_proj_map", &CoreWrapper::getProjMapCallback, this);
publishMapDataSrv_ = nh.advertiseService("publish_map", &CoreWrapper::publishMapCallback, this); publishMapDataSrv_ = nh.advertiseService("publish_map", &CoreWrapper::publishMapCallback, this);
@@ -550,9 +582,8 @@ CoreWrapper::~CoreWrapper()
printf("rtabmap: Saving database/long-term memory... (located at %s)\n", databasePath_.c_str()); printf("rtabmap: Saving database/long-term memory... (located at %s)\n", databasePath_.c_str());
} }
ParametersMap CoreWrapper::loadParameters(const std::string & configFile) void CoreWrapper::loadParameters(const std::string & configFile, ParametersMap & parameters)
{ {
ParametersMap parameters = Parameters::getDefaultParameters();
if(!configFile.empty()) if(!configFile.empty())
{ {
ROS_INFO("Loading parameters from %s", configFile.c_str()); ROS_INFO("Loading parameters from %s", configFile.c_str());
@@ -562,9 +593,6 @@ ParametersMap CoreWrapper::loadParameters(const std::string & configFile)
} }
Parameters::readINI(configFile.c_str(), parameters); Parameters::readINI(configFile.c_str(), parameters);
} }
// otherwise take default parameters
return parameters;
} }
void CoreWrapper::saveParameters(const std::string & configFile) void CoreWrapper::saveParameters(const std::string & configFile)
@@ -993,12 +1021,14 @@ void CoreWrapper::commonDepthCallback(
} }
cv::Mat scan; cv::Mat scan;
Transform scanLocalTransform = Transform::getIdentity();
if(scan2dMsg.get() != 0) if(scan2dMsg.get() != 0)
{ {
// make sure the frame of the laser is updated too // make sure the frame of the laser is updated too
if(getTransform(frameId_, scanLocalTransform = getTransform(frameId_,
scan2dMsg->header.frame_id, scan2dMsg->header.frame_id,
scan2dMsg->header.stamp + ros::Duration().fromSec(scan2dMsg->ranges.size()*scan2dMsg->time_increment)).isNull()) scan2dMsg->header.stamp + ros::Duration().fromSec(scan2dMsg->ranges.size()*scan2dMsg->time_increment));
if(scanLocalTransform.isNull())
{ {
ROS_ERROR("TF of received laser scan topic at time %fs is not set, aborting rtabmap update.", scan2dMsg->header.stamp.toSec()); ROS_ERROR("TF of received laser scan topic at time %fs is not set, aborting rtabmap update.", scan2dMsg->header.stamp.toSec());
return; return;
@@ -1007,7 +1037,7 @@ void CoreWrapper::commonDepthCallback(
//transform in frameId_ frame //transform in frameId_ frame
sensor_msgs::PointCloud2 scanOut; sensor_msgs::PointCloud2 scanOut;
laser_geometry::LaserProjection projection; laser_geometry::LaserProjection projection;
projection.transformLaserScanToPointCloud(frameId_, *scan2dMsg, scanOut, tfListener_); projection.transformLaserScanToPointCloud(scan2dMsg->header.frame_id, *scan2dMsg, scanOut, tfListener_);
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(scanOut, *pclScan); pcl::fromROSMsg(scanOut, *pclScan);
@@ -1024,8 +1054,7 @@ void CoreWrapper::commonDepthCallback(
} }
else else
{ {
Transform t = odomT.inverse() * sensorT; scanLocalTransform = odomT.inverse() * sensorT * scanLocalTransform;
pclScan = util3d::transformPointCloud(pclScan, t);
} }
} }
@@ -1051,13 +1080,12 @@ void CoreWrapper::commonDepthCallback(
} }
// sync with odometry stamp // sync with odometry stamp
Transform localScanTransform = getTransform(frameId_, scan3dMsg->header.frame_id, scan3dMsg->header.stamp); scanLocalTransform = getTransform(frameId_, scan3dMsg->header.frame_id, scan3dMsg->header.stamp);
if(localScanTransform.isNull()) if(scanLocalTransform.isNull())
{ {
ROS_ERROR("TF of received scan cloud at time %fs is not set, aborting rtabmap update.", scan3dMsg->header.stamp.toSec()); ROS_ERROR("TF of received scan cloud at time %fs is not set, aborting rtabmap update.", scan3dMsg->header.stamp.toSec());
return; return;
} }
Transform laserOdomT = localScanTransform;
if(lastPoseStamp_ != scan3dMsg->header.stamp) if(lastPoseStamp_ != scan3dMsg->header.stamp)
{ {
if(!odomT.isNull()) if(!odomT.isNull())
@@ -1070,7 +1098,7 @@ void CoreWrapper::commonDepthCallback(
} }
else else
{ {
laserOdomT = odomT.inverse() * sensorT * localScanTransform; scanLocalTransform = odomT.inverse() * sensorT * scanLocalTransform;
} }
} }
@@ -1080,10 +1108,6 @@ void CoreWrapper::commonDepthCallback(
{ {
pcl::PointCloud<pcl::PointNormal>::Ptr pclScan(new pcl::PointCloud<pcl::PointNormal>); pcl::PointCloud<pcl::PointNormal>::Ptr pclScan(new pcl::PointCloud<pcl::PointNormal>);
pcl::fromROSMsg(*scan3dMsg, *pclScan); pcl::fromROSMsg(*scan3dMsg, *pclScan);
if(!laserOdomT.isIdentity())
{
pclScan = util3d::transformPointCloud(pclScan, laserOdomT);
}
scan = util3d::laserScanFromPointCloud(*pclScan); scan = util3d::laserScanFromPointCloud(*pclScan);
} }
else else
@@ -1091,11 +1115,6 @@ void CoreWrapper::commonDepthCallback(
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(*scan3dMsg, *pclScan); pcl::fromROSMsg(*scan3dMsg, *pclScan);
if(!laserOdomT.isIdentity())
{
pclScan = util3d::transformPointCloud(pclScan, laserOdomT);
}
if(scanCloudNormalK_ > 0) if(scanCloudNormalK_ > 0)
{ {
//compute normals //compute normals
@@ -1126,8 +1145,10 @@ void CoreWrapper::commonDepthCallback(
} }
SensorData data(scan, SensorData data(scan,
scan2dMsg.get() != 0?(int)scan2dMsg->ranges.size():(genScan_?genMaxScanPts:scan3dMsg.get() != 0?scanCloudMaxPoints_:0), LaserScanInfo(
scan2dMsg.get() != 0?scan2dMsg->range_max:(genScan_?genScanMaxDepth_:0.0f), scan2dMsg.get() != 0?(int)scan2dMsg->ranges.size():(genScan_?genMaxScanPts:scan3dMsg.get() != 0?scanCloudMaxPoints_:0),
scan2dMsg.get() != 0?scan2dMsg->range_max:(genScan_?genScanMaxDepth_:0.0f),
scanLocalTransform),
rgb, rgb,
depth, depth,
cameraModels, cameraModels,
@@ -1167,6 +1188,77 @@ void CoreWrapper::commonStereoCallback(
return; return;
} }
cv_bridge::CvImagePtr ptrLeftImage, ptrRightImage;
if(leftImageMsg->encoding.compare(sensor_msgs::image_encodings::MONO8) == 0 ||
leftImageMsg->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0)
{
ptrLeftImage = cv_bridge::toCvCopy(leftImageMsg, "mono8");
}
else
{
ptrLeftImage = cv_bridge::toCvCopy(leftImageMsg, "bgr8");
}
ptrRightImage = cv_bridge::toCvCopy(rightImageMsg, "mono8");
Transform localTransform = getTransform(frameId_, leftImageMsg->header.frame_id, leftImageMsg->header.stamp);
if(localTransform.isNull())
{
return;
}
rtabmap::StereoCameraModel stereoModel = rtabmap_ros::stereoCameraModelFromROS(*leftCamInfoMsg, *rightCamInfoMsg, localTransform);
if(stereoModel.baseline() > 10.0)
{
static bool shown = false;
if(!shown)
{
ROS_WARN("Detected baseline (%f m) is quite large! Is your "
"right camera_info P(0,3) correctly set? Note that "
"baseline=-P(0,3)/P(0,0). This warning is printed only once.",
stereoModel.baseline());
shown = true;
}
}
if(stereoToDepth_)
{
// cv::stereoBM() see "$ rosrun rtabmap_ros rtabmap --params | grep StereoBM" for parameters
cv::Mat disparity = util2d::disparityFromStereoImages(ptrLeftImage->image, ptrRightImage->image, parameters_);
if(disparity.empty())
{
ROS_ERROR("Could not compute disparity image (\"stereo_to_depth\" is true)!");
return;
}
cv::Mat depth = util2d::depthFromDisparity(
disparity,
stereoModel.left().fx(),
stereoModel.baseline());
if(depth.empty())
{
ROS_ERROR("Could not compute depth image (\"stereo_to_depth\" is true)!");
return;
}
UASSERT(depth.type() == CV_16UC1 || depth.type() == CV_32FC1);
// move to common depth callback
cv_bridge::CvImage imgDepth;
if(depth.type() == CV_16UC1)
{
imgDepth.encoding = sensor_msgs::image_encodings::TYPE_16UC1;
}
else // CV_32FC1
{
imgDepth.encoding = sensor_msgs::image_encodings::TYPE_32FC1;
}
imgDepth.image = depth;
sensor_msgs::ImagePtr depthMsg = imgDepth.toImageMsg();
depthMsg->header = leftImageMsg->header;
commonDepthCallback(odomFrameId, leftImageMsg, depthMsg, leftCamInfoMsg, scan2dMsg, scan3dMsg);
}
//for sync transform //for sync transform
Transform odomT = getTransform(odomFrameId, frameId_, lastPoseStamp_); Transform odomT = getTransform(odomFrameId, frameId_, lastPoseStamp_);
if(odomT.isNull() && !odomFrameId_.empty()) if(odomT.isNull() && !odomFrameId_.empty())
@@ -1175,12 +1267,6 @@ void CoreWrapper::commonStereoCallback(
odomFrameId.c_str(), frameId_.c_str()); odomFrameId.c_str(), frameId_.c_str());
} }
Transform localTransform = getTransform(frameId_, leftImageMsg->header.frame_id, leftImageMsg->header.stamp);
if(localTransform.isNull())
{
return;
}
// sync with odometry stamp // sync with odometry stamp
if(lastPoseStamp_ != leftImageMsg->header.stamp) if(lastPoseStamp_ != leftImageMsg->header.stamp)
{ {
@@ -1196,12 +1282,14 @@ void CoreWrapper::commonStereoCallback(
} }
cv::Mat scan; cv::Mat scan;
Transform scanLocalTransform = Transform::getIdentity();
if(scan2dMsg.get() != 0) if(scan2dMsg.get() != 0)
{ {
// make sure the frame of the laser is updated too // make sure the frame of the laser is updated too
if(getTransform(frameId_, scanLocalTransform = getTransform(frameId_,
scan2dMsg->header.frame_id, scan2dMsg->header.frame_id,
scan2dMsg->header.stamp + ros::Duration().fromSec(scan2dMsg->ranges.size()*scan2dMsg->time_increment)).isNull()) scan2dMsg->header.stamp + ros::Duration().fromSec(scan2dMsg->ranges.size()*scan2dMsg->time_increment));
if(scanLocalTransform.isNull())
{ {
ROS_ERROR("TF of received laser scan topic at time %fs is not set, aborting rtabmap update.", scan2dMsg->header.stamp.toSec()); ROS_ERROR("TF of received laser scan topic at time %fs is not set, aborting rtabmap update.", scan2dMsg->header.stamp.toSec());
return; return;
@@ -1211,7 +1299,7 @@ void CoreWrapper::commonStereoCallback(
sensor_msgs::PointCloud2 scanOut; sensor_msgs::PointCloud2 scanOut;
laser_geometry::LaserProjection projection; laser_geometry::LaserProjection projection;
//projection.transformLaserScanToPointCloud(frameId_, *scanMsg, scanOut, tfBuffer_); //projection.transformLaserScanToPointCloud(frameId_, *scanMsg, scanOut, tfBuffer_);
projection.transformLaserScanToPointCloud(frameId_, *scan2dMsg, scanOut, tfListener_); projection.transformLaserScanToPointCloud(scan2dMsg->header.frame_id, *scan2dMsg, scanOut, tfListener_);
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(scanOut, *pclScan); pcl::fromROSMsg(scanOut, *pclScan);
@@ -1225,9 +1313,7 @@ void CoreWrapper::commonStereoCallback(
{ {
return; return;
} }
Transform t = odomT.inverse() * sensorT; scanLocalTransform = odomT.inverse() * sensorT * scanLocalTransform;
pclScan = util3d::transformPointCloud(pclScan, t);
} }
} }
@@ -1252,13 +1338,12 @@ void CoreWrapper::commonStereoCallback(
} }
// sync with odometry stamp // sync with odometry stamp
Transform localScanTransform = getTransform(frameId_, scan3dMsg->header.frame_id, scan3dMsg->header.stamp); scanLocalTransform = getTransform(frameId_, scan3dMsg->header.frame_id, scan3dMsg->header.stamp);
if(localScanTransform.isNull()) if(scanLocalTransform.isNull())
{ {
ROS_ERROR("TF of received scan cloud at time %fs is not set, aborting rtabmap update.", scan3dMsg->header.stamp.toSec()); ROS_ERROR("TF of received scan cloud at time %fs is not set, aborting rtabmap update.", scan3dMsg->header.stamp.toSec());
return; return;
} }
Transform laserOdomT = localScanTransform;
if(lastPoseStamp_ != scan3dMsg->header.stamp) if(lastPoseStamp_ != scan3dMsg->header.stamp)
{ {
if(!odomT.isNull()) if(!odomT.isNull())
@@ -1271,7 +1356,7 @@ void CoreWrapper::commonStereoCallback(
} }
else else
{ {
laserOdomT = odomT.inverse() * sensorT * localScanTransform; scanLocalTransform = odomT.inverse() * sensorT * scanLocalTransform;
} }
} }
@@ -1282,11 +1367,6 @@ void CoreWrapper::commonStereoCallback(
pcl::PointCloud<pcl::PointNormal>::Ptr pclScan(new pcl::PointCloud<pcl::PointNormal>); pcl::PointCloud<pcl::PointNormal>::Ptr pclScan(new pcl::PointCloud<pcl::PointNormal>);
pcl::fromROSMsg(*scan3dMsg, *pclScan); pcl::fromROSMsg(*scan3dMsg, *pclScan);
if(!laserOdomT.isIdentity())
{
pclScan = util3d::transformPointCloud(pclScan, laserOdomT);
}
scan = util3d::laserScanFromPointCloud(*pclScan); scan = util3d::laserScanFromPointCloud(*pclScan);
} }
else else
@@ -1294,11 +1374,6 @@ void CoreWrapper::commonStereoCallback(
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(*scan3dMsg, *pclScan); pcl::fromROSMsg(*scan3dMsg, *pclScan);
if(!laserOdomT.isIdentity())
{
pclScan = util3d::transformPointCloud(pclScan, laserOdomT);
}
if(scanCloudNormalK_ > 0) if(scanCloudNormalK_ > 0)
{ {
//compute normals //compute normals
@@ -1314,33 +1389,6 @@ void CoreWrapper::commonStereoCallback(
} }
} }
cv_bridge::CvImagePtr ptrLeftImage, ptrRightImage;
if(leftImageMsg->encoding.compare(sensor_msgs::image_encodings::MONO8) == 0 ||
leftImageMsg->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0)
{
ptrLeftImage = cv_bridge::toCvCopy(leftImageMsg, "mono8");
}
else
{
ptrLeftImage = cv_bridge::toCvCopy(leftImageMsg, "bgr8");
}
ptrRightImage = cv_bridge::toCvCopy(rightImageMsg, "mono8");
rtabmap::StereoCameraModel stereoModel = rtabmap_ros::stereoCameraModelFromROS(*leftCamInfoMsg, *rightCamInfoMsg, localTransform);
if(stereoModel.baseline() > 10.0)
{
static bool shown = false;
if(!shown)
{
ROS_WARN("Detected baseline (%f m) is quite large! Is your "
"right camera_info P(0,3) correctly set? Note that "
"baseline=-P(0,3)/P(0,0). This warning is printed only once.",
stereoModel.baseline());
shown = true;
}
}
ros::Time stamp = scan2dMsg.get() != 0?scan2dMsg->header.stamp: ros::Time stamp = scan2dMsg.get() != 0?scan2dMsg->header.stamp:
scan3dMsg.get() != 0?scan3dMsg->header.stamp: scan3dMsg.get() != 0?scan3dMsg->header.stamp:
leftImageMsg->header.stamp; leftImageMsg->header.stamp;
@@ -1352,8 +1400,10 @@ void CoreWrapper::commonStereoCallback(
} }
SensorData data(scan, SensorData data(scan,
scan2dMsg.get() != 0?(int)scan2dMsg->ranges.size():scan3dMsg.get() != 0?scanCloudMaxPoints_:0, LaserScanInfo(
scan2dMsg.get() != 0?scan2dMsg->range_max:0, scan2dMsg.get() != 0?(int)scan2dMsg->ranges.size():scan3dMsg.get() != 0?scanCloudMaxPoints_:0,
scan2dMsg.get() != 0?scan2dMsg->range_max:0,
scanLocalTransform),
ptrLeftImage->image, ptrLeftImage->image,
ptrRightImage->image, ptrRightImage->image,
stereoModel, stereoModel,
@@ -1621,9 +1671,6 @@ void CoreWrapper::process(
rtabmap_.getMemory(), rtabmap_.getMemory(),
false, false,
false, false,
false,
false,
false,
tmpSignature); tmpSignature);
timeUpdateMaps = timer.ticks(); timeUpdateMaps = timer.ticks();
@@ -1916,6 +1963,7 @@ bool CoreWrapper::updateRtabmapCallback(std_srvs::Empty::Request&, std_srvs::Emp
ROS_INFO("RTAB-Map rate detection = %f Hz", rate_); ROS_INFO("RTAB-Map rate detection = %f Hz", rate_);
} }
rtabmap_.parseParameters(parameters_); rtabmap_.parseParameters(parameters_);
mapsManager_.setParameters(parameters_);
return true; return true;
} }
@@ -2039,7 +2087,7 @@ bool CoreWrapper::setLogError(std_srvs::Empty::Request&, std_srvs::Empty::Respon
return true; return true;
} }
bool CoreWrapper::getMapCallback(rtabmap_ros::GetMap::Request& req, rtabmap_ros::GetMap::Response& res) bool CoreWrapper::getMapDataCallback(rtabmap_ros::GetMap::Request& req, rtabmap_ros::GetMap::Response& res)
{ {
ROS_INFO("rtabmap: Getting map (global=%s optimized=%s graphOnly=%s)...", ROS_INFO("rtabmap: Getting map (global=%s optimized=%s graphOnly=%s)...",
req.global?"true":"false", req.global?"true":"false",
@@ -2083,65 +2131,41 @@ bool CoreWrapper::getMapCallback(rtabmap_ros::GetMap::Request& req, rtabmap_ros:
bool CoreWrapper::getProjMapCallback(nav_msgs::GetMap::Request &req, nav_msgs::GetMap::Response &res) bool CoreWrapper::getProjMapCallback(nav_msgs::GetMap::Request &req, nav_msgs::GetMap::Response &res)
{ {
std::map<int, rtabmap::Transform> filteredPoses; if(parameters_.find(Parameters::kGridFromDepth()) != parameters_.end() &&
filteredPoses = mapsManager_.updateMapCaches( !uStr2Bool(parameters_.at(Parameters::kGridFromDepth())))
rtabmap_.getLocalOptimizedPoses(),
rtabmap_.getMemory(),
false,
true,
false,
false,
false);
if(filteredPoses.size())
{ {
// create the projection map ROS_WARN("/get_proj_map service is deprecated! Call /get_grid_map service "
float xMin=0.0f, yMin=0.0f, gridCellSize = 0.05f; "instead with <param name=\"%s\" type=\"string\" value=\"true\"/>. "
cv::Mat pixels = mapsManager_.generateProjMap(filteredPoses, xMin, yMin, gridCellSize); "Do \"$ rosrun rtabmap_ros rtabmap --params | grep Grid\" to see "
"all occupancy grid parameters.",
if(!pixels.empty()) Parameters::kGridFromDepth().c_str());
{
//init
res.map.info.resolution = gridCellSize;
res.map.info.origin.position.x = 0.0;
res.map.info.origin.position.y = 0.0;
res.map.info.origin.position.z = 0.0;
res.map.info.origin.orientation.x = 0.0;
res.map.info.origin.orientation.y = 0.0;
res.map.info.origin.orientation.z = 0.0;
res.map.info.origin.orientation.w = 1.0;
res.map.info.width = pixels.cols;
res.map.info.height = pixels.rows;
res.map.info.origin.position.x = xMin;
res.map.info.origin.position.y = yMin;
res.map.data.resize(res.map.info.width * res.map.info.height);
memcpy(res.map.data.data(), pixels.data, res.map.info.width * res.map.info.height);
res.map.header.frame_id = mapFrameId_;
res.map.header.stamp = ros::Time::now();
return true;
}
} }
return false; else
{
ROS_WARN("/get_proj_map service is deprecated! Call /get_grid_map service instead.");
}
return getGridMapCallback(req, res);
} }
bool CoreWrapper::getGridMapCallback(nav_msgs::GetMap::Request &req, nav_msgs::GetMap::Response &res) bool CoreWrapper::getGridMapCallback(nav_msgs::GetMap::Request &req, nav_msgs::GetMap::Response &res)
{
ROS_WARN("/get_grid_map service is deprecated! Call /get_map service instead.");
return getMapCallback(req, res);
}
bool CoreWrapper::getMapCallback(nav_msgs::GetMap::Request &req, nav_msgs::GetMap::Response &res)
{ {
std::map<int, rtabmap::Transform> filteredPoses; std::map<int, rtabmap::Transform> filteredPoses;
filteredPoses = mapsManager_.updateMapCaches( filteredPoses = mapsManager_.updateMapCaches(
rtabmap_.getLocalOptimizedPoses(), rtabmap_.getLocalOptimizedPoses(),
rtabmap_.getMemory(), rtabmap_.getMemory(),
false,
false,
true, true,
false,
false); false);
if(filteredPoses.size()) if(filteredPoses.size())
{ {
// create the grid map // create the grid map
float xMin=0.0f, yMin=0.0f, gridCellSize = 0.05f; float xMin=0.0f, yMin=0.0f, gridCellSize = 0.05f;
cv::Mat pixels = mapsManager_.generateProjMap(filteredPoses, xMin, yMin, gridCellSize); cv::Mat pixels = mapsManager_.generateGridMap(filteredPoses, xMin, yMin, gridCellSize);
if(!pixels.empty()) if(!pixels.empty())
{ {
@@ -2247,9 +2271,6 @@ bool CoreWrapper::publishMapCallback(rtabmap_ros::PublishMap::Request& req, rtab
rtabmap_.getMemory(), rtabmap_.getMemory(),
false, false,
false, false,
false,
false,
false,
signatures); signatures);
} }
else else
@@ -2715,7 +2736,7 @@ bool CoreWrapper::octomapBinaryCallback(
res.map.header.stamp = ros::Time::now(); res.map.header.stamp = ros::Time::now();
std::map<int, Transform> poses = rtabmap_.getLocalOptimizedPoses(); std::map<int, Transform> poses = rtabmap_.getLocalOptimizedPoses();
poses = mapsManager_.updateMapCaches(poses, rtabmap_.getMemory(), false, false, false, false, true); poses = mapsManager_.updateMapCaches(poses, rtabmap_.getMemory(), false, true);
const rtabmap::OctoMap * octomap = mapsManager_.getOctomap(); const rtabmap::OctoMap * octomap = mapsManager_.getOctomap();
bool success = octomap->octree()->size() && octomap_msgs::binaryMapToMsg(*octomap->octree(), res.map); bool success = octomap->octree()->size() && octomap_msgs::binaryMapToMsg(*octomap->octree(), res.map);
@@ -2731,7 +2752,7 @@ bool CoreWrapper::octomapFullCallback(
res.map.header.stamp = ros::Time::now(); res.map.header.stamp = ros::Time::now();
std::map<int, Transform> poses = rtabmap_.getLocalOptimizedPoses(); std::map<int, Transform> poses = rtabmap_.getLocalOptimizedPoses();
poses = mapsManager_.updateMapCaches(poses, rtabmap_.getMemory(), false, false, false, false, true); poses = mapsManager_.updateMapCaches(poses, rtabmap_.getMemory(), false, true);
const rtabmap::OctoMap * octomap = mapsManager_.getOctomap(); const rtabmap::OctoMap * octomap = mapsManager_.getOctomap();
bool success = octomap->octree()->size() && octomap_msgs::fullMapToMsg(*octomap->octree(), res.map); bool success = octomap->octree()->size() && octomap_msgs::fullMapToMsg(*octomap->octree(), res.map);
+126 -22
View File
@@ -407,9 +407,9 @@ void GuiWrapper::handleEvent(UEvent * anEvent)
getMapSrv.request.global = cmdEvent->value1().toBool(); getMapSrv.request.global = cmdEvent->value1().toBool();
getMapSrv.request.optimized = cmdEvent->value2().toBool(); getMapSrv.request.optimized = cmdEvent->value2().toBool();
getMapSrv.request.graphOnly = cmdEvent->value3().toBool(); getMapSrv.request.graphOnly = cmdEvent->value3().toBool();
if(!ros::service::call("get_map", getMapSrv)) if(!ros::service::call("get_map_data", getMapSrv))
{ {
ROS_WARN("Can't call \"get_map\" service"); ROS_WARN("Can't call \"get_map_data\" service");
this->post(new RtabmapEvent3DMap(1)); // service error this->post(new RtabmapEvent3DMap(1)); // service error
} }
else else
@@ -588,6 +588,7 @@ void GuiWrapper::commonDepthCallback(
cv::Mat depth; cv::Mat depth;
std::vector<CameraModel> cameraModels; std::vector<CameraModel> cameraModels;
cv::Mat scan; cv::Mat scan;
Transform scanLocalTransform = Transform::getIdentity();
rtabmap::OdometryInfo info; rtabmap::OdometryInfo info;
bool ignoreData = false; bool ignoreData = false;
@@ -693,15 +694,20 @@ void GuiWrapper::commonDepthCallback(
if(scan2dMsg.get() != 0) if(scan2dMsg.get() != 0)
{ {
// make sure the frame of the laser is updated too // make sure the frame of the laser is updated too
if(getTransform(frameId_, scan2dMsg->header.frame_id, scan2dMsg->header.stamp).isNull()) scanLocalTransform = getTransform(
frameId_,
scan2dMsg->header.frame_id,
scan2dMsg->header.stamp + ros::Duration().fromSec(scan2dMsg->ranges.size()*scan2dMsg->time_increment));
if(scanLocalTransform.isNull())
{ {
ROS_ERROR("TF of received scan at time %fs is not set, aborting rtabmapviz update.", scan2dMsg->header.stamp.toSec());
return; return;
} }
//transform in frameId_ frame //transform in frameId_ frame
sensor_msgs::PointCloud2 scanOut; sensor_msgs::PointCloud2 scanOut;
laser_geometry::LaserProjection projection; laser_geometry::LaserProjection projection;
projection.transformLaserScanToPointCloud(frameId_, *scan2dMsg, scanOut, tfListener_); projection.transformLaserScanToPointCloud(scan2dMsg->header.frame_id, *scan2dMsg, scanOut, tfListener_);
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(scanOut, *pclScan); pcl::fromROSMsg(scanOut, *pclScan);
@@ -715,18 +721,62 @@ void GuiWrapper::commonDepthCallback(
{ {
return; return;
} }
Transform t = odomT.inverse() * sensorT; scanLocalTransform = odomT.inverse() * sensorT * scanLocalTransform;
pclScan = util3d::transformPointCloud(pclScan, t);
} }
} }
scan = util3d::laserScanFromPointCloud(*pclScan); scan = util3d::laserScanFromPointCloud(*pclScan);
} }
else if(scan3dMsg.get() != 0) else if(scan3dMsg.get() != 0)
{ {
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>); bool containNormals = false;
pcl::fromROSMsg(*scan3dMsg, *pclScan); for(unsigned int i=0; i<scan3dMsg->fields.size(); ++i)
scan = util3d::laserScanFromPointCloud(*pclScan); {
if(scan3dMsg->fields[i].name.compare("normal_x") == 0)
{
containNormals = true;
break;
}
}
// sync with odometry stamp
scanLocalTransform = getTransform(frameId_, scan3dMsg->header.frame_id, scan3dMsg->header.stamp);
if(scanLocalTransform.isNull())
{
ROS_ERROR("TF of received scan cloud at time %fs is not set, aborting rtabmap update.", scan3dMsg->header.stamp.toSec());
return;
}
if(odomHeader.stamp != scan3dMsg->header.stamp)
{
if(!odomT.isNull())
{
Transform sensorT = getTransform(odomHeader.frame_id, frameId_, scan3dMsg->header.stamp);
if(sensorT.isNull())
{
ROS_WARN("Could not get odometry value for laser scan stamp (%fs). Latest odometry "
"stamp is %fs. The laser scan pose will not be synchronized with odometry.", scan3dMsg->header.stamp.toSec(), odomHeader.stamp.toSec());
}
else
{
scanLocalTransform = odomT.inverse() * sensorT * scanLocalTransform;
}
}
}
if(containNormals)
{
pcl::PointCloud<pcl::PointNormal>::Ptr pclScan(new pcl::PointCloud<pcl::PointNormal>);
pcl::fromROSMsg(*scan3dMsg, *pclScan);
scan = util3d::laserScanFromPointCloud(*pclScan);
}
else
{
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(*scan3dMsg, *pclScan);
scan = util3d::laserScanFromPointCloud(*pclScan);
}
} }
if(odomInfoMsg.get()) if(odomInfoMsg.get())
@@ -749,8 +799,10 @@ void GuiWrapper::commonDepthCallback(
rtabmap::OdometryEvent odomEvent( rtabmap::OdometryEvent odomEvent(
rtabmap::SensorData( rtabmap::SensorData(
scan, scan,
scan2dMsg.get()?(int)scan2dMsg->ranges.size():0, LaserScanInfo(
scan2dMsg.get()?(int)scan2dMsg->range_max:0, scan2dMsg.get()?(int)scan2dMsg->ranges.size():0,
scan2dMsg.get()?(int)scan2dMsg->range_max:0,
scanLocalTransform),
rgb, rgb,
depth, depth,
cameraModels, cameraModels,
@@ -854,6 +906,7 @@ void GuiWrapper::commonStereoCallback(
cv::Mat left; cv::Mat left;
cv::Mat right; cv::Mat right;
cv::Mat scan; cv::Mat scan;
Transform scanLocalTransform = Transform::getIdentity();
rtabmap::StereoCameraModel stereoModel; rtabmap::StereoCameraModel stereoModel;
rtabmap::OdometryInfo info; rtabmap::OdometryInfo info;
bool ignoreData = false; bool ignoreData = false;
@@ -898,15 +951,20 @@ void GuiWrapper::commonStereoCallback(
if(scan2dMsg.get() != 0) if(scan2dMsg.get() != 0)
{ {
// make sure the frame of the laser is updated too // make sure the frame of the laser is updated too
if(getTransform(frameId_, scan2dMsg->header.frame_id, scan2dMsg->header.stamp).isNull()) scanLocalTransform = getTransform(
frameId_,
scan2dMsg->header.frame_id,
scan2dMsg->header.stamp + ros::Duration().fromSec(scan2dMsg->ranges.size()*scan2dMsg->time_increment));
if(scanLocalTransform.isNull())
{ {
ROS_ERROR("TF of received scan at time %fs is not set, aborting rtabmapviz update.", scan2dMsg->header.stamp.toSec());
return; return;
} }
//transform in frameId_ frame //transform in frameId_ frame
sensor_msgs::PointCloud2 scanOut; sensor_msgs::PointCloud2 scanOut;
laser_geometry::LaserProjection projection; laser_geometry::LaserProjection projection;
projection.transformLaserScanToPointCloud(frameId_, *scan2dMsg, scanOut, tfListener_); projection.transformLaserScanToPointCloud(scan2dMsg->header.frame_id, *scan2dMsg, scanOut, tfListener_);
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(scanOut, *pclScan); pcl::fromROSMsg(scanOut, *pclScan);
@@ -920,18 +978,62 @@ void GuiWrapper::commonStereoCallback(
{ {
return; return;
} }
Transform t = odomT.inverse() * sensorT; scanLocalTransform = odomT.inverse() * sensorT * scanLocalTransform;
pclScan = util3d::transformPointCloud(pclScan, t);
} }
} }
scan = util3d::laserScan2dFromPointCloud(*pclScan); scan = util3d::laserScan2dFromPointCloud(*pclScan);
} }
else if(scan3dMsg.get() != 0) else if(scan3dMsg.get() != 0)
{ {
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>); bool containNormals = false;
pcl::fromROSMsg(*scan3dMsg, *pclScan); for(unsigned int i=0; i<scan3dMsg->fields.size(); ++i)
scan = util3d::laserScanFromPointCloud(*pclScan); {
if(scan3dMsg->fields[i].name.compare("normal_x") == 0)
{
containNormals = true;
break;
}
}
// sync with odometry stamp
scanLocalTransform = getTransform(frameId_, scan3dMsg->header.frame_id, scan3dMsg->header.stamp);
if(scanLocalTransform.isNull())
{
ROS_ERROR("TF of received scan cloud at time %fs is not set, aborting rtabmap update.", scan3dMsg->header.stamp.toSec());
return;
}
if(odomHeader.stamp != scan3dMsg->header.stamp)
{
if(!odomT.isNull())
{
Transform sensorT = getTransform(odomHeader.frame_id, frameId_, scan3dMsg->header.stamp);
if(sensorT.isNull())
{
ROS_WARN("Could not get odometry value for laser scan stamp (%fs). Latest odometry "
"stamp is %fs. The laser scan pose will not be synchronized with odometry.", scan3dMsg->header.stamp.toSec(), odomHeader.stamp.toSec());
}
else
{
scanLocalTransform = odomT.inverse() * sensorT * scanLocalTransform;
}
}
}
if(containNormals)
{
pcl::PointCloud<pcl::PointNormal>::Ptr pclScan(new pcl::PointCloud<pcl::PointNormal>);
pcl::fromROSMsg(*scan3dMsg, *pclScan);
scan = util3d::laserScanFromPointCloud(*pclScan);
}
else
{
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(*scan3dMsg, *pclScan);
scan = util3d::laserScanFromPointCloud(*pclScan);
}
} }
if(odomInfoMsg.get()) if(odomInfoMsg.get())
@@ -954,8 +1056,10 @@ void GuiWrapper::commonStereoCallback(
rtabmap::OdometryEvent odomEvent( rtabmap::OdometryEvent odomEvent(
rtabmap::SensorData( rtabmap::SensorData(
scan, scan,
scan2dMsg.get()?(int)scan2dMsg->ranges.size():0, LaserScanInfo(
scan2dMsg.get()?(int)scan2dMsg->range_max:0, scan2dMsg.get()?(int)scan2dMsg->ranges.size():0,
scan2dMsg.get()?(int)scan2dMsg->range_max:0,
scanLocalTransform),
left, left,
right, right,
stereoModel, stereoModel,
-3
View File
@@ -99,9 +99,6 @@ public:
0, 0,
false, false,
false, false,
false,
false,
false,
nodes_); nodes_);
mapsManager_.publishMaps(poses, msg->header.stamp, msg->header.frame_id); mapsManager_.publishMaps(poses, msg->header.stamp, msg->header.frame_id);
+392 -645
View File
File diff suppressed because it is too large Load Diff
+59 -24
View File
@@ -332,16 +332,42 @@ rtabmap::CameraModel cameraModelFromROS(
const sensor_msgs::CameraInfo & camInfo, const sensor_msgs::CameraInfo & camInfo,
const rtabmap::Transform & localTransform) const rtabmap::Transform & localTransform)
{ {
image_geometry::PinholeCameraModel model; cv::Mat D;
model.fromCameraInfo(camInfo); if(camInfo.D.size())
{
D = cv::Mat(1, camInfo.D.size(), CV_64FC1);
memcpy(D.data, camInfo.D.data(), D.cols*sizeof(double));
}
cv:: Mat K;
UASSERT(camInfo.K.empty() || camInfo.K.size() == 9);
if(!camInfo.K.empty())
{
K = cv::Mat(3, 3, CV_64FC1);
memcpy(K.data, camInfo.K.elems, 9*sizeof(double));
}
cv:: Mat R;
UASSERT(camInfo.R.empty() || camInfo.R.size() == 9);
if(!camInfo.R.empty())
{
R = cv::Mat(3, 3, CV_64FC1);
memcpy(R.data, camInfo.R.elems, 9*sizeof(double));
}
cv:: Mat P;
UASSERT(camInfo.P.empty() || camInfo.P.size() == 12);
if(!camInfo.P.empty())
{
P = cv::Mat(3, 4, CV_64FC1);
memcpy(P.data, camInfo.P.elems, 12*sizeof(double));
}
return rtabmap::CameraModel( return rtabmap::CameraModel(
model.fx(), "ros",
model.fy(), cv::Size(camInfo.width, camInfo.height),
model.cx(), K, D, R, P,
model.cy(), localTransform);
localTransform,
0.0,
cv::Size(model.fullResolution().width, model.fullResolution().height));
} }
void cameraModelToROS( void cameraModelToROS(
const rtabmap::CameraModel & model, const rtabmap::CameraModel & model,
@@ -401,16 +427,11 @@ rtabmap::StereoCameraModel stereoCameraModelFromROS(
const sensor_msgs::CameraInfo & rightCamInfo, const sensor_msgs::CameraInfo & rightCamInfo,
const rtabmap::Transform & localTransform) const rtabmap::Transform & localTransform)
{ {
image_geometry::StereoCameraModel model;
model.fromCameraInfo(leftCamInfo, rightCamInfo);
return rtabmap::StereoCameraModel( return rtabmap::StereoCameraModel(
model.left().fx(), "ros",
model.left().fy(), cameraModelFromROS(leftCamInfo, localTransform),
model.left().cx(), cameraModelFromROS(rightCamInfo, localTransform),
model.left().cy(), rtabmap::Transform());
model.baseline(),
localTransform,
cv::Size(model.left().fullResolution().width, model.left().fullResolution().height));
} }
void mapDataFromROS( void mapDataFromROS(
@@ -587,8 +608,10 @@ rtabmap::Signature nodeDataFromROS(const rtabmap_ros::NodeData & msg)
stereoModel.isValidForProjection()? stereoModel.isValidForProjection()?
rtabmap::SensorData( rtabmap::SensorData(
compressedMatFromBytes(msg.laserScan), compressedMatFromBytes(msg.laserScan),
msg.laserScanMaxPts, rtabmap::LaserScanInfo(
msg.laserScanMaxRange, msg.laserScanMaxPts,
msg.laserScanMaxRange,
transformFromGeometryMsg(msg.laserScanLocalTransform)),
compressedMatFromBytes(msg.image), compressedMatFromBytes(msg.image),
compressedMatFromBytes(msg.depth), compressedMatFromBytes(msg.depth),
stereoModel, stereoModel,
@@ -597,8 +620,10 @@ rtabmap::Signature nodeDataFromROS(const rtabmap_ros::NodeData & msg)
compressedMatFromBytes(msg.userData)): compressedMatFromBytes(msg.userData)):
rtabmap::SensorData( rtabmap::SensorData(
compressedMatFromBytes(msg.laserScan), compressedMatFromBytes(msg.laserScan),
msg.laserScanMaxPts, rtabmap::LaserScanInfo(
msg.laserScanMaxRange, msg.laserScanMaxPts,
msg.laserScanMaxRange,
transformFromGeometryMsg(msg.laserScanLocalTransform)),
compressedMatFromBytes(msg.image), compressedMatFromBytes(msg.image),
compressedMatFromBytes(msg.depth), compressedMatFromBytes(msg.depth),
models, models,
@@ -608,6 +633,11 @@ rtabmap::Signature nodeDataFromROS(const rtabmap_ros::NodeData & msg)
s.setWords(words); s.setWords(words);
s.setWords3(words3D); s.setWords3(words3D);
s.setWordsDescriptors(wordsDescriptors); s.setWordsDescriptors(wordsDescriptors);
s.sensorData().setOccupancyGrid(
compressedMatFromBytes(msg.grid_ground),
compressedMatFromBytes(msg.grid_obstacles),
msg.grid_cell_size,
point3fFromROS(msg.grid_view_point));
return s; return s;
} }
void nodeDataToROS(const rtabmap::Signature & signature, rtabmap_ros::NodeData & msg) void nodeDataToROS(const rtabmap::Signature & signature, rtabmap_ros::NodeData & msg)
@@ -624,8 +654,13 @@ void nodeDataToROS(const rtabmap::Signature & signature, rtabmap_ros::NodeData &
compressedMatToBytes(signature.sensorData().depthOrRightCompressed(), msg.depth); compressedMatToBytes(signature.sensorData().depthOrRightCompressed(), msg.depth);
compressedMatToBytes(signature.sensorData().laserScanCompressed(), msg.laserScan); compressedMatToBytes(signature.sensorData().laserScanCompressed(), msg.laserScan);
compressedMatToBytes(signature.sensorData().userDataCompressed(), msg.userData); compressedMatToBytes(signature.sensorData().userDataCompressed(), msg.userData);
msg.laserScanMaxPts = signature.sensorData().laserScanMaxPts(); compressedMatToBytes(signature.sensorData().gridGroundCellsCompressed(), msg.grid_ground);
msg.laserScanMaxRange = signature.sensorData().laserScanMaxRange(); compressedMatToBytes(signature.sensorData().gridObstacleCellsCompressed(), msg.grid_obstacles);
point3fToROS(signature.sensorData().gridViewPoint(), msg.grid_view_point);
msg.grid_cell_size = signature.sensorData().gridCellSize();
msg.laserScanMaxPts = signature.sensorData().laserScanInfo().maxPoints();
msg.laserScanMaxRange = signature.sensorData().laserScanInfo().maxRange();
transformToGeometryMsg(signature.sensorData().laserScanInfo().localTransform(), msg.laserScanLocalTransform);
msg.baseline = 0; msg.baseline = 0;
if(signature.sensorData().cameraModels().size()) if(signature.sensorData().cameraModels().size())
{ {
+6 -16
View File
@@ -93,9 +93,10 @@ private:
void callbackScan(const sensor_msgs::LaserScanConstPtr& scanMsg) void callbackScan(const sensor_msgs::LaserScanConstPtr& scanMsg)
{ {
// make sure the frame of the laser is updated too // make sure the frame of the laser is updated too
if(getTransform(this->frameId(), Transform localScanTransform = getTransform(this->frameId(),
scanMsg->header.frame_id, scanMsg->header.frame_id,
scanMsg->header.stamp + ros::Duration().fromSec(scanMsg->ranges.size()*scanMsg->time_increment)).isNull()) scanMsg->header.stamp + ros::Duration().fromSec(scanMsg->ranges.size()*scanMsg->time_increment));
if(localScanTransform.isNull())
{ {
ROS_ERROR("TF of received laser scan topic at time %fs is not set, aborting odometry update.", scanMsg->header.stamp.toSec()); ROS_ERROR("TF of received laser scan topic at time %fs is not set, aborting odometry update.", scanMsg->header.stamp.toSec());
return; return;
@@ -104,7 +105,7 @@ private:
//transform in frameId_ frame //transform in frameId_ frame
sensor_msgs::PointCloud2 scanOut; sensor_msgs::PointCloud2 scanOut;
laser_geometry::LaserProjection projection; laser_geometry::LaserProjection projection;
projection.transformLaserScanToPointCloud(this->frameId(), *scanMsg, scanOut, this->tfListener()); projection.transformLaserScanToPointCloud(scanMsg->header.frame_id, *scanMsg, scanOut, this->tfListener());
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(scanOut, *pclScan); pcl::fromROSMsg(scanOut, *pclScan);
@@ -112,8 +113,7 @@ private:
rtabmap::SensorData data( rtabmap::SensorData data(
scan, scan,
(int)scanMsg->ranges.size(), LaserScanInfo((int)scanMsg->ranges.size(), scanMsg->range_max, localScanTransform),
scanMsg->range_max,
cv::Mat(), cv::Mat(),
cv::Mat(), cv::Mat(),
CameraModel(), CameraModel(),
@@ -147,10 +147,6 @@ private:
{ {
pcl::PointCloud<pcl::PointNormal>::Ptr pclScan(new pcl::PointCloud<pcl::PointNormal>); pcl::PointCloud<pcl::PointNormal>::Ptr pclScan(new pcl::PointCloud<pcl::PointNormal>);
pcl::fromROSMsg(*cloudMsg, *pclScan); pcl::fromROSMsg(*cloudMsg, *pclScan);
if(!localScanTransform.isIdentity())
{
pclScan = util3d::transformPointCloud(pclScan, localScanTransform);
}
scan = util3d::laserScanFromPointCloud(*pclScan); scan = util3d::laserScanFromPointCloud(*pclScan);
} }
else else
@@ -158,11 +154,6 @@ private:
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(*cloudMsg, *pclScan); pcl::fromROSMsg(*cloudMsg, *pclScan);
if(!localScanTransform.isIdentity())
{
pclScan = util3d::transformPointCloud(pclScan, localScanTransform);
}
if(scanCloudNormalK_ > 0) if(scanCloudNormalK_ > 0)
{ {
//compute normals //compute normals
@@ -179,8 +170,7 @@ private:
rtabmap::SensorData data( rtabmap::SensorData data(
scan, scan,
scanCloudMaxPoints_, LaserScanInfo(scanCloudMaxPoints_, 0, localScanTransform),
0,
cv::Mat(), cv::Mat(),
cv::Mat(), cv::Mat(),
CameraModel(), CameraModel(),
+10 -15
View File
@@ -266,12 +266,14 @@ private:
cv_bridge::CvImagePtr ptrDepth = cv_bridge::toCvCopy(depth); cv_bridge::CvImagePtr ptrDepth = cv_bridge::toCvCopy(depth);
cv::Mat scan; cv::Mat scan;
Transform localScanTransform = Transform::getIdentity();
if(scanMsg.get() != 0) if(scanMsg.get() != 0)
{ {
// make sure the frame of the laser is updated too // make sure the frame of the laser is updated too
if(getTransform(this->frameId(), localScanTransform = getTransform(this->frameId(),
scanMsg->header.frame_id, scanMsg->header.frame_id,
scanMsg->header.stamp + ros::Duration().fromSec(scanMsg->ranges.size()*scanMsg->time_increment)).isNull()) scanMsg->header.stamp + ros::Duration().fromSec(scanMsg->ranges.size()*scanMsg->time_increment));
if(localScanTransform.isNull())
{ {
ROS_ERROR("TF of received laser scan topic at time %fs is not set, aborting odometry update.", scanMsg->header.stamp.toSec()); ROS_ERROR("TF of received laser scan topic at time %fs is not set, aborting odometry update.", scanMsg->header.stamp.toSec());
return; return;
@@ -280,7 +282,7 @@ private:
//transform in frameId_ frame //transform in frameId_ frame
sensor_msgs::PointCloud2 scanOut; sensor_msgs::PointCloud2 scanOut;
laser_geometry::LaserProjection projection; laser_geometry::LaserProjection projection;
projection.transformLaserScanToPointCloud(this->frameId(), *scanMsg, scanOut, this->tfListener()); projection.transformLaserScanToPointCloud(scanMsg->header.frame_id, *scanMsg, scanOut, this->tfListener());
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(scanOut, *pclScan); pcl::fromROSMsg(scanOut, *pclScan);
@@ -297,7 +299,7 @@ private:
break; break;
} }
} }
Transform localScanTransform = getTransform(this->frameId(), cloudMsg->header.frame_id, cloudMsg->header.stamp); localScanTransform = getTransform(this->frameId(), cloudMsg->header.frame_id, cloudMsg->header.stamp);
if(localScanTransform.isNull()) if(localScanTransform.isNull())
{ {
ROS_ERROR("TF of received scan cloud at time %fs is not set, aborting rtabmap update.", cloudMsg->header.stamp.toSec()); ROS_ERROR("TF of received scan cloud at time %fs is not set, aborting rtabmap update.", cloudMsg->header.stamp.toSec());
@@ -308,10 +310,6 @@ private:
{ {
pcl::PointCloud<pcl::PointNormal>::Ptr pclScan(new pcl::PointCloud<pcl::PointNormal>); pcl::PointCloud<pcl::PointNormal>::Ptr pclScan(new pcl::PointCloud<pcl::PointNormal>);
pcl::fromROSMsg(*cloudMsg, *pclScan); pcl::fromROSMsg(*cloudMsg, *pclScan);
if(!localScanTransform.isIdentity())
{
pclScan = util3d::transformPointCloud(pclScan, localScanTransform);
}
scan = util3d::laserScanFromPointCloud(*pclScan); scan = util3d::laserScanFromPointCloud(*pclScan);
} }
else else
@@ -319,11 +317,6 @@ private:
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(*cloudMsg, *pclScan); pcl::fromROSMsg(*cloudMsg, *pclScan);
if(!localScanTransform.isIdentity())
{
pclScan = util3d::transformPointCloud(pclScan, localScanTransform);
}
if(scanCloudNormalK_ > 0) if(scanCloudNormalK_ > 0)
{ {
//compute normals //compute normals
@@ -341,8 +334,10 @@ private:
rtabmap::SensorData data( rtabmap::SensorData data(
scan, scan,
scanMsg.get() != 0?(int)scanMsg->ranges.size():cloudMsg.get() != 0?scanCloudMaxPoints_:0, LaserScanInfo(
scanMsg.get() != 0?scanMsg->range_max:0, scanMsg.get() != 0?(int)scanMsg->ranges.size():cloudMsg.get() != 0?scanCloudMaxPoints_:0,
scanMsg.get() != 0?scanMsg->range_max:0,
localScanTransform),
ptrImage->image, ptrImage->image,
ptrDepth->image, ptrDepth->image,
rtabmapModel, rtabmapModel,