35 #include <sensor_msgs/LaserScan.h> 36 #include <sensor_msgs/PointCloud2.h> 60 scanCloudMaxPoints_(0),
61 scanDownsamplingStep_(1),
64 scanNormalRadius_(0.0)
79 pnh.
param(
"scan_cloud_max_points", scanCloudMaxPoints_, scanCloudMaxPoints_);
80 pnh.
param(
"scan_downsampling_step", scanDownsamplingStep_, scanDownsamplingStep_);
81 pnh.
param(
"scan_voxel_size", scanVoxelSize_, scanVoxelSize_);
82 pnh.
param(
"scan_normal_k", scanNormalK_, scanNormalK_);
85 ROS_WARN(
"rtabmap: Parameter \"scan_cloud_normal_k\" has been renamed to \"scan_normal_k\". " 86 "The value is still used. Use \"scan_normal_k\" to avoid this warning.");
87 pnh.
param(
"scan_cloud_normal_k", scanNormalK_, scanNormalK_);
89 pnh.
param(
"scan_normal_radius", scanNormalRadius_, scanNormalRadius_);
91 NODELET_INFO(
"IcpOdometry: scan_cloud_max_points = %d", scanCloudMaxPoints_);
92 NODELET_INFO(
"IcpOdometry: scan_downsampling_step = %d", scanDownsamplingStep_);
93 NODELET_INFO(
"IcpOdometry: scan_voxel_size = %f", scanVoxelSize_);
94 NODELET_INFO(
"IcpOdometry: scan_normal_k = %d", scanNormalK_);
95 NODELET_INFO(
"IcpOdometry: scan_normal_radius = %f", scanNormalRadius_);
97 scan_sub_ = nh.
subscribe(
"scan", 1, &ICPOdometry::callbackScan,
this);
98 cloud_sub_ = nh.
subscribe(
"scan_cloud", 1, &ICPOdometry::callbackCloud,
this);
104 ParametersMap::iterator iter = parameters.find(Parameters::kRegStrategy());
105 if(iter != parameters.end() && iter->second.compare(
"1") != 0)
107 ROS_WARN(
"ICP odometry works only with \"Reg/Strategy\"=1. Ignoring value %s.", iter->second.c_str());
112 iter = parameters.find(Parameters::kIcpDownsamplingStep());
113 if(iter != parameters.end())
118 if(!pnh.
hasParam(
"scan_downsampling_step"))
120 ROS_WARN(
"IcpOdometry: Transferring value %s of \"%s\" to ros parameter \"scan_downsampling_step\" for convenience. \"%s\" is set to 0.", iter->second.c_str(), iter->first.c_str(), iter->first.c_str());
121 scanDownsamplingStep_ = value;
126 ROS_WARN(
"IcpOdometry: Both parameter \"%s\" and ros parameter \"scan_downsampling_step\" are set.", iter->first.c_str());
130 iter = parameters.find(Parameters::kIcpVoxelSize());
131 if(iter != parameters.end())
136 if(!pnh.
hasParam(
"scan_voxel_size"))
138 ROS_WARN(
"IcpOdometry: Transferring value %s of \"%s\" to ros parameter \"scan_voxel_size\" for convenience. \"%s\" is set to 0.", iter->second.c_str(), iter->first.c_str(), iter->first.c_str());
139 scanVoxelSize_ = value;
144 ROS_WARN(
"IcpOdometry: Both parameter \"%s\" and ros parameter \"scan_voxel_size\" are set.", iter->first.c_str());
148 iter = parameters.find(Parameters::kIcpPointToPlaneK());
149 if(iter != parameters.end())
156 ROS_WARN(
"IcpOdometry: Transferring value %s of \"%s\" to ros parameter \"scan_normal_k\" for convenience.", iter->second.c_str(), iter->first.c_str());
157 scanNormalK_ = value;
161 iter = parameters.find(Parameters::kIcpPointToPlaneRadius());
162 if(iter != parameters.end())
167 if(!pnh.
hasParam(
"scan_normal_radius"))
169 ROS_WARN(
"IcpOdometry: Transferring value %s of \"%s\" to ros parameter \"scan_normal_radius\" for convenience.", iter->second.c_str(), iter->first.c_str());
170 scanNormalRadius_ = value;
180 scanMsg->header.frame_id,
181 scanMsg->header.stamp +
ros::Duration().
fromSec(scanMsg->ranges.size()*scanMsg->time_increment));
182 if(localScanTransform.
isNull())
184 ROS_ERROR(
"TF of received laser scan topic at time %fs is not set, aborting odometry update.", scanMsg->header.stamp.toSec());
189 sensor_msgs::PointCloud2 scanOut;
192 pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(
new pcl::PointCloud<pcl::PointXYZ>);
194 pclScan->is_dense =
true;
197 int maxLaserScans = (int)scanMsg->ranges.size();
200 if(scanDownsamplingStep_ > 1)
203 maxLaserScans /= scanDownsamplingStep_;
205 if(scanVoxelSize_ > 0.0
f)
207 float pointsBeforeFiltering = (float)pclScan->size();
209 float ratio = float(pclScan->size()) / pointsBeforeFiltering;
210 maxLaserScans = int(
float(maxLaserScans) * ratio);
212 if(scanNormalK_ > 0 || scanNormalRadius_>0.0
f)
215 pcl::PointCloud<pcl::Normal>::Ptr normals;
216 if(scanVoxelSize_ > 0.0
f)
224 pcl::PointCloud<pcl::PointNormal>::Ptr pclScanNormal(
new pcl::PointCloud<pcl::PointNormal>);
225 pcl::concatenateFields(*pclScan, *normals, *pclScanNormal);
242 this->processData(data, scanMsg->header.
stamp);
248 bool containNormals =
false;
249 if(scanVoxelSize_ == 0.0
f)
251 for(
unsigned int i=0; i<cloudMsg->fields.size(); ++i)
253 if(cloudMsg->fields[i].name.compare(
"normal_x") == 0)
255 containNormals =
true;
261 Transform localScanTransform =
getTransform(this->frameId(), cloudMsg->header.frame_id, cloudMsg->header.stamp);
262 if(localScanTransform.
isNull())
264 ROS_ERROR(
"TF of received scan cloud at time %fs is not set, aborting rtabmap update.", cloudMsg->header.stamp.toSec());
268 int maxLaserScans = scanCloudMaxPoints_;
271 pcl::PointCloud<pcl::PointNormal>::Ptr pclScan(
new pcl::PointCloud<pcl::PointNormal>);
273 if(pclScan->size() && scanDownsamplingStep_ > 1)
276 maxLaserScans /= scanDownsamplingStep_;
282 pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(
new pcl::PointCloud<pcl::PointXYZ>);
284 if(pclScan->size() && scanDownsamplingStep_ > 1)
287 maxLaserScans /= scanDownsamplingStep_;
289 if(!pclScan->is_dense)
296 if(scanVoxelSize_ > 0.0
f)
298 float pointsBeforeFiltering = (float)pclScan->size();
300 float ratio = float(pclScan->size()) / pointsBeforeFiltering;
301 maxLaserScans = int(
float(maxLaserScans) * ratio);
303 if(scanNormalK_ > 0 || scanNormalRadius_>0.0
f)
306 pcl::PointCloud<pcl::Normal>::Ptr normals =
util3d::computeNormals(pclScan, scanNormalK_, scanNormalRadius_);
307 pcl::PointCloud<pcl::PointNormal>::Ptr pclScanNormal(
new pcl::PointCloud<pcl::PointNormal>);
308 pcl::concatenateFields(*pclScan, *normals, *pclScanNormal);
326 this->processData(data, cloudMsg->header.
stamp);
LaserScan RTABMAP_EXP laserScanFromPointCloud(const pcl::PCLPointCloud2 &cloud, bool filterNaNs=true)
virtual void flushCallbacks()
pcl::PointCloud< pcl::Normal >::Ptr RTABMAP_EXP computeNormals2D(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, int searchK=5, float searchRadius=0.0f, const Eigen::Vector3f &viewPoint=Eigen::Vector3f(0, 0, 0))
int scanDownsamplingStep_
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
std::pair< std::string, std::string > ParametersPair
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_EXP removeNaNFromPointCloud(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud)
ros::Subscriber scan_sub_
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
rtabmap::Transform getTransform(const std::string &fromFrameId, const std::string &toFrameId, const ros::Time &stamp, tf::TransformListener &listener, double waitForTransform)
ros::Subscriber cloud_sub_
pcl::PointCloud< pcl::Normal >::Ptr RTABMAP_EXP computeFastOrganizedNormals2D(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, int searchK=5, float searchRadius=0.0f, const Eigen::Vector3f &viewPoint=Eigen::Vector3f(0, 0, 0))
void callbackScan(const sensor_msgs::LaserScanConstPtr &scanMsg)
LaserScan RTABMAP_EXP downsample(const LaserScan &cloud, int step)
cv::Mat RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud< pcl::PointXYZ > &cloud, const Transform &transform=Transform(), bool filterNaNs=true)
PLUGINLIB_EXPORT_CLASS(rtabmap_ros::ICPOdometry, nodelet::Nodelet)
int uStr2Int(const std::string &str)
void callbackCloud(const sensor_msgs::PointCloud2ConstPtr &cloudMsg)
Duration & fromSec(double t)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
cv::Mat RTABMAP_EXP computeNormals(const cv::Mat &laserScan, int searchK, float searchRadius)
QMap< QString, QVariant > ParametersMap
virtual void onOdomInit()
#define NODELET_INFO(...)
virtual void updateParameters(ParametersMap ¶meters)
double timestampFromROS(const ros::Time &stamp)
float uStr2Float(const std::string &str)
void transformLaserScanToPointCloud(const std::string &target_frame, const sensor_msgs::LaserScan &scan_in, sensor_msgs::PointCloud &cloud_out, tf::Transformer &tf, double range_cutoff, int channel_options=channel_option::Default)
bool hasParam(const std::string &key) const
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_EXP voxelize(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const pcl::IndicesPtr &indices, float voxelSize)
static LaserScan backwardCompatibility(const cv::Mat &oldScanFormat, int maxPoints=0, int maxRange=0, const Transform &localTransform=Transform::getIdentity())
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)