Merge branch 'master' of https://github.com/introlab/rtabmap_ros into kinetic-devel

This commit is contained in:
matlabbe
2017-01-07 13:58:42 -05:00
65 changed files with 7275 additions and 5005 deletions
+46
View File
@@ -0,0 +1,46 @@
sudo: true
dist: trusty
language: cpp
compiler:
- gcc
- clang
addons:
apt:
packages:
- cmake
- libopencv-dev
- libqt4-dev
- libsqlite3-dev
install:
- sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu trusty main" > /etc/apt/sources.list.d/ros-latest.list'
- wget http://packages.ros.org/ros.key -O - | sudo apt-key add -
- sudo apt-get update
- sudo apt-get -y install ros-indigo-ros-base libpcl-1.7-all libfreenect-dev ros-indigo-libg2o ros-indigo-octomap libopenni2-dev ros-indigo-costmap-2d ros-indigo-octomap-ros ros-indigo-rviz ros-indigo-cv-bridge ros-indigo-move-base-msgs ros-indigo-costmap-2d ros-indigo-image-geometry ros-indigo-message-filters ros-indigo-image-transport ros-indigo-eigen-conversions ros-indigo-stereo-msgs ros-indigo-nav-msgs ros-indigo-sensor-msgs ros-indigo-tf-conversions ros-indigo-laser-geometry ros-indigo-pcl-conversions ros-indigo-pcl-ros ros-indigo-dynamic-reconfigure ros-indigo-nodelet
script:
- source /opt/ros/indigo/setup.bash
- export PYTHONPATH=$PYTHONPATH:/usr/lib/python2.7/dist-packages
- cd ..
- mkdir -p catkin_ws/src
- cd catkin_ws/src
- catkin_init_workspace
- cd ..
- catkin_make
- cd ..
- mv rtabmap_ros catkin_ws/src/.
- git clone https://github.com/introlab/rtabmap.git
- cd rtabmap
- mkdir -p build && cd build
- cmake -DCMAKE_INSTALL_PREFIX=~/build/introlab/catkin_ws/devel ..
- make
- make install
- cd ../../catkin_ws
- source devel/setup.bash
- catkin_make
notifications:
email:
- [email protected]
+26 -4
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.8 REQUIRED) find_package(RTABMap 0.11.13 REQUIRED)
find_package(OpenCV REQUIRED) find_package(OpenCV REQUIRED)
@@ -72,6 +72,8 @@ add_message_files(
Point2f.msg Point2f.msg
Point3f.msg Point3f.msg
Goal.msg Goal.msg
RGBDImage.msg
UserData.msg
) )
## Generate services in the 'srv' folder ## Generate services in the 'srv' folder
@@ -151,6 +153,8 @@ SET(Libraries
SET(rtabmap_ros_lib_src SET(rtabmap_ros_lib_src
src/nodelets/rgbd_odometry.cpp src/nodelets/rgbd_odometry.cpp
src/nodelets/stereo_odometry.cpp src/nodelets/stereo_odometry.cpp
src/nodelets/rgbdicp_odometry.cpp
src/nodelets/icp_odometry.cpp
src/nodelets/data_throttle.cpp src/nodelets/data_throttle.cpp
src/nodelets/stereo_throttle.cpp src/nodelets/stereo_throttle.cpp
src/nodelets/data_odom_sync.cpp src/nodelets/data_odom_sync.cpp
@@ -158,10 +162,19 @@ SET(rtabmap_ros_lib_src
src/nodelets/point_cloud_xyz.cpp src/nodelets/point_cloud_xyz.cpp
src/nodelets/disparity_to_depth.cpp src/nodelets/disparity_to_depth.cpp
src/nodelets/obstacles_detection.cpp src/nodelets/obstacles_detection.cpp
src/nodelets/obstacles_detection_old.cpp
src/nodelets/point_cloud_aggregator.cpp src/nodelets/point_cloud_aggregator.cpp
src/nodelets/OdometryROS.cpp src/nodelets/undistort_depth.cpp
src/nodelets/rgbd_sync.cpp
src/OdometryROS.cpp
src/MsgConversion.cpp src/MsgConversion.cpp
src/MapsManager.cpp src/MapsManager.cpp
src/CommonDataSubscriber.cpp
src/CoreWrapper.cpp
src/impl/CommonDataSubscriberDepth.cpp
src/impl/CommonDataSubscriberStereo.cpp
src/impl/CommonDataSubscriberRGBD.cpp
src/impl/CommonDataSubscriberRGBD2.cpp
) )
# If costmap_2d is found, add the plugin # If costmap_2d is found, add the plugin
@@ -259,8 +272,8 @@ IF(Qt5_FOUND)
ENDIF(Qt5_FOUND) ENDIF(Qt5_FOUND)
add_dependencies(rtabmap_ros ${${PROJECT_NAME}_EXPORTED_TARGETS}) add_dependencies(rtabmap_ros ${${PROJECT_NAME}_EXPORTED_TARGETS})
add_executable(rtabmap src/CoreNode.cpp src/CoreWrapper.cpp) add_executable(rtabmap src/CoreNode.cpp)
target_link_libraries(rtabmap rtabmap_ros ${Libraries}) target_link_libraries(rtabmap ${Libraries})
add_executable(rgbd_odometry src/RGBDOdometryNode.cpp) add_executable(rgbd_odometry src/RGBDOdometryNode.cpp)
target_link_libraries(rgbd_odometry ${Libraries}) target_link_libraries(rgbd_odometry ${Libraries})
@@ -268,6 +281,12 @@ target_link_libraries(rgbd_odometry ${Libraries})
add_executable(stereo_odometry src/StereoOdometryNode.cpp) add_executable(stereo_odometry src/StereoOdometryNode.cpp)
target_link_libraries(stereo_odometry ${Libraries}) target_link_libraries(stereo_odometry ${Libraries})
add_executable(rgbdicp_odometry src/RGBDICPOdometryNode.cpp)
target_link_libraries(rgbdicp_odometry ${Libraries})
add_executable(icp_odometry src/ICPOdometryNode.cpp)
target_link_libraries(icp_odometry ${Libraries})
add_executable(map_optimizer src/MapOptimizerNode.cpp) add_executable(map_optimizer src/MapOptimizerNode.cpp)
target_link_libraries(map_optimizer rtabmap_ros ${Libraries}) target_link_libraries(map_optimizer rtabmap_ros ${Libraries})
@@ -318,6 +337,7 @@ install(TARGETS
rtabmap rtabmap
rtabmapviz rtabmapviz
rgbd_odometry rgbd_odometry
rgbdicp_odometry
stereo_odometry stereo_odometry
map_assembler map_assembler
map_optimizer map_optimizer
@@ -332,6 +352,7 @@ install(TARGETS
rtabmap_ros rtabmap_ros
rtabmap rtabmap
rgbd_odometry rgbd_odometry
rgbdicp_odometry
stereo_odometry stereo_odometry
map_assembler map_assembler
map_optimizer map_optimizer
@@ -392,3 +413,4 @@ ENDIF(costmap_2d_FOUND)
## Add folders to be run by python nosetests ## Add folders to be run by python nosetests
# catkin_add_nosetests(test) # catkin_add_nosetests(test)
+4 -3
View File
@@ -1,4 +1,4 @@
rtabmap_ros rtabmap_ros [![Build Status](https://travis-ci.org/introlab/rtabmap_ros.svg?branch=master)](https://travis-ci.org/introlab/rtabmap_ros)
=========== ===========
RTAB-Map's ROS package. RTAB-Map's ROS package.
@@ -35,7 +35,7 @@ $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/ros/kinetic/lib/x86_64-linux-gnu
``` ```
### Build from source ### Build from source
This section shows how to install RTAB-Map ros-pkg on **ROS Hydro/Indigo/Jade/Kinetic** (Catkin build). RTAB-Map works only with the PCL 1.7, which is the default version installed with ROS Hydro/Indigo/Jade/Kinetic (**Fuerte and Groovy are not supported**). This section shows how to install RTAB-Map ros-pkg on **ROS Hydro/Indigo/Jade/Kinetic** (Catkin build). RTAB-Map works only with the PCL >=1.7, which is the default version installed with ROS Hydro/Indigo/Jade/Kinetic (**Fuerte and Groovy are not supported**).
* The next instructions assume that you have set up your ROS workspace using this [tutorial](http://wiki.ros.org/catkin/Tutorials/create_a_workspace). I will use kinetic prefix for convenience, but it should work with Hydro, Indigo and Jade. The workspace path is `~/catkin_ws` and your `~/.bashrc` contains: * The next instructions assume that you have set up your ROS workspace using this [tutorial](http://wiki.ros.org/catkin/Tutorials/create_a_workspace). I will use kinetic prefix for convenience, but it should work with Hydro, Indigo and Jade. The workspace path is `~/catkin_ws` and your `~/.bashrc` contains:
@@ -57,7 +57,7 @@ $ sudo apt-get remove ros-kinetic-rtabmap
$ sudo apt-get install libqt4-dev libpcl-1.7-all-dev libdc1394-dev ros-kinetic-openni-launch ros-kinetic-openni2-launch ros-kinetic-freenect-launch ros-kinetic-costmap-2d ros-kinetic-octomap-ros ros-kinetic-g2o ros-kinetic-rviz ros-kinetic-cv-bridge $ sudo apt-get install libqt4-dev libpcl-1.7-all-dev libdc1394-dev ros-kinetic-openni-launch ros-kinetic-openni2-launch ros-kinetic-freenect-launch ros-kinetic-costmap-2d ros-kinetic-octomap-ros ros-kinetic-g2o ros-kinetic-rviz ros-kinetic-cv-bridge
``` ```
* [GTSAM](https://collab.cc.gatech.edu/borg/gtsam): Follow installation instructions from [here](https://collab.cc.gatech.edu/borg/gtsam/#quickstart). RTAB-Map needs latest version from source (`git clone https://bitbucket.org/gtborg/gtsam.git`), it will not build with 3.2.1. * [GTSAM](https://collab.cc.gatech.edu/borg/gtsam): Follow installation instructions from [here](https://collab.cc.gatech.edu/borg/gtsam/#quickstart). RTAB-Map needs latest version from source (`git clone https://bitbucket.org/gtborg/gtsam.git`), it will **not build** with 3.2.1.
* [cvsba](http://www.uco.es/investiga/grupos/ava/node/39): Follow installation instructions from [here](http://www.uco.es/investiga/grupos/ava/node/39). Their installation is not standard CMake, you need these extra steps so RTAB-Map can find it: * [cvsba](http://www.uco.es/investiga/grupos/ava/node/39): Follow installation instructions from [here](http://www.uco.es/investiga/grupos/ava/node/39). Their installation is not standard CMake, you need these extra steps so RTAB-Map can find it:
```bash ```bash
@@ -94,6 +94,7 @@ $ git pull origin master
$ cd build $ cd build
$ make $ make
$ make install $ make install
# Do "sudo make install" if you installed rtabmap in "/usr/local"
$ roscd rtabmap_ros $ roscd rtabmap_ros
$ git pull origin master $ git pull origin master
+264
View File
@@ -0,0 +1,264 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef INCLUDE_RTABMAP_ROS_COMMONDATASUBSCRIBER_H_
#define INCLUDE_RTABMAP_ROS_COMMONDATASUBSCRIBER_H_
#include <message_filters/subscriber.h>
#include <message_filters/synchronizer.h>
#include <message_filters/sync_policies/approximate_time.h>
#include <message_filters/sync_policies/exact_time.h>
#include <image_transport/image_transport.h>
#include <image_transport/subscriber_filter.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/PointCloud2.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/CameraInfo.h>
#include <sensor_msgs/LaserScan.h>
#include <nav_msgs/Odometry.h>
#include <rtabmap_ros/RGBDImage.h>
#include <rtabmap_ros/UserData.h>
#include <rtabmap_ros/OdomInfo.h>
#include <rtabmap_ros/CommonDataSubscriberDefines.h>
#include <boost/thread.hpp>
namespace rtabmap_ros {
class CommonDataSubscriber {
public:
CommonDataSubscriber(bool gui);
virtual ~CommonDataSubscriber();
bool isSubscribedToDepth() const {return subscribedToDepth_;}
bool isSubscribedToStereo() const {return subscribedToStereo_;}
bool isSubscribedToRGBD() const {return subscribedToRGBD_;}
bool isSubscribedToScan2d() const {return subscribedToScan2d_;}
bool isSubscribedToScan3d() const {return subscribedToScan3d_;}
bool isSubscribedToOdomInfo() const {return subscribedToOdomInfo_;}
bool isDataSubscribed() const {return isSubscribedToDepth() || isSubscribedToStereo() || isSubscribedToRGBD();}
int getQueueSize() const {return queueSize_;}
protected:
void setupCallbacks(ros::NodeHandle & nh, ros::NodeHandle & pnh, const std::string & name);
virtual void commonDepthCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const std::vector<cv_bridge::CvImageConstPtr> & imageMsgs,
const std::vector<cv_bridge::CvImageConstPtr> & depthMsgs,
const std::vector<sensor_msgs::CameraInfo> & cameraInfoMsgs,
const sensor_msgs::LaserScanConstPtr& scanMsg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg) = 0;
virtual void commonStereoCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg) = 0;
void commonSingleDepthCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const cv_bridge::CvImageConstPtr & imageMsg,
const cv_bridge::CvImageConstPtr & depthMsg,
const sensor_msgs::CameraInfo & cameraInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg);
private:
void warningLoop();
void callbackCalled() {callbackCalled_ = true;}
void setupDepthCallbacks(
ros::NodeHandle & nh,
ros::NodeHandle & pnh,
bool subscribeOdom,
bool subscribeUserData,
bool subscribeScan2d,
bool subscribeScan3d,
bool subscribeOdomInfo,
int queueSize,
bool approxSync);
void setupStereoCallbacks(
ros::NodeHandle & nh,
ros::NodeHandle & pnh,
bool subscribeOdom,
bool subscribeOdomInfo,
int queueSize,
bool approxSync);
void setupRGBDCallbacks(
ros::NodeHandle & nh,
ros::NodeHandle & pnh,
bool subscribeOdom,
bool subscribeUserData,
bool subscribeScan2d,
bool subscribeScan3d,
bool subscribeOdomInfo,
int queueSize,
bool approxSync);
void setupRGBD2Callbacks(
ros::NodeHandle & nh,
ros::NodeHandle & pnh,
bool subscribeOdom,
bool subscribeUserData,
bool subscribeScan2d,
bool subscribeScan3d,
bool subscribeOdomInfo,
int queueSize,
bool approxSync);
protected:
std::string subscribedTopicsMsg_;
int queueSize_;
private:
bool approxSync_;
boost::thread* warningThread_;
bool callbackCalled_;
bool subscribedToDepth_;
bool subscribedToStereo_;
bool subscribedToRGBD_;
bool subscribedToScan2d_;
bool subscribedToScan3d_;
bool subscribedToOdomInfo_;
std::string name_;
//for depth callback
image_transport::SubscriberFilter imageSub_;
image_transport::SubscriberFilter imageDepthSub_;
message_filters::Subscriber<sensor_msgs::CameraInfo> cameraInfoSub_;
//for rgbd callback
ros::Subscriber rgbdSub_;
std::vector<message_filters::Subscriber<rtabmap_ros::RGBDImage>*> rgbdSubs_;
//stereo callback
image_transport::SubscriberFilter imageRectLeft_;
image_transport::SubscriberFilter imageRectRight_;
message_filters::Subscriber<sensor_msgs::CameraInfo> cameraInfoLeft_;
message_filters::Subscriber<sensor_msgs::CameraInfo> cameraInfoRight_;
message_filters::Subscriber<nav_msgs::Odometry> odomSub_;
message_filters::Subscriber<rtabmap_ros::UserData> userDataSub_;
message_filters::Subscriber<sensor_msgs::LaserScan> scanSub_;
message_filters::Subscriber<sensor_msgs::PointCloud2> scan3dSub_;
message_filters::Subscriber<rtabmap_ros::OdomInfo> odomInfoSub_;
// RGB + Depth
DATA_SYNCS3(depth, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo);
DATA_SYNCS4(depthScan2d, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::LaserScan);
DATA_SYNCS4(depthScan3d, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::PointCloud2);
DATA_SYNCS4(depthInfo, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, rtabmap_ros::OdomInfo);
// RGB + Depth + Odom
DATA_SYNCS4(depthOdom, nav_msgs::Odometry, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo);
DATA_SYNCS5(depthOdomScan2d, nav_msgs::Odometry, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::LaserScan);
DATA_SYNCS5(depthOdomScan3d, nav_msgs::Odometry, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::PointCloud2);
DATA_SYNCS5(depthOdomInfo, nav_msgs::Odometry, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, rtabmap_ros::OdomInfo);
// RGB + Depth + User Data
DATA_SYNCS4(depthData, rtabmap_ros::UserData, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo);
DATA_SYNCS5(depthDataScan2d, rtabmap_ros::UserData, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::LaserScan);
DATA_SYNCS5(depthDataScan3d, rtabmap_ros::UserData, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::PointCloud2);
DATA_SYNCS5(depthDataInfo, rtabmap_ros::UserData, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, rtabmap_ros::OdomInfo);
// RGB + Depth + Odom + User Data
DATA_SYNCS5(depthOdomData, nav_msgs::Odometry, rtabmap_ros::UserData, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo);
DATA_SYNCS6(depthOdomDataScan2d, nav_msgs::Odometry, rtabmap_ros::UserData, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::LaserScan);
DATA_SYNCS6(depthOdomDataScan3d, nav_msgs::Odometry, rtabmap_ros::UserData, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::PointCloud2);
DATA_SYNCS6(depthOdomDataInfo, nav_msgs::Odometry, rtabmap_ros::UserData, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, rtabmap_ros::OdomInfo);
// Stereo
DATA_SYNCS4(stereo, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::CameraInfo);
DATA_SYNCS5(stereoInfo, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::CameraInfo, rtabmap_ros::OdomInfo);
// Stereo + Odom
DATA_SYNCS5(stereoOdom, nav_msgs::Odometry, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::CameraInfo);
DATA_SYNCS6(stereoOdomInfo, nav_msgs::Odometry, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::CameraInfo, rtabmap_ros::OdomInfo);
// 1 RGBD
void rgbdCallback(const rtabmap_ros::RGBDImageConstPtr&);
DATA_SYNCS2(rgbdScan2d, rtabmap_ros::RGBDImage, sensor_msgs::LaserScan);
DATA_SYNCS2(rgbdScan3d, rtabmap_ros::RGBDImage, sensor_msgs::PointCloud2);
DATA_SYNCS2(rgbdInfo, rtabmap_ros::RGBDImage, rtabmap_ros::OdomInfo);
// 1 RGBD + Odom
DATA_SYNCS2(rgbdOdom, nav_msgs::Odometry, rtabmap_ros::RGBDImage);
DATA_SYNCS3(rgbdOdomScan2d, nav_msgs::Odometry, rtabmap_ros::RGBDImage, sensor_msgs::LaserScan);
DATA_SYNCS3(rgbdOdomScan3d, nav_msgs::Odometry, rtabmap_ros::RGBDImage, sensor_msgs::PointCloud2);
DATA_SYNCS3(rgbdOdomInfo, nav_msgs::Odometry, rtabmap_ros::RGBDImage, rtabmap_ros::OdomInfo);
// 1 RGBD + User Data
DATA_SYNCS2(rgbdData, rtabmap_ros::UserData, rtabmap_ros::RGBDImage);
DATA_SYNCS3(rgbdDataScan2d, rtabmap_ros::UserData, rtabmap_ros::RGBDImage, sensor_msgs::LaserScan);
DATA_SYNCS3(rgbdDataScan3d, rtabmap_ros::UserData, rtabmap_ros::RGBDImage, sensor_msgs::PointCloud2);
DATA_SYNCS3(rgbdDataInfo, rtabmap_ros::UserData, rtabmap_ros::RGBDImage, rtabmap_ros::OdomInfo);
// 1 RGBD + Odom + User Data
DATA_SYNCS3(rgbdOdomData, nav_msgs::Odometry, rtabmap_ros::UserData, rtabmap_ros::RGBDImage);
DATA_SYNCS4(rgbdOdomDataScan2d, nav_msgs::Odometry, rtabmap_ros::UserData, rtabmap_ros::RGBDImage, sensor_msgs::LaserScan);
DATA_SYNCS4(rgbdOdomDataScan3d, nav_msgs::Odometry, rtabmap_ros::UserData, rtabmap_ros::RGBDImage, sensor_msgs::PointCloud2);
DATA_SYNCS4(rgbdOdomDataInfo, nav_msgs::Odometry, rtabmap_ros::UserData, rtabmap_ros::RGBDImage, rtabmap_ros::OdomInfo);
// 2 RGBD
DATA_SYNCS2(rgbd2, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage);
DATA_SYNCS3(rgbd2Scan2d, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage, sensor_msgs::LaserScan);
DATA_SYNCS3(rgbd2Scan3d, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage, sensor_msgs::PointCloud2);
DATA_SYNCS3(rgbd2Info, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage, rtabmap_ros::OdomInfo);
// 2 RGBD + Odom
DATA_SYNCS3(rgbd2Odom, nav_msgs::Odometry, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage);
DATA_SYNCS4(rgbd2OdomScan2d, nav_msgs::Odometry, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage, sensor_msgs::LaserScan);
DATA_SYNCS4(rgbd2OdomScan3d, nav_msgs::Odometry, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage, sensor_msgs::PointCloud2);
DATA_SYNCS4(rgbd2OdomInfo, nav_msgs::Odometry, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage, rtabmap_ros::OdomInfo);
// 2 RGBD + User Data
DATA_SYNCS3(rgbd2Data, rtabmap_ros::UserData, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage);
DATA_SYNCS4(rgbd2DataScan2d, rtabmap_ros::UserData, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage, sensor_msgs::LaserScan);
DATA_SYNCS4(rgbd2DataScan3d, rtabmap_ros::UserData, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage, sensor_msgs::PointCloud2);
DATA_SYNCS4(rgbd2DataInfo, rtabmap_ros::UserData, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage, rtabmap_ros::OdomInfo);
// 2 RGBD + Odom + User Data
DATA_SYNCS4(rgbd2OdomData, nav_msgs::Odometry, rtabmap_ros::UserData, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage);
DATA_SYNCS5(rgbd2OdomDataScan2d, nav_msgs::Odometry, rtabmap_ros::UserData, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage, sensor_msgs::LaserScan);
DATA_SYNCS5(rgbd2OdomDataScan3d, nav_msgs::Odometry, rtabmap_ros::UserData, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage, sensor_msgs::PointCloud2);
DATA_SYNCS5(rgbd2OdomDataInfo, nav_msgs::Odometry, rtabmap_ros::UserData, rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage, rtabmap_ros::OdomInfo);
};
} /* namespace rtabmap_ros */
#endif /* INCLUDE_RTABMAP_ROS_COMMONDATASUBSCRIBER_H_ */
@@ -0,0 +1,195 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef INCLUDE_RTABMAP_ROS_COMMONDATASUBSCRIBERIMPL_H_
#define INCLUDE_RTABMAP_ROS_COMMONDATASUBSCRIBERIMPL_H_
#include <rtabmap/utilite/UConversion.h>
#define DATA_SYNC2(PREFIX, SYNC_NAME, MSG0, MSG1) \
typedef message_filters::sync_policies::SYNC_NAME##Time<MSG0, MSG1> PREFIX##SYNC_NAME##SyncPolicy; \
message_filters::Synchronizer<PREFIX##SYNC_NAME##SyncPolicy> * PREFIX##SYNC_NAME##Sync_;
#define DATA_SYNCS2(PREFIX, MSG0, MSG1) \
DATA_SYNC2(PREFIX, Approximate, MSG0, MSG1) \
DATA_SYNC2(PREFIX, Exact, MSG0, MSG1) \
void PREFIX##Callback(const MSG0##ConstPtr&, const MSG1##ConstPtr&);
#define DATA_SYNC3(PREFIX, SYNC_NAME, MSG0, MSG1, MSG2) \
typedef message_filters::sync_policies::SYNC_NAME##Time<MSG0, MSG1, MSG2> PREFIX##SYNC_NAME##SyncPolicy; \
message_filters::Synchronizer<PREFIX##SYNC_NAME##SyncPolicy> * PREFIX##SYNC_NAME##Sync_;
#define DATA_SYNCS3(PREFIX, MSG0, MSG1, MSG2) \
DATA_SYNC3(PREFIX, Approximate, MSG0, MSG1, MSG2) \
DATA_SYNC3(PREFIX, Exact, MSG0, MSG1, MSG2) \
void PREFIX##Callback(const MSG0##ConstPtr&, const MSG1##ConstPtr&, const MSG2##ConstPtr&); \
#define DATA_SYNC4(PREFIX, SYNC_NAME, MSG0, MSG1, MSG2, MSG3) \
typedef message_filters::sync_policies::SYNC_NAME##Time<MSG0, MSG1, MSG2, MSG3> PREFIX##SYNC_NAME##SyncPolicy; \
message_filters::Synchronizer<PREFIX##SYNC_NAME##SyncPolicy> * PREFIX##SYNC_NAME##Sync_;
#define DATA_SYNCS4(PREFIX, MSG0, MSG1, MSG2, MSG3) \
DATA_SYNC4(PREFIX, Approximate, MSG0, MSG1, MSG2, MSG3) \
DATA_SYNC4(PREFIX, Exact, MSG0, MSG1, MSG2, MSG3) \
void PREFIX##Callback(const MSG0##ConstPtr&, const MSG1##ConstPtr&, const MSG2##ConstPtr&, const MSG3##ConstPtr&); \
#define DATA_SYNC5(PREFIX, SYNC_NAME, MSG0, MSG1, MSG2, MSG3, MSG4) \
typedef message_filters::sync_policies::SYNC_NAME##Time<MSG0, MSG1, MSG2, MSG3, MSG4> PREFIX##SYNC_NAME##SyncPolicy; \
message_filters::Synchronizer<PREFIX##SYNC_NAME##SyncPolicy> * PREFIX##SYNC_NAME##Sync_;
#define DATA_SYNCS5(PREFIX, MSG0, MSG1, MSG2, MSG3, MSG4) \
DATA_SYNC5(PREFIX, Approximate, MSG0, MSG1, MSG2, MSG3, MSG4) \
DATA_SYNC5(PREFIX, Exact, MSG0, MSG1, MSG2, MSG3, MSG4) \
void PREFIX##Callback(const MSG0##ConstPtr&, const MSG1##ConstPtr&, const MSG2##ConstPtr&, const MSG3##ConstPtr&, const MSG4##ConstPtr&); \
#define DATA_SYNC6(PREFIX, SYNC_NAME, MSG0, MSG1, MSG2, MSG3, MSG4, MSG5) \
typedef message_filters::sync_policies::SYNC_NAME##Time<MSG0, MSG1, MSG2, MSG3, MSG4, MSG5> PREFIX##SYNC_NAME##SyncPolicy; \
message_filters::Synchronizer<PREFIX##SYNC_NAME##SyncPolicy> * PREFIX##SYNC_NAME##Sync_;
#define DATA_SYNCS6(PREFIX, MSG0, MSG1, MSG2, MSG3, MSG4, MSG5) \
DATA_SYNC6(PREFIX, Approximate, MSG0, MSG1, MSG2, MSG3, MSG4, MSG5) \
DATA_SYNC6(PREFIX, Exact, MSG0, MSG1, MSG2, MSG3, MSG4, MSG5) \
void PREFIX##Callback(const MSG0##ConstPtr&, const MSG1##ConstPtr&, const MSG2##ConstPtr&, const MSG3##ConstPtr&, const MSG4##ConstPtr&, const MSG5##ConstPtr&); \
// Constructor
#define SYNC_INIT(PREFIX) \
PREFIX##ApproximateSync_(0), \
PREFIX##ExactSync_(0)
// Destructor
#define SYNC_DEL(PREFIX) \
if(PREFIX##ApproximateSync_) delete PREFIX##ApproximateSync_; \
if(PREFIX##ExactSync_) delete PREFIX##ExactSync_;
// Sync declarations
#define SYNC_DECL2(PREFIX, APPROX, QUEUE_SIZE, SUB0, SUB1) \
if(APPROX) \
{ \
PREFIX##ApproximateSync_ = new message_filters::Synchronizer<PREFIX##ApproximateSyncPolicy>( \
PREFIX##ApproximateSyncPolicy(QUEUE_SIZE), SUB0, SUB1); \
PREFIX##ApproximateSync_->registerCallback(boost::bind(&CommonDataSubscriber::PREFIX##Callback, this, _1, _2)); \
} \
else \
{ \
PREFIX##ExactSync_ = new message_filters::Synchronizer<PREFIX##ExactSyncPolicy>( \
PREFIX##ExactSyncPolicy(QUEUE_SIZE), SUB0, SUB1); \
PREFIX##ExactSync_->registerCallback(boost::bind(&CommonDataSubscriber::PREFIX##Callback, this, _1, _2)); \
} \
subscribedTopicsMsg_ = uFormat("\n%s subscribed to (%s sync):\n %s,\n %s", \
name_.c_str(), \
APPROX?"approx":"exact", \
SUB0.getTopic().c_str(), \
SUB1.getTopic().c_str());
#define SYNC_DECL3(PREFIX, APPROX, QUEUE_SIZE, SUB0, SUB1, SUB2) \
if(APPROX) \
{ \
PREFIX##ApproximateSync_ = new message_filters::Synchronizer<PREFIX##ApproximateSyncPolicy>( \
PREFIX##ApproximateSyncPolicy(QUEUE_SIZE), SUB0, SUB1, SUB2); \
PREFIX##ApproximateSync_->registerCallback(boost::bind(&CommonDataSubscriber::PREFIX##Callback, this, _1, _2, _3)); \
} \
else \
{ \
PREFIX##ExactSync_ = new message_filters::Synchronizer<PREFIX##ExactSyncPolicy>( \
PREFIX##ExactSyncPolicy(QUEUE_SIZE), SUB0, SUB1, SUB2); \
PREFIX##ExactSync_->registerCallback(boost::bind(&CommonDataSubscriber::PREFIX##Callback, this, _1, _2, _3)); \
} \
subscribedTopicsMsg_ = uFormat("\n%s subscribed to (%s sync):\n %s,\n %s,\n %s", \
name_.c_str(), \
APPROX?"approx":"exact", \
SUB0.getTopic().c_str(), \
SUB1.getTopic().c_str(), \
SUB2.getTopic().c_str());
#define SYNC_DECL4(PREFIX, APPROX, QUEUE_SIZE, SUB0, SUB1, SUB2, SUB3) \
if(APPROX) \
{ \
PREFIX##ApproximateSync_ = new message_filters::Synchronizer<PREFIX##ApproximateSyncPolicy>( \
PREFIX##ApproximateSyncPolicy(QUEUE_SIZE), SUB0, SUB1, SUB2, SUB3); \
PREFIX##ApproximateSync_->registerCallback(boost::bind(&CommonDataSubscriber::PREFIX##Callback, this, _1, _2, _3, _4)); \
} \
else \
{ \
PREFIX##ExactSync_ = new message_filters::Synchronizer<PREFIX##ExactSyncPolicy>( \
PREFIX##ExactSyncPolicy(QUEUE_SIZE), SUB0, SUB1, SUB2, SUB3); \
PREFIX##ExactSync_->registerCallback(boost::bind(&CommonDataSubscriber::PREFIX##Callback, this, _1, _2, _3, _4)); \
} \
subscribedTopicsMsg_ = uFormat("\n%s subscribed to (%s sync):\n %s,\n %s,\n %s,\n %s", \
name_.c_str(), \
APPROX?"approx":"exact", \
SUB0.getTopic().c_str(), \
SUB1.getTopic().c_str(), \
SUB2.getTopic().c_str(), \
SUB3.getTopic().c_str());
#define SYNC_DECL5(PREFIX, APPROX, QUEUE_SIZE, SUB0, SUB1, SUB2, SUB3, SUB4) \
if(APPROX) \
{ \
PREFIX##ApproximateSync_ = new message_filters::Synchronizer<PREFIX##ApproximateSyncPolicy>( \
PREFIX##ApproximateSyncPolicy(QUEUE_SIZE), SUB0, SUB1, SUB2, SUB3, SUB4); \
PREFIX##ApproximateSync_->registerCallback(boost::bind(&CommonDataSubscriber::PREFIX##Callback, this, _1, _2, _3, _4, _5)); \
} \
else \
{ \
PREFIX##ExactSync_ = new message_filters::Synchronizer<PREFIX##ExactSyncPolicy>( \
PREFIX##ExactSyncPolicy(QUEUE_SIZE), SUB0, SUB1, SUB2, SUB3, SUB4); \
PREFIX##ExactSync_->registerCallback(boost::bind(&CommonDataSubscriber::PREFIX##Callback, this, _1, _2, _3, _4, _5)); \
} \
subscribedTopicsMsg_ = uFormat("\n%s subscribed to (%s sync):\n %s,\n %s,\n %s,\n %s,\n %s", \
name_.c_str(), \
approxSync?"approx":"exact", \
SUB0.getTopic().c_str(), \
SUB1.getTopic().c_str(), \
SUB2.getTopic().c_str(), \
SUB3.getTopic().c_str(), \
SUB4.getTopic().c_str());
#define SYNC_DECL6(PREFIX, APPROX, QUEUE_SIZE, SUB0, SUB1, SUB2, SUB3, SUB4, SUB5) \
if(APPROX) \
{ \
PREFIX##ApproximateSync_ = new message_filters::Synchronizer<PREFIX##ApproximateSyncPolicy>( \
PREFIX##ApproximateSyncPolicy(QUEUE_SIZE), SUB0, SUB1, SUB2, SUB3, SUB4, SUB5); \
PREFIX##ApproximateSync_->registerCallback(boost::bind(&CommonDataSubscriber::PREFIX##Callback, this, _1, _2, _3, _4, _5, _6)); \
} \
else \
{ \
PREFIX##ExactSync_ = new message_filters::Synchronizer<PREFIX##ExactSyncPolicy>( \
PREFIX##ExactSyncPolicy(QUEUE_SIZE), SUB0, SUB1, SUB2, SUB3, SUB4, SUB5); \
PREFIX##ExactSync_->registerCallback(boost::bind(&CommonDataSubscriber::PREFIX##Callback, this, _1, _2, _3, _4, _5, _6)); \
} \
subscribedTopicsMsg_ = uFormat("\n%s subscribed to (%s sync):\n %s,\n %s,\n %s,\n %s,\n %s,\n %s", \
name_.c_str(), \
APPROX?"approx":"exact", \
SUB0.getTopic().c_str(), \
SUB1.getTopic().c_str(), \
SUB2.getTopic().c_str(), \
SUB3.getTopic().c_str(), \
SUB4.getTopic().c_str(), \
SUB5.getTopic().c_str());
#endif /* INCLUDE_RTABMAP_ROS_COMMONDATASUBSCRIBERIMPL_H_ */
+264
View File
@@ -0,0 +1,264 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef COREWRAPPER_H_
#define COREWRAPPER_H_
#include <ros/ros.h>
#include <nodelet/nodelet.h>
#include <std_srvs/Empty.h>
#include <tf/transform_listener.h>
#include <tf2_ros/transform_broadcaster.h>
#include <std_msgs/Empty.h>
#include <std_msgs/Int32.h>
#include <nav_msgs/GetMap.h>
#include <rtabmap/core/Parameters.h>
#include <rtabmap/core/Rtabmap.h>
#include "rtabmap_ros/GetMap.h"
#include "rtabmap_ros/ListLabels.h"
#include "rtabmap_ros/PublishMap.h"
#include "rtabmap_ros/SetGoal.h"
#include "rtabmap_ros/SetLabel.h"
#include "rtabmap_ros/Goal.h"
#include "rtabmap_ros/CommonDataSubscriber.h"
#include "MapsManager.h"
#ifdef WITH_OCTOMAP_ROS
#include <octomap_msgs/GetOctomap.h>
#endif
#include <actionlib/client/simple_action_client.h>
#include <move_base_msgs/MoveBaseAction.h>
#include <move_base_msgs/MoveBaseActionGoal.h>
#include <move_base_msgs/MoveBaseActionResult.h>
#include <move_base_msgs/MoveBaseActionFeedback.h>
#include <actionlib_msgs/GoalStatusArray.h>
typedef actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> MoveBaseClient;
namespace rtabmap {
class StereoDense;
}
namespace rtabmap_ros {
class CoreWrapper : public CommonDataSubscriber, public nodelet::Nodelet
{
public:
CoreWrapper();
virtual ~CoreWrapper();
private:
virtual void onInit();
bool odomUpdate(const nav_msgs::OdometryConstPtr & odomMsg);
bool odomTFUpdate(const ros::Time & stamp); // TF odom
virtual void commonDepthCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const std::vector<cv_bridge::CvImageConstPtr> & imageMsgs,
const std::vector<cv_bridge::CvImageConstPtr> & depthMsgs,
const std::vector<sensor_msgs::CameraInfo> & cameraInfoMsgs,
const sensor_msgs::LaserScanConstPtr& scanMsg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg);
void commonDepthCallbackImpl(
const std::string & odomFrameId,
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const std::vector<cv_bridge::CvImageConstPtr> & imageMsgs,
const std::vector<cv_bridge::CvImageConstPtr> & depthMsgs,
const std::vector<sensor_msgs::CameraInfo> & cameraInfoMsgs,
const sensor_msgs::LaserScanConstPtr& scan2dMsg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg);
virtual void commonStereoCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg);
void defaultCallback(const sensor_msgs::ImageConstPtr & imageMsg); // no odom
void goalCommonCallback(int id, const std::string & label, const rtabmap::Transform & pose, const ros::Time & stamp, double * planningTime = 0);
void goalCallback(const geometry_msgs::PoseStampedConstPtr & msg);
void goalNodeCallback(const rtabmap_ros::GoalConstPtr & msg);
void updateGoal(const ros::Time & stamp);
void process(
const ros::Time & stamp,
const rtabmap::SensorData & data,
const rtabmap::Transform & odom = rtabmap::Transform(),
const std::string & odomFrameId = "",
float odomRotationalVariance = 1.0,
float odomTransitionalVariance = 1.0);
bool updateRtabmapCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool resetRtabmapCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool pauseRtabmapCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool resumeRtabmapCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool triggerNewMapCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool backupDatabaseCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool setModeLocalizationCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool setModeMappingCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool setLogDebug(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 setLogError(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
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 getGridMapCallback(nav_msgs::GetMap::Request &req, nav_msgs::GetMap::Response &res);
bool publishMapCallback(rtabmap_ros::PublishMap::Request&, rtabmap_ros::PublishMap::Response&);
bool setGoalCallback(rtabmap_ros::SetGoal::Request& req, rtabmap_ros::SetGoal::Response& res);
bool cancelGoalCallback(std_srvs::Empty::Request& req, std_srvs::Empty::Response& res);
bool setLabelCallback(rtabmap_ros::SetLabel::Request& req, rtabmap_ros::SetLabel::Response& res);
bool listLabelsCallback(rtabmap_ros::ListLabels::Request& req, rtabmap_ros::ListLabels::Response& res);
#ifdef WITH_OCTOMAP_ROS
bool octomapBinaryCallback(octomap_msgs::GetOctomap::Request &req, octomap_msgs::GetOctomap::Response &res);
bool octomapFullCallback(octomap_msgs::GetOctomap::Request &req, octomap_msgs::GetOctomap::Response &res);
#endif
void loadParameters(const std::string & configFile, rtabmap::ParametersMap & parameters);
void saveParameters(const std::string & configFile);
void publishLoop(double tfDelay, double tfTolerance);
void publishStats(const ros::Time & stamp);
void publishCurrentGoal(const ros::Time & stamp);
void goalDoneCb(const actionlib::SimpleClientGoalState& state, const move_base_msgs::MoveBaseResultConstPtr& result);
void goalActiveCb();
void goalFeedbackCb(const move_base_msgs::MoveBaseFeedbackConstPtr& feedback);
void publishLocalPath(const ros::Time & stamp);
void publishGlobalPath(const ros::Time & stamp);
private:
rtabmap::Rtabmap rtabmap_;
bool paused_;
rtabmap::Transform lastPose_;
ros::Time lastPoseStamp_;
bool lastPoseIntermediate_;
float rotVariance_;
float transVariance_;
rtabmap::Transform currentMetricGoal_;
bool latestNodeWasReached_;
rtabmap::ParametersMap parameters_;
std::string frameId_;
std::string odomFrameId_;
std::string mapFrameId_;
std::string groundTruthFrameId_;
std::string groundTruthBaseFrameId_;
std::string configPath_;
std::string databasePath_;
bool waitForTransform_;
double waitForTransformDuration_;
bool useActionForGoal_;
bool genScan_;
double genScanMaxDepth_;
double genScanMinDepth_;
int scanCloudMaxPoints_;
int scanCloudNormalK_;
rtabmap::Transform mapToOdom_;
boost::mutex mapToOdomMutex_;
MapsManager mapsManager_;
ros::Publisher infoPub_;
ros::Publisher mapDataPub_;
ros::Publisher mapGraphPub_;
ros::Publisher labelsPub_;
//Planning stuff
ros::Subscriber goalSub_;
ros::Subscriber goalNodeSub_;
ros::Publisher nextMetricGoalPub_;
ros::Publisher goalReachedPub_;
ros::Publisher globalPathPub_;
ros::Publisher localPathPub_;
tf2_ros::TransformBroadcaster tfBroadcaster_;
tf::TransformListener tfListener_;
ros::ServiceServer updateSrv_;
ros::ServiceServer resetSrv_;
ros::ServiceServer pauseSrv_;
ros::ServiceServer resumeSrv_;
ros::ServiceServer triggerNewMapSrv_;
ros::ServiceServer backupDatabase_;
ros::ServiceServer setModeLocalizationSrv_;
ros::ServiceServer setModeMappingSrv_;
ros::ServiceServer setLogDebugSrv_;
ros::ServiceServer setLogInfoSrv_;
ros::ServiceServer setLogWarnSrv_;
ros::ServiceServer setLogErrorSrv_;
ros::ServiceServer getMapDataSrv_;
ros::ServiceServer getProjMapSrv_;
ros::ServiceServer getMapSrv_;
ros::ServiceServer getGridMapSrv_;
ros::ServiceServer publishMapDataSrv_;
ros::ServiceServer setGoalSrv_;
ros::ServiceServer cancelGoalSrv_;
ros::ServiceServer setLabelSrv_;
ros::ServiceServer listLabelsSrv_;
#ifdef WITH_OCTOMAP_ROS
ros::ServiceServer octomapBinarySrv_;
ros::ServiceServer octomapFullSrv_;
#endif
MoveBaseClient mbClient_;
boost::thread* transformThread_;
bool tfThreadRunning_;
// for loop closure detection only
image_transport::Subscriber defaultSub_;
bool stereoToDepth_;
bool odomSensorSync_;
float rate_;
bool createIntermediateNodes_;
ros::Time time_;
ros::Time previousStamp_;
};
}
#endif /* COREWRAPPER_H_ */
+128
View File
@@ -0,0 +1,128 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GUIWRAPPER_H_
#define GUIWRAPPER_H_
#include <ros/ros.h>
#include "rtabmap_ros/Info.h"
#include "rtabmap_ros/MapData.h"
#include "rtabmap_ros/OdomInfo.h"
#include "rtabmap_ros/Goal.h"
#include "rtabmap/utilite/UEventsHandler.h"
#include "rtabmap/core/Transform.h"
#include <tf/transform_listener.h>
#include <geometry_msgs/TwistStamped.h>
#include <nav_msgs/Path.h>
#include <std_msgs/Bool.h>
#include <rtabmap_ros/CommonDataSubscriber.h>
namespace rtabmap
{
class MainWindow;
}
class QApplication;
namespace rtabmap_ros {
class GuiWrapper : public UEventsHandler, public CommonDataSubscriber
{
public:
GuiWrapper(int & argc, char** argv);
virtual ~GuiWrapper();
protected:
virtual void handleEvent(UEvent * anEvent);
private:
void infoMapCallback(const rtabmap_ros::InfoConstPtr & infoMsg, const rtabmap_ros::MapDataConstPtr & mapMsg);
void goalPathCallback(const rtabmap_ros::GoalConstPtr & goalMsg, const nav_msgs::PathConstPtr & pathMsg);
void goalReachedCallback(const std_msgs::BoolConstPtr & value);
virtual void commonDepthCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const std::vector<cv_bridge::CvImageConstPtr> & imageMsgs,
const std::vector<cv_bridge::CvImageConstPtr> & depthMsgs,
const std::vector<sensor_msgs::CameraInfo> & cameraInfoMsgs,
const sensor_msgs::LaserScanConstPtr& scan2dMsg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg);
virtual void commonStereoCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg,
const sensor_msgs::LaserScanConstPtr& scan2dMsg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg);
void defaultCallback(const nav_msgs::OdometryConstPtr & odomMsg);
void processRequestedMap(const rtabmap_ros::MapData & map);
private:
rtabmap::MainWindow * mainWindow_;
std::string cameraNodeName_;
double lastOdomInfoUpdateTime_;
// odometry subscription stuffs
std::string frameId_;
std::string odomFrameId_;
bool waitForTransform_;
double waitForTransformDuration_;
bool odomSensorSync_;
tf::TransformListener tfListener_;
message_filters::Subscriber<rtabmap_ros::Info> infoTopic_;
message_filters::Subscriber<rtabmap_ros::MapData> mapDataTopic_;
message_filters::Subscriber<rtabmap_ros::Goal> goalTopic_;
message_filters::Subscriber<nav_msgs::Path> pathTopic_;
ros::Subscriber goalReachedTopic_;
ros::Subscriber defaultSub_; // odometry only
typedef message_filters::sync_policies::ExactTime<
rtabmap_ros::Info,
rtabmap_ros::MapData> MyInfoMapSyncPolicy;
message_filters::Synchronizer<MyInfoMapSyncPolicy> * infoMapSync_;
typedef message_filters::sync_policies::ExactTime<
rtabmap_ros::Goal,
nav_msgs::Path> MyGoalPathSyncPolicy;
message_filters::Synchronizer<MyGoalPathSyncPolicy> * goalPathSync_;
};
}
#endif /* GUIWRAPPER_H_ */
@@ -29,6 +29,8 @@ 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 <rtabmap/core/FlannIndex.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,15 +39,19 @@ 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
class MapsManager { class MapsManager {
public: public:
MapsManager(bool usePublicNamespace); MapsManager();
virtual ~MapsManager(); virtual ~MapsManager();
void init(ros::NodeHandle & nh, ros::NodeHandle & pnh, const std::string & name, bool usePublicNamespace);
void clear(); void clear();
bool hasSubscribers() const; bool hasSubscribers() const;
void backwardCompatibilityParameters(ros::NodeHandle & pnh, 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 +59,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,52 +68,33 @@ 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,
float & yMin, float & yMin,
float & gridCellSize); float & gridCellSize);
rtabmap::OctoMap * getOctomap() const {return octomap_;} const rtabmap::OctoMap * getOctomap() const {return octomap_;}
const rtabmap::OccupancyGrid * getOccupancyGrid() const {return occupancyGrid_;}
private: private:
// mapping stuff // mapping stuff
int cloudDecimation_;
double cloudMaxDepth_;
double cloudMinDepth_;
double cloudVoxelSize_;
double cloudFloorCullingHeight_;
double cloudCeilingCullingHeight_;
bool cloudOutputVoxelized_; bool cloudOutputVoxelized_;
bool cloudFrustumCulling_; bool cloudSubtractFiltering_;
double cloudNoiseFilteringRadius_; int cloudSubtractFilteringMinNeighbors_;
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_;
bool gridUnknownSpaceFilled_; double footprintRadius_;
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_;
@@ -120,15 +104,27 @@ 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_;
rtabmap::FlannIndex assembledGroundIndex_;
rtabmap::FlannIndex assembledObstacleIndex_;
std::map<int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr > groundClouds_;
std::map<int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr > obstacleClouds_;
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_; double octomapOccupancyThr_;
rtabmap::ParametersMap parameters_;
}; };
#endif /* MAPSMANAGER_H_ */ #endif /* MAPSMANAGER_H_ */
+79
View File
@@ -29,12 +29,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define MSGCONVERSION_H_ #define MSGCONVERSION_H_
#include <tf/tf.h> #include <tf/tf.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/Transform.h> #include <geometry_msgs/Transform.h>
#include <geometry_msgs/Pose.h> #include <geometry_msgs/Pose.h>
#include <sensor_msgs/CameraInfo.h> #include <sensor_msgs/CameraInfo.h>
#include <sensor_msgs/LaserScan.h>
#include <sensor_msgs/Image.h>
#include <opencv2/opencv.hpp> #include <opencv2/opencv.hpp>
#include <opencv2/features2d/features2d.hpp> #include <opencv2/features2d/features2d.hpp>
#include <cv_bridge/cv_bridge.h>
#include <rtabmap/core/Transform.h> #include <rtabmap/core/Transform.h>
#include <rtabmap/core/Link.h> #include <rtabmap/core/Link.h>
@@ -52,6 +56,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap_ros/NodeData.h> #include <rtabmap_ros/NodeData.h>
#include <rtabmap_ros/OdomInfo.h> #include <rtabmap_ros/OdomInfo.h>
#include <rtabmap_ros/Info.h> #include <rtabmap_ros/Info.h>
#include <rtabmap_ros/RGBDImage.h>
#include <rtabmap_ros/UserData.h>
namespace rtabmap_ros { namespace rtabmap_ros {
@@ -64,6 +70,9 @@ rtabmap::Transform transformFromGeometryMsg(const geometry_msgs::Transform & msg
void transformToPoseMsg(const rtabmap::Transform & transform, geometry_msgs::Pose & msg); void transformToPoseMsg(const rtabmap::Transform & transform, geometry_msgs::Pose & msg);
rtabmap::Transform transformFromPoseMsg(const geometry_msgs::Pose & msg); rtabmap::Transform transformFromPoseMsg(const geometry_msgs::Pose & msg);
void toCvCopy(const rtabmap_ros::RGBDImage & image, cv_bridge::CvImagePtr & rgb, cv_bridge::CvImagePtr & depth);
void toCvShare(const rtabmap_ros::RGBDImageConstPtr & image, cv_bridge::CvImageConstPtr & rgb, cv_bridge::CvImageConstPtr & depth);
// copy data // copy data
void compressedMatToBytes(const cv::Mat & compressed, std::vector<unsigned char> & bytes); void compressedMatToBytes(const cv::Mat & compressed, std::vector<unsigned char> & bytes);
cv::Mat compressedMatFromBytes(const std::vector<unsigned char> & bytes, bool copy = true); cv::Mat compressedMatFromBytes(const std::vector<unsigned char> & bytes, bool copy = true);
@@ -137,8 +146,78 @@ void nodeInfoToROS(const rtabmap::Signature & signature, rtabmap_ros::NodeData &
rtabmap::OdometryInfo odomInfoFromROS(const rtabmap_ros::OdomInfo & msg); rtabmap::OdometryInfo odomInfoFromROS(const rtabmap_ros::OdomInfo & msg);
void odomInfoToROS(const rtabmap::OdometryInfo & info, rtabmap_ros::OdomInfo & msg); void odomInfoToROS(const rtabmap::OdometryInfo & info, rtabmap_ros::OdomInfo & msg);
cv::Mat userDataFromROS(const rtabmap_ros::UserData & dataMsg);
void userDataToROS(const cv::Mat & data, rtabmap_ros::UserData & dataMsg, bool compress);
inline double timestampFromROS(const ros::Time & stamp) {return double(stamp.sec) + double(stamp.nsec)/1000000000.0;} inline double timestampFromROS(const ros::Time & stamp) {return double(stamp.sec) + double(stamp.nsec)/1000000000.0;}
// common stuff
rtabmap::Transform getTransform(
const std::string & fromFrameId,
const std::string & toFrameId,
const ros::Time & stamp,
tf::TransformListener & listener,
double waitForTransform);
// get moving transform accordingly to a fixed frame. For example get
// transform of /base_link between two stamps accordingly to /odom frame.
rtabmap::Transform getTransform(
const std::string & sourceTargetFrame,
const std::string & fixedFrame,
const ros::Time & stampSource,
const ros::Time & stampTarget,
tf::TransformListener & listener,
double waitForTransform);
bool convertRGBDMsgs(
const std::vector<cv_bridge::CvImageConstPtr> & imageMsgs,
const std::vector<cv_bridge::CvImageConstPtr> & depthMsgs,
const std::vector<sensor_msgs::CameraInfo> & cameraInfoMsgs,
const std::string & frameId,
const std::string & odomFrameId,
const ros::Time & odomStamp,
cv::Mat & rgb,
cv::Mat & depth,
std::vector<rtabmap::CameraModel> & cameraModels,
tf::TransformListener & listener,
double waitForTransform);
bool convertStereoMsg(
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg,
const std::string & frameId,
const std::string & odomFrameId,
const ros::Time & odomStamp,
cv::Mat & left,
cv::Mat & right,
rtabmap::StereoCameraModel & stereoModel,
tf::TransformListener & listener,
double waitForTransform);
bool convertScanMsg(
const sensor_msgs::LaserScanConstPtr& scan2dMsg,
const std::string & frameId,
const std::string & odomFrameId,
const ros::Time & odomStamp,
cv::Mat & scan,
rtabmap::Transform & scanLocalTransform,
tf::TransformListener & listener,
double waitForTransform);
bool convertScan3dMsg(
const sensor_msgs::PointCloud2ConstPtr & scan3dMsg,
const std::string & frameId,
const std::string & odomFrameId,
const ros::Time & odomStamp,
int scanCloudNormalK,
cv::Mat & scan,
rtabmap::Transform & scanLocalTransform,
tf::TransformListener & listener,
double waitForTransform);
} }
#endif /* MSGCONVERSION_H_ */ #endif /* MSGCONVERSION_H_ */
@@ -41,6 +41,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/SensorData.h> #include <rtabmap/core/SensorData.h>
#include <rtabmap/core/Parameters.h> #include <rtabmap/core/Parameters.h>
#include <boost/thread.hpp>
namespace rtabmap { namespace rtabmap {
class Odometry; class Odometry;
} }
@@ -51,7 +53,7 @@ class OdometryROS : public nodelet::Nodelet
{ {
public: public:
OdometryROS(bool stereo); OdometryROS(bool stereoParams, bool visParams, bool icpParams);
virtual ~OdometryROS(); virtual ~OdometryROS();
void processData(const rtabmap::SensorData & data, const ros::Time & stamp); void processData(const rtabmap::SensorData & data, const ros::Time & stamp);
@@ -68,25 +70,32 @@ public:
const std::string & frameId() const {return frameId_;} const std::string & frameId() const {return frameId_;}
const std::string & odomFrameId() const {return odomFrameId_;} const std::string & odomFrameId() const {return odomFrameId_;}
const rtabmap::ParametersMap & parameters() const {return parameters_;} const rtabmap::ParametersMap & parameters() const {return parameters_;}
const tf::TransformListener & tfListener() const {return tfListener_;}
bool isPaused() const {return paused_;} bool isPaused() const {return paused_;}
bool isOdometryF2M() const;
rtabmap::Transform getTransform(const std::string & fromFrameId, const std::string & toFrameId, const ros::Time & stamp) const; rtabmap::Transform getTransform(const std::string & fromFrameId, const std::string & toFrameId, const ros::Time & stamp) const;
protected: protected:
void startWarningThread(const std::string & subscribedTopicsMsg, bool approxSync);
void callbackCalled() {callbackCalled_ = true;}
virtual void flushCallbacks() = 0; virtual void flushCallbacks() = 0;
tf::TransformListener & tfListener() {return tfListener_;}
private: private:
void warningLoop(const std::string & subscribedTopicsMsg, bool approxSync);
virtual void onInit(); virtual void onInit();
virtual void onOdomInit() = 0; virtual void onOdomInit() = 0;
virtual void updateParameters(rtabmap::ParametersMap & parameters) {}
private: private:
rtabmap::Odometry * odometry_; rtabmap::Odometry * odometry_;
boost::thread * warningThread_;
bool callbackCalled_;
// parameters // parameters
std::string frameId_; std::string frameId_;
std::string odomFrameId_; std::string odomFrameId_;
std::string groundTruthFrameId_; std::string groundTruthFrameId_;
std::string guessFrameId_;
bool publishTf_; bool publishTf_;
bool waitForTransform_; bool waitForTransform_;
double waitForTransformDuration_; double waitForTransformDuration_;
@@ -97,6 +106,7 @@ private:
ros::Publisher odomPub_; ros::Publisher odomPub_;
ros::Publisher odomInfoPub_; ros::Publisher odomInfoPub_;
ros::Publisher odomLocalMap_; ros::Publisher odomLocalMap_;
ros::Publisher odomLocalScanMap_;
ros::Publisher odomLastFrame_; ros::Publisher odomLastFrame_;
ros::ServiceServer resetSrv_; ros::ServiceServer resetSrv_;
ros::ServiceServer resetToPoseSrv_; ros::ServiceServer resetToPoseSrv_;
@@ -112,7 +122,9 @@ private:
bool paused_; bool paused_;
int resetCountdown_; int resetCountdown_;
int resetCurrentCount_; int resetCurrentCount_;
bool stereo_; bool stereoParams_;
bool visParams_;
bool icpParams_;
}; };
} }
@@ -28,7 +28,7 @@
<rosparam file="$(find rtabmap_ros)/launch/azimut3/config/costmap_common_params.yaml" command="load" ns="global_costmap" /> <rosparam file="$(find rtabmap_ros)/launch/azimut3/config/costmap_common_params.yaml" command="load" ns="global_costmap" />
<rosparam file="$(find rtabmap_ros)/launch/azimut3/config/costmap_common_params.yaml" command="load" ns="local_costmap" /> <rosparam file="$(find rtabmap_ros)/launch/azimut3/config/costmap_common_params.yaml" command="load" ns="local_costmap" />
<rosparam file="$(find rtabmap_ros)/launch/azimut3/config/local_costmap_params_3d.yaml" command="load" /> <rosparam file="$(find rtabmap_ros)/launch/azimut3/config/local_costmap_params_3d.yaml" command="load" />
<rosparam file="$(find rtabmap_ros)/launch/azimut3/config/global_costmap_params.yaml" command="load" /> <rosparam file="$(find rtabmap_ros)/launch/azimut3/config/global_costmap_params.yaml" command="load" ns="global_costmap"/>
<rosparam file="$(find rtabmap_ros)/launch/azimut3/config/base_local_planner_params.yaml" command="load" /> <rosparam file="$(find rtabmap_ros)/launch/azimut3/config/base_local_planner_params.yaml" command="load" />
</node> </node>
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 551 KiB

+1 -1
View File
@@ -180,7 +180,7 @@ Visualization Manager:
Draw Behind: false Draw Behind: false
Enabled: true Enabled: true
Name: Map Name: Map
Topic: /rtabmap/proj_map Topic: /rtabmap/grid_map
Value: true Value: true
- Class: rtabmap_ros/Info - Class: rtabmap_ros/Info
Enabled: true Enabled: true
+5 -3
View File
@@ -5,7 +5,8 @@
<arg name="subscribe_depth" default="true"/> <arg name="subscribe_depth" default="true"/>
<arg name="subscribe_stereo" default="false"/> <arg name="subscribe_stereo" default="false"/>
<arg name="subscribe_scan" default="false"/> <arg name="subscribe_scan" default="false"/>
<arg name="stereo_approx_sync" default="false"/> <arg if="$(arg subscribe_stereo)" name="approx_sync" default="false"/>
<arg unless="$(arg subscribe_stereo)" name="approx_sync" default="true"/>
<arg name="frame_id" default="camera_link"/> <arg name="frame_id" default="camera_link"/>
<arg name="odom_frame_id" default=""/> <!-- use topic when not set, otherwise use TF if set --> <arg name="odom_frame_id" default=""/> <!-- use topic when not set, otherwise use TF if set -->
@@ -41,7 +42,8 @@
<param name="publish_tf" type="bool" value="false"/> <!-- don't publish TF --> <param name="publish_tf" type="bool" value="false"/> <!-- don't publish TF -->
<param name="RGBD/ProximityBySpace" type="string" value="false"/> <param name="RGBD/ProximityBySpace" type="string" value="false"/>
<param name="RGBD/LinearUpdate" type="string" value="0"/> <param name="RGBD/LinearUpdate" type="string" value="0"/>
<param name="RGBD/AngularUpdate" type="string" value="0"/> <param name="RGBD/AngularUpdate" type="string" value="0"/>
<param name="RGBD/CreateOccupancyGrid" type="string" value="false"/>
<param unless="$(arg subscribe_odometry)" name="RGBD/Enabled" type="string" value="false"/> <param unless="$(arg subscribe_odometry)" name="RGBD/Enabled" type="string" value="false"/>
<param name="Rtabmap/DetectionRate" type="string" value="$(arg max_rate)"/> <param name="Rtabmap/DetectionRate" type="string" value="$(arg max_rate)"/>
@@ -52,7 +54,7 @@
<param name="subscribe_scan" type="bool" value="$(arg subscribe_scan)"/> <param name="subscribe_scan" type="bool" value="$(arg subscribe_scan)"/>
<param name="subscribe_stereo" type="bool" value="$(arg subscribe_stereo)"/> <param name="subscribe_stereo" type="bool" value="$(arg subscribe_stereo)"/>
<param name="queue_size" type="int" value="$(arg queue_size)"/> <param name="queue_size" type="int" value="$(arg queue_size)"/>
<param name="stereo_approx_sync" type="bool" value="$(arg stereo_approx_sync)"/> <param name="approx_sync" type="bool" value="$(arg approx_sync)"/>
<!-- Hack to use a fake odom_frame_id=frame_id if subscribe_odometry = false --> <!-- Hack to use a fake odom_frame_id=frame_id if subscribe_odometry = false -->
<param if="$(arg subscribe_odometry)" name="odom_frame_id" type="string" value="$(arg odom_frame_id)"/> <param if="$(arg subscribe_odometry)" name="odom_frame_id" type="string" value="$(arg odom_frame_id)"/>
@@ -6,6 +6,7 @@
<!-- Choose visualization --> <!-- Choose visualization -->
<arg name="rviz" default="false" /> <arg name="rviz" default="false" />
<arg name="rtabmapviz" default="true" /> <arg name="rtabmapviz" default="true" />
<arg name="rtabmap_args" default="" />
<param name="use_sim_time" type="bool" value="True"/> <param name="use_sim_time" type="bool" value="True"/>
@@ -13,7 +14,7 @@
<!-- SLAM (robot side) --> <!-- SLAM (robot side) -->
<!-- args: "delete_db_on_start" and "udebug" --> <!-- args: "delete_db_on_start" and "udebug" -->
<node name="rtabmap" pkg="rtabmap_ros" type="rtabmap" output="screen" args=""> <node name="rtabmap" pkg="rtabmap_ros" type="rtabmap" output="screen" args="$(arg rtabmap_args)">
<param name="frame_id" type="string" value="base_footprint"/> <param name="frame_id" type="string" value="base_footprint"/>
<param name="subscribe_depth" type="bool" value="true"/> <param name="subscribe_depth" type="bool" value="true"/>
@@ -33,7 +34,7 @@
<!-- RTAB-Map's parameters: do "rosrun rtabmap rtabmap (double-dash)params" to see the list of available parameters. --> <!-- RTAB-Map's parameters: do "rosrun rtabmap rtabmap (double-dash)params" to see the list of available parameters. -->
<param name="RGBD/NeighborLinkRefining" type="string" value="false"/> <param name="RGBD/NeighborLinkRefining" type="string" value="false"/>
<param name="RGBD/ProximityBySpace" type="string" value="false"/> <param name="RGBD/ProximityBySpace" type="string" value="false"/> <!-- Referred paper did only global loop closure detection -->
<param name="RGBD/ProximityByTime" type="string" value="false"/> <param name="RGBD/ProximityByTime" type="string" value="false"/>
<param name="RGBD/OptimizeFromGraphEnd" type="string" value="true"/> <param name="RGBD/OptimizeFromGraphEnd" type="string" value="true"/>
<param name="Reg/Strategy" type="string" value="1"/> <param name="Reg/Strategy" type="string" value="1"/>
@@ -49,8 +50,12 @@
<param name="Bayes/FullPredictionUpdate" type="string" value="true"/> <param name="Bayes/FullPredictionUpdate" type="string" value="true"/>
<param name="Kp/DetectorStrategy" type="string" value="0"/> <!-- use SURF --> <param name="Kp/DetectorStrategy" type="string" value="0"/> <!-- use SURF -->
<param name="Kp/MaxFeatures" type="string" value="400"/> <param name="Kp/MaxFeatures" type="string" value="400"/>
<param name="Optimizer/Slam2D" type="string" value="true"/>
<param name="Reg/Force3DoF" type="string" value="true"/> <param name="Reg/Force3DoF" type="string" value="true"/>
<param name="RGBD/OptimizeMaxError" type="string" value="0.25"/>
<param name="Optimizer/Strategy" type="string" value="0"/> <!-- TORO is the most stable for multi-session mapping -->
<param name="Optimizer/Iterations" type="string" value="100"/>
<param name="Kp/IncrementalFlann" type="string" value="false"/> <!-- Referred paper didn't use incremental FLANN -->
<param name="Grid/FromDepth" type="string" value="false"/>
</node> </node>
<!-- Visualisation RTAB-Map --> <!-- Visualisation RTAB-Map -->
+3 -4
View File
@@ -33,19 +33,18 @@
<remap from="depth/image" to="/data_throttled_image_depth"/> <remap from="depth/image" to="/data_throttled_image_depth"/>
<remap from="rgb/camera_info" to="/data_throttled_camera_info"/> <remap from="rgb/camera_info" to="/data_throttled_camera_info"/>
<param name="rgb/image_transport" type="string" value="compressed"/> <param name="rgb/image_transport" type="string" value="compressed"/>
<param name="depth/image_transport" type="string" value="compressedDepth"/> <param name="depth/image_transport" type="string" value="compressedDepth"/>
<!-- RTAB-Map's parameters: do "rosrun rtabmap rtabmap (double-dash)params" to see the list of available parameters. --> <!-- RTAB-Map's parameters: do "rosrun rtabmap rtabmap (double-dash)params" to see the list of available parameters. -->
<param name="RGBD/NeighborLinkRefining" type="string" value="true"/> <!-- Do odometry correction with consecutive laser scans --> <param name="RGBD/NeighborLinkRefining" type="string" value="true"/> <!-- Do odometry correction with consecutive laser scans -->
<param name="RGBD/ProximityBySpace" type="string" value="true"/> <!-- Local loop closure detection (using estimated position) with locations in WM --> <param name="RGBD/ProximityBySpace" type="string" value="true"/> <!-- Local loop closure detection (using estimated position) with locations in WM -->
<param name="RGBD/ProximityByTime" type="string" value="false"/> <!-- Local loop closure detection with locations in STM --> <param name="RGBD/ProximityByTime" type="string" value="false"/> <!-- Local loop closure detection with locations in STM -->
<param name="RGBD/OptimizeFromGraphEnd" type="string" value="true"/>
<param name="Reg/Strategy" type="string" value="1"/> <!-- 0=Visual, 1=ICP, 2=Visual+ICP --> <param name="Reg/Strategy" type="string" value="1"/> <!-- 0=Visual, 1=ICP, 2=Visual+ICP -->
<param name="Vis/InlierDistance" type="string" value="0.1"/> <!-- 3D visual words correspondence distance --> <param name="Vis/InlierDistance" type="string" value="0.1"/> <!-- 3D visual words correspondence distance -->
<param name="RGBD/OptimizeFromGraphEnd" type="string" value="false"/> <!-- Optimize graph from initial node so /map -> /odom transform will be generated --> <param name="RGBD/OptimizeFromGraphEnd" type="string" value="false"/> <!-- Optimize graph from initial node so /map -> /odom transform will be generated -->
<param name="Optimizer/Slam2D" type="string" value="true"/>
<param name="Reg/Force3DoF" type="string" value="true"/> <param name="Reg/Force3DoF" type="string" value="true"/>
<param name="Grid/FromDepth" type="string" value="false"/>
<!-- localization mode --> <!-- localization mode -->
<param if="$(arg localization)" name="Mem/IncrementalMemory" type="string" value="false"/> <param if="$(arg localization)" name="Mem/IncrementalMemory" type="string" value="false"/>
+2
View File
@@ -77,6 +77,8 @@
<!-- RTAB-Map's parameters --> <!-- RTAB-Map's parameters -->
<param name="Rtabmap/TimeThr" type="string" value="700"/> <param name="Rtabmap/TimeThr" type="string" value="700"/>
<param name="Grid/DepthDecimation" type="string" value="4"/>
<param name="Grid/FlatObstacleDetected" type="string" value="true"/>
<param name="Kp/MaxFeatures" type="string" value="200"/> <param name="Kp/MaxFeatures" type="string" value="200"/>
<param name="Kp/MaxDepth" type="string" value="10"/> <param name="Kp/MaxDepth" type="string" value="10"/>
<param name="Kp/DetectorStrategy" type="string" value="0"/> <!-- use SURF --> <param name="Kp/DetectorStrategy" type="string" value="0"/> <!-- use SURF -->
+34 -49
View File
@@ -1,7 +1,7 @@
<launch> <launch>
<!-- Multi-cameras demo with 2 Kinects --> <!-- Multi-cameras demo with 2 Kinects -->
<!-- Cameras --> <!-- Cameras -->
<include file="$(find freenect_launch)/launch/freenect.launch"> <include file="$(find freenect_launch)/launch/freenect.launch">
@@ -15,7 +15,7 @@
<arg name="device_id" value="#2" /> <arg name="device_id" value="#2" />
</include> </include>
<!-- Frames: Kinects are placed at 90 degrees --> <!-- Frames: Kinects are placed at 90 degrees, clockwise -->
<node pkg="tf" type="static_transform_publisher" name="base_to_camera1_tf" <node pkg="tf" type="static_transform_publisher" name="base_to_camera1_tf"
args="0.0 0.0 0.0 0.0 0.0 0.0 /base_link /camera1_link 100" /> args="0.0 0.0 0.0 0.0 0.0 0.0 /base_link /camera1_link 100" />
<node pkg="tf" type="static_transform_publisher" name="base_to_camera2_tf" <node pkg="tf" type="static_transform_publisher" name="base_to_camera2_tf"
@@ -46,21 +46,33 @@
<arg name="local_map" default="1000" /> <arg name="local_map" default="1000" />
<arg name="odom_info_data" default="true" /> <arg name="odom_info_data" default="true" />
<arg name="wait_for_transform" default="true" /> <arg name="wait_for_transform" default="true" />
<!-- sync rgb/depth images per camera -->
<group ns="camera1">
<node pkg="nodelet" type="nodelet" name="rgbd_sync" args="load rtabmap_ros/rgbd_sync camera1_nodelet_manager">
<remap from="rgb/image" to="rgb/image_rect_color"/>
<remap from="depth/image" to="depth_registered/image_raw"/>
<remap from="rgb/camera_info" to="rgb/camera_info"/>
</node>
</group>
<group ns="camera2">
<node pkg="nodelet" type="nodelet" name="rgbd_sync" args="load rtabmap_ros/rgbd_sync camera2_nodelet_manager">
<remap from="rgb/image" to="rgb/image_rect_color"/>
<remap from="depth/image" to="depth_registered/image_raw"/>
<remap from="rgb/camera_info" to="rgb/camera_info"/>
</node>
</group>
<group ns="rtabmap"> <group ns="rtabmap">
<!-- Odometry --> <!-- Odometry -->
<node pkg="rtabmap_ros" type="rgbd_odometry" name="rgbd_odometry" output="screen"> <node pkg="rtabmap_ros" type="rgbd_odometry" name="rgbd_odometry" output="screen">
<remap from="rgb0/image" to="/camera1/rgb/image_rect_color"/> <remap from="rgbd_image0" to="/camera1/rgbd_image"/>
<remap from="depth0/image" to="/camera1/depth_registered/image_raw"/> <remap from="rgbd_image1" to="/camera2/rgbd_image"/>
<remap from="rgb0/camera_info" to="/camera1/rgb/camera_info"/>
<remap from="rgb1/image" to="/camera2/rgb/image_rect_color"/>
<remap from="depth1/image" to="/camera2/depth_registered/image_raw"/>
<remap from="rgb1/camera_info" to="/camera2/rgb/camera_info"/>
<param name="subscribe_rgbd" type="bool" value="true"/>
<param name="frame_id" type="string" value="base_link"/> <param name="frame_id" type="string" value="base_link"/>
<param name="depth_cameras" type="int" value="2"/> <param name="rgbd_cameras" type="int" value="2"/>
<param name="wait_for_transform" type="bool" value="$(arg wait_for_transform)"/> <param name="wait_for_transform" type="bool" value="$(arg wait_for_transform)"/>
<param name="Odom/Strategy" type="string" value="$(arg strategy)"/> <param name="Odom/Strategy" type="string" value="$(arg strategy)"/>
<param name="Vis/FeatureType" type="string" value="$(arg feature)"/> <param name="Vis/FeatureType" type="string" value="$(arg feature)"/>
@@ -75,65 +87,38 @@
<!-- Visual SLAM (robot side) --> <!-- Visual SLAM (robot side) -->
<!-- args: "delete_db_on_start" and "udebug" --> <!-- args: "delete_db_on_start" and "udebug" -->
<node name="rtabmap" pkg="rtabmap_ros" type="rtabmap" output="screen" args="--delete_db_on_start"> <node name="rtabmap" pkg="rtabmap_ros" type="rtabmap" output="screen" args="--delete_db_on_start">
<param name="subscribe_depth" type="bool" value="true"/> <param name="subscribe_depth" type="bool" value="false"/>
<param name="depth_cameras" type="int" value="2"/> <param name="subscribe_rgbd" type="bool" value="true"/>
<param name="rgbd_cameras" type="int" value="2"/>
<param name="frame_id" type="string" value="base_link"/> <param name="frame_id" type="string" value="base_link"/>
<param name="gen_scan" type="bool" value="true"/> <param name="gen_scan" type="bool" value="true"/>
<param name="wait_for_transform" type="bool" value="$(arg wait_for_transform)"/> <param name="wait_for_transform" type="bool" value="$(arg wait_for_transform)"/>
<param name="map_negative_poses_ignored" type="bool" value="true"/>
<remap from="rgb0/image" to="/camera1/rgb/image_rect_color"/> <remap from="rgbd_image0" to="/camera1/rgbd_image"/>
<remap from="depth0/image" to="/camera1/depth_registered/image_raw"/> <remap from="rgbd_image1" to="/camera2/rgbd_image"/>
<remap from="rgb0/camera_info" to="/camera1/rgb/camera_info"/>
<remap from="rgb1/image" to="/camera2/rgb/image_rect_color"/>
<remap from="depth1/image" to="/camera2/depth_registered/image_raw"/>
<remap from="rgb1/camera_info" to="/camera2/rgb/camera_info"/>
<param name="Grid/FromDepth" type="string" value="false"/>
<param name="Vis/MinInliers" type="string" value="10"/> <param name="Vis/MinInliers" type="string" value="10"/>
<param name="Vis/InlierDistance" type="string" value="$(arg inlier_distance)"/> <param name="Vis/InlierDistance" type="string" value="$(arg inlier_distance)"/>
</node> </node>
<!-- Visualisation RTAB-Map --> <!-- Visualisation RTAB-Map -->
<node if="$(arg rtabmapviz)" pkg="rtabmap_ros" type="rtabmapviz" name="rtabmapviz" args="-d $(find rtabmap_ros)/launch/config/rgbd_gui.ini" output="screen"> <node if="$(arg rtabmapviz)" pkg="rtabmap_ros" type="rtabmapviz" name="rtabmapviz" args="-d $(find rtabmap_ros)/launch/config/rgbd_gui.ini" output="screen">
<param name="subscribe_depth" type="bool" value="true"/> <param name="subscribe_depth" type="bool" value="false"/>
<param name="subscribe_rgbd" type="bool" value="true"/>
<param name="subscribe_odom_info" type="bool" value="$(arg odom_info_data)"/> <param name="subscribe_odom_info" type="bool" value="$(arg odom_info_data)"/>
<param name="frame_id" type="string" value="base_link"/> <param name="frame_id" type="string" value="base_link"/>
<param name="depth_cameras" type="int" value="2"/> <param name="rgbd_cameras" type="int" value="2"/>
<param name="wait_for_transform" type="bool" value="$(arg wait_for_transform)"/> <param name="wait_for_transform" type="bool" value="$(arg wait_for_transform)"/>
<remap from="rgb0/image" to="/camera1/rgb/image_rect_color"/> <remap from="rgbd_image0" to="/camera1/rgbd_image"/>
<remap from="depth0/image" to="/camera1/depth_registered/image_raw"/> <remap from="rgbd_image1" to="/camera2/rgbd_image"/>
<remap from="rgb0/camera_info" to="/camera1/rgb/camera_info"/>
<remap from="rgb1/image" to="/camera2/rgb/image_rect_color"/>
<remap from="depth1/image" to="/camera2/depth_registered/image_raw"/>
<remap from="rgb1/camera_info" to="/camera2/rgb/camera_info"/>
</node> </node>
</group> </group>
<!-- Visualization RVIZ --> <!-- Visualization RVIZ -->
<node if="$(arg rviz)" pkg="rviz" type="rviz" name="rviz" args="-d $(find rtabmap_ros)/launch/config/rgbd.rviz"/> <node if="$(arg rviz)" pkg="rviz" type="rviz" name="rviz" args="-d $(find rtabmap_ros)/launch/config/rgbd.rviz"/>
<!-- sync cloud with odometry and voxelize the point cloud (for fast visualization in rviz) -->
<node if="$(arg rviz)" pkg="nodelet" type="nodelet" name="standalone_nodelet" args="manager" output="screen"/>
<node if="$(arg rviz)" pkg="nodelet" type="nodelet" name="data_odom_sync" args="load rtabmap_ros/data_odom_sync standalone_nodelet">
<remap from="rgb/image_in" to="camera1/rgb/image_rect_color"/>
<remap from="depth/image_in" to="camera1/depth_registered/image_raw"/>
<remap from="rgb/camera_info_in" to="camera1/rgb/camera_info"/>
<remap from="odom_in" to="rtabmap/odom"/>
<remap from="rgb/image_out" to="data_odom_sync/image"/>
<remap from="depth/image_out" to="data_odom_sync/depth"/>
<remap from="rgb/camera_info_out" to="data_odom_sync/camera_info"/>
<remap from="odom_out" to="odom_sync"/>
</node>
<node if="$(arg rviz)" pkg="nodelet" type="nodelet" name="points_xyzrgb" args="load rtabmap_ros/point_cloud_xyzrgb standalone_nodelet">
<remap from="rgb/image" to="data_odom_sync/image"/>
<remap from="depth/image" to="data_odom_sync/depth"/>
<remap from="rgb/camera_info" to="data_odom_sync/camera_info"/>
<remap from="cloud" to="voxel_cloud" />
<param name="voxel_size" type="double" value="0.01"/>
</node>
</launch> </launch>
+5 -3
View File
@@ -15,8 +15,8 @@
<arg name="localization" default="false"/> <arg name="localization" default="false"/>
<!-- Corresponding config files --> <!-- Corresponding config files -->
<arg name="rtabmapviz_cfg" default="-d $(find rtabmap_ros)/launch/config/rgbd_gui.ini" /> <arg name="rtabmapviz_cfg" default="~/.ros/rtabmap_gui.ini" />
<arg name="rviz_cfg" default="-d $(find rtabmap_ros)/launch/config/rgbd.rviz" /> <arg name="rviz_cfg" default="$(find rtabmap_ros)/launch/config/rgbd.rviz" />
<arg name="frame_id" default="camera_link"/> <!-- Fixed frame id, you may set "base_link" or "base_footprint" if they are published --> <arg name="frame_id" default="camera_link"/> <!-- Fixed frame id, you may set "base_link" or "base_footprint" if they are published -->
<arg name="database_path" default="~/.ros/rtabmap.db"/> <arg name="database_path" default="~/.ros/rtabmap.db"/>
@@ -37,6 +37,7 @@
<arg name="visual_odometry" default="true"/> <!-- Generate visual odometry --> <arg name="visual_odometry" default="true"/> <!-- Generate visual odometry -->
<arg name="odom_topic" default="/odom"/> <!-- Odometry topic used if visual_odometry is false --> <arg name="odom_topic" default="/odom"/> <!-- Odometry topic used if visual_odometry is false -->
<arg name="odom_frame_id" default=""/> <!-- If set, TF is used to get odometry instead of the topic -->
<arg name="namespace" default="rtabmap"/> <arg name="namespace" default="rtabmap"/>
<arg name="wait_for_transform" default="0.2"/> <arg name="wait_for_transform" default="0.2"/>
@@ -68,7 +69,8 @@
<arg name="scan_cloud_topic" value="$(arg scan_cloud_topic)"/> <arg name="scan_cloud_topic" value="$(arg scan_cloud_topic)"/>
<arg name="visual_odometry" value="$(arg visual_odometry)"/> <arg name="visual_odometry" value="$(arg visual_odometry)"/>
<arg name="odom_topic" value="$(arg odom_topic)"/> <arg name="odom_topic" value="$(arg odom_topic)"/>
<arg name="odom_frame_id" value="$(arg odom_frame_id)"/>
<arg name="odom_args" value="$(arg rtabmap_args)"/> <arg name="odom_args" value="$(arg rtabmap_args)"/>
</include> </include>
+12 -6
View File
@@ -27,7 +27,7 @@
<!-- Corresponding config files --> <!-- Corresponding config files -->
<arg name="cfg" default="" /> <!-- To change RTAB-Map's parameters, set the path of config file (*.ini) generated by the standalone app --> <arg name="cfg" default="" /> <!-- To change RTAB-Map's parameters, set the path of config file (*.ini) generated by the standalone app -->
<arg name="gui_cfg" default="~/.ros/rtabmap_gui.ini" /> <arg name="gui_cfg" default="~/.ros/rtabmap_gui.ini" />
<arg name="rviz_cfg" default="-d $(find rtabmap_ros)/launch/config/rgbd.rviz" /> <arg name="rviz_cfg" default="$(find rtabmap_ros)/launch/config/rgbd.rviz" />
<arg name="frame_id" default="camera_link"/> <!-- Fixed frame id, you may set "base_link" or "base_footprint" if they are published --> <arg name="frame_id" default="camera_link"/> <!-- Fixed frame id, you may set "base_link" or "base_footprint" if they are published -->
<arg name="namespace" default="rtabmap"/> <arg name="namespace" default="rtabmap"/>
@@ -36,7 +36,10 @@
<arg name="wait_for_transform" default="0.2"/> <arg name="wait_for_transform" default="0.2"/>
<arg name="rtabmap_args" default=""/> <!-- delete_db_on_start, udebug --> <arg name="rtabmap_args" default=""/> <!-- delete_db_on_start, udebug -->
<arg name="launch_prefix" default=""/> <!-- for debugging purpose, it fills launch-prefix tag of the nodes --> <arg name="launch_prefix" default=""/> <!-- for debugging purpose, it fills launch-prefix tag of the nodes -->
<arg name="approx_sync" default="true"/> <!-- if timestamps of the input topics are not synchronized -->
<!-- if timestamps of the input topics are synchronized using approximate or exact time policy-->
<arg if="$(arg stereo)" name="approx_sync" default="false"/>
<arg unless="$(arg stereo)" name="approx_sync" default="true"/>
<!-- RGB-D related topics --> <!-- RGB-D related topics -->
<arg name="rgb_topic" default="/camera/rgb/image_rect_color" /> <arg name="rgb_topic" default="/camera/rgb/image_rect_color" />
@@ -51,9 +54,8 @@
<arg name="right_camera_info_topic" default="$(arg stereo_namespace)/right/camera_info" /> <arg name="right_camera_info_topic" default="$(arg stereo_namespace)/right/camera_info" />
<arg name="compressed" default="false"/> <!-- If you want to subscribe to compressed image topics --> <arg name="compressed" default="false"/> <!-- If you want to subscribe to compressed image topics -->
<!-- For depth_topic, "compressedDepth" image_transport is used. -->
<!-- For rgb_topic, see "rgb_image_transport" argument. -->
<arg name="rgb_image_transport" default="compressed"/> <!-- Common types: compressed, theora (see "rosrun image_transport list_transports") --> <arg name="rgb_image_transport" default="compressed"/> <!-- Common types: compressed, theora (see "rosrun image_transport list_transports") -->
<arg name="depth_image_transport" default="compressedDepth"/> <!-- Common types: compressed, theora (see "rosrun image_transport list_transports") -->
<arg name="subscribe_scan" default="false"/> <arg name="subscribe_scan" default="false"/>
<arg name="scan_topic" default="/scan"/> <arg name="scan_topic" default="/scan"/>
@@ -63,6 +65,7 @@
<arg name="visual_odometry" default="true"/> <!-- Launch rtabmap visual odometry node --> <arg name="visual_odometry" default="true"/> <!-- Launch rtabmap visual odometry node -->
<arg name="odom_topic" default="/odom"/> <!-- Odometry topic used if visual_odometry is false --> <arg name="odom_topic" default="/odom"/> <!-- Odometry topic used if visual_odometry is false -->
<arg name="odom_frame_id" default=""/> <!-- If set, TF is used to get odometry instead of the topic -->
<arg name="odom_args" default="$(arg rtabmap_args)"/> <arg name="odom_args" default="$(arg rtabmap_args)"/>
<!-- These arguments should not be modified directly, see referred topics without "_relay" suffix above --> <!-- These arguments should not be modified directly, see referred topics without "_relay" suffix above -->
@@ -81,7 +84,7 @@
<!-- RGB-D Odometry --> <!-- RGB-D Odometry -->
<group unless="$(arg stereo)"> <group unless="$(arg stereo)">
<node if="$(arg compressed)" name="republish_rgb" type="republish" pkg="image_transport" args="$(arg rgb_image_transport) in:=$(arg rgb_topic) raw out:=$(arg rgb_topic_relay)" /> <node if="$(arg compressed)" name="republish_rgb" type="republish" pkg="image_transport" args="$(arg rgb_image_transport) in:=$(arg rgb_topic) raw out:=$(arg rgb_topic_relay)" />
<node if="$(arg compressed)" name="republish_depth" type="republish" pkg="image_transport" args="compressedDepth in:=$(arg depth_topic) raw out:=$(arg depth_topic_relay)" /> <node if="$(arg compressed)" name="republish_depth" type="republish" pkg="image_transport" args="$(arg depth_image_transport) in:=$(arg depth_topic) raw out:=$(arg depth_topic_relay)" />
<node if="$(arg visual_odometry)" pkg="rtabmap_ros" type="rgbd_odometry" name="rgbd_odometry" output="screen" args="$(arg odom_args)" launch-prefix="$(arg launch_prefix)"> <node if="$(arg visual_odometry)" pkg="rtabmap_ros" type="rgbd_odometry" name="rgbd_odometry" output="screen" args="$(arg odom_args)" launch-prefix="$(arg launch_prefix)">
<remap from="rgb/image" to="$(arg rgb_topic_relay)"/> <remap from="rgb/image" to="$(arg rgb_topic_relay)"/>
@@ -124,6 +127,7 @@
<param name="subscribe_scan" type="bool" value="$(arg subscribe_scan)"/> <param name="subscribe_scan" type="bool" value="$(arg subscribe_scan)"/>
<param name="subscribe_scan_cloud" type="bool" value="$(arg subscribe_scan_cloud)"/> <param name="subscribe_scan_cloud" type="bool" value="$(arg subscribe_scan_cloud)"/>
<param name="frame_id" type="string" value="$(arg frame_id)"/> <param name="frame_id" type="string" value="$(arg frame_id)"/>
<param name="odom_frame_id" type="string" value="$(arg odom_frame_id)"/>
<param name="wait_for_transform_duration" type="double" value="$(arg wait_for_transform)"/> <param name="wait_for_transform_duration" type="double" value="$(arg wait_for_transform)"/>
<param name="database_path" type="string" value="$(arg database_path)"/> <param name="database_path" type="string" value="$(arg database_path)"/>
<param name="approx_sync" type="bool" value="$(arg approx_sync)"/> <param name="approx_sync" type="bool" value="$(arg approx_sync)"/>
@@ -158,8 +162,10 @@
<param name="subscribe_scan_cloud" type="bool" value="$(arg subscribe_scan_cloud)"/> <param name="subscribe_scan_cloud" type="bool" value="$(arg subscribe_scan_cloud)"/>
<param name="subscribe_odom_info" type="bool" value="$(arg visual_odometry)"/> <param name="subscribe_odom_info" type="bool" value="$(arg visual_odometry)"/>
<param name="frame_id" type="string" value="$(arg frame_id)"/> <param name="frame_id" type="string" value="$(arg frame_id)"/>
<param name="odom_frame_id" type="string" value="$(arg odom_frame_id)"/>
<param name="wait_for_transform_duration" type="double" value="$(arg wait_for_transform)"/> <param name="wait_for_transform_duration" type="double" value="$(arg wait_for_transform)"/>
<param name="queue_size" type="int" value="$(arg queue_size)"/> <param name="queue_size" type="int" value="$(arg queue_size)"/>
<param name="approx_sync" type="bool" value="$(arg approx_sync)"/>
<remap from="rgb/image" to="$(arg rgb_topic_relay)"/> <remap from="rgb/image" to="$(arg rgb_topic_relay)"/>
<remap from="depth/image" to="$(arg depth_topic_relay)"/> <remap from="depth/image" to="$(arg depth_topic_relay)"/>
@@ -178,7 +184,7 @@
</group> </group>
<!-- Visualization RVIZ --> <!-- Visualization RVIZ -->
<node if="$(arg rviz)" pkg="rviz" type="rviz" name="rviz" args="$(arg rviz_cfg)"/> <node if="$(arg rviz)" pkg="rviz" type="rviz" name="rviz" args="-d $(arg rviz_cfg)"/>
<node if="$(arg rviz)" pkg="nodelet" type="nodelet" name="points_xyzrgb" args="standalone rtabmap_ros/point_cloud_xyzrgb"> <node if="$(arg rviz)" pkg="nodelet" type="nodelet" name="points_xyzrgb" args="standalone rtabmap_ros/point_cloud_xyzrgb">
<remap from="left/image" to="$(arg left_image_topic_relay)"/> <remap from="left/image" to="$(arg left_image_topic_relay)"/>
<remap from="right/image" to="$(arg right_image_topic_relay)"/> <remap from="right/image" to="$(arg right_image_topic_relay)"/>
+5 -4
View File
@@ -15,8 +15,8 @@
<arg name="localization" default="false"/> <arg name="localization" default="false"/>
<!-- Corresponding config files --> <!-- Corresponding config files -->
<arg name="rtabmapviz_cfg" default="-d $(find rtabmap_ros)/launch/config/rgbd_gui.ini" /> <arg name="rtabmapviz_cfg" default="$(find rtabmap_ros)/launch/config/rgbd_gui.ini" />
<arg name="rviz_cfg" default="-d $(find rtabmap_ros)/launch/config/rgbd.rviz" /> <arg name="rviz_cfg" default="$(find rtabmap_ros)/launch/config/rgbd.rviz" />
<arg name="frame_id" default="base_link"/> <!-- Fixed frame id, you may set "base_link" or "base_footprint" if they are published --> <arg name="frame_id" default="base_link"/> <!-- Fixed frame id, you may set "base_link" or "base_footprint" if they are published -->
<arg name="database_path" default="~/.ros/rtabmap.db"/> <arg name="database_path" default="~/.ros/rtabmap.db"/>
@@ -39,12 +39,12 @@
<arg name="visual_odometry" default="true"/> <!-- Generate visual odometry --> <arg name="visual_odometry" default="true"/> <!-- Generate visual odometry -->
<arg name="odom_topic" default="/odom"/> <!-- Odometry topic used if visual_odometry is false --> <arg name="odom_topic" default="/odom"/> <!-- Odometry topic used if visual_odometry is false -->
<arg name="odom_frame_id" default=""/> <!-- If set, TF is used to get odometry instead of the topic -->
<arg name="namespace" default="rtabmap"/> <arg name="namespace" default="rtabmap"/>
<arg name="wait_for_transform" default="0.2"/> <arg name="wait_for_transform" default="0.2"/>
<include file="$(find rtabmap_ros)/launch/rtabmap.launch"> <include file="$(find rtabmap_ros)/launch/rtabmap.launch">
<arg name="rgbd" value="false"/>
<arg name="stereo" value="true"/> <arg name="stereo" value="true"/>
<arg name="rtabmapviz" value="$(arg rtabmapviz)" /> <arg name="rtabmapviz" value="$(arg rtabmapviz)" />
<arg name="rviz" value="$(arg rviz)" /> <arg name="rviz" value="$(arg rviz)" />
@@ -75,7 +75,8 @@
<arg name="scan_cloud_topic" value="$(arg scan_cloud_topic)"/> <arg name="scan_cloud_topic" value="$(arg scan_cloud_topic)"/>
<arg name="visual_odometry" value="$(arg visual_odometry)"/> <arg name="visual_odometry" value="$(arg visual_odometry)"/>
<arg name="odom_topic" value="$(arg odom_topic)"/> <arg name="odom_topic" value="$(arg odom_topic)"/>
<arg name="odom_frame_id" value="$(arg odom_frame_id)"/>
<arg name="odom_args" value="$(arg rtabmap_args)"/> <arg name="odom_args" value="$(arg rtabmap_args)"/>
</include> </include>
+2
View File
@@ -62,6 +62,8 @@
<param name="RGBD/LoopClosureReextractFeatures" type="string" value="false"/> <param name="RGBD/LoopClosureReextractFeatures" type="string" value="false"/>
<param name="Mem/RawDescriptorsKept" type="string" value="true"/> <param name="Mem/RawDescriptorsKept" type="string" value="true"/>
<param name="Kp/DetectorStrategy" type="string" value="0"/> <param name="Kp/DetectorStrategy" type="string" value="0"/>
<param name="RGBD/CreateOccupancyGrid" type="string" value="false"/>
<param name="Rtabmap/CreateIntermediateNodes" type="string" value="true"/>
<param name="frame_id" type="string" value="kinect"/> <param name="frame_id" type="string" value="kinect"/>
<param name="ground_truth_frame_id" type="string" value="world"/> <param name="ground_truth_frame_id" type="string" value="world"/>
@@ -1,6 +1,7 @@
<launch> <launch>
<arg name="localization" default="false"/> <arg name="localization" default="false"/>
<arg name="uid"/>
<!-- Kinect: --> <!-- Kinect: -->
<include file="$(find freenect_launch)/launch/freenect.launch"> <include file="$(find freenect_launch)/launch/freenect.launch">
@@ -12,7 +13,7 @@
<node pkg="imu_brick" type="imu_brick_node" name="imu_brick"> <node pkg="imu_brick" type="imu_brick_node" name="imu_brick">
<param name="frame_id" value="imu_link"/> <param name="frame_id" value="imu_link"/>
<param name="period_ms" value="10"/> <param name="period_ms" value="10"/>
<param name="uid" type="string" value="6xDEo7"/> <param name="uid" type="string" value="$(arg uid)"/>
<param name="cov_orientation" type="double" value="0.0005"/> <param name="cov_orientation" type="double" value="0.0005"/>
<param name="cov_velocity" type="double" value="0.00025"/> <param name="cov_velocity" type="double" value="0.00025"/>
<param name="cov_acceleration" type="double" value="0.1"/> <param name="cov_acceleration" type="double" value="0.1"/>
+53
View File
@@ -0,0 +1,53 @@
<launch>
<!-- We test here ICP odometry using a guess from visual odometry -->
<arg name="rgbd" default="false"/>
<include file="$(find freenect_launch)/launch/freenect.launch" >
<arg name="depth_registration" value="true"/>
<arg name="data_skip" value="3"/>
</include>
<group ns="camera">
<node pkg="nodelet" type="nodelet" name="points_xyz" args="load rtabmap_ros/point_cloud_xyz camera_nodelet_manager">
<remap from="depth/image" to="depth_registered/image_raw"/>
<remap from="depth/camera_info" to="depth_registered/camera_info"/>
<remap from="cloud" to="/voxel_cloud" />
<param name="voxel_size" type="double" value="0.05"/>
<param name="decimation" type="int" value="8"/>
<param name="Odom/AlignWithGround" type="string" value="true"/>
</node>
<node if="$(arg rgbd)" pkg="nodelet" type="nodelet" name="rgbdicp_odometry" args="load rtabmap_ros/rgbdicp_odometry camera_nodelet_manager">
<remap from="scan_cloud" to="/voxel_cloud"/>
<remap from="depth/image" to="depth_registered/image_raw"/>
<remap from="rgb/camera_info" to="rgb/camera_info"/>
<remap from="rgb/image" to="rgb/image_rect_mono"/>
<param name="frame_id" type="string" value="camera_link"/>
<param name="scan_cloud_normal_k" type="int" value="10"/>
<param name="subscribe_scan_cloud" type="bool" value="true"/>
<param name="Icp/PointToPlane" type="string" value="true"/>
<param name="Icp/VoxelSize" type="string" value="0"/>
</node>
<node unless="$(arg rgbd)" pkg="nodelet" type="nodelet" name="icp_odometry" args="load rtabmap_ros/icp_odometry camera_nodelet_manager">
<remap from="scan_cloud" to="/voxel_cloud"/>
<param name="frame_id" type="string" value="camera_link"/>
<param name="scan_cloud_normal_k" type="int" value="10"/>
<param name="Icp/PointToPlane" type="string" value="true"/>
<param name="Icp/VoxelSize" type="string" value="0"/>
<param name="Odom/GuessMotion" type="string" value="true"/>
</node>
</group>
<!-- Visualization RVIZ -->
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find rtabmap_ros)/launch/config/rgbd.rviz"/>
</launch>
+24
View File
@@ -0,0 +1,24 @@
<launch>
<include file="$(find rtabmap_ros)/launch/rtabmap.launch">
<arg name="rtabmap_args" value="
--delete_db_on_start
--RGBD/OptimizeMaxError 0
--Optimizer/Iterations 0
--RGBD/ProximityBySpace false"/>
<arg name="rtabmapviz" value="false"/>
</include>
<group ns="rtabmap">
<node pkg="rtabmap_ros" type="map_optimizer" name="map_optimizer"/>
<node pkg="rtabmap_ros" type="rtabmapviz" name="rtabmapviz" output="screen">
<remap from="mapData" to="mapData_optimized"/>
<param name="frame_id" value="camera_link"/>
<param name="subscribe_depth" value="false"/>
</node>
<node pkg="rtabmap_ros" type="map_assembler" name="map_assembler">
<remap from="mapData" to="mapData_optimized"/>
</node>
</group>
</launch>
@@ -1,8 +1,6 @@
<launch> <launch>
<!-- Use stereo_outdoorA.bag for testing --> <!-- Use stereo_outdoorA.bag for testing -->
<arg name="optimize_for_close_objects" default="false" />
<include file="$(find rtabmap_ros)/launch/demo/demo_stereo_outdoor.launch"/> <include file="$(find rtabmap_ros)/launch/demo/demo_stereo_outdoor.launch"/>
<group ns="/stereo_camera" > <group ns="/stereo_camera" >
@@ -23,7 +21,6 @@
<param name="wait_for_transform" type="bool" value="true"/> <param name="wait_for_transform" type="bool" value="true"/>
<param name="min_cluster_size" type="int" value="20"/> <param name="min_cluster_size" type="int" value="20"/>
<param name="max_obstacles_height" type="double" value="0.0"/> <param name="max_obstacles_height" type="double" value="0.0"/>
<param name="optimize_for_close_objects" type="bool" value="$(arg optimize_for_close_objects)"/>
</node> </node>
</group> </group>
+48
View File
@@ -0,0 +1,48 @@
<launch>
<arg name="compressed" default="false"/>
<group ns="camera">
<node pkg="nodelet" type="nodelet" name="rgbd_sync" args="load rtabmap_ros/rgbd_sync camera_nodelet_manager">
<remap from="rgb/image" to="rgb/image_rect_color"/>
<remap from="depth/image" to="depth_registered/image_raw"/>
<remap from="rgb/camera_info" to="rgb/camera_info"/>
</node>
</group>
<!-- Nodes -->
<group ns="rtabmap">
<!-- RGB-D Odometry -->
<node pkg="rtabmap_ros" type="rgbd_odometry" name="rgbd_odometry" output="screen">
<remap from="rgb/image" to="/camera/rgb/image_rect_color"/>
<remap from="depth/image" to="/camera/depth_registered/image_raw"/>
<remap from="rgb/camera_info" to="/camera/rgb/camera_info"/>
<param name="Odom/AlignWithGround" type="string" value="true"/>
<param name="frame_id" type="string" value="camera_link"/>
</node>
<node name="rtabmap" pkg="rtabmap_ros" type="rtabmap" output="screen" args="--delete_db_on_start">
<param name="subscribe_depth" type="bool" value="false"/>
<param name="subscribe_rgbd" type="bool" value="true"/>
<param name="frame_id" type="string" value="camera_link"/>
<param name="approx_sync" type="string" value="false"/>
<remap if="$(arg compressed)" from="rgbd_image" to="/camera/rgbd_image/compressed"/>
<remap unless="$(arg compressed)" from="rgbd_image" to="/camera/rgbd_image"/>
</node>
<node pkg="rtabmap_ros" type="rtabmapviz" name="rtabmapviz" output="screen">
<param name="subscribe_depth" type="bool" value="false"/>
<param name="subscribe_rgbd" type="bool" value="true"/>
<param name="frame_id" type="string" value="camera_link"/>
<param name="approx_sync" type="string" value="false"/>
<remap if="$(arg compressed)" from="rgbd_image" to="/camera/rgbd_image/compressed"/>
<remap unless="$(arg compressed)" from="rgbd_image" to="/camera/rgbd_image"/>
<param name="subscribe_odom_info" type="bool" value="true"/>
</node>
</group>
</launch>
+49
View File
@@ -0,0 +1,49 @@
<launch>
<!-- Kinect: -->
<include file="$(find freenect_launch)/launch/freenect.launch">
<arg name="depth_registration" value="true" />
</include>
<arg name="frame_id" default="camera_link"/>
<arg name="rtabmap_args" default=""/> <!-- delete_db_on_start, udebug -->
<arg name="odom_args" default="$(arg rtabmap_args)"/>
<!-- RGB-D related topics -->
<arg name="rgb_topic" default="/camera/rgb/image_rect_color" />
<arg name="depth_topic" default="/camera/depth_registered/image_raw" />
<arg name="camera_info_topic" default="/camera/rgb/camera_info" />
<group ns="camera">
<!-- Use RGBD synchronization -->
<node pkg="nodelet" type="nodelet" name="rgbd_sync" args="load rtabmap_ros/rgbd_sync camera_nodelet_manager">
<remap from="rgb/image" to="$(arg rgb_topic)"/>
<remap from="depth/image" to="$(arg depth_topic)"/>
<remap from="rgb/camera_info" to="$(arg camera_info_topic)"/>
</node>
<!-- RGB-D Odometry -->
<node pkg="nodelet" type="nodelet" name="rgbd_odometry" args="load rtabmap_ros/rgbd_odometry camera_nodelet_manager $(arg odom_args)">
<param name="frame_id" type="string" value="$(arg frame_id)"/>
<param name="subscribe_depth" type="bool" value="false"/>
<param name="subscribe_rgbd" type="bool" value="true"/>
</node>
<!-- RTAB-Map -->
<node pkg="nodelet" type="nodelet" name="rtabmap" args="load rtabmap_ros/rtabmap camera_nodelet_manager $(arg rtabmap_args)">
<param name="frame_id" type="string" value="$(arg frame_id)"/>
<param name="subscribe_depth" type="bool" value="false"/>
<param name="subscribe_rgbd" type="bool" value="true"/>
<param name="approx_sync" type="bool" value="false"/>
</node>
<!-- Visualisation -->
<node pkg="rtabmap_ros" type="rtabmapviz" name="rtabmapviz" output="screen">
<param name="frame_id" type="string" value="$(arg frame_id)"/>
</node>
</group>
</launch>
+20
View File
@@ -0,0 +1,20 @@
<launch>
<!-- Kinect: -->
<include file="$(find openni2_launch)/launch/openni2.launch">
<arg name="depth_registration" value="true" />
</include>
<arg name="depth" default="/camera/depth_registered/image_raw" />
<arg name="model" default="$(find rtabmap_ros)/launch/calibration/distortion_model_PS1080.bin" /> <!-- XTION Live Pro -->
<group ns="camera">
<!-- Undistort depth image -->
<node pkg="nodelet" type="nodelet" name="undistort" args="load rtabmap_ros/undistort_depth camera_nodelet_manager">
<remap from="depth" to="$(arg depth)"/>
<param name="model" value="$(arg model)"/>
</node>
</group>
</launch>
+15 -1
View File
@@ -24,6 +24,8 @@ float32[] fx
float32[] fy float32[] fy
float32[] cx float32[] cx
float32[] cy float32[] cy
float32[] width
float32[] height
float32 baseline float32 baseline
# local transform (/base_link -> /camera_link) # local transform (/base_link -> /camera_link)
geometry_msgs/Transform[] localTransform geometry_msgs/Transform[] localTransform
@@ -33,13 +35,25 @@ 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
KeyPoint[] wordKpts KeyPoint[] wordKpts
sensor_msgs/PointCloud2 wordPts sensor_msgs/PointCloud2 wordPts
# compressed descriptors
# use rtabmap::util3d::uncompressData() from "rtabmap/core/util3d.h"
uint8[] descriptors
+9 -2
View File
@@ -6,7 +6,8 @@ Header header
# bool lost; # bool lost;
# int matches; # int matches;
# int inliers; # int inliers;
# float variance; # float varianceLin;
# float varianceAng;
# int features; # int features;
# int localMapSize; # int localMapSize;
# float time; # float time;
@@ -27,9 +28,11 @@ Header header
bool lost bool lost
int32 matches int32 matches
int32 inliers int32 inliers
float32 variance float32 varianceLin
float32 varianceAng
int32 features int32 features
int32 localMapSize int32 localMapSize
int32 localScanMapSize
float32 timeEstimation float32 timeEstimation
float32 timeParticleFiltering float32 timeParticleFiltering
float32 stamp float32 stamp
@@ -52,3 +55,7 @@ int32[] cornerInliers
geometry_msgs/Transform transform geometry_msgs/Transform transform
geometry_msgs/Transform transformFiltered geometry_msgs/Transform transformFiltered
# compressed local scan map data
# use rtabmap::util3d::uncompressData() from "rtabmap/core/util3d.h"
uint8[] localScanMap
+12
View File
@@ -0,0 +1,12 @@
Header header
sensor_msgs/CameraInfo cameraInfo
# Raw
sensor_msgs/Image rgb
sensor_msgs/Image depth
# Compressed
sensor_msgs/CompressedImage rgbCompressed
sensor_msgs/CompressedImage depthCompressed
+12
View File
@@ -0,0 +1,12 @@
Header header
# OpenCV matrix containing the user data. A matrix of type CV_8UC1
# with 1 row is considered to be compressed (with rtabmap::compressData() method).
# If you have one dimension unsigned 8 bits uncompressed data, make sure to transpose it
# (to have multiple rows instead of multiple columns) in order to be detected as
# not compressed.
uint32 rows
uint32 cols
uint32 type
uint8[] data
+49
View File
@@ -1,5 +1,13 @@
<library path="lib/librtabmap_ros"> <library path="lib/librtabmap_ros">
<class name="rtabmap_ros/rtabmap"
type="rtabmap_ros::CoreWrapper"
base_class_type="nodelet::Nodelet">
<description>
This is my nodelet.
</description>
</class>
<class name="rtabmap_ros/rgbd_odometry" <class name="rtabmap_ros/rgbd_odometry"
type="rtabmap_ros::RGBDOdometry" type="rtabmap_ros::RGBDOdometry"
base_class_type="nodelet::Nodelet"> base_class_type="nodelet::Nodelet">
@@ -15,6 +23,22 @@
This is my nodelet. This is my nodelet.
</description> </description>
</class> </class>
<class name="rtabmap_ros/rgbdicp_odometry"
type="rtabmap_ros::RGBDICPOdometry"
base_class_type="nodelet::Nodelet">
<description>
This is my nodelet.
</description>
</class>
<class name="rtabmap_ros/icp_odometry"
type="rtabmap_ros::ICPOdometry"
base_class_type="nodelet::Nodelet">
<description>
This is my nodelet.
</description>
</class>
<class name="rtabmap_ros/data_throttle" <class name="rtabmap_ros/data_throttle"
type="rtabmap_ros::DataThrottleNodelet" type="rtabmap_ros::DataThrottleNodelet"
@@ -71,6 +95,14 @@
This is my nodelet. This is my nodelet.
</description> </description>
</class> </class>
<class name="rtabmap_ros/obstacles_detection_old"
type="rtabmap_ros::ObstaclesDetectionOld"
base_class_type="nodelet::Nodelet">
<description>
This is my nodelet.
</description>
</class>
<class name="rtabmap_ros/point_cloud_aggregator" <class name="rtabmap_ros/point_cloud_aggregator"
type="rtabmap_ros::PointCloudAggregator" type="rtabmap_ros::PointCloudAggregator"
@@ -79,5 +111,22 @@
This is my nodelet. This is my nodelet.
</description> </description>
</class> </class>
<class name="rtabmap_ros/rgbd_sync"
type="rtabmap_ros::RGBDSync"
base_class_type="nodelet::Nodelet">
<description>
This is my nodelet.
</description>
</class>
<class name="rtabmap_ros/undistort_depth"
type="rtabmap_ros::UndistortDepth"
base_class_type="nodelet::Nodelet">
<description>
This is my nodelet.
</description>
</class>
</library> </library>
+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.8</version> <version>0.11.13</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="[email protected]">Mathieu Labbe</maintainer> <maintainer email="[email protected]">Mathieu Labbe</maintainer>
<author>Mathieu Labbe</author> <author>Mathieu Labbe</author>
+411
View File
@@ -0,0 +1,411 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtabmap_ros/CommonDataSubscriber.h>
namespace rtabmap_ros {
CommonDataSubscriber::CommonDataSubscriber(bool gui) :
queueSize_(10),
approxSync_(true),
warningThread_(0),
callbackCalled_(false),
subscribedToDepth_(!gui),
subscribedToStereo_(false),
subscribedToRGBD_(false),
subscribedToScan2d_(false),
subscribedToScan3d_(false),
subscribedToOdomInfo_(false),
// RGB + Depth
SYNC_INIT(depth),
SYNC_INIT(depthScan2d),
SYNC_INIT(depthScan3d),
SYNC_INIT(depthInfo),
// RGB + Depth + Odom
SYNC_INIT(depthOdom),
SYNC_INIT(depthOdomScan2d),
SYNC_INIT(depthOdomScan3d),
SYNC_INIT(depthOdomInfo),
// RGB + Depth + User Data
SYNC_INIT(depthData),
SYNC_INIT(depthDataScan2d),
SYNC_INIT(depthDataScan3d),
SYNC_INIT(depthDataInfo),
// RGB + Depth + Odom + User Data
SYNC_INIT(depthOdomData),
SYNC_INIT(depthOdomDataScan2d),
SYNC_INIT(depthOdomDataScan3d),
SYNC_INIT(depthOdomDataInfo),
// Stereo
SYNC_INIT(stereo),
SYNC_INIT(stereoInfo),
// Stereo + Odom
SYNC_INIT(stereoOdom),
SYNC_INIT(stereoOdomInfo),
// 1 RGBD
SYNC_INIT(rgbdScan2d),
SYNC_INIT(rgbdScan3d),
SYNC_INIT(rgbdInfo),
// 1 RGBD + Odom
SYNC_INIT(rgbdOdom),
SYNC_INIT(rgbdOdomScan2d),
SYNC_INIT(rgbdOdomScan3d),
SYNC_INIT(rgbdOdomInfo),
// 1 RGBD + User Data
SYNC_INIT(rgbdData),
SYNC_INIT(rgbdDataScan2d),
SYNC_INIT(rgbdDataScan3d),
SYNC_INIT(rgbdDataInfo),
// 1 RGBD + Odom + User Data
SYNC_INIT(rgbdOdomData),
SYNC_INIT(rgbdOdomDataScan2d),
SYNC_INIT(rgbdOdomDataScan3d),
SYNC_INIT(rgbdOdomDataInfo),
// 2 RGBD
SYNC_INIT(rgbd2),
SYNC_INIT(rgbd2Scan2d),
SYNC_INIT(rgbd2Scan3d),
SYNC_INIT(rgbd2Info),
// 2 RGBD + Odom
SYNC_INIT(rgbd2Odom),
SYNC_INIT(rgbd2OdomScan2d),
SYNC_INIT(rgbd2OdomScan3d),
SYNC_INIT(rgbd2OdomInfo),
// 2 RGBD + User Data
SYNC_INIT(rgbd2Data),
SYNC_INIT(rgbd2DataScan2d),
SYNC_INIT(rgbd2DataScan3d),
SYNC_INIT(rgbd2DataInfo),
// 2 RGBD + Odom + User Data
SYNC_INIT(rgbd2OdomData),
SYNC_INIT(rgbd2OdomDataScan2d),
SYNC_INIT(rgbd2OdomDataScan3d),
SYNC_INIT(rgbd2OdomDataInfo)
{
}
void CommonDataSubscriber::setupCallbacks(ros::NodeHandle & nh, ros::NodeHandle & pnh, const std::string & name)
{
bool subscribeScan2d = false;
bool subscribeScan3d = false;
bool subscribeOdomInfo = false;
bool subscribeUserData = false;
int rgbdCameras = 1;
name_ = name;
// ROS related parameters (private)
pnh.param("subscribe_depth", subscribedToDepth_, subscribedToDepth_);
if(pnh.getParam("subscribe_laserScan", subscribeScan2d) && subscribeScan2d)
{
ROS_WARN("rtabmap: \"subscribe_laserScan\" parameter is deprecated, use \"subscribe_scan\" instead. The scan topic is still subscribed.");
}
pnh.param("subscribe_scan", subscribeScan2d, subscribeScan2d);
pnh.param("subscribe_scan_cloud", subscribeScan3d, subscribeScan3d);
pnh.param("subscribe_stereo", subscribedToStereo_, subscribedToStereo_);
pnh.param("subscribe_rgbd", subscribedToRGBD_, subscribedToRGBD_);
pnh.param("subscribe_odom_info", subscribeOdomInfo, subscribeOdomInfo);
pnh.param("subscribe_user_data", subscribeUserData, subscribeUserData);
if(subscribedToDepth_ && subscribedToStereo_)
{
ROS_WARN("rtabmap: Parameters subscribe_depth and subscribe_stereo cannot be true at the same time. Parameter subscribe_depth is set to false.");
subscribedToDepth_ = false;
}
if(subscribedToDepth_ && subscribedToRGBD_)
{
ROS_WARN("rtabmap: Parameters subscribe_depth and subscribe_rgbd cannot be true at the same time. Parameter subscribe_depth is set to false.");
subscribedToDepth_ = false;
}
if(subscribedToStereo_ && subscribedToRGBD_)
{
ROS_WARN("rtabmap: Parameters subscribe_stereo and subscribe_rgbd cannot be true at the same time. Parameter subscribe_stereo is set to false.");
subscribedToStereo_ = false;
}
if(subscribeScan2d && subscribeScan3d)
{
ROS_WARN("rtabmap: Parameters subscribe_scan and subscribe_scan_cloud cannot be true at the same time. Parameter subscribe_scan_cloud is set to false.");
subscribeScan3d = false;
}
if(subscribeScan2d || subscribeScan3d)
{
if(!subscribedToDepth_ && !subscribedToStereo_ && !subscribedToRGBD_)
{
ROS_WARN("When subscribing to laser scan, you should subscribe to depth, stereo or rgbd too. Subscribing to depth by default...");
subscribedToDepth_ = true;
}
}
if(subscribedToStereo_)
{
approxSync_ = false; // default for stereo: exact sync
}
std::string odomFrameId;
pnh.getParam("odom_frame_id", odomFrameId);
pnh.param("rgbd_cameras", rgbdCameras, rgbdCameras);
if(pnh.hasParam("depth_cameras"))
{
ROS_ERROR("\"depth_cameras\" parameter doesn't exist anymore. It is replaced by \"rgbd_cameras\" used when \"subscribe_rgbd\" is true.");
}
pnh.param("queue_size", queueSize_, queueSize_);
if(pnh.hasParam("stereo_approx_sync") && !pnh.hasParam("approx_sync"))
{
ROS_WARN("Parameter \"stereo_approx_sync\" has been renamed "
"to \"approx_sync\"! Your value is still copied to "
"corresponding parameter.");
pnh.param("stereo_approx_sync", approxSync_, approxSync_);
}
else
{
pnh.param("approx_sync", approxSync_, approxSync_);
}
if(rgbdCameras <= 0 && subscribedToRGBD_)
{
rgbdCameras = 1;
}
ROS_INFO("%s: queue_size = %d", name.c_str(), queueSize_);
ROS_INFO("%s: rgbd_cameras = %d", name.c_str(), rgbdCameras);
ROS_INFO("%s: approx_sync = %s", name.c_str(), approxSync_?"true":"false");
bool subscribeOdom = odomFrameId.empty();
if(subscribedToDepth_)
{
setupDepthCallbacks(
nh,
pnh,
subscribeOdom,
subscribeUserData,
subscribeScan2d,
subscribeScan3d,
subscribeOdomInfo,
queueSize_,
approxSync_);
}
else if(subscribedToStereo_)
{
setupStereoCallbacks(
nh,
pnh,
subscribeOdom,
subscribeOdomInfo,
queueSize_,
approxSync_);
}
else if(subscribedToRGBD_)
{
if(rgbdCameras == 2)
{
setupRGBD2Callbacks(
nh,
pnh,
subscribeOdom,
subscribeUserData,
subscribeScan2d,
subscribeScan3d,
subscribeOdomInfo,
queueSize_,
approxSync_);
}
else
{
setupRGBDCallbacks(
nh,
pnh,
subscribeOdom,
subscribeUserData,
subscribeScan2d,
subscribeScan3d,
subscribeOdomInfo,
queueSize_,
approxSync_);
}
}
if(subscribedToDepth_ || subscribedToStereo_ || subscribedToRGBD_)
{
warningThread_ = new boost::thread(boost::bind(&CommonDataSubscriber::warningLoop, this));
ROS_INFO("%s", subscribedTopicsMsg_.c_str());
}
}
CommonDataSubscriber::~CommonDataSubscriber()
{
if(warningThread_)
{
callbackCalled();
warningThread_->join();
delete warningThread_;
}
// RGB + Depth
SYNC_DEL(depth);
SYNC_DEL(depthScan2d);
SYNC_DEL(depthScan3d);
SYNC_DEL(depthInfo);
// RGB + Depth + Odom
SYNC_DEL(depthOdom);
SYNC_DEL(depthOdomScan2d);
SYNC_DEL(depthOdomScan3d);
SYNC_DEL(depthOdomInfo);
// RGB + Depth + User Data
SYNC_DEL(depthData);
SYNC_DEL(depthDataScan2d);
SYNC_DEL(depthDataScan3d);
SYNC_DEL(depthDataInfo);
// RGB + Depth + Odom + User Data
SYNC_DEL(depthOdomData);
SYNC_DEL(depthOdomDataScan2d);
SYNC_DEL(depthOdomDataScan3d);
SYNC_DEL(depthOdomDataInfo);
// Stereo
SYNC_DEL(stereo);
SYNC_DEL(stereoInfo);
// Stereo + Odom
SYNC_DEL(stereoOdom);
SYNC_DEL(stereoOdomInfo);
// 1 RGBD
SYNC_DEL(rgbdScan2d);
SYNC_DEL(rgbdScan3d);
SYNC_DEL(rgbdInfo);
// 1 RGBD + Odom
SYNC_DEL(rgbdOdom);
SYNC_DEL(rgbdOdomScan2d);
SYNC_DEL(rgbdOdomScan3d);
SYNC_DEL(rgbdOdomInfo);
// 1 RGBD + User Data
SYNC_DEL(rgbdData);
SYNC_DEL(rgbdDataScan2d);
SYNC_DEL(rgbdDataScan3d);
SYNC_DEL(rgbdDataInfo);
// 1 RGBD + Odom + User Data
SYNC_DEL(rgbdOdomData);
SYNC_DEL(rgbdOdomDataScan2d);
SYNC_DEL(rgbdOdomDataScan3d);
SYNC_DEL(rgbdOdomDataInfo);
// 2 RGBD
SYNC_DEL(rgbd2);
SYNC_DEL(rgbd2Scan2d);
SYNC_DEL(rgbd2Scan3d);
SYNC_DEL(rgbd2Info);
// 2 RGBD + Odom
SYNC_DEL(rgbd2Odom);
SYNC_DEL(rgbd2OdomScan2d);
SYNC_DEL(rgbd2OdomScan3d);
SYNC_DEL(rgbd2OdomInfo);
// 2 RGBD + User Data
SYNC_DEL(rgbd2Data);
SYNC_DEL(rgbd2DataScan2d);
SYNC_DEL(rgbd2DataScan3d);
SYNC_DEL(rgbd2DataInfo);
// 2 RGBD + Odom + User Data
SYNC_DEL(rgbd2OdomData);
SYNC_DEL(rgbd2OdomDataScan2d);
SYNC_DEL(rgbd2OdomDataScan3d);
SYNC_DEL(rgbd2OdomDataInfo);
for(unsigned int i=0; i<rgbdSubs_.size(); ++i)
{
delete rgbdSubs_[i];
}
rgbdSubs_.clear();
}
void CommonDataSubscriber::warningLoop()
{
ros::Duration r(5.0);
while(!callbackCalled_)
{
r.sleep();
if(!callbackCalled_)
{
ROS_WARN("%s: Did not receive data since 5 seconds! Make sure the input topics are "
"published (\"$ rostopic hz my_topic\") and the timestamps in their "
"header are set. If topics are coming from different computers, make sure "
"the clocks of the computers are synchronized (\"ntpdate\"). %s%s",
name_.c_str(),
approxSync_?
uFormat("If topics are not published at the same rate, you could increase \"queue_size\" parameter (current=%d).", queueSize_).c_str():
"Parameter \"approx_sync\" is false, which means that input topics should have all the exact timestamp for the callback to be called.",
subscribedTopicsMsg_.c_str());
}
}
}
void CommonDataSubscriber::commonSingleDepthCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const cv_bridge::CvImageConstPtr & imageMsg,
const cv_bridge::CvImageConstPtr & depthMsg,
const sensor_msgs::CameraInfo & cameraInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg)
{
callbackCalled();
std::vector<cv_bridge::CvImageConstPtr> imageMsgs;
std::vector<cv_bridge::CvImageConstPtr> depthMsgs;
std::vector<sensor_msgs::CameraInfo> cameraInfoMsgs;
if(imageMsg.get())
{
imageMsgs.push_back(imageMsg);
}
if(depthMsg.get())
{
depthMsgs.push_back(depthMsg);
}
cameraInfoMsgs.push_back(cameraInfoMsg);
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
} /* namespace rtabmap_ros */
+12 -16
View File
@@ -25,12 +25,14 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "CoreWrapper.h" #include "ros/ros.h"
#include <rtabmap/core/Parameters.h>
#include <rtabmap/utilite/ULogger.h> #include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UDirectory.h> #include <rtabmap/utilite/UDirectory.h>
#include <rtabmap/utilite/UStl.h> #include <rtabmap/utilite/UStl.h>
#include <rtabmap/utilite/UFile.h> #include <rtabmap/utilite/UFile.h>
#include <rtabmap/core/Version.h> #include <rtabmap/core/Version.h>
#include "nodelet/loader.h"
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
@@ -41,19 +43,14 @@ int main(int argc, char** argv)
ros::init(argc, argv, "rtabmap"); ros::init(argc, argv, "rtabmap");
bool deleteDbOnStart = false; nodelet::V_string nargv;
for(int i=1;i<argc;++i) for(int i=1;i<argc;++i)
{ {
if(strcmp(argv[i], "--delete_db_on_start") == 0) if(strcmp(argv[i], "--params") == 0 || strcmp(argv[i], "--params-all") == 0)
{
deleteDbOnStart = true;
}
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)
{ {
@@ -86,16 +83,15 @@ int main(int argc, char** argv)
"argument \"--params\" is detected!"); "argument \"--params\" is detected!");
exit(0); exit(0);
} }
nargv.push_back(argv[i]);
} }
rtabmap::ParametersMap parameters = rtabmap::Parameters::parseArguments(argc, argv); nodelet::Loader nodelet;
nodelet::M_string remap(ros::names::getRemappings());
CoreWrapper * rtabmap = new CoreWrapper(deleteDbOnStart, parameters); std::string nodelet_name = ros::this_node::getName();
nodelet.load(nodelet_name, "rtabmap_ros/rtabmap", remap, nargv);
ROS_INFO("rtabmap %s started...", RTABMAP_VERSION); ROS_INFO("rtabmap %s started...", RTABMAP_VERSION);
ros::spin(); ros::spin();
delete rtabmap;
return 0; return 0;
} }
+595 -1351
View File
File diff suppressed because it is too large Load Diff
-487
View File
@@ -1,487 +0,0 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef COREWRAPPER_H_
#define COREWRAPPER_H_
#include <ros/ros.h>
#include <std_srvs/Empty.h>
#include <tf/transform_listener.h>
#include <tf2_ros/transform_broadcaster.h>
#include <std_msgs/Empty.h>
#include <std_msgs/Int32.h>
#include <sensor_msgs/PointCloud2.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/CameraInfo.h>
#include <sensor_msgs/LaserScan.h>
#include <nav_msgs/Odometry.h>
#include <nav_msgs/GetMap.h>
#include <rtabmap/core/Parameters.h>
#include <rtabmap/core/Rtabmap.h>
#include "rtabmap_ros/GetMap.h"
#include "rtabmap_ros/ListLabels.h"
#include "rtabmap_ros/PublishMap.h"
#include "rtabmap_ros/SetGoal.h"
#include "rtabmap_ros/SetLabel.h"
#include "rtabmap_ros/Goal.h"
#include "MapsManager.h"
#include <message_filters/subscriber.h>
#include <message_filters/synchronizer.h>
#include <message_filters/sync_policies/approximate_time.h>
#include <message_filters/sync_policies/exact_time.h>
#include <image_transport/image_transport.h>
#include <image_transport/subscriber_filter.h>
#ifdef WITH_OCTOMAP_ROS
#include <octomap_msgs/GetOctomap.h>
#endif
#include <actionlib/client/simple_action_client.h>
#include <move_base_msgs/MoveBaseAction.h>
#include <move_base_msgs/MoveBaseActionGoal.h>
#include <move_base_msgs/MoveBaseActionResult.h>
#include <move_base_msgs/MoveBaseActionFeedback.h>
#include <actionlib_msgs/GoalStatusArray.h>
typedef actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> MoveBaseClient;
class CoreWrapper
{
public:
CoreWrapper(bool deleteDbOnStart, const rtabmap::ParametersMap & parameters);
virtual ~CoreWrapper();
private:
void setupCallbacks(
bool subscribeDepth,
bool subscribeScan2d,
bool subscribeScan3d,
bool subscribeStereo,
int queueSize,
bool approxSync,
int depthCameras);
void defaultCallback(const sensor_msgs::ImageConstPtr & imageMsg); // no odom
bool commonOdomUpdate(const nav_msgs::OdometryConstPtr & odomMsg);
bool commonOdomTFUpdate(const ros::Time & stamp); // TF odom
rtabmap::Transform getTransform(const std::string & fromFrameId, const std::string & toFrameId, const ros::Time & stamp) const;
void commonDepthCallback(
const std::string & odomFrameId,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg);
void commonDepthCallback(
const std::string & odomFrameId,
const std::vector<sensor_msgs::ImageConstPtr> & imageMsgs,
const std::vector<sensor_msgs::ImageConstPtr> & depthMsgs,
const std::vector<sensor_msgs::CameraInfoConstPtr> & cameraInfoMsgs,
const sensor_msgs::LaserScanConstPtr& scanMsg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg);
void commonStereoCallback(
const std::string & odomFrameId,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg);
// with odom msg
void depthCallback(
const sensor_msgs::ImageConstPtr& imageMsg,
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& imageDepthMsg,
const sensor_msgs::CameraInfoConstPtr& camInfoMsg);
void depthScanCallback(
const sensor_msgs::ImageConstPtr& imageMsg,
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& imageDepthMsg,
const sensor_msgs::CameraInfoConstPtr& camInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg);
void depthScan3dCallback(
const sensor_msgs::ImageConstPtr& imageMsg,
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& imageDepthMsg,
const sensor_msgs::CameraInfoConstPtr& camInfoMsg,
const sensor_msgs::PointCloud2ConstPtr& scanMsg);
void stereoCallback(
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg,
const nav_msgs::OdometryConstPtr & odomMsg);
void stereoScanCallback(
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg,
const nav_msgs::OdometryConstPtr & odomMsg);
void stereoScan3dCallback(
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg,
const sensor_msgs::PointCloud2ConstPtr& scanMsg,
const nav_msgs::OdometryConstPtr & odomMsg);
void depth2Callback(
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& image1Msg,
const sensor_msgs::ImageConstPtr& imageDepth1Msg,
const sensor_msgs::CameraInfoConstPtr& camInfo1Msg,
const sensor_msgs::ImageConstPtr& image2Msg,
const sensor_msgs::ImageConstPtr& imageDept2hMsg,
const sensor_msgs::CameraInfoConstPtr& camInfo2Msg);
// without odom, when TF is used for odom
void depthTFCallback(
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& imageDepthMsg,
const sensor_msgs::CameraInfoConstPtr& camInfoMsg);
void depthScanTFCallback(
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& imageDepthMsg,
const sensor_msgs::CameraInfoConstPtr& camInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg);
void depthScan3dTFCallback(
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& imageDepthMsg,
const sensor_msgs::CameraInfoConstPtr& camInfoMsg,
const sensor_msgs::PointCloud2ConstPtr& scanMsg);
void stereoTFCallback(
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg);
void stereoScanTFCallback(
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg);
void stereoScan3dTFCallback(
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg,
const sensor_msgs::PointCloud2ConstPtr& scanMsg);
void goalCommonCallback(int id, const std::string & label, const rtabmap::Transform & pose, const ros::Time & stamp, double * planningTime = 0);
void goalCallback(const geometry_msgs::PoseStampedConstPtr & msg);
void goalNodeCallback(const rtabmap_ros::GoalConstPtr & msg);
void updateGoal(const ros::Time & stamp);
void process(
const ros::Time & stamp,
const rtabmap::SensorData & data,
const rtabmap::Transform & odom = rtabmap::Transform(),
const std::string & odomFrameId = "",
float odomRotationalVariance = 1.0,
float odomTransitionalVariance = 1.0);
bool updateRtabmapCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool resetRtabmapCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool pauseRtabmapCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool resumeRtabmapCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool triggerNewMapCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool backupDatabaseCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool setModeLocalizationCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool setModeMappingCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool setLogDebug(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 setLogError(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
bool getMapCallback(rtabmap_ros::GetMap::Request& req, rtabmap_ros::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 publishMapCallback(rtabmap_ros::PublishMap::Request&, rtabmap_ros::PublishMap::Response&);
bool setGoalCallback(rtabmap_ros::SetGoal::Request& req, rtabmap_ros::SetGoal::Response& res);
bool cancelGoalCallback(std_srvs::Empty::Request& req, std_srvs::Empty::Response& res);
bool setLabelCallback(rtabmap_ros::SetLabel::Request& req, rtabmap_ros::SetLabel::Response& res);
bool listLabelsCallback(rtabmap_ros::ListLabels::Request& req, rtabmap_ros::ListLabels::Response& res);
#ifdef WITH_OCTOMAP_ROS
bool octomapBinaryCallback(octomap_msgs::GetOctomap::Request &req, octomap_msgs::GetOctomap::Response &res);
bool octomapFullCallback(octomap_msgs::GetOctomap::Request &req, octomap_msgs::GetOctomap::Response &res);
#endif
rtabmap::ParametersMap loadParameters(const std::string & configFile);
void saveParameters(const std::string & configFile);
void publishLoop(double tfDelay, double tfTolerance);
void publishStats(const ros::Time & stamp);
void publishCurrentGoal(const ros::Time & stamp);
void goalDoneCb(const actionlib::SimpleClientGoalState& state, const move_base_msgs::MoveBaseResultConstPtr& result);
void goalActiveCb();
void goalFeedbackCb(const move_base_msgs::MoveBaseFeedbackConstPtr& feedback);
void publishLocalPath(const ros::Time & stamp);
void publishGlobalPath(const ros::Time & stamp);
private:
rtabmap::Rtabmap rtabmap_;
bool paused_;
rtabmap::Transform lastPose_;
ros::Time lastPoseStamp_;
bool lastPoseIntermediate_;
float rotVariance_;
float transVariance_;
rtabmap::Transform currentMetricGoal_;
bool latestNodeWasReached_;
rtabmap::ParametersMap parameters_;
std::string frameId_;
std::string mapFrameId_;
std::string odomFrameId_;
std::string groundTruthFrameId_;
std::string configPath_;
std::string databasePath_;
bool waitForTransform_;
double waitForTransformDuration_;
bool useActionForGoal_;
bool genScan_;
double genScanMaxDepth_;
double genScanMinDepth_;
int scanCloudMaxPoints_;
int scanCloudNormalK_;
bool flipScan_;
rtabmap::Transform mapToOdom_;
boost::mutex mapToOdomMutex_;
MapsManager mapsManager_;
ros::Publisher infoPub_;
ros::Publisher mapDataPub_;
ros::Publisher mapGraphPub_;
ros::Publisher labelsPub_;
//Planning stuff
ros::Subscriber goalSub_;
ros::Subscriber goalNodeSub_;
ros::Publisher nextMetricGoalPub_;
ros::Publisher goalReachedPub_;
ros::Publisher globalPathPub_;
ros::Publisher localPathPub_;
// for loop closure detection only
image_transport::Subscriber defaultSub_;
//for depth callback
std::vector<image_transport::SubscriberFilter*> imageSubs_;
std::vector<image_transport::SubscriberFilter*> imageDepthSubs_;
std::vector<message_filters::Subscriber<sensor_msgs::CameraInfo>*> cameraInfoSubs_;
//stereo callback
image_transport::SubscriberFilter imageRectLeft_;
image_transport::SubscriberFilter imageRectRight_;
message_filters::Subscriber<sensor_msgs::CameraInfo> cameraInfoLeft_;
message_filters::Subscriber<sensor_msgs::CameraInfo> cameraInfoRight_;
message_filters::Subscriber<nav_msgs::Odometry> odomSub_;
message_filters::Subscriber<sensor_msgs::LaserScan> scanSub_;
message_filters::Subscriber<sensor_msgs::PointCloud2> scan3dSub_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::Image,
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::LaserScan> MyDepthScanSyncPolicy;
message_filters::Synchronizer<MyDepthScanSyncPolicy> * depthScanSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::Image,
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::PointCloud2> MyDepthScan3dSyncPolicy;
message_filters::Synchronizer<MyDepthScan3dSyncPolicy> * depthScan3dSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::Image,
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepthSyncPolicy;
message_filters::Synchronizer<MyDepthSyncPolicy> * depthSync_;
typedef message_filters::sync_policies::ExactTime<
sensor_msgs::Image,
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepthExactSyncPolicy;
message_filters::Synchronizer<MyDepthExactSyncPolicy> * depthExactSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo,
sensor_msgs::LaserScan,
nav_msgs::Odometry> MyStereoScanSyncPolicy;
message_filters::Synchronizer<MyStereoScanSyncPolicy> * stereoScanSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo,
sensor_msgs::PointCloud2,
nav_msgs::Odometry> MyStereoScan3dSyncPolicy;
message_filters::Synchronizer<MyStereoScan3dSyncPolicy> * stereoScan3dSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo,
nav_msgs::Odometry> MyStereoApproxSyncPolicy;
message_filters::Synchronizer<MyStereoApproxSyncPolicy> * stereoApproxSync_;
typedef message_filters::sync_policies::ExactTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo,
nav_msgs::Odometry> MyStereoExactSyncPolicy;
message_filters::Synchronizer<MyStereoExactSyncPolicy> * stereoExactSync_;
typedef message_filters::sync_policies::ApproximateTime<
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepth2SyncPolicy;
message_filters::Synchronizer<MyDepth2SyncPolicy> * depth2Sync_;
// without odom, when TF is used for odom
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::LaserScan> MyDepthScanTFSyncPolicy;
message_filters::Synchronizer<MyDepthScanTFSyncPolicy> * depthScanTFSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::PointCloud2> MyDepthScan3dTFSyncPolicy;
message_filters::Synchronizer<MyDepthScan3dTFSyncPolicy> * depthScan3dTFSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepthTFSyncPolicy;
message_filters::Synchronizer<MyDepthTFSyncPolicy> * depthTFSync_;
typedef message_filters::sync_policies::ExactTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepthTFExactSyncPolicy;
message_filters::Synchronizer<MyDepthTFExactSyncPolicy> * depthTFExactSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo,
sensor_msgs::LaserScan> MyStereoScanTFSyncPolicy;
message_filters::Synchronizer<MyStereoScanTFSyncPolicy> * stereoScanTFSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo,
sensor_msgs::PointCloud2> MyStereoScan3dTFSyncPolicy;
message_filters::Synchronizer<MyStereoScan3dTFSyncPolicy> * stereoScan3dTFSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo> MyStereoApproxTFSyncPolicy;
message_filters::Synchronizer<MyStereoApproxTFSyncPolicy> * stereoApproxTFSync_;
typedef message_filters::sync_policies::ExactTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo> MyStereoExactTFSyncPolicy;
message_filters::Synchronizer<MyStereoExactTFSyncPolicy> * stereoExactTFSync_;
tf2_ros::TransformBroadcaster tfBroadcaster_;
tf::TransformListener tfListener_;
ros::ServiceServer updateSrv_;
ros::ServiceServer resetSrv_;
ros::ServiceServer pauseSrv_;
ros::ServiceServer resumeSrv_;
ros::ServiceServer triggerNewMapSrv_;
ros::ServiceServer backupDatabase_;
ros::ServiceServer setModeLocalizationSrv_;
ros::ServiceServer setModeMappingSrv_;
ros::ServiceServer setLogDebugSrv_;
ros::ServiceServer setLogInfoSrv_;
ros::ServiceServer setLogWarnSrv_;
ros::ServiceServer setLogErrorSrv_;
ros::ServiceServer getMapDataSrv_;
ros::ServiceServer getProjMapSrv_;
ros::ServiceServer getGridMapSrv_;
ros::ServiceServer publishMapDataSrv_;
ros::ServiceServer setGoalSrv_;
ros::ServiceServer cancelGoalSrv_;
ros::ServiceServer setLabelSrv_;
ros::ServiceServer listLabelsSrv_;
#ifdef WITH_OCTOMAP_ROS
ros::ServiceServer octomapBinarySrv_;
ros::ServiceServer octomapFullSrv_;
#endif
MoveBaseClient mbClient_;
boost::thread* transformThread_;
float rate_;
bool createIntermediateNodes_;
ros::Time time_;
ros::Time previousStamp_;
};
#endif /* COREWRAPPER_H_ */
+2 -2
View File
@@ -25,7 +25,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "GuiWrapper.h" #include "rtabmap_ros/GuiWrapper.h"
#include "rtabmap/utilite/ULogger.h" #include "rtabmap/utilite/ULogger.h"
#include <QApplication> #include <QApplication>
@@ -54,7 +54,7 @@ int main(int argc, char** argv)
app = new QApplication(argc, argv); app = new QApplication(argc, argv);
app->connect( app, SIGNAL( lastWindowClosed() ), app, SLOT( quit() ) ); app->connect( app, SIGNAL( lastWindowClosed() ), app, SLOT( quit() ) );
GuiWrapper * gui = new GuiWrapper(argc, argv); rtabmap_ros::GuiWrapper * gui = new rtabmap_ros::GuiWrapper(argc, argv);
// Catch ctrl-c to close the gui // Catch ctrl-c to close the gui
// (Place this after QApplication's constructor) // (Place this after QApplication's constructor)
+143 -1359
View File
File diff suppressed because it is too large Load Diff
-492
View File
@@ -1,492 +0,0 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GUIWRAPPER_H_
#define GUIWRAPPER_H_
#include <ros/ros.h>
#include "rtabmap_ros/Info.h"
#include "rtabmap_ros/MapData.h"
#include "rtabmap_ros/OdomInfo.h"
#include "rtabmap_ros/Goal.h"
#include "rtabmap/utilite/UEventsHandler.h"
#include "rtabmap/core/Transform.h"
#include <tf/transform_listener.h>
#include <geometry_msgs/TwistStamped.h>
#include <sensor_msgs/PointCloud2.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/CameraInfo.h>
#include <sensor_msgs/LaserScan.h>
#include <nav_msgs/Odometry.h>
#include <nav_msgs/Path.h>
#include <std_msgs/Bool.h>
#include <message_filters/subscriber.h>
#include <message_filters/synchronizer.h>
#include <message_filters/sync_policies/approximate_time.h>
#include <message_filters/sync_policies/exact_time.h>
#include <image_transport/image_transport.h>
#include <image_transport/subscriber_filter.h>
namespace rtabmap
{
class MainWindow;
}
class QApplication;
class GuiWrapper : public UEventsHandler
{
public:
GuiWrapper(int & argc, char** argv);
virtual ~GuiWrapper();
protected:
virtual void handleEvent(UEvent * anEvent);
private:
void infoMapCallback(const rtabmap_ros::InfoConstPtr & infoMsg, const rtabmap_ros::MapDataConstPtr & mapMsg);
void goalPathCallback(const rtabmap_ros::GoalConstPtr & goalMsg, const nav_msgs::PathConstPtr & pathMsg);
void goalReachedCallback(const std_msgs::BoolConstPtr & value);
void setupCallbacks(
bool subscribeDepth,
bool subscribeLaserScan2d,
bool subscribeLaserScan3d,
bool subscribeOdomInfo,
bool subscribeStereo,
int queueSize,
int depthCameras);
void commonDepthCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg,
const sensor_msgs::LaserScanConstPtr& scan2dMsg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg);
void commonDepthCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const std::vector<sensor_msgs::ImageConstPtr> & imageMsgs,
const std::vector<sensor_msgs::ImageConstPtr> & depthMsgs,
const std::vector<sensor_msgs::CameraInfoConstPtr> & cameraInfoMsgs,
const sensor_msgs::LaserScanConstPtr& scan2dMsg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg);
void commonStereoCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg,
const sensor_msgs::LaserScanConstPtr& scan2dMsg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg);
void defaultCallback(const nav_msgs::OdometryConstPtr & odomMsg);
// With odom msg
void depthCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& imageDepthMsg,
const sensor_msgs::CameraInfoConstPtr& camInfoMsg);
void depth2Callback(
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& image1Msg,
const sensor_msgs::ImageConstPtr& depth1Msg,
const sensor_msgs::CameraInfoConstPtr& cameraInfo1Msg,
const sensor_msgs::ImageConstPtr& image2Msg,
const sensor_msgs::ImageConstPtr& depth2Msg,
const sensor_msgs::CameraInfoConstPtr& cameraInfo2Msg);
void depthOdomInfoCallback(
const rtabmap_ros::OdomInfoConstPtr & odomInfoMsg,
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg);
void depthOdomInfo2Callback(
const rtabmap_ros::OdomInfoConstPtr & odomInfoMsg,
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& image1Msg,
const sensor_msgs::ImageConstPtr& depth1Msg,
const sensor_msgs::CameraInfoConstPtr& cameraInfo1Msg,
const sensor_msgs::ImageConstPtr& image2Msg,
const sensor_msgs::ImageConstPtr& depth2Msg,
const sensor_msgs::CameraInfoConstPtr& cameraInfo2Msg);
void depthScanCallback(
const sensor_msgs::LaserScanConstPtr& scanMsg,
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& imageDepthMsg,
const sensor_msgs::CameraInfoConstPtr& camInfoMsg);
void depthScanOdomInfoCallback(
const rtabmap_ros::OdomInfoConstPtr & odomInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg,
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& imageDepthMsg,
const sensor_msgs::CameraInfoConstPtr& camInfoMsg);
void depthScan3dCallback(
const sensor_msgs::PointCloud2ConstPtr& scanMsg,
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& imageDepthMsg,
const sensor_msgs::CameraInfoConstPtr& camInfoMsg);
void depthScan3dOdomInfoCallback(
const rtabmap_ros::OdomInfoConstPtr & odomInfoMsg,
const sensor_msgs::PointCloud2ConstPtr& scanMsg,
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& imageDepthMsg,
const sensor_msgs::CameraInfoConstPtr& camInfoMsg);
void stereoScanCallback(
const sensor_msgs::LaserScanConstPtr& scanMsg,
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCameraInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCameraInfoMsg);
void stereoScanOdomInfoCallback(
const rtabmap_ros::OdomInfoConstPtr & odomInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg,
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCameraInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCameraInfoMsg);
void stereoScan3dCallback(
const sensor_msgs::PointCloud2ConstPtr& scanMsg,
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCameraInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCameraInfoMsg);
void stereoScan3dOdomInfoCallback(
const rtabmap_ros::OdomInfoConstPtr & odomInfoMsg,
const sensor_msgs::PointCloud2ConstPtr& scanMsg,
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCameraInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCameraInfoMsg);
void stereoOdomInfoCallback(
const rtabmap_ros::OdomInfoConstPtr & odomInfoMsg,
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCameraInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCameraInfoMsg);
void stereoCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCameraInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCameraInfoMsg);
// with TF
void depthTFCallback(const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& imageDepthMsg,
const sensor_msgs::CameraInfoConstPtr& camInfoMsg);
void depthOdomInfoTFCallback(
const rtabmap_ros::OdomInfoConstPtr & odomInfoMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg);
void depthScanTFCallback(
const sensor_msgs::LaserScanConstPtr& scanMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& imageDepthMsg,
const sensor_msgs:: CameraInfoConstPtr& camInfoMsg);
void depthScan3dTFCallback(
const sensor_msgs::PointCloud2ConstPtr& scanMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& imageDepthMsg,
const sensor_msgs:: CameraInfoConstPtr& camInfoMsg);
void stereoScanTFCallback(
const sensor_msgs::LaserScanConstPtr& scanMsg,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCameraInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCameraInfoMsg);
void stereoScan3dTFCallback(
const sensor_msgs::PointCloud2ConstPtr& scanMsg,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCameraInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCameraInfoMsg);
void stereoOdomInfoTFCallback(
const rtabmap_ros::OdomInfoConstPtr & odomInfoMsg,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCameraInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCameraInfoMsg);
void stereoTFCallback(
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCameraInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCameraInfoMsg);
void processRequestedMap(const rtabmap_ros::MapData & map);
rtabmap::Transform getTransform(const std::string & fromFrameId, const std::string & toFrameId, const ros::Time & stamp) const;
private:
rtabmap::MainWindow * mainWindow_;
std::string cameraNodeName_;
double lastOdomInfoUpdateTime_;
// odometry subscription stuffs
std::string frameId_;
std::string odomFrameId_;
bool waitForTransform_;
double waitForTransformDuration_;
tf::TransformListener tfListener_;
message_filters::Subscriber<rtabmap_ros::Info> infoTopic_;
message_filters::Subscriber<rtabmap_ros::MapData> mapDataTopic_;
message_filters::Subscriber<rtabmap_ros::Goal> goalTopic_;
message_filters::Subscriber<nav_msgs::Path> pathTopic_;
ros::Subscriber goalReachedTopic_;
ros::Subscriber defaultSub_; // odometry only
std::vector<image_transport::SubscriberFilter*> imageSubs_;
std::vector<image_transport::SubscriberFilter*> imageDepthSubs_;
std::vector<message_filters::Subscriber<sensor_msgs::CameraInfo>* > cameraInfoSubs_;
message_filters::Subscriber<nav_msgs::Odometry> odomSub_;
message_filters::Subscriber<rtabmap_ros::OdomInfo> odomInfoSub_;
message_filters::Subscriber<sensor_msgs::LaserScan> scanSub_;
message_filters::Subscriber<sensor_msgs::PointCloud2> scan3dSub_;
image_transport::SubscriberFilter imageRectLeft_;
image_transport::SubscriberFilter imageRectRight_;
message_filters::Subscriber<sensor_msgs::CameraInfo> cameraInfoLeft_;
message_filters::Subscriber<sensor_msgs::CameraInfo> cameraInfoRight_;
typedef message_filters::sync_policies::ExactTime<
rtabmap_ros::Info,
rtabmap_ros::MapData> MyInfoMapSyncPolicy;
message_filters::Synchronizer<MyInfoMapSyncPolicy> * infoMapSync_;
typedef message_filters::sync_policies::ExactTime<
rtabmap_ros::Goal,
nav_msgs::Path> MyGoalPathSyncPolicy;
message_filters::Synchronizer<MyGoalPathSyncPolicy> * goalPathSync_;
// with odom msg
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::LaserScan,
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepthScanSyncPolicy;
message_filters::Synchronizer<MyDepthScanSyncPolicy> * depthScanSync_;
typedef message_filters::sync_policies::ApproximateTime<
rtabmap_ros::OdomInfo,
sensor_msgs::LaserScan,
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepthScanOdomInfoSyncPolicy;
message_filters::Synchronizer<MyDepthScanOdomInfoSyncPolicy> * depthScanOdomInfoSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::PointCloud2,
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepthScan3dSyncPolicy;
message_filters::Synchronizer<MyDepthScan3dSyncPolicy> * depthScan3dSync_;
typedef message_filters::sync_policies::ApproximateTime<
rtabmap_ros::OdomInfo,
sensor_msgs::PointCloud2,
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepthScan3dOdomInfoSyncPolicy;
message_filters::Synchronizer<MyDepthScan3dOdomInfoSyncPolicy> * depthScan3dOdomInfoSync_;
typedef message_filters::sync_policies::ApproximateTime<
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepthSyncPolicy;
message_filters::Synchronizer<MyDepthSyncPolicy> * depthSync_;
typedef message_filters::sync_policies::ApproximateTime<
rtabmap_ros::OdomInfo,
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepthOdomInfoSyncPolicy;
message_filters::Synchronizer<MyDepthOdomInfoSyncPolicy> * depthOdomInfoSync_;
typedef message_filters::sync_policies::ApproximateTime<
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo> MyStereoSyncPolicy;
message_filters::Synchronizer<MyStereoSyncPolicy> * stereoSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::LaserScan,
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo> MyStereoScanSyncPolicy;
message_filters::Synchronizer<MyStereoScanSyncPolicy> * stereoScanSync_;
typedef message_filters::sync_policies::ApproximateTime<
rtabmap_ros::OdomInfo,
sensor_msgs::LaserScan,
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo> MyStereoScanOdomInfoSyncPolicy;
message_filters::Synchronizer<MyStereoScanOdomInfoSyncPolicy> * stereoScanOdomInfoSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::PointCloud2,
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo> MyStereoScan3dSyncPolicy;
message_filters::Synchronizer<MyStereoScan3dSyncPolicy> * stereoScan3dSync_;
typedef message_filters::sync_policies::ApproximateTime<
rtabmap_ros::OdomInfo,
sensor_msgs::PointCloud2,
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo> MyStereoScan3dOdomInfoSyncPolicy;
message_filters::Synchronizer<MyStereoScan3dOdomInfoSyncPolicy> * stereoScan3dOdomInfoSync_;
typedef message_filters::sync_policies::ApproximateTime<
rtabmap_ros::OdomInfo,
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo> MyStereoOdomInfoSyncPolicy;
message_filters::Synchronizer<MyStereoOdomInfoSyncPolicy> * stereoOdomInfoSync_;
typedef message_filters::sync_policies::ApproximateTime<
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepth2SyncPolicy;
message_filters::Synchronizer<MyDepth2SyncPolicy> * depth2Sync_;
typedef message_filters::sync_policies::ApproximateTime<
rtabmap_ros::OdomInfo,
nav_msgs::Odometry,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepthOdomInfo2SyncPolicy;
message_filters::Synchronizer<MyDepthOdomInfo2SyncPolicy> * depthOdomInfo2Sync_;
// with odom TF
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::LaserScan,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepthScanTFSyncPolicy;
message_filters::Synchronizer<MyDepthScanTFSyncPolicy> * depthScanTFSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::PointCloud2,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepthScan3dTFSyncPolicy;
message_filters::Synchronizer<MyDepthScan3dTFSyncPolicy> * depthScan3dTFSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepthTFSyncPolicy;
message_filters::Synchronizer<MyDepthTFSyncPolicy> * depthTFSync_;
typedef message_filters::sync_policies::ApproximateTime<
rtabmap_ros::OdomInfo,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyDepthOdomInfoTFSyncPolicy;
message_filters::Synchronizer<MyDepthOdomInfoTFSyncPolicy> * depthOdomInfoTFSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo> MyStereoTFSyncPolicy;
message_filters::Synchronizer<MyStereoTFSyncPolicy> * stereoTFSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::LaserScan,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo> MyStereoScanTFSyncPolicy;
message_filters::Synchronizer<MyStereoScanTFSyncPolicy> * stereoScanTFSync_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::PointCloud2,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo> MyStereoScan3dTFSyncPolicy;
message_filters::Synchronizer<MyStereoScan3dTFSyncPolicy> * stereoScan3dTFSync_;
typedef message_filters::sync_policies::ApproximateTime<
rtabmap_ros::OdomInfo,
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo,
sensor_msgs::CameraInfo> MyStereoOdomInfoTFSyncPolicy;
message_filters::Synchronizer<MyStereoOdomInfoTFSyncPolicy> * stereoOdomInfoTFSync_;
};
#endif /* GUIWRAPPER_H_ */
+78
View File
@@ -0,0 +1,78 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ros/ros.h"
#include "nodelet/loader.h"
#include <rtabmap/utilite/ULogger.h>
#include <rtabmap/core/Parameters.h>
int main(int argc, char **argv)
{
ULogger::setType(ULogger::kTypeConsole);
ULogger::setLevel(ULogger::kWarning);
ros::init(argc, argv, "icp_odometry");
// process "--params" argument
nodelet::V_string nargv;
for(int i=1;i<argc;++i)
{
if(strcmp(argv[i], "--params") == 0)
{
rtabmap::ParametersMap parametersOdom = rtabmap::Parameters::getDefaultOdometryParameters(false, false, true);
for(rtabmap::ParametersMap::iterator iter=parametersOdom.begin(); iter!=parametersOdom.end(); ++iter)
{
std::string str = "Param: " + iter->first + " = \"" + iter->second + "\"";
std::cout <<
str <<
std::setw(60 - str.size()) <<
" [" <<
rtabmap::Parameters::getDescription(iter->first).c_str() <<
"]" <<
std::endl;
}
ROS_WARN("Node will now exit after showing default odometry parameters because "
"argument \"--params\" is detected!");
exit(0);
}
else if(strcmp(argv[i], "--udebug") == 0)
{
ULogger::setLevel(ULogger::kDebug);
}
else if(strcmp(argv[i], "--uinfo") == 0)
{
ULogger::setLevel(ULogger::kInfo);
}
nargv.push_back(argv[i]);
}
nodelet::Loader nodelet;
nodelet::M_string remap(ros::names::getRemappings());
std::string nodelet_name = ros::this_node::getName();
nodelet.load(nodelet_name, "rtabmap_ros/icp_odometry", remap, nargv);
ros::spin();
return 0;
}
+5 -7
View File
@@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <ros/ros.h> #include <ros/ros.h>
#include "rtabmap_ros/MapData.h" #include "rtabmap_ros/MapData.h"
#include "rtabmap_ros/MsgConversion.h" #include "rtabmap_ros/MsgConversion.h"
#include "MapsManager.h" #include "rtabmap_ros/MapsManager.h"
#include <rtabmap/core/util3d_transforms.h> #include <rtabmap/core/util3d_transforms.h>
#include <rtabmap/core/util3d.h> #include <rtabmap/core/util3d.h>
#include <rtabmap/core/util3d_filtering.h> #include <rtabmap/core/util3d_filtering.h>
@@ -49,12 +49,13 @@ class MapAssembler
{ {
public: public:
MapAssembler() : MapAssembler()
mapsManager_(false)
{ {
ros::NodeHandle pnh("~"); ros::NodeHandle pnh("~");
ros::NodeHandle nh; ros::NodeHandle nh;
mapsManager_.init(nh, pnh, ros::this_node::getName(), false);
mapDataTopic_ = nh.subscribe("mapData", 1, &MapAssembler::mapDataReceivedCallback, this); mapDataTopic_ = nh.subscribe("mapData", 1, &MapAssembler::mapDataReceivedCallback, this);
// private service // private service
@@ -99,9 +100,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);
+4 -4
View File
@@ -84,7 +84,7 @@ public:
parameters.insert(ParametersPair(Parameters::kOptimizerEpsilon(), uNumber2Str(epsilon))); parameters.insert(ParametersPair(Parameters::kOptimizerEpsilon(), uNumber2Str(epsilon)));
parameters.insert(ParametersPair(Parameters::kOptimizerIterations(), uNumber2Str(iterations))); parameters.insert(ParametersPair(Parameters::kOptimizerIterations(), uNumber2Str(iterations)));
parameters.insert(ParametersPair(Parameters::kOptimizerRobust(), uBool2Str(robust))); parameters.insert(ParametersPair(Parameters::kOptimizerRobust(), uBool2Str(robust)));
parameters.insert(ParametersPair(Parameters::kOptimizerSlam2D(), uBool2Str(slam2d))); parameters.insert(ParametersPair(Parameters::kRegForce3DoF(), uBool2Str(slam2d)));
parameters.insert(ParametersPair(Parameters::kOptimizerVarianceIgnored(), uBool2Str(ignoreVariance))); parameters.insert(ParametersPair(Parameters::kOptimizerVarianceIgnored(), uBool2Str(ignoreVariance)));
optimizer_ = Optimizer::create(parameters); optimizer_ = Optimizer::create(parameters);
@@ -254,10 +254,10 @@ public:
{ {
optimizedPoses = poses; optimizedPoses = poses;
} }
else if(poses.size() || constraints.size()) else if(poses.size() == 0 && constraints.size())
{ {
ROS_ERROR("map_optimizer: Poses=%d and edges=%d (poses must " ROS_ERROR("map_optimizer: Poses=%d and edges=%d: poses must "
"not be null if there are edges, and edges must be null if poses <= 1)", "not be null if there are edges.",
(int)poses.size(), (int)constraints.size()); (int)poses.size(), (int)constraints.size());
} }
+654 -630
View File
File diff suppressed because it is too large Load Diff
+689 -31
View File
@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <zlib.h> #include <zlib.h>
#include <ros/ros.h> #include <ros/ros.h>
#include <rtabmap/core/util3d.h> #include <rtabmap/core/util3d.h>
#include <rtabmap/core/Compression.h>
#include <rtabmap/utilite/UStl.h> #include <rtabmap/utilite/UStl.h>
#include <rtabmap/utilite/ULogger.h> #include <rtabmap/utilite/ULogger.h>
#include <pcl_conversions/pcl_conversions.h> #include <pcl_conversions/pcl_conversions.h>
@@ -38,6 +39,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <tf_conversions/tf_eigen.h> #include <tf_conversions/tf_eigen.h>
#include <image_geometry/pinhole_camera_model.h> #include <image_geometry/pinhole_camera_model.h>
#include <image_geometry/stereo_camera_model.h> #include <image_geometry/stereo_camera_model.h>
#include <sensor_msgs/image_encodings.h>
#include <laser_geometry/laser_geometry.h>
#include <rtabmap/core/util3d_surface.h>
namespace rtabmap_ros { namespace rtabmap_ros {
@@ -114,6 +118,78 @@ rtabmap::Transform transformFromPoseMsg(const geometry_msgs::Pose & msg)
return rtabmap::Transform::fromEigen3d(tfPose); return rtabmap::Transform::fromEigen3d(tfPose);
} }
void toCvCopy(const rtabmap_ros::RGBDImage & image, cv_bridge::CvImagePtr & rgb, cv_bridge::CvImagePtr & depth)
{
if(!image.rgb.data.empty())
{
rgb = cv_bridge::toCvCopy(image.rgb);
}
else if(!image.rgbCompressed.data.empty())
{
rgb = cv_bridge::toCvCopy(image.rgbCompressed);
}
else
{
// empty
rgb = boost::make_shared<cv_bridge::CvImage>();
}
if(!image.depth.data.empty())
{
depth = cv_bridge::toCvCopy(image.depth);
}
else if(!image.depthCompressed.data.empty())
{
cv_bridge::CvImagePtr ptr = boost::make_shared<cv_bridge::CvImage>();
ptr->header = image.depthCompressed.header;
ptr->image = rtabmap::uncompressImage(image.depthCompressed.data);
ROS_ASSERT(ptr->image.empty() || ptr->image.type() == CV_32FC1 || ptr->image.type() == CV_16UC1);
ptr->encoding = ptr->image.empty()?"":ptr->image.type() == CV_32FC1?sensor_msgs::image_encodings::TYPE_32FC1:sensor_msgs::image_encodings::TYPE_16UC1;
depth = ptr;
}
else
{
// empty
depth = boost::make_shared<cv_bridge::CvImage>();
}
}
void toCvShare(const rtabmap_ros::RGBDImageConstPtr & image, cv_bridge::CvImageConstPtr & rgb, cv_bridge::CvImageConstPtr & depth)
{
if(!image->rgb.data.empty())
{
rgb = cv_bridge::toCvShare(image->rgb, image);
}
else if(!image->rgbCompressed.data.empty())
{
rgb = cv_bridge::toCvCopy(image->rgbCompressed);
}
else
{
// empty
rgb = boost::make_shared<cv_bridge::CvImage>();
}
if(!image->depth.data.empty())
{
depth = cv_bridge::toCvShare(image->depth, image);
}
else if(!image->depthCompressed.data.empty())
{
cv_bridge::CvImagePtr ptr = boost::make_shared<cv_bridge::CvImage>();
ptr->header = image->depthCompressed.header;
ptr->image = rtabmap::uncompressImage(image->depthCompressed.data);
ROS_ASSERT(ptr->image.empty() || ptr->image.type() == CV_32FC1 || ptr->image.type() == CV_16UC1);
ptr->encoding = ptr->image.empty()?"":ptr->image.type() == CV_32FC1?sensor_msgs::image_encodings::TYPE_32FC1:sensor_msgs::image_encodings::TYPE_16UC1;
depth = ptr;
}
else
{
// empty
depth = boost::make_shared<cv_bridge::CvImage>();
}
}
void compressedMatToBytes(const cv::Mat & compressed, std::vector<unsigned char> & bytes) void compressedMatToBytes(const cv::Mat & compressed, std::vector<unsigned char> & bytes)
{ {
UASSERT(compressed.empty() || compressed.type() == CV_8UC1); UASSERT(compressed.empty() || compressed.type() == CV_8UC1);
@@ -331,16 +407,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,
@@ -400,16 +502,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(
@@ -504,11 +601,14 @@ rtabmap::Signature nodeDataFromROS(const rtabmap_ros::NodeData & msg)
//Features stuff... //Features stuff...
std::multimap<int, cv::KeyPoint> words; std::multimap<int, cv::KeyPoint> words;
std::multimap<int, cv::Point3f> words3D; std::multimap<int, cv::Point3f> words3D;
std::multimap<int, cv::Mat> wordsDescriptors;
pcl::PointCloud<pcl::PointXYZ> cloud; pcl::PointCloud<pcl::PointXYZ> cloud;
cv::Mat descriptors;
if(msg.wordPts.data.size() && if(msg.wordPts.data.size() &&
msg.wordPts.height*msg.wordPts.width == msg.wordIds.size()) msg.wordPts.height*msg.wordPts.width == msg.wordIds.size())
{ {
pcl::fromROSMsg(msg.wordPts, cloud); pcl::fromROSMsg(msg.wordPts, cloud);
descriptors = rtabmap::uncompressData(msg.descriptors);
} }
for(unsigned int i=0; i<msg.wordIds.size() && i<msg.wordKpts.size(); ++i) for(unsigned int i=0; i<msg.wordIds.size() && i<msg.wordKpts.size(); ++i)
@@ -520,6 +620,10 @@ rtabmap::Signature nodeDataFromROS(const rtabmap_ros::NodeData & msg)
{ {
words3D.insert(std::make_pair(wordId, cv::Point3f(cloud[i].x, cloud[i].y, cloud[i].z))); words3D.insert(std::make_pair(wordId, cv::Point3f(cloud[i].x, cloud[i].y, cloud[i].z)));
} }
if(i < descriptors.rows)
{
wordsDescriptors.insert(std::make_pair(wordId, descriptors.row(i).clone()));
}
} }
if(words3D.size() && words3D.size() != words.size()) if(words3D.size() && words3D.size() != words.size())
@@ -533,9 +637,11 @@ rtabmap::Signature nodeDataFromROS(const rtabmap_ros::NodeData & msg)
{ {
// stereo model // stereo model
if(msg.fx.size() == 1 && if(msg.fx.size() == 1 &&
msg.fy.size() == 1, msg.fy.size() == 1 &&
msg.cx.size() == 1, msg.cx.size() == 1 &&
msg.cy.size() == 1, msg.cy.size() == 1 &&
msg.width.size() == 1 &&
msg.height.size() == 1 &&
msg.localTransform.size() == 1) msg.localTransform.size() == 1)
{ {
stereoModel = rtabmap::StereoCameraModel( stereoModel = rtabmap::StereoCameraModel(
@@ -544,7 +650,8 @@ rtabmap::Signature nodeDataFromROS(const rtabmap_ros::NodeData & msg)
msg.cx[0], msg.cx[0],
msg.cy[0], msg.cy[0],
msg.baseline, msg.baseline,
transformFromGeometryMsg(msg.localTransform[0])); transformFromGeometryMsg(msg.localTransform[0]),
cv::Size(msg.width[0], msg.height[0]));
} }
} }
else else
@@ -563,7 +670,9 @@ rtabmap::Signature nodeDataFromROS(const rtabmap_ros::NodeData & msg)
msg.fy[i], msg.fy[i],
msg.cx[i], msg.cx[i],
msg.cy[i], msg.cy[i],
transformFromGeometryMsg(msg.localTransform[i]))); transformFromGeometryMsg(msg.localTransform[i]),
0.0,
cv::Size(msg.width[i], msg.height[i])));
} }
} }
} }
@@ -579,8 +688,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,
@@ -589,8 +700,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,
@@ -599,6 +712,12 @@ rtabmap::Signature nodeDataFromROS(const rtabmap_ros::NodeData & msg)
compressedMatFromBytes(msg.userData))); compressedMatFromBytes(msg.userData)));
s.setWords(words); s.setWords(words);
s.setWords3(words3D); s.setWords3(words3D);
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)
@@ -615,8 +734,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())
{ {
@@ -624,6 +748,8 @@ void nodeDataToROS(const rtabmap::Signature & signature, rtabmap_ros::NodeData &
msg.fy.resize(signature.sensorData().cameraModels().size()); msg.fy.resize(signature.sensorData().cameraModels().size());
msg.cx.resize(signature.sensorData().cameraModels().size()); msg.cx.resize(signature.sensorData().cameraModels().size());
msg.cy.resize(signature.sensorData().cameraModels().size()); msg.cy.resize(signature.sensorData().cameraModels().size());
msg.width.resize(signature.sensorData().cameraModels().size());
msg.height.resize(signature.sensorData().cameraModels().size());
msg.localTransform.resize(signature.sensorData().cameraModels().size()); msg.localTransform.resize(signature.sensorData().cameraModels().size());
for(unsigned int i=0; i<signature.sensorData().cameraModels().size(); ++i) for(unsigned int i=0; i<signature.sensorData().cameraModels().size(); ++i)
{ {
@@ -631,6 +757,8 @@ void nodeDataToROS(const rtabmap::Signature & signature, rtabmap_ros::NodeData &
msg.fy[i] = signature.sensorData().cameraModels()[i].fy(); msg.fy[i] = signature.sensorData().cameraModels()[i].fy();
msg.cx[i] = signature.sensorData().cameraModels()[i].cx(); msg.cx[i] = signature.sensorData().cameraModels()[i].cx();
msg.cy[i] = signature.sensorData().cameraModels()[i].cy(); msg.cy[i] = signature.sensorData().cameraModels()[i].cy();
msg.width[i] = signature.sensorData().cameraModels()[i].imageWidth();
msg.height[i] = signature.sensorData().cameraModels()[i].imageHeight();
transformToGeometryMsg(signature.sensorData().cameraModels()[i].localTransform(), msg.localTransform[i]); transformToGeometryMsg(signature.sensorData().cameraModels()[i].localTransform(), msg.localTransform[i]);
} }
} }
@@ -640,6 +768,8 @@ void nodeDataToROS(const rtabmap::Signature & signature, rtabmap_ros::NodeData &
msg.fy.push_back(signature.sensorData().stereoCameraModel().left().fy()); msg.fy.push_back(signature.sensorData().stereoCameraModel().left().fy());
msg.cx.push_back(signature.sensorData().stereoCameraModel().left().cx()); msg.cx.push_back(signature.sensorData().stereoCameraModel().left().cx());
msg.cy.push_back(signature.sensorData().stereoCameraModel().left().cy()); msg.cy.push_back(signature.sensorData().stereoCameraModel().left().cy());
msg.width.push_back(signature.sensorData().stereoCameraModel().left().imageWidth());
msg.height.push_back(signature.sensorData().stereoCameraModel().left().imageHeight());
msg.baseline = signature.sensorData().stereoCameraModel().baseline(); msg.baseline = signature.sensorData().stereoCameraModel().baseline();
msg.localTransform.resize(1); msg.localTransform.resize(1);
transformToGeometryMsg(signature.sensorData().stereoCameraModel().left().localTransform(), msg.localTransform[0]); transformToGeometryMsg(signature.sensorData().stereoCameraModel().left().localTransform(), msg.localTransform[0]);
@@ -677,6 +807,42 @@ void nodeDataToROS(const rtabmap::Signature & signature, rtabmap_ros::NodeData &
(int)signature.getWords().size(), (int)signature.getWords().size(),
(int)signature.getWords3().size()); (int)signature.getWords3().size());
} }
if(signature.getWordsDescriptors().size() && signature.getWordsDescriptors().size() == signature.getWords().size())
{
cv::Mat descriptors(
signature.getWordsDescriptors().size(),
signature.getWordsDescriptors().begin()->second.cols,
signature.getWordsDescriptors().begin()->second.type());
index = 0;
bool valid = true;
for(std::multimap<int, cv::Mat>::const_iterator jter=signature.getWordsDescriptors().begin();
jter!=signature.getWordsDescriptors().end() && valid;
++jter)
{
if(jter->second.cols == descriptors.cols &&
jter->second.type() == descriptors.type())
{
jter->second.copyTo(descriptors.row(index++));
}
else
{
valid = false;
ROS_ERROR("Some descriptors have different type/size! Cannot copy them...");
}
}
if(valid)
{
msg.descriptors = rtabmap::compressData(descriptors);
}
}
else if(signature.getWordsDescriptors().size())
{
ROS_ERROR("Words and descriptors must have the same size (%d vs %d)!",
(int)signature.getWords().size(),
(int)signature.getWordsDescriptors().size());
}
} }
rtabmap::Signature nodeInfoFromROS(const rtabmap_ros::NodeData & msg) rtabmap::Signature nodeInfoFromROS(const rtabmap_ros::NodeData & msg)
@@ -711,8 +877,10 @@ rtabmap::OdometryInfo odomInfoFromROS(const rtabmap_ros::OdomInfo & msg)
info.features = msg.features; info.features = msg.features;
info.inliers = msg.inliers; info.inliers = msg.inliers;
info.localMapSize = msg.localMapSize; info.localMapSize = msg.localMapSize;
info.localScanMapSize = msg.localScanMapSize;
info.timeEstimation = msg.timeEstimation; info.timeEstimation = msg.timeEstimation;
info.variance = msg.variance; info.varianceLin = msg.varianceLin;
info.varianceAng = msg.varianceAng;
info.timeParticleFiltering = msg.timeParticleFiltering; info.timeParticleFiltering = msg.timeParticleFiltering;
info.stamp = msg.stamp; info.stamp = msg.stamp;
info.interval = msg.interval; info.interval = msg.interval;
@@ -742,6 +910,8 @@ rtabmap::OdometryInfo odomInfoFromROS(const rtabmap_ros::OdomInfo & msg)
info.localMap.insert(std::make_pair(msg.localMapKeys[i], point3fFromROS(msg.localMapValues[i]))); info.localMap.insert(std::make_pair(msg.localMapKeys[i], point3fFromROS(msg.localMapValues[i])));
} }
info.localScanMap = rtabmap::uncompressData(msg.localScanMap);
return info; return info;
} }
@@ -752,8 +922,10 @@ void odomInfoToROS(const rtabmap::OdometryInfo & info, rtabmap_ros::OdomInfo & m
msg.features = info.features; msg.features = info.features;
msg.inliers = info.inliers; msg.inliers = info.inliers;
msg.localMapSize = info.localMapSize; msg.localMapSize = info.localMapSize;
msg.localScanMapSize = info.localScanMapSize;
msg.timeEstimation = info.timeEstimation; msg.timeEstimation = info.timeEstimation;
msg.variance = info.variance; msg.varianceLin = info.varianceLin;
msg.varianceAng = info.varianceAng;
msg.timeParticleFiltering = info.timeParticleFiltering; msg.timeParticleFiltering = info.timeParticleFiltering;
msg.stamp = info.stamp; msg.stamp = info.stamp;
msg.interval = info.interval; msg.interval = info.interval;
@@ -777,6 +949,492 @@ void odomInfoToROS(const rtabmap::OdometryInfo & info, rtabmap_ros::OdomInfo & m
msg.localMapKeys = uKeys(info.localMap); msg.localMapKeys = uKeys(info.localMap);
points3fToROS(uValues(info.localMap), msg.localMapValues); points3fToROS(uValues(info.localMap), msg.localMapValues);
msg.localScanMap = rtabmap::compressData(info.localScanMap);
}
cv::Mat userDataFromROS(const rtabmap_ros::UserData & dataMsg)
{
cv::Mat data;
if(!dataMsg.data.empty())
{
if(dataMsg.cols > 0 && dataMsg.rows > 0 && dataMsg.type >= 0)
{
data = cv::Mat(dataMsg.rows, dataMsg.cols, dataMsg.type, (void*)dataMsg.data.data()).clone();
}
else
{
if(dataMsg.cols != (int)dataMsg.data.size() || dataMsg.rows != 1 || dataMsg.type != CV_8UC1)
{
ROS_ERROR("cols, rows and type fields of the UserData msg "
"are not correctly set (cols=%d, rows=%d, type=%d)! We assume that the data "
"is compressed (cols=%d, rows=1, type=%d(CV_8UC1)).",
dataMsg.cols, dataMsg.rows, dataMsg.type, (int)dataMsg.data.size(), CV_8UC1);
}
data = cv::Mat(1, dataMsg.data.size(), CV_8UC1, (void*)dataMsg.data.data()).clone();
}
}
return data;
}
void userDataToROS(const cv::Mat & data, rtabmap_ros::UserData & dataMsg, bool compress)
{
if(!data.empty())
{
if(compress)
{
dataMsg.data = rtabmap::compressData(data);
dataMsg.rows = 1;
dataMsg.cols = dataMsg.data.size();
dataMsg.type = CV_8UC1;
}
else
{
dataMsg.data.resize(data.step[0] * data.rows); // use step for non-contiguous matrices
memcpy(dataMsg.data.data(), data.data, dataMsg.data.size());
dataMsg.rows = data.rows;
dataMsg.cols = data.cols;
dataMsg.type = data.type();
}
}
}
rtabmap::Transform getTransform(
const std::string & fromFrameId,
const std::string & toFrameId,
const ros::Time & stamp,
tf::TransformListener & listener,
double waitForTransform)
{
// TF ready?
rtabmap::Transform transform;
try
{
if(waitForTransform > 0.0 && !stamp.isZero())
{
//if(!tfBuffer_.canTransform(fromFrameId, toFrameId, stamp, ros::Duration(1)))
std::string errorMsg;
if(!listener.waitForTransform(fromFrameId, toFrameId, stamp, ros::Duration(waitForTransform), ros::Duration(0.01), &errorMsg))
{
ROS_WARN("Could not get transform from %s to %s after %f seconds (for stamp=%f)! Error=\"%s\".",
fromFrameId.c_str(), toFrameId.c_str(), waitForTransform, stamp.toSec(), errorMsg.c_str());
return transform;
}
}
tf::StampedTransform tmp;
listener.lookupTransform(fromFrameId, toFrameId, stamp, tmp);
transform = rtabmap_ros::transformFromTF(tmp);
}
catch(tf::TransformException & ex)
{
ROS_WARN("%s",ex.what());
}
return transform;
}
// get moving transform accordingly to a fixed frame. For example get
// transform between moving /base_link between two stamps accordingly to /odom frame.
rtabmap::Transform getTransform(
const std::string & sourceTargetFrame,
const std::string & fixedFrame,
const ros::Time & stampSource,
const ros::Time & stampTarget,
tf::TransformListener & listener,
double waitForTransform)
{
// TF ready?
rtabmap::Transform transform;
try
{
ros::Time stamp = stampSource>stampTarget?stampSource:stampTarget;
if(waitForTransform > 0.0 && !stamp.isZero())
{
std::string errorMsg;
if(!listener.waitForTransform(sourceTargetFrame, fixedFrame, stamp, ros::Duration(waitForTransform), ros::Duration(0.01), &errorMsg))
{
ROS_WARN("Could not get transform from %s to %s accordingly to %s after %f seconds (for stamps=%f -> %f)! Error=\"%s\".",
sourceTargetFrame.c_str(), sourceTargetFrame.c_str(), fixedFrame.c_str(), waitForTransform, stampSource.toSec(), stampTarget.toSec(), errorMsg.c_str());
return transform;
}
}
tf::StampedTransform tmp;
listener.lookupTransform(sourceTargetFrame, stampTarget, sourceTargetFrame, stampSource, fixedFrame, tmp);
transform = rtabmap_ros::transformFromTF(tmp);
}
catch(tf::TransformException & ex)
{
ROS_WARN("%s",ex.what());
}
return transform;
}
bool convertRGBDMsgs(
const std::vector<cv_bridge::CvImageConstPtr> & imageMsgs,
const std::vector<cv_bridge::CvImageConstPtr> & depthMsgs,
const std::vector<sensor_msgs::CameraInfo> & cameraInfoMsgs,
const std::string & frameId,
const std::string & odomFrameId,
const ros::Time & odomStamp,
cv::Mat & rgb,
cv::Mat & depth,
std::vector<rtabmap::CameraModel> & cameraModels,
tf::TransformListener & listener,
double waitForTransform)
{
UASSERT(imageMsgs.size()>0 &&
imageMsgs.size() == depthMsgs.size() &&
imageMsgs.size() == cameraInfoMsgs.size());
int imageWidth = imageMsgs[0]->image.cols;
int imageHeight = imageMsgs[0]->image.rows;
int cameraCount = imageMsgs.size();
for(unsigned int i=0; i<imageMsgs.size(); ++i)
{
if(!(imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::TYPE_8UC1) == 0 ||
imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::MONO8) ==0 ||
imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::MONO16) ==0 ||
imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::BGR8) == 0 ||
imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::RGB8) == 0) ||
!(depthMsgs[i]->encoding.compare(sensor_msgs::image_encodings::TYPE_16UC1) == 0 ||
depthMsgs[i]->encoding.compare(sensor_msgs::image_encodings::TYPE_32FC1) == 0 ||
depthMsgs[i]->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0))
{
ROS_ERROR("Input type must be image=mono8,mono16,rgb8,bgr8 and image_depth=32FC1,16UC1,mono16");
return false;
}
UASSERT_MSG(imageMsgs[i]->image.cols == imageWidth && imageMsgs[i]->image.rows == imageHeight,
uFormat("imageWidth=%d vs %d imageHeight=%d vs %d",
imageWidth,
imageMsgs[i]->image.cols,
imageHeight,
imageMsgs[i]->image.rows).c_str());
UASSERT_MSG(depthMsgs[i]->image.cols == imageWidth && depthMsgs[i]->image.rows == imageHeight,
uFormat("imageWidth=%d vs %d imageHeight=%d vs %d",
imageWidth,
depthMsgs[i]->image.cols,
imageHeight,
depthMsgs[i]->image.rows).c_str());
rtabmap::Transform localTransform = rtabmap_ros::getTransform(frameId, depthMsgs[i]->header.frame_id, depthMsgs[i]->header.stamp, listener, waitForTransform);
if(localTransform.isNull())
{
ROS_ERROR("TF of received depth image %d at time %fs is not set!", i, depthMsgs[i]->header.stamp.toSec());
return false;
}
// sync with odometry stamp
if(!odomFrameId.empty() && odomStamp != depthMsgs[i]->header.stamp)
{
rtabmap::Transform sensorT = getTransform(
frameId,
odomFrameId,
odomStamp,
depthMsgs[i]->header.stamp,
listener,
waitForTransform);
if(sensorT.isNull())
{
ROS_WARN("Could not get odometry value for depth image stamp (%fs). Latest odometry "
"stamp is %fs. The depth image pose will not be synchronized with odometry.", depthMsgs[i]->header.stamp.toSec(), odomStamp.toSec());
}
else
{
//ROS_WARN("RGBD correction = %s (time diff=%fs)", sensorT.prettyPrint().c_str(), fabs(depthMsgs[i]->header.stamp.toSec()-odomStamp.toSec()));
localTransform = sensorT * localTransform;
}
}
cv_bridge::CvImageConstPtr ptrImage = imageMsgs[i];
if(imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::TYPE_8UC1)==0 ||
imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::MONO8) == 0 ||
imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::BGR8) == 0)
{
// do nothing
}
else if(imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0)
{
ptrImage = cv_bridge::cvtColor(imageMsgs[i], "mono8");
}
else
{
ptrImage = cv_bridge::cvtColor(imageMsgs[i], "bgr8");
}
cv_bridge::CvImageConstPtr ptrDepth = depthMsgs[i];
cv::Mat subDepth = ptrDepth->image;
// initialize
if(rgb.empty())
{
rgb = cv::Mat(imageHeight, imageWidth*cameraCount, ptrImage->image.type());
}
if(depth.empty())
{
depth = cv::Mat(imageHeight, imageWidth*cameraCount, subDepth.type());
}
if(ptrImage->image.type() == rgb.type())
{
ptrImage->image.copyTo(cv::Mat(rgb, cv::Rect(i*imageWidth, 0, imageWidth, imageHeight)));
}
else
{
ROS_ERROR("Some RGB images are not the same type!");
return false;
}
if(subDepth.type() == depth.type())
{
subDepth.copyTo(cv::Mat(depth, cv::Rect(i*imageWidth, 0, imageWidth, imageHeight)));
}
else
{
ROS_ERROR("Some Depth images are not the same type!");
return false;
}
cameraModels.push_back(rtabmap_ros::cameraModelFromROS(cameraInfoMsgs[i], localTransform));
}
return true;
}
bool convertStereoMsg(
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg,
const std::string & frameId,
const std::string & odomFrameId,
const ros::Time & odomStamp,
cv::Mat & left,
cv::Mat & right,
rtabmap::StereoCameraModel & stereoModel,
tf::TransformListener & listener,
double waitForTransform)
{
UASSERT(leftImageMsg.get() && rightImageMsg.get());
UASSERT(leftCamInfoMsg.get() && rightCamInfoMsg.get());
if(!(leftImageMsg->encoding.compare(sensor_msgs::image_encodings::MONO8) == 0 ||
leftImageMsg->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0 ||
leftImageMsg->encoding.compare(sensor_msgs::image_encodings::BGR8) == 0 ||
leftImageMsg->encoding.compare(sensor_msgs::image_encodings::RGB8) == 0) ||
!(rightImageMsg->encoding.compare(sensor_msgs::image_encodings::MONO8) == 0 ||
rightImageMsg->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0 ||
rightImageMsg->encoding.compare(sensor_msgs::image_encodings::BGR8) == 0 ||
rightImageMsg->encoding.compare(sensor_msgs::image_encodings::RGB8) == 0))
{
ROS_ERROR("Input type must be image=mono8,mono16,rgb8,bgr8");
return false;
}
if(leftImageMsg->encoding.compare(sensor_msgs::image_encodings::MONO8) == 0 ||
leftImageMsg->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0)
{
left = cv_bridge::toCvCopy(leftImageMsg, "mono8")->image;
}
else
{
left = cv_bridge::toCvCopy(leftImageMsg, "bgr8")->image;
}
right = cv_bridge::toCvCopy(rightImageMsg, "mono8")->image;
rtabmap::Transform localTransform = getTransform(frameId, leftImageMsg->header.frame_id, leftImageMsg->header.stamp, listener, waitForTransform);
if(localTransform.isNull())
{
return false;
}
// sync with odometry stamp
if(!odomFrameId.empty() && odomStamp != leftImageMsg->header.stamp)
{
rtabmap::Transform sensorT = getTransform(
frameId,
odomFrameId,
odomStamp,
leftImageMsg->header.stamp,
listener,
waitForTransform);
if(sensorT.isNull())
{
ROS_WARN("Could not get odometry value for stereo msg stamp (%fs). Latest odometry "
"stamp is %fs. The stereo image pose will not be synchronized with odometry.", leftImageMsg->header.stamp.toSec(), odomStamp.toSec());
}
else
{
localTransform = sensorT * localTransform;
}
}
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). You may need to calibrate your camera. "
"This warning is printed only once.",
stereoModel.baseline());
shown = true;
}
}
return true;
}
bool convertScanMsg(
const sensor_msgs::LaserScanConstPtr& scan2dMsg,
const std::string & frameId,
const std::string & odomFrameId,
const ros::Time & odomStamp,
cv::Mat & scan,
rtabmap::Transform & scanLocalTransform,
tf::TransformListener & listener,
double waitForTransform)
{
// make sure the frame of the laser is updated too
rtabmap::Transform tmpT = getTransform(
odomFrameId.empty()?frameId:odomFrameId,
scan2dMsg->header.frame_id,
scan2dMsg->header.stamp + ros::Duration().fromSec(scan2dMsg->ranges.size()*scan2dMsg->time_increment),
listener,
waitForTransform);
if(tmpT.isNull())
{
return false;
}
scanLocalTransform = getTransform(
frameId,
scan2dMsg->header.frame_id,
scan2dMsg->header.stamp,
listener,
waitForTransform);
if(scanLocalTransform.isNull())
{
return false;
}
//transform in frameId_ frame
sensor_msgs::PointCloud2 scanOut;
laser_geometry::LaserProjection projection;
projection.transformLaserScanToPointCloud(odomFrameId.empty()?frameId:odomFrameId, *scan2dMsg, scanOut, listener);
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(scanOut, *pclScan);
//transform back in laser frame
rtabmap::Transform laserToOdom = getTransform(
scan2dMsg->header.frame_id,
odomFrameId.empty()?frameId:odomFrameId,
scan2dMsg->header.stamp,
listener,
waitForTransform);
if(laserToOdom.isNull())
{
return false;
}
// sync with odometry stamp
if(!odomFrameId.empty() && odomStamp != scan2dMsg->header.stamp)
{
rtabmap::Transform sensorT = getTransform(
frameId,
odomFrameId,
odomStamp,
scan2dMsg->header.stamp,
listener,
waitForTransform);
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.", scan2dMsg->header.stamp.toSec(), odomStamp.toSec());
}
else
{
//ROS_WARN("scan correction = %s (time diff=%fs)", sensorT.prettyPrint().c_str(), fabs(scan2dMsg->header.stamp.toSec()-odomStamp.toSec()));
scanLocalTransform = sensorT * scanLocalTransform;
}
}
scan = rtabmap::util3d::laserScan2dFromPointCloud(*pclScan, laserToOdom); // put back in laser frame
return true;
}
bool convertScan3dMsg(
const sensor_msgs::PointCloud2ConstPtr & scan3dMsg,
const std::string & frameId,
const std::string & odomFrameId,
const ros::Time & odomStamp,
int scanCloudNormalK,
cv::Mat & scan,
rtabmap::Transform & scanLocalTransform,
tf::TransformListener & listener,
double waitForTransform)
{
bool containNormals = false;
for(unsigned int i=0; i<scan3dMsg->fields.size(); ++i)
{
if(scan3dMsg->fields[i].name.compare("normal_x") == 0)
{
containNormals = true;
break;
}
}
scanLocalTransform = getTransform(frameId, scan3dMsg->header.frame_id, scan3dMsg->header.stamp, listener, waitForTransform);
if(scanLocalTransform.isNull())
{
ROS_ERROR("TF of received scan cloud at time %fs is not set, aborting rtabmap update.", scan3dMsg->header.stamp.toSec());
return false;
}
// sync with odometry stamp
if(!odomFrameId.empty() && odomStamp != scan3dMsg->header.stamp)
{
rtabmap::Transform sensorT = getTransform(
frameId,
odomFrameId,
odomStamp,
scan3dMsg->header.stamp,
listener,
waitForTransform);
if(sensorT.isNull())
{
ROS_WARN("Could not get odometry value for laser scan stamp (%fs). Latest odometry "
"stamp is %fs. The 3d laser scan pose will not be synchronized with odometry.", scan3dMsg->header.stamp.toSec(), odomStamp.toSec());
}
else
{
scanLocalTransform = sensorT * scanLocalTransform;
}
}
if(containNormals)
{
pcl::PointCloud<pcl::PointNormal>::Ptr pclScan(new pcl::PointCloud<pcl::PointNormal>);
pcl::fromROSMsg(*scan3dMsg, *pclScan);
scan = rtabmap::util3d::laserScanFromPointCloud(*pclScan);
}
else
{
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(*scan3dMsg, *pclScan);
if(scanCloudNormalK > 0)
{
//compute normals
pcl::PointCloud<pcl::Normal>::Ptr normals = rtabmap::util3d::computeNormals(pclScan, scanCloudNormalK);
pcl::PointCloud<pcl::PointNormal>::Ptr pclScanNormal(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*pclScan, *normals, *pclScanNormal);
scan = rtabmap::util3d::laserScanFromPointCloud(*pclScanNormal);
}
else
{
scan = rtabmap::util3d::laserScanFromPointCloud(*pclScan);
}
}
return true;
} }
} }
@@ -25,7 +25,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "OdometryROS.h" #include "rtabmap_ros/OdometryROS.h"
#include <sensor_msgs/Image.h> #include <sensor_msgs/Image.h>
#include <sensor_msgs/image_encodings.h> #include <sensor_msgs/image_encodings.h>
@@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/Rtabmap.h> #include <rtabmap/core/Rtabmap.h>
#include <rtabmap/core/OdometryF2M.h> #include <rtabmap/core/OdometryF2M.h>
#include <rtabmap/core/OdometryF2F.h> #include <rtabmap/core/OdometryF2F.h>
#include <rtabmap/core/util3d.h>
#include <rtabmap/core/util3d_transforms.h> #include <rtabmap/core/util3d_transforms.h>
#include <rtabmap/core/Memory.h> #include <rtabmap/core/Memory.h>
#include <rtabmap/core/Signature.h> #include <rtabmap/core/Signature.h>
@@ -55,11 +56,14 @@ using namespace rtabmap;
namespace rtabmap_ros { namespace rtabmap_ros {
OdometryROS::OdometryROS(bool stereo) : OdometryROS::OdometryROS(bool stereoParams, bool visParams, bool icpParams) :
odometry_(0), odometry_(0),
warningThread_(0),
callbackCalled_(false),
frameId_("base_link"), frameId_("base_link"),
odomFrameId_("odom"), odomFrameId_("odom"),
groundTruthFrameId_(""), groundTruthFrameId_(""),
guessFrameId_(""),
publishTf_(true), publishTf_(true),
waitForTransform_(true), waitForTransform_(true),
waitForTransformDuration_(0.1), // 100 ms waitForTransformDuration_(0.1), // 100 ms
@@ -68,13 +72,21 @@ OdometryROS::OdometryROS(bool stereo) :
paused_(false), paused_(false),
resetCountdown_(0), resetCountdown_(0),
resetCurrentCount_(0), resetCurrentCount_(0),
stereo_(stereo) stereoParams_(stereoParams),
visParams_(visParams),
icpParams_(icpParams)
{ {
} }
OdometryROS::~OdometryROS() OdometryROS::~OdometryROS()
{ {
if(warningThread_)
{
callbackCalled();
warningThread_->join();
delete warningThread_;
}
ros::NodeHandle & pnh = getPrivateNodeHandle(); ros::NodeHandle & pnh = getPrivateNodeHandle();
if(pnh.ok()) if(pnh.ok())
{ {
@@ -95,6 +107,7 @@ void OdometryROS::onInit()
odomPub_ = nh.advertise<nav_msgs::Odometry>("odom", 1); odomPub_ = nh.advertise<nav_msgs::Odometry>("odom", 1);
odomInfoPub_ = nh.advertise<rtabmap_ros::OdomInfo>("odom_info", 1); odomInfoPub_ = nh.advertise<rtabmap_ros::OdomInfo>("odom_info", 1);
odomLocalMap_ = nh.advertise<sensor_msgs::PointCloud2>("odom_local_map", 1); odomLocalMap_ = nh.advertise<sensor_msgs::PointCloud2>("odom_local_map", 1);
odomLocalScanMap_ = nh.advertise<sensor_msgs::PointCloud2>("odom_local_scan_map", 1);
odomLastFrame_ = nh.advertise<sensor_msgs::PointCloud2>("odom_last_frame", 1); odomLastFrame_ = nh.advertise<sensor_msgs::PointCloud2>("odom_last_frame", 1);
Transform initialPose = Transform::getIdentity(); Transform initialPose = Transform::getIdentity();
@@ -112,10 +125,13 @@ void OdometryROS::onInit()
pnh.param("config_path", configPath, configPath); pnh.param("config_path", configPath, configPath);
pnh.param("publish_null_when_lost", publishNullWhenLost_, publishNullWhenLost_); pnh.param("publish_null_when_lost", publishNullWhenLost_, publishNullWhenLost_);
pnh.param("guess_from_tf", guessFromTf_, guessFromTf_); pnh.param("guess_from_tf", guessFromTf_, guessFromTf_);
pnh.param("guess_frame_id", guessFrameId_, frameId_);
if(publishTf_ && guessFromTf_) if(publishTf_ && guessFromTf_ && guessFrameId_.compare(frameId_) == 0)
{ {
NODELET_WARN( "\"publish_tf\" and \"guess_from_tf\" cannot be used at the same time. \"guess_from_tf\" is disabled."); NODELET_WARN( "\"publish_tf\" and \"guess_from_tf\" cannot be used "
"at the same time if \"guess_frame_id\" and \"frame_id\" "
"are the same frame (value=\"%s\"). \"guess_from_tf\" is disabled.", frameId_.c_str());
guessFromTf_ = false; guessFromTf_ = false;
} }
@@ -159,7 +175,7 @@ void OdometryROS::onInit()
//parameters //parameters
parameters_ = Parameters::getDefaultOdometryParameters(stereo_); parameters_ = Parameters::getDefaultOdometryParameters(stereoParams_, visParams_, icpParams_);
if(!configPath.empty()) if(!configPath.empty())
{ {
if(UFile::exists(configPath.c_str())) if(UFile::exists(configPath.c_str()))
@@ -267,6 +283,9 @@ void OdometryROS::onInit()
Parameters::parse(parameters_, Parameters::kOdomResetCountdown(), resetCountdown_); Parameters::parse(parameters_, Parameters::kOdomResetCountdown(), resetCountdown_);
parameters_.at(Parameters::kOdomResetCountdown()) = "0"; // use modified reset countdown here parameters_.at(Parameters::kOdomResetCountdown()) = "0"; // use modified reset countdown here
this->updateParameters(parameters_);
odometry_ = Odometry::create(parameters_); odometry_ = Odometry::create(parameters_);
if(!initialPose.isIdentity()) if(!initialPose.isIdentity())
{ {
@@ -286,6 +305,31 @@ void OdometryROS::onInit()
onOdomInit(); onOdomInit();
} }
void OdometryROS::startWarningThread(const std::string & subscribedTopicsMsg, bool approxSync)
{
warningThread_ = new boost::thread(boost::bind(&OdometryROS::warningLoop, this, subscribedTopicsMsg, approxSync));
NODELET_INFO("%s", subscribedTopicsMsg.c_str());
}
void OdometryROS::warningLoop(const std::string & subscribedTopicsMsg, bool approxSync)
{
ros::Duration r(5.0);
while(!callbackCalled_)
{
r.sleep();
if(!callbackCalled_)
{
ROS_WARN("%s: Did not receive data since 5 seconds! Make sure the input topics are "
"published (\"$ rostopic hz my_topic\") and the timestamps in their "
"header are set. %s%s",
getName().c_str(),
approxSync?"":"Parameter \"approx_sync\" is false, which means that input "
"topics should have all the exact timestamp for the callback to be called.",
subscribedTopicsMsg.c_str());
}
}
}
Transform OdometryROS::getTransform(const std::string & fromFrameId, const std::string & toFrameId, const ros::Time & stamp) const Transform OdometryROS::getTransform(const std::string & fromFrameId, const std::string & toFrameId, const ros::Time & stamp) const
{ {
// TF ready? // TF ready?
@@ -295,10 +339,11 @@ Transform OdometryROS::getTransform(const std::string & fromFrameId, const std::
if(waitForTransform_ && !stamp.isZero() && waitForTransformDuration_ > 0.0) if(waitForTransform_ && !stamp.isZero() && waitForTransformDuration_ > 0.0)
{ {
//if(!tfBuffer_.canTransform(fromFrameId, toFrameId, stamp, ros::Duration(1))) //if(!tfBuffer_.canTransform(fromFrameId, toFrameId, stamp, ros::Duration(1)))
if(!tfListener_.waitForTransform(fromFrameId, toFrameId, stamp, ros::Duration(waitForTransformDuration_))) std::string errorMsg;
if(!tfListener_.waitForTransform(fromFrameId, toFrameId, stamp, ros::Duration(waitForTransformDuration_), ros::Duration(0.01), &errorMsg))
{ {
NODELET_WARN( "odometry: Could not get transform from %s to %s (stamp=%f) after %f seconds (\"wait_for_transform_duration\"=%f)!", NODELET_WARN( "odometry: Could not get transform from %s to %s (stamp=%f) after %f seconds (\"wait_for_transform_duration\"=%f)! Error=\"%s\"",
fromFrameId.c_str(), toFrameId.c_str(), stamp.toSec(), waitForTransformDuration_, waitForTransformDuration_); fromFrameId.c_str(), toFrameId.c_str(), stamp.toSec(), waitForTransformDuration_, waitForTransformDuration_, errorMsg.c_str());
return transform; return transform;
} }
} }
@@ -336,8 +381,8 @@ void OdometryROS::processData(const SensorData & data, const ros::Time & stamp)
Transform guess; Transform guess;
if(guessFromTf_) if(guessFromTf_)
{ {
Transform previousPose = this->getTransform(odomFrameId_, frameId_, ros::Time(odometry_->previousStamp())); Transform previousPose = this->getTransform(odomFrameId_, guessFrameId_, ros::Time(odometry_->previousStamp()));
Transform pose = this->getTransform(odomFrameId_, frameId_, stamp); Transform pose = this->getTransform(odomFrameId_, guessFrameId_, stamp);
if(!previousPose.isNull() && !pose.isNull()) if(!previousPose.isNull() && !pose.isNull())
{ {
guess = previousPose.inverse() * pose; guess = previousPose.inverse() * pose;
@@ -352,6 +397,11 @@ void OdometryROS::processData(const SensorData & data, const ros::Time & stamp)
} }
NODELET_WARN( "TF Guess %s", guess.prettyPrint().c_str());*/ NODELET_WARN( "TF Guess %s", guess.prettyPrint().c_str());*/
} }
else
{
ROS_ERROR("\"guess_from_tf\" is true, but guess cannot be computed between frames \"%s\" -> \"%s\". Aborting odometry update...", odomFrameId_.c_str(), guessFrameId_.c_str());
return;
}
} }
// process data // process data
@@ -393,12 +443,12 @@ void OdometryROS::processData(const SensorData & data, const ros::Time & stamp)
//set covariance //set covariance
// libviso2 uses approximately vel variance * 2 // libviso2 uses approximately vel variance * 2
odom.pose.covariance.at(0) = info.variance*2; // xx odom.pose.covariance.at(0) = info.varianceLin*2; // xx
odom.pose.covariance.at(7) = info.variance*2; // yy odom.pose.covariance.at(7) = info.varianceLin*2; // yy
odom.pose.covariance.at(14) = info.variance*2; // zz odom.pose.covariance.at(14) = info.varianceLin*2; // zz
odom.pose.covariance.at(21) = info.variance*2; // rr odom.pose.covariance.at(21) = info.varianceAng*2; // rr
odom.pose.covariance.at(28) = info.variance*2; // pp odom.pose.covariance.at(28) = info.varianceAng*2; // pp
odom.pose.covariance.at(35) = info.variance*2; // yawyaw odom.pose.covariance.at(35) = info.varianceAng*2; // yawyaw
//set velocity //set velocity
bool setTwist = !odometry_->previousVelocityTransform().isNull(); bool setTwist = !odometry_->previousVelocityTransform().isNull();
@@ -414,19 +464,19 @@ void OdometryROS::processData(const SensorData & data, const ros::Time & stamp)
odom.twist.twist.angular.z = yaw; odom.twist.twist.angular.z = yaw;
} }
odom.twist.covariance.at(0) = setTwist?info.variance:BAD_COVARIANCE; // xx odom.twist.covariance.at(0) = setTwist?info.varianceLin:BAD_COVARIANCE; // xx
odom.twist.covariance.at(7) = setTwist?info.variance:BAD_COVARIANCE; // yy odom.twist.covariance.at(7) = setTwist?info.varianceLin:BAD_COVARIANCE; // yy
odom.twist.covariance.at(14) = setTwist?info.variance:BAD_COVARIANCE; // zz odom.twist.covariance.at(14) = setTwist?info.varianceLin:BAD_COVARIANCE; // zz
odom.twist.covariance.at(21) = setTwist?info.variance:BAD_COVARIANCE; // rr odom.twist.covariance.at(21) = setTwist?info.varianceAng:BAD_COVARIANCE; // rr
odom.twist.covariance.at(28) = setTwist?info.variance:BAD_COVARIANCE; // pp odom.twist.covariance.at(28) = setTwist?info.varianceAng:BAD_COVARIANCE; // pp
odom.twist.covariance.at(35) = setTwist?info.variance:BAD_COVARIANCE; // yawyaw odom.twist.covariance.at(35) = setTwist?info.varianceAng:BAD_COVARIANCE; // yawyaw
//publish the message //publish the message
odomPub_.publish(odom); odomPub_.publish(odom);
} }
// local map / reference frame // local map / reference frame
if(odomLocalMap_.getNumSubscribers() && dynamic_cast<OdometryF2M*>(odometry_)) if(odomLocalMap_.getNumSubscribers() && odometry_->getType() == Odometry::kTypeF2M)
{ {
pcl::PointCloud<pcl::PointXYZ> cloud; pcl::PointCloud<pcl::PointXYZ> cloud;
const std::multimap<int, cv::Point3f> & map = ((OdometryF2M*)odometry_)->getMap().getWords3(); const std::multimap<int, cv::Point3f> & map = ((OdometryF2M*)odometry_)->getMap().getWords3();
@@ -443,7 +493,8 @@ void OdometryROS::processData(const SensorData & data, const ros::Time & stamp)
if(odomLastFrame_.getNumSubscribers()) if(odomLastFrame_.getNumSubscribers())
{ {
if(dynamic_cast<OdometryF2M*>(odometry_)) // check which type of Odometry is using
if(odometry_->getType() == Odometry::kTypeF2M) // If it's Frame to Map Odometry
{ {
const std::multimap<int, cv::Point3f> & words3 = ((OdometryF2M*)odometry_)->getLastFrame().getWords3(); const std::multimap<int, cv::Point3f> & words3 = ((OdometryF2M*)odometry_)->getLastFrame().getWords3();
if(words3.size()) if(words3.size())
@@ -463,10 +514,10 @@ void OdometryROS::processData(const SensorData & data, const ros::Time & stamp)
odomLastFrame_.publish(cloudMsg); odomLastFrame_.publish(cloudMsg);
} }
} }
else else if(odometry_->getType() == Odometry::kTypeF2F) // if Using Frame to Frame Odometry
{ {
//Frame to Frame
const Signature & refFrame = ((OdometryF2F*)odometry_)->getRefFrame(); const Signature & refFrame = ((OdometryF2F*)odometry_)->getRefFrame();
if(refFrame.getWords3().size()) if(refFrame.getWords3().size())
{ {
pcl::PointCloud<pcl::PointXYZ> cloud; pcl::PointCloud<pcl::PointXYZ> cloud;
@@ -482,8 +533,29 @@ void OdometryROS::processData(const SensorData & data, const ros::Time & stamp)
cloudMsg.header.frame_id = odomFrameId_; cloudMsg.header.frame_id = odomFrameId_;
odomLastFrame_.publish(cloudMsg); odomLastFrame_.publish(cloudMsg);
} }
}else{
NODELET_ERROR("ERROR, Wrong Type of Odometry, Shouldn't happen");
} }
} }
if(odomLocalScanMap_.getNumSubscribers() && !info.localScanMap.empty())
{
sensor_msgs::PointCloud2 cloudMsg;
if(info.localScanMap.channels() == 6)
{
pcl::PointCloud<pcl::PointNormal>::Ptr cloud = util3d::laserScanToPointCloudNormal(info.localScanMap);
pcl::toROSMsg(*cloud, cloudMsg);
}
else
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = util3d::laserScanToPointCloud(info.localScanMap);
pcl::toROSMsg(*cloud, cloudMsg);
}
cloudMsg.header.stamp = stamp; // use corresponding time stamp to image
cloudMsg.header.frame_id = odomFrameId_;
odomLocalScanMap_.publish(cloudMsg);
}
} }
else if(publishNullWhenLost_) else if(publishNullWhenLost_)
{ {
@@ -544,12 +616,22 @@ void OdometryROS::processData(const SensorData & data, const ros::Time & stamp)
odomInfoPub_.publish(infoMsg); odomInfoPub_.publish(infoMsg);
} }
NODELET_INFO( "Odom: quality=%d, std dev=%fm, update time=%fs", info.inliers, pose.isNull()?0.0f:std::sqrt(info.variance), (ros::WallTime::now()-time).toSec()); if(visParams_)
} {
if(icpParams_)
{
NODELET_INFO( "Odom: quality=%d, ratio=%f, std dev=%fm|%frad, update time=%fs", info.inliers, info.icpInliersRatio, pose.isNull()?0.0f:std::sqrt(info.varianceLin), pose.isNull()?0.0f:std::sqrt(info.varianceAng), (ros::WallTime::now()-time).toSec());
}
else
{
NODELET_INFO( "Odom: quality=%d, std dev=%fm|%frad, update time=%fs", info.inliers, pose.isNull()?0.0f:std::sqrt(info.varianceLin), pose.isNull()?0.0f:std::sqrt(info.varianceAng), (ros::WallTime::now()-time).toSec());
}
}
else
{
NODELET_INFO( "Odom: ratio=%f, std dev=%fm|%frad, update time=%fs", info.icpInliersRatio, pose.isNull()?0.0f:std::sqrt(info.varianceLin), pose.isNull()?0.0f:std::sqrt(info.varianceAng), (ros::WallTime::now()-time).toSec());
}
bool OdometryROS::isOdometryF2M() const
{
return dynamic_cast<OdometryF2M*>(odometry_) != 0;
} }
bool OdometryROS::reset(std_srvs::Empty::Request&, std_srvs::Empty::Response&) bool OdometryROS::reset(std_srvs::Empty::Request&, std_srvs::Empty::Response&)
+1 -1
View File
@@ -25,7 +25,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "PreferencesDialogROS.h" #include "rtabmap_ros/PreferencesDialogROS.h"
#include <rtabmap/core/Parameters.h> #include <rtabmap/core/Parameters.h>
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
+78
View File
@@ -0,0 +1,78 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ros/ros.h"
#include "nodelet/loader.h"
#include <rtabmap/utilite/ULogger.h>
#include <rtabmap/core/Parameters.h>
int main(int argc, char **argv)
{
ULogger::setType(ULogger::kTypeConsole);
ULogger::setLevel(ULogger::kWarning);
ros::init(argc, argv, "rgbdicp_odometry");
// process "--params" argument
nodelet::V_string nargv;
for(int i=1;i<argc;++i)
{
if(strcmp(argv[i], "--params") == 0)
{
rtabmap::ParametersMap parametersOdom = rtabmap::Parameters::getDefaultOdometryParameters(false, true, true);
for(rtabmap::ParametersMap::iterator iter=parametersOdom.begin(); iter!=parametersOdom.end(); ++iter)
{
std::string str = "Param: " + iter->first + " = \"" + iter->second + "\"";
std::cout <<
str <<
std::setw(60 - str.size()) <<
" [" <<
rtabmap::Parameters::getDescription(iter->first).c_str() <<
"]" <<
std::endl;
}
ROS_WARN("Node will now exit after showing default odometry parameters because "
"argument \"--params\" is detected!");
exit(0);
}
else if(strcmp(argv[i], "--udebug") == 0)
{
ULogger::setLevel(ULogger::kDebug);
}
else if(strcmp(argv[i], "--uinfo") == 0)
{
ULogger::setLevel(ULogger::kInfo);
}
nargv.push_back(argv[i]);
}
nodelet::Loader nodelet;
nodelet::M_string remap(ros::names::getRemappings());
std::string nodelet_name = ros::this_node::getName();
nodelet.load(nodelet_name, "rtabmap_ros/rgbdicp_odometry", remap, nargv);
ros::spin();
return 0;
}
+369
View File
@@ -0,0 +1,369 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtabmap_ros/CommonDataSubscriber.h>
namespace rtabmap_ros {
// RGB + Depth
void CommonDataSubscriber::depthCallback(
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg)
{
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::depthScan2dCallback(
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg)
{
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::depthScan3dCallback(
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg,
const sensor_msgs::PointCloud2ConstPtr& scanMsg)
{
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::LaserScanConstPtr scan2dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scan2dMsg, scanMsg, odomInfoMsg);
}
void CommonDataSubscriber::depthInfoCallback(
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg)
{
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::LaserScanConstPtr scan2dMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scan2dMsg, scan3dMsg, odomInfoMsg);
}
// RGB + Depth + Odom
void CommonDataSubscriber::depthOdomCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg)
{
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::depthOdomScan2dCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg)
{
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::depthOdomScan3dCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg,
const sensor_msgs::PointCloud2ConstPtr& scanMsg)
{
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::LaserScanConstPtr scan2dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scan2dMsg, scanMsg, odomInfoMsg);
}
void CommonDataSubscriber::depthOdomInfoCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg)
{
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::LaserScanConstPtr scan2dMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scan2dMsg, scan3dMsg, odomInfoMsg);
}
// RGB + Depth + User Data
void CommonDataSubscriber::depthDataCallback(
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg)
{
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::depthDataScan2dCallback(
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg)
{
nav_msgs::OdometryConstPtr odomMsg; // null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::depthDataScan3dCallback(
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg,
const sensor_msgs::PointCloud2ConstPtr& scanMsg)
{
nav_msgs::OdometryConstPtr odomMsg; // null
sensor_msgs::LaserScanConstPtr scan2dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scan2dMsg, scanMsg, odomInfoMsg);
}
void CommonDataSubscriber::depthDataInfoCallback(
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg)
{
nav_msgs::OdometryConstPtr odomMsg; // null
sensor_msgs::LaserScanConstPtr scan2dMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scan2dMsg, scan3dMsg, odomInfoMsg);
}
// RGB + Depth + Odom + User Data
void CommonDataSubscriber::depthOdomDataCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg)
{
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::depthOdomDataScan2dCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg,
const sensor_msgs::LaserScanConstPtr& scanMsg)
{
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::depthOdomDataScan3dCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg,
const sensor_msgs::PointCloud2ConstPtr& scanMsg)
{
sensor_msgs::LaserScanConstPtr scan2dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scan2dMsg, scanMsg, odomInfoMsg);
}
void CommonDataSubscriber::depthOdomDataInfoCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const sensor_msgs::ImageConstPtr& imageMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg)
{
sensor_msgs::LaserScanConstPtr scan2dMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
commonSingleDepthCallback(odomMsg, userDataMsg, cv_bridge::toCvShare(imageMsg), cv_bridge::toCvShare(depthMsg), *cameraInfoMsg, scan2dMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::setupDepthCallbacks(
ros::NodeHandle & nh,
ros::NodeHandle & pnh,
bool subscribeOdom,
bool subscribeUserData,
bool subscribeScan2d,
bool subscribeScan3d,
bool subscribeOdomInfo,
int queueSize,
bool approxSync)
{
ROS_INFO("Setup depth callback");
std::string rgbPrefix = "rgb";
std::string depthPrefix = "depth";
ros::NodeHandle rgb_nh(nh, rgbPrefix);
ros::NodeHandle depth_nh(nh, depthPrefix);
ros::NodeHandle rgb_pnh(pnh, rgbPrefix);
ros::NodeHandle depth_pnh(pnh, depthPrefix);
image_transport::ImageTransport rgb_it(rgb_nh);
image_transport::ImageTransport depth_it(depth_nh);
image_transport::TransportHints hintsRgb("raw", ros::TransportHints(), rgb_pnh);
image_transport::TransportHints hintsDepth("raw", ros::TransportHints(), depth_pnh);
imageSub_.subscribe(rgb_it, rgb_nh.resolveName("image"), 1, hintsRgb);
imageDepthSub_.subscribe(depth_it, depth_nh.resolveName("image"), 1, hintsDepth);
cameraInfoSub_.subscribe(rgb_nh, "camera_info", 1);
if(subscribeOdom && subscribeUserData)
{
odomSub_.subscribe(nh, "odom", 1);
userDataSub_.subscribe(nh, "user_data", 1);
if(subscribeScan2d)
{
subscribedToScan2d_ = true;
scanSub_.subscribe(nh, "scan", 1);
SYNC_DECL6(depthOdomDataScan2d, approxSync, queueSize, odomSub_, userDataSub_, imageSub_, imageDepthSub_, cameraInfoSub_, scanSub_);
}
else if(subscribeScan3d)
{
subscribedToScan3d_ = true;
scan3dSub_.subscribe(nh, "scan_cloud", 1);
SYNC_DECL6(depthOdomDataScan3d, approxSync, queueSize, odomSub_, userDataSub_, imageSub_, imageDepthSub_, cameraInfoSub_, scan3dSub_);
}
else if(subscribeOdomInfo)
{
subscribedToOdomInfo_ = true;
odomInfoSub_.subscribe(nh, "odom_info", 1);
SYNC_DECL6(depthOdomDataInfo, approxSync, queueSize, odomSub_, userDataSub_, imageSub_, imageDepthSub_, cameraInfoSub_, odomInfoSub_);
}
else
{
SYNC_DECL5(depthOdomData, approxSync, queueSize, odomSub_, userDataSub_, imageSub_, imageDepthSub_, cameraInfoSub_);
}
}
else if(subscribeOdom)
{
odomSub_.subscribe(nh, "odom", 1);
if(subscribeScan2d)
{
subscribedToScan2d_ = true;
scanSub_.subscribe(nh, "scan", 1);
SYNC_DECL5(depthOdomScan2d, approxSync, queueSize, odomSub_, imageSub_, imageDepthSub_, cameraInfoSub_, scanSub_);
}
else if(subscribeScan3d)
{
subscribedToScan3d_ = true;
scan3dSub_.subscribe(nh, "scan_cloud", 1);
SYNC_DECL5(depthOdomScan3d, approxSync, queueSize, odomSub_, imageSub_, imageDepthSub_, cameraInfoSub_, scan3dSub_);
}
else if(subscribeOdomInfo)
{
subscribedToOdomInfo_ = true;
odomInfoSub_.subscribe(nh, "odom_info", 1);
SYNC_DECL5(depthOdomInfo, approxSync, queueSize, odomSub_, imageSub_, imageDepthSub_, cameraInfoSub_, odomInfoSub_);
}
else
{
SYNC_DECL4(depthOdom, approxSync, queueSize, odomSub_, imageSub_, imageDepthSub_, cameraInfoSub_);
}
}
else if(subscribeUserData)
{
userDataSub_.subscribe(nh, "user_data", 1);
if(subscribeScan2d)
{
subscribedToScan2d_ = true;
scanSub_.subscribe(nh, "scan", 1);
SYNC_DECL5(depthDataScan2d, approxSync, queueSize, userDataSub_, imageSub_, imageDepthSub_, cameraInfoSub_, scanSub_);
}
else if(subscribeScan3d)
{
subscribedToScan3d_ = true;
scan3dSub_.subscribe(nh, "scan_cloud", 1);
SYNC_DECL5(depthDataScan3d, approxSync, queueSize, userDataSub_, imageSub_, imageDepthSub_, cameraInfoSub_, scan3dSub_);
}
else if(subscribeOdomInfo)
{
subscribedToOdomInfo_ = true;
odomInfoSub_.subscribe(nh, "odom_info", 1);
SYNC_DECL5(depthDataInfo, approxSync, queueSize, userDataSub_, imageSub_, imageDepthSub_, cameraInfoSub_, odomInfoSub_);
}
else
{
SYNC_DECL4(depthData, approxSync, queueSize, userDataSub_, imageSub_, imageDepthSub_, cameraInfoSub_);
}
}
else
{
if(subscribeScan2d)
{
subscribedToScan2d_ = true;
scanSub_.subscribe(nh, "scan", 1);
SYNC_DECL4(depthScan2d, approxSync, queueSize, imageSub_, imageDepthSub_, cameraInfoSub_, scanSub_);
}
else if(subscribeScan3d)
{
subscribedToScan3d_ = true;
scan3dSub_.subscribe(nh, "scan_cloud", 1);
SYNC_DECL4(depthScan3d, approxSync, queueSize, imageSub_, imageDepthSub_, cameraInfoSub_, scan3dSub_);
}
else if(subscribeOdomInfo)
{
subscribedToOdomInfo_ = true;
odomInfoSub_.subscribe(nh, "odom_info", 1);
SYNC_DECL4(depthInfo, approxSync, queueSize, imageSub_, imageDepthSub_, cameraInfoSub_, odomInfoSub_);
}
else
{
SYNC_DECL3(depth, approxSync, queueSize, imageSub_, imageDepthSub_, cameraInfoSub_);
}
}
}
} /* namespace rtabmap_ros */
+387
View File
@@ -0,0 +1,387 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtabmap_ros/CommonDataSubscriber.h>
#include <rtabmap/utilite/UConversion.h>
#include <rtabmap_ros/MsgConversion.h>
#include <cv_bridge/cv_bridge.h>
namespace rtabmap_ros {
// 1 RGBD camera
void CommonDataSubscriber::rgbdCallback(
const rtabmap_ros::RGBDImageConstPtr& image1Msg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbdScan2dCallback(
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const sensor_msgs::LaserScanConstPtr& scanMsg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbdScan3dCallback(
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbdInfoCallback(
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
commonSingleDepthCallback(odomMsg, userDataMsg, rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
// 1 RGBD camera + Odom
void CommonDataSubscriber::rgbdOdomCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbdOdomScan2dCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const sensor_msgs::LaserScanConstPtr& scanMsg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbdOdomScan3dCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbdOdomInfoCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
commonSingleDepthCallback(odomMsg, userDataMsg, rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
// 1 RGBD camera + User Data
void CommonDataSubscriber::rgbdDataCallback(
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg, rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbdDataScan2dCallback(
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const sensor_msgs::LaserScanConstPtr& scanMsg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg,rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbdDataScan3dCallback(
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg,rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbdDataInfoCallback(
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
commonSingleDepthCallback(odomMsg, userDataMsg,rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
// 1 RGBD camera + Odom + User Data
void CommonDataSubscriber::rgbdOdomDataCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg,rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbdOdomDataScan2dCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const sensor_msgs::LaserScanConstPtr& scanMsg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg,rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbdOdomDataScan3dCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
sensor_msgs::LaserScanConstPtr scanMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonSingleDepthCallback(odomMsg, userDataMsg,rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbdOdomDataInfoCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::UserDataConstPtr & userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg)
{
cv_bridge::CvImageConstPtr rgb, depth;
rtabmap_ros::toCvShare(image1Msg, rgb, depth);
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
commonSingleDepthCallback(odomMsg, userDataMsg,rgb, depth, image1Msg->cameraInfo, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::setupRGBDCallbacks(
ros::NodeHandle & nh,
ros::NodeHandle & pnh,
bool subscribeOdom,
bool subscribeUserData,
bool subscribeScan2d,
bool subscribeScan3d,
bool subscribeOdomInfo,
int queueSize,
bool approxSync)
{
ROS_INFO("Setup rgbd callback");
if(subscribeOdom || subscribeUserData || subscribeScan2d || subscribeScan3d || subscribeOdomInfo)
{
rgbdSubs_.resize(1);
rgbdSubs_[0] = new message_filters::Subscriber<rtabmap_ros::RGBDImage>;
rgbdSubs_[0]->subscribe(nh, "rgbd_image", 1);
if(subscribeOdom && subscribeUserData)
{
odomSub_.subscribe(nh, "odom", 1);
userDataSub_.subscribe(nh, "user_data", 1);
if(subscribeScan2d)
{
subscribedToScan2d_ = true;
scanSub_.subscribe(nh, "scan", 1);
SYNC_DECL4(rgbdOdomDataScan2d, approxSync, queueSize, odomSub_, userDataSub_, (*rgbdSubs_[0]), scanSub_);
}
else if(subscribeScan3d)
{
subscribedToScan3d_ = true;
scan3dSub_.subscribe(nh, "scan_cloud", 1);
SYNC_DECL4(rgbdOdomDataScan3d, approxSync, queueSize, odomSub_, userDataSub_, (*rgbdSubs_[0]), scan3dSub_);
}
else if(subscribeOdomInfo)
{
subscribedToOdomInfo_ = true;
odomInfoSub_.subscribe(nh, "odom_info", 1);
SYNC_DECL4(rgbdOdomDataInfo, approxSync, queueSize, odomSub_, userDataSub_, (*rgbdSubs_[0]), odomInfoSub_);
}
else
{
SYNC_DECL3(rgbdOdomData, approxSync, queueSize, odomSub_, userDataSub_, (*rgbdSubs_[0]));
}
}
else if(subscribeOdom)
{
odomSub_.subscribe(nh, "odom", 1);
if(subscribeScan2d)
{
subscribedToScan2d_ = true;
scanSub_.subscribe(nh, "scan", 1);
SYNC_DECL3(rgbdOdomScan2d, approxSync, queueSize, odomSub_, (*rgbdSubs_[0]), scanSub_);
}
else if(subscribeScan3d)
{
subscribedToScan3d_ = true;
scan3dSub_.subscribe(nh, "scan_cloud", 1);
SYNC_DECL3(rgbdOdomScan3d, approxSync, queueSize, odomSub_, (*rgbdSubs_[0]), scan3dSub_);
}
else if(subscribeOdomInfo)
{
subscribedToOdomInfo_ = true;
odomInfoSub_.subscribe(nh, "odom_info", 1);
SYNC_DECL3(rgbdOdomInfo, approxSync, queueSize, odomSub_, (*rgbdSubs_[0]), odomInfoSub_);
}
else
{
SYNC_DECL2(rgbdOdom, approxSync, queueSize, odomSub_, (*rgbdSubs_[0]));
}
}
else if(subscribeUserData)
{
userDataSub_.subscribe(nh, "user_data", 1);
if(subscribeScan2d)
{
subscribedToScan2d_ = true;
scanSub_.subscribe(nh, "scan", 1);
SYNC_DECL3(rgbdDataScan2d, approxSync, queueSize, userDataSub_, (*rgbdSubs_[0]), scanSub_);
}
else if(subscribeScan3d)
{
subscribedToScan3d_ = true;
scan3dSub_.subscribe(nh, "scan_cloud", 1);
SYNC_DECL3(rgbdDataScan3d, approxSync, queueSize, userDataSub_, (*rgbdSubs_[0]), scan3dSub_);
}
else if(subscribeOdomInfo)
{
subscribedToOdomInfo_ = true;
odomInfoSub_.subscribe(nh, "odom_info", 1);
SYNC_DECL3(rgbdDataInfo, approxSync, queueSize, userDataSub_, (*rgbdSubs_[0]), odomInfoSub_);
}
else
{
SYNC_DECL2(rgbdData, approxSync, queueSize, userDataSub_, (*rgbdSubs_[0]));
}
}
else
{
if(subscribeScan2d)
{
subscribedToScan2d_ = true;
scanSub_.subscribe(nh, "scan", 1);
SYNC_DECL2(rgbdScan2d, approxSync, queueSize, (*rgbdSubs_[0]), scanSub_);
}
else if(subscribeScan3d)
{
subscribedToScan3d_ = true;
scan3dSub_.subscribe(nh, "scan_cloud", 1);
SYNC_DECL2(rgbdScan3d, approxSync, queueSize, (*rgbdSubs_[0]), scan3dSub_);
}
else if(subscribeOdomInfo)
{
subscribedToOdomInfo_ = true;
odomInfoSub_.subscribe(nh, "odom_info", 1);
SYNC_DECL2(rgbdInfo, approxSync, queueSize, (*rgbdSubs_[0]), odomInfoSub_);
}
else
{
ROS_FATAL("Not supposed to be here!");
}
}
}
else
{
rgbdSub_ = nh.subscribe("rgbd_image", 1, &CommonDataSubscriber::rgbdCallback, this);
subscribedTopicsMsg_ =
uFormat("\n%s subscribed to:\n %s",
ros::this_node::getName().c_str(),
rgbdSub_.getTopic().c_str());
}
}
} /* namespace rtabmap_ros */
+386
View File
@@ -0,0 +1,386 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtabmap_ros/CommonDataSubscriber.h>
#include <rtabmap/utilite/UConversion.h>
#include <rtabmap_ros/MsgConversion.h>
#include <cv_bridge/cv_bridge.h>
namespace rtabmap_ros {
#define IMAGE_CONVERSION() \
callbackCalled(); \
std::vector<cv_bridge::CvImageConstPtr> imageMsgs(2); \
std::vector<cv_bridge::CvImageConstPtr> depthMsgs(2); \
rtabmap_ros::toCvShare(image1Msg, imageMsgs[0], depthMsgs[0]); \
rtabmap_ros::toCvShare(image2Msg, imageMsgs[1], depthMsgs[1]); \
std::vector<sensor_msgs::CameraInfo> cameraInfoMsgs; \
cameraInfoMsgs.push_back(image1Msg->cameraInfo); \
cameraInfoMsgs.push_back(image2Msg->cameraInfo);
// 2 RGBD
void CommonDataSubscriber::rgbd2Callback(
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg)
{
IMAGE_CONVERSION();
nav_msgs::OdometryConstPtr odomMsg; // Null
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbd2Scan2dCallback(
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg,
const sensor_msgs::LaserScanConstPtr& scanMsg)
{
IMAGE_CONVERSION();
nav_msgs::OdometryConstPtr odomMsg; // Null
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbd2Scan3dCallback(
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg)
{
IMAGE_CONVERSION();
nav_msgs::OdometryConstPtr odomMsg; // Null
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbd2InfoCallback(
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg)
{
IMAGE_CONVERSION();
nav_msgs::OdometryConstPtr odomMsg; // Null
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
// 2 RGBD + Odom
void CommonDataSubscriber::rgbd2OdomCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg)
{
IMAGE_CONVERSION();
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbd2OdomScan2dCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg,
const sensor_msgs::LaserScanConstPtr& scanMsg)
{
IMAGE_CONVERSION();
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbd2OdomScan3dCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg)
{
IMAGE_CONVERSION();
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbd2OdomInfoCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg)
{
IMAGE_CONVERSION();
rtabmap_ros::UserDataConstPtr userDataMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
// 2 RGBD + User Data
void CommonDataSubscriber::rgbd2DataCallback(
const rtabmap_ros::UserDataConstPtr& userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg)
{
IMAGE_CONVERSION();
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbd2DataScan2dCallback(
const rtabmap_ros::UserDataConstPtr& userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg,
const sensor_msgs::LaserScanConstPtr& scanMsg)
{
IMAGE_CONVERSION();
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbd2DataScan3dCallback(
const rtabmap_ros::UserDataConstPtr& userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg)
{
IMAGE_CONVERSION();
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbd2DataInfoCallback(
const rtabmap_ros::UserDataConstPtr& userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg)
{
IMAGE_CONVERSION();
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
// 2 RGBD + Odom + User Data
void CommonDataSubscriber::rgbd2OdomDataCallback(
const nav_msgs::OdometryConstPtr& odomMsg,
const rtabmap_ros::UserDataConstPtr& userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg)
{
IMAGE_CONVERSION();
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbd2OdomDataScan2dCallback(
const nav_msgs::OdometryConstPtr& odomMsg,
const rtabmap_ros::UserDataConstPtr& userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg,
const sensor_msgs::LaserScanConstPtr& scanMsg)
{
IMAGE_CONVERSION();
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbd2OdomDataScan3dCallback(
const nav_msgs::OdometryConstPtr& odomMsg,
const rtabmap_ros::UserDataConstPtr& userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg,
const sensor_msgs::PointCloud2ConstPtr& scan3dMsg)
{
IMAGE_CONVERSION();
sensor_msgs::LaserScanConstPtr scanMsg; // Null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::rgbd2OdomDataInfoCallback(
const nav_msgs::OdometryConstPtr& odomMsg,
const rtabmap_ros::UserDataConstPtr& userDataMsg,
const rtabmap_ros::RGBDImageConstPtr& image1Msg,
const rtabmap_ros::RGBDImageConstPtr& image2Msg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg)
{
IMAGE_CONVERSION();
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
commonDepthCallback(odomMsg, userDataMsg, imageMsgs, depthMsgs, cameraInfoMsgs, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::setupRGBD2Callbacks(
ros::NodeHandle & nh,
ros::NodeHandle & pnh,
bool subscribeOdom,
bool subscribeUserData,
bool subscribeScan2d,
bool subscribeScan3d,
bool subscribeOdomInfo,
int queueSize,
bool approxSync)
{
ROS_INFO("Setup rgbd2 callback");
rgbdSubs_.resize(2);
for(int i=0; i<2; ++i)
{
rgbdSubs_[i] = new message_filters::Subscriber<rtabmap_ros::RGBDImage>;
rgbdSubs_[i]->subscribe(nh, uFormat("rgbd_image%d", i), 1);
}
if(subscribeOdom && subscribeUserData)
{
odomSub_.subscribe(nh, "odom", 1);
userDataSub_.subscribe(nh, "user_data", 1);
if(subscribeScan2d)
{
subscribedToScan2d_ = true;
scanSub_.subscribe(nh, "scan", 1);
SYNC_DECL5(rgbd2OdomDataScan2d, approxSync, queueSize, odomSub_, userDataSub_, (*rgbdSubs_[0]), (*rgbdSubs_[1]), scanSub_);
}
else if(subscribeScan3d)
{
subscribedToScan3d_ = true;
scan3dSub_.subscribe(nh, "scan_cloud", 1);
SYNC_DECL5(rgbd2OdomDataScan3d, approxSync, queueSize, odomSub_, userDataSub_, (*rgbdSubs_[0]), (*rgbdSubs_[1]), scan3dSub_);
}
else if(subscribeOdomInfo)
{
subscribedToOdomInfo_ = true;
odomInfoSub_.subscribe(nh, "odom_info", 1);
SYNC_DECL5(rgbd2OdomDataInfo, approxSync, queueSize, odomSub_, userDataSub_, (*rgbdSubs_[0]), (*rgbdSubs_[1]), odomInfoSub_);
}
else
{
SYNC_DECL4(rgbd2OdomData, approxSync, queueSize, odomSub_, userDataSub_, (*rgbdSubs_[0]), (*rgbdSubs_[1]));
}
}
else if(subscribeOdom)
{
odomSub_.subscribe(nh, "odom", 1);
if(subscribeScan2d)
{
subscribedToScan2d_ = true;
scanSub_.subscribe(nh, "scan", 1);
SYNC_DECL4(rgbd2OdomScan2d, approxSync, queueSize, odomSub_, (*rgbdSubs_[0]), (*rgbdSubs_[1]), scanSub_);
}
else if(subscribeScan3d)
{
subscribedToScan3d_ = true;
scan3dSub_.subscribe(nh, "scan_cloud", 1);
SYNC_DECL4(rgbd2OdomScan3d, approxSync, queueSize, odomSub_, (*rgbdSubs_[0]), (*rgbdSubs_[1]), scan3dSub_);
}
else if(subscribeOdomInfo)
{
subscribedToOdomInfo_ = true;
odomInfoSub_.subscribe(nh, "odom_info", 1);
SYNC_DECL4(rgbd2OdomInfo, approxSync, queueSize, odomSub_, (*rgbdSubs_[0]), (*rgbdSubs_[1]), odomInfoSub_);
}
else
{
SYNC_DECL3(rgbd2Odom, approxSync, queueSize, odomSub_, (*rgbdSubs_[0]), (*rgbdSubs_[1]));
}
}
else if(subscribeUserData)
{
userDataSub_.subscribe(nh, "user_data", 1);
if(subscribeScan2d)
{
subscribedToScan2d_ = true;
scanSub_.subscribe(nh, "scan", 1);
SYNC_DECL4(rgbd2DataScan2d, approxSync, queueSize, userDataSub_, (*rgbdSubs_[0]), (*rgbdSubs_[1]), scanSub_);
}
else if(subscribeScan3d)
{
subscribedToScan3d_ = true;
scan3dSub_.subscribe(nh, "scan_cloud", 1);
SYNC_DECL4(rgbd2DataScan3d, approxSync, queueSize, userDataSub_, (*rgbdSubs_[0]), (*rgbdSubs_[1]), scan3dSub_);
}
else if(subscribeOdomInfo)
{
subscribedToOdomInfo_ = true;
odomInfoSub_.subscribe(nh, "odom_info", 1);
SYNC_DECL4(rgbd2DataInfo, approxSync, queueSize, userDataSub_, (*rgbdSubs_[0]), (*rgbdSubs_[1]), odomInfoSub_);
}
else
{
SYNC_DECL3(rgbd2Data, approxSync, queueSize, userDataSub_, (*rgbdSubs_[0]), (*rgbdSubs_[1]));
}
}
else
{
if(subscribeScan2d)
{
subscribedToScan2d_ = true;
scanSub_.subscribe(nh, "scan", 1);
SYNC_DECL3(rgbd2Scan2d, approxSync, queueSize, (*rgbdSubs_[0]), (*rgbdSubs_[1]), scanSub_);
}
else if(subscribeScan3d)
{
subscribedToScan3d_ = true;
scan3dSub_.subscribe(nh, "scan_cloud", 1);
SYNC_DECL3(rgbd2Scan3d, approxSync, queueSize, (*rgbdSubs_[0]), (*rgbdSubs_[1]), scan3dSub_);
}
else if(subscribeOdomInfo)
{
subscribedToOdomInfo_ = true;
odomInfoSub_.subscribe(nh, "odom_info", 1);
SYNC_DECL3(rgbd2Info, approxSync, queueSize, (*rgbdSubs_[0]), (*rgbdSubs_[1]), odomInfoSub_);
}
else
{
SYNC_DECL2(rgbd2, approxSync, queueSize, (*rgbdSubs_[0]), (*rgbdSubs_[1]));
}
}
}
} /* namespace rtabmap_ros */
+142
View File
@@ -0,0 +1,142 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtabmap_ros/CommonDataSubscriber.h>
namespace rtabmap_ros {
// Stereo
void CommonDataSubscriber::stereoCallback(
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg)
{
callbackCalled();
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::LaserScanConstPtr scanMsg; // null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonStereoCallback(odomMsg, leftImageMsg, rightImageMsg, leftCamInfoMsg, rightCamInfoMsg, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::stereoInfoCallback(
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg,
const rtabmap_ros::OdomInfoConstPtr& odomInfoMsg)
{
callbackCalled();
nav_msgs::OdometryConstPtr odomMsg; // Null
sensor_msgs::LaserScanConstPtr scan2dMsg; // null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // null
commonStereoCallback(odomMsg, leftImageMsg, rightImageMsg, leftCamInfoMsg, rightCamInfoMsg, scan2dMsg, scan3dMsg, odomInfoMsg);
}
// Stereo + Odom
void CommonDataSubscriber::stereoOdomCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg)
{
callbackCalled();
sensor_msgs::LaserScanConstPtr scanMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // null
rtabmap_ros::OdomInfoConstPtr odomInfoMsg; // null
commonStereoCallback(odomMsg, leftImageMsg, rightImageMsg, leftCamInfoMsg, rightCamInfoMsg, scanMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::stereoOdomInfoCallback(
const nav_msgs::OdometryConstPtr & odomMsg,
const sensor_msgs::ImageConstPtr& leftImageMsg,
const sensor_msgs::ImageConstPtr& rightImageMsg,
const sensor_msgs::CameraInfoConstPtr& leftCamInfoMsg,
const sensor_msgs::CameraInfoConstPtr& rightCamInfoMsg,
const rtabmap_ros::OdomInfoConstPtr & odomInfoMsg)
{
callbackCalled();
sensor_msgs::LaserScanConstPtr scan2dMsg; // Null
sensor_msgs::PointCloud2ConstPtr scan3dMsg; // Null
commonStereoCallback(odomMsg, leftImageMsg, rightImageMsg, leftCamInfoMsg, rightCamInfoMsg, scan2dMsg, scan3dMsg, odomInfoMsg);
}
void CommonDataSubscriber::setupStereoCallbacks(
ros::NodeHandle & nh,
ros::NodeHandle & pnh,
bool subscribeOdom,
bool subscribeOdomInfo,
int queueSize,
bool approxSync)
{
ROS_INFO("Setup stereo callback");
ros::NodeHandle left_nh(nh, "left");
ros::NodeHandle right_nh(nh, "right");
ros::NodeHandle left_pnh(pnh, "left");
ros::NodeHandle right_pnh(pnh, "right");
image_transport::ImageTransport left_it(left_nh);
image_transport::ImageTransport right_it(right_nh);
image_transport::TransportHints hintsLeft("raw", ros::TransportHints(), left_pnh);
image_transport::TransportHints hintsRight("raw", ros::TransportHints(), right_pnh);
imageRectLeft_.subscribe(left_it, left_nh.resolveName("image_rect"), 1, hintsLeft);
imageRectRight_.subscribe(right_it, right_nh.resolveName("image_rect"), 1, hintsRight);
cameraInfoLeft_.subscribe(left_nh, "camera_info", 1);
cameraInfoRight_.subscribe(right_nh, "camera_info", 1);
if(subscribeOdom)
{
odomSub_.subscribe(nh, "odom", 1);
if(subscribeOdomInfo)
{
subscribedToOdomInfo_ = true;
odomInfoSub_.subscribe(nh, "odom_info", 1);
SYNC_DECL6(stereoOdomInfo, approxSync, queueSize, odomSub_, imageRectLeft_, imageRectRight_, cameraInfoLeft_, cameraInfoRight_, odomInfoSub_);
}
else
{
SYNC_DECL5(stereoOdom, approxSync, queueSize, odomSub_, imageRectLeft_, imageRectRight_, cameraInfoLeft_, cameraInfoRight_);
}
}
else
{
if(subscribeOdomInfo)
{
subscribedToOdomInfo_ = true;
odomInfoSub_.subscribe(nh, "odom_info", 1);
SYNC_DECL5(stereoInfo, approxSync, queueSize, imageRectLeft_, imageRectRight_, cameraInfoLeft_, cameraInfoRight_, odomInfoSub_);
}
else
{
SYNC_DECL4(stereo, approxSync, queueSize, imageRectLeft_, imageRectRight_, cameraInfoLeft_, cameraInfoRight_);
}
}
}
} /* namespace rtabmap_ros */
+198
View File
@@ -0,0 +1,198 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtabmap_ros/OdometryROS.h>
#include <pluginlib/class_list_macros.h>
#include <nodelet/nodelet.h>
#include <laser_geometry/laser_geometry.h>
#include <sensor_msgs/LaserScan.h>
#include <sensor_msgs/PointCloud2.h>
#include <pcl_conversions/pcl_conversions.h>
#include "rtabmap_ros/MsgConversion.h"
#include <rtabmap/core/util3d.h>
#include <rtabmap/core/util3d_surface.h>
#include <rtabmap/core/util3d_transforms.h>
#include <rtabmap/core/util2d.h>
#include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UConversion.h>
#include <rtabmap/utilite/UStl.h>
using namespace rtabmap;
namespace rtabmap_ros
{
class ICPOdometry : public rtabmap_ros::OdometryROS
{
public:
ICPOdometry() :
OdometryROS(false, false, true),
scanCloudMaxPoints_(0),
scanCloudNormalK_(0)
{
}
virtual ~ICPOdometry()
{
}
private:
virtual void onOdomInit()
{
ros::NodeHandle & nh = getNodeHandle();
ros::NodeHandle & pnh = getPrivateNodeHandle();
pnh.param("scan_cloud_max_points", scanCloudMaxPoints_, scanCloudMaxPoints_);
pnh.param("scan_cloud_normal_k", scanCloudNormalK_, scanCloudNormalK_);
scan_sub_ = nh.subscribe("scan", 1, &ICPOdometry::callbackScan, this);
cloud_sub_ = nh.subscribe("scan_cloud", 1, &ICPOdometry::callbackCloud, this);
}
virtual void updateParameters(ParametersMap & parameters)
{
//make sure we are using Reg/Strategy=0
ParametersMap::iterator iter = parameters.find(Parameters::kRegStrategy());
if(iter != parameters.end() && iter->second.compare("0") != 0)
{
ROS_WARN("ICP odometry works only with \"Reg/Strategy\"=1. Ignoring value %s.", iter->second.c_str());
}
uInsert(parameters, ParametersPair(Parameters::kRegStrategy(), "1"));
}
void callbackScan(const sensor_msgs::LaserScanConstPtr& scanMsg)
{
// make sure the frame of the laser is updated too
Transform localScanTransform = getTransform(this->frameId(),
scanMsg->header.frame_id,
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());
return;
}
//transform in frameId_ frame
sensor_msgs::PointCloud2 scanOut;
laser_geometry::LaserProjection projection;
projection.transformLaserScanToPointCloud(scanMsg->header.frame_id, *scanMsg, scanOut, this->tfListener());
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(scanOut, *pclScan);
cv::Mat scan = util3d::laserScan2dFromPointCloud(*pclScan);
rtabmap::SensorData data(
scan,
LaserScanInfo((int)scanMsg->ranges.size(), scanMsg->range_max, localScanTransform),
cv::Mat(),
cv::Mat(),
CameraModel(),
0,
rtabmap_ros::timestampFromROS(scanMsg->header.stamp));
this->processData(data, scanMsg->header.stamp);
}
void callbackCloud(const sensor_msgs::PointCloud2ConstPtr& cloudMsg)
{
cv::Mat scan;
bool containNormals = false;
for(unsigned int i=0; i<cloudMsg->fields.size(); ++i)
{
if(cloudMsg->fields[i].name.compare("normal_x") == 0)
{
containNormals = true;
break;
}
}
Transform localScanTransform = getTransform(this->frameId(), cloudMsg->header.frame_id, cloudMsg->header.stamp);
if(localScanTransform.isNull())
{
ROS_ERROR("TF of received scan cloud at time %fs is not set, aborting rtabmap update.", cloudMsg->header.stamp.toSec());
return;
}
if(containNormals)
{
pcl::PointCloud<pcl::PointNormal>::Ptr pclScan(new pcl::PointCloud<pcl::PointNormal>);
pcl::fromROSMsg(*cloudMsg, *pclScan);
scan = util3d::laserScanFromPointCloud(*pclScan);
}
else
{
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(*cloudMsg, *pclScan);
if(scanCloudNormalK_ > 0)
{
//compute normals
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(pclScan, scanCloudNormalK_);
pcl::PointCloud<pcl::PointNormal>::Ptr pclScanNormal(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*pclScan, *normals, *pclScanNormal);
scan = util3d::laserScanFromPointCloud(*pclScanNormal);
}
else
{
scan = util3d::laserScanFromPointCloud(*pclScan);
}
}
rtabmap::SensorData data(
scan,
LaserScanInfo(scanCloudMaxPoints_, 0, localScanTransform),
cv::Mat(),
cv::Mat(),
CameraModel(),
0,
rtabmap_ros::timestampFromROS(cloudMsg->header.stamp));
this->processData(data, cloudMsg->header.stamp);
}
protected:
virtual void flushCallbacks()
{
// flush callbacks
}
private:
ros::Subscriber scan_sub_;
ros::Subscriber cloud_sub_;
int scanCloudMaxPoints_;
int scanCloudNormalK_;
};
PLUGINLIB_EXPORT_CLASS(rtabmap_ros::ICPOdometry, nodelet::Nodelet);
}
+216 -177
View File
@@ -36,28 +36,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <tf/transform_listener.h> #include <tf/transform_listener.h>
#include <sensor_msgs/PointCloud2.h> #include <sensor_msgs/PointCloud2.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/image_encodings.h>
#include <sensor_msgs/CameraInfo.h>
#include <stereo_msgs/DisparityImage.h>
#include <image_transport/image_transport.h>
#include <image_transport/subscriber_filter.h>
#include <image_geometry/pinhole_camera_model.h>
#include <message_filters/sync_policies/approximate_time.h>
#include <message_filters/subscriber.h>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/highgui/highgui.hpp>
#include <rtabmap_ros/MsgConversion.h> #include <rtabmap_ros/MsgConversion.h>
#include "rtabmap/core/util3d.h" #include "rtabmap/core/OccupancyGrid.h"
#include "rtabmap/core/util3d_filtering.h" #include "rtabmap/utilite/UStl.h"
#include "rtabmap/core/util3d_mapping.h"
#include "rtabmap/core/util3d_transforms.h"
namespace rtabmap_ros namespace rtabmap_ros
{ {
@@ -67,51 +50,156 @@ class ObstaclesDetection : public nodelet::Nodelet
public: public:
ObstaclesDetection() : ObstaclesDetection() :
frameId_("base_link"), frameId_("base_link"),
normalKSearch_(20), waitForTransform_(false)
groundNormalAngle_(M_PI_4),
clusterRadius_(0.05),
minClusterSize_(20),
maxObstaclesHeight_(0.0), // if<=0.0 -> disabled
maxGroundHeight_(0.0), // if<=0.0 -> disabled, used only if detect_flat_obstacles is true
segmentFlatObstacles_(false),
waitForTransform_(false),
optimizeForCloseObjects_(false),
projVoxelSize_(0.01)
{} {}
virtual ~ObstaclesDetection() virtual ~ObstaclesDetection()
{} {}
private: private:
void parameterMoved(
ros::NodeHandle & nh,
const std::string & rosName,
const std::string & parameterName,
rtabmap::ParametersMap & parameters)
{
if(nh.hasParam(rosName))
{
rtabmap::ParametersMap gridParameters = rtabmap::Parameters::getDefaultParameters("Grid");
rtabmap::ParametersMap::const_iterator iter =gridParameters.find(parameterName);
if(iter != gridParameters.end())
{
NODELET_ERROR("obstacles_detection: Parameter \"%s\" has moved from "
"rtabmap_ros to rtabmap library. Use "
"parameter \"%s\" instead. The value is still "
"copied to new parameter name.",
rosName.c_str(),
parameterName.c_str());
std::string type = rtabmap::Parameters::getType(parameterName);
if(type.compare("float") || type.compare("double"))
{
double v = uStr2Double(iter->second);
nh.getParam(rosName, v);
parameters.insert(rtabmap::ParametersPair(parameterName, uNumber2Str(v)));
}
else if(type.compare("int") || type.compare("unsigned int"))
{
int v = uStr2Int(iter->second);
nh.getParam(rosName, v);
parameters.insert(rtabmap::ParametersPair(parameterName, uNumber2Str(v)));
}
else
{
NODELET_ERROR("Not handled type \"%s\" for parameter \"%s\"", type.c_str(), parameterName.c_str());
}
}
else
{
NODELET_ERROR("Parameter \"%s\" not found in default parameters.", parameterName.c_str());
}
}
}
virtual void onInit() virtual void onInit()
{ {
ROS_DEBUG("_"); // not sure why, but all NODELET_*** log are not shown if a normal ROS_*** is not called!?
ros::NodeHandle & nh = getNodeHandle(); ros::NodeHandle & nh = getNodeHandle();
ros::NodeHandle & pnh = getPrivateNodeHandle(); ros::NodeHandle & pnh = getPrivateNodeHandle();
int queueSize = 10; int queueSize = 10;
pnh.param("queue_size", queueSize, queueSize); pnh.param("queue_size", queueSize, queueSize);
pnh.param("frame_id", frameId_, frameId_); pnh.param("frame_id", frameId_, frameId_);
pnh.param("normal_k", normalKSearch_, normalKSearch_); pnh.param("map_frame_id", mapFrameId_, mapFrameId_);
pnh.param("ground_normal_angle", groundNormalAngle_, groundNormalAngle_);
if(pnh.hasParam("normal_estimation_radius") && !pnh.hasParam("cluster_radius"))
{
NODELET_WARN("Parameter \"normal_estimation_radius\" has been renamed "
"to \"cluster_radius\"! Your value is still copied to "
"corresponding parameter. Instead of normal radius, nearest neighbors count "
"\"normal_k\" is used instead (default 20).");
pnh.param("normal_estimation_radius", clusterRadius_, clusterRadius_);
}
else
{
pnh.param("cluster_radius", clusterRadius_, clusterRadius_);
}
pnh.param("min_cluster_size", minClusterSize_, minClusterSize_);
pnh.param("max_obstacles_height", maxObstaclesHeight_, maxObstaclesHeight_);
pnh.param("max_ground_height", maxGroundHeight_, maxGroundHeight_);
pnh.param("detect_flat_obstacles", segmentFlatObstacles_, segmentFlatObstacles_);
pnh.param("wait_for_transform", waitForTransform_, waitForTransform_); pnh.param("wait_for_transform", waitForTransform_, waitForTransform_);
pnh.param("optimize_for_close_objects", optimizeForCloseObjects_, optimizeForCloseObjects_);
pnh.param("proj_voxel_size", projVoxelSize_, projVoxelSize_); if(pnh.hasParam("optimize_for_close_objects"))
{
NODELET_ERROR("\"optimize_for_close_objects\" parameter doesn't exist "
"anymore. Use rtabmap_ros/obstacles_detection_old nodelet to use "
"the old interface.");
}
rtabmap::ParametersMap parameters;
// Backward compatibility
for(std::map<std::string, std::pair<bool, std::string> >::const_iterator iter=rtabmap::Parameters::getRemovedParameters().begin();
iter!=rtabmap::Parameters::getRemovedParameters().end();
++iter)
{
std::string vStr;
if(pnh.getParam(iter->first, vStr))
{
if(iter->second.first)
{
// can be migrated
uInsert(parameters, rtabmap::ParametersPair(iter->second.second, vStr));
NODELET_ERROR("obstacles_detection: 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());
}
else
{
if(iter->second.second.empty())
{
NODELET_ERROR("obstacles_detection: Parameter \"%s\" doesn't exist anymore!",
iter->first.c_str());
}
else
{
NODELET_ERROR("obstacles_detection: Parameter \"%s\" doesn't exist anymore! You may look at this similar parameter: \"%s\"",
iter->first.c_str(), iter->second.second.c_str());
}
}
}
}
rtabmap::ParametersMap gridParameters2 = rtabmap::Parameters::getDefaultParameters();
rtabmap::ParametersMap gridParameters = rtabmap::Parameters::getDefaultParameters("Grid");
for(rtabmap::ParametersMap::iterator iter=gridParameters.begin(); iter!=gridParameters.end(); ++iter)
{
std::string vStr;
bool vBool;
int vInt;
double vDouble;
if(pnh.getParam(iter->first, vStr))
{
NODELET_INFO("obstacles_detection: Setting parameter \"%s\"=\"%s\"", iter->first.c_str(), vStr.c_str());
iter->second = vStr;
}
else if(pnh.getParam(iter->first, vBool))
{
NODELET_INFO("obstacles_detection: Setting parameter \"%s\"=\"%s\"", iter->first.c_str(), uBool2Str(vBool).c_str());
iter->second = uBool2Str(vBool);
}
else if(pnh.getParam(iter->first, vDouble))
{
NODELET_INFO("obstacles_detection: Setting parameter \"%s\"=\"%s\"", iter->first.c_str(), uNumber2Str(vDouble).c_str());
iter->second = uNumber2Str(vDouble);
}
else if(pnh.getParam(iter->first, vInt))
{
NODELET_INFO("obstacles_detection: Setting parameter \"%s\"=\"%s\"", iter->first.c_str(), uNumber2Str(vInt).c_str());
iter->second = uNumber2Str(vInt);
}
}
uInsert(parameters, gridParameters);
parameterMoved(pnh, "proj_voxel_size", rtabmap::Parameters::kGridCellSize(), parameters);
parameterMoved(pnh, "ground_normal_angle", rtabmap::Parameters::kGridMaxGroundAngle(), parameters);
parameterMoved(pnh, "min_cluster_size", rtabmap::Parameters::kGridMinClusterSize(), parameters);
parameterMoved(pnh, "normal_estimation_radius", rtabmap::Parameters::kGridClusterRadius(), parameters);
parameterMoved(pnh, "cluster_radius", rtabmap::Parameters::kGridClusterRadius(), parameters);
parameterMoved(pnh, "max_obstacles_height", rtabmap::Parameters::kGridMaxObstacleHeight(), parameters);
parameterMoved(pnh, "max_ground_height", rtabmap::Parameters::kGridMaxGroundHeight(), parameters);
parameterMoved(pnh, "detect_flat_obstacles", rtabmap::Parameters::kGridFlatObstacleDetected(), parameters);
parameterMoved(pnh, "normal_k", rtabmap::Parameters::kGridNormalK(), parameters);
UASSERT(uContains(parameters, rtabmap::Parameters::kGridMapFrameProjection()));
if(uStr2Bool(parameters.at(rtabmap::Parameters::kGridMapFrameProjection())) && mapFrameId_.empty())
{
NODELET_ERROR("obstacles_detection: Parameter \"%s\" is true but map_frame_id is not set!", rtabmap::Parameters::kGridMapFrameProjection().c_str());
}
grid_.parseParameters(parameters);
cloudSub_ = nh.subscribe("cloud", 1, &ObstaclesDetection::callback, this); cloudSub_ = nh.subscribe("cloud", 1, &ObstaclesDetection::callback, this);
@@ -153,8 +241,32 @@ private:
return; return;
} }
pcl::PointCloud<pcl::PointXYZ>::Ptr originalCloud(new pcl::PointCloud<pcl::PointXYZ>); rtabmap::Transform pose = rtabmap::Transform::getIdentity();
pcl::fromROSMsg(*cloudMsg, *originalCloud); if(!mapFrameId_.empty())
{
try
{
if(waitForTransform_)
{
if(!tfListener_.waitForTransform(mapFrameId_, frameId_, cloudMsg->header.stamp, ros::Duration(1)))
{
NODELET_ERROR("Could not get transform from %s to %s after 1 second!", mapFrameId_.c_str(), frameId_.c_str());
return;
}
}
tf::StampedTransform tmp;
tfListener_.lookupTransform(mapFrameId_, frameId_, cloudMsg->header.stamp, tmp);
pose = rtabmap_ros::transformFromTF(tmp);
}
catch(tf::TransformException & ex)
{
NODELET_ERROR("%s",ex.what());
return;
}
}
pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(*cloudMsg, *inputCloud);
//Common variables for all strategies //Common variables for all strategies
pcl::IndicesPtr ground, obstacles; pcl::IndicesPtr ground, obstacles;
@@ -162,135 +274,69 @@ private:
pcl::PointCloud<pcl::PointXYZ>::Ptr groundCloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr groundCloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr obstaclesCloudWithoutFlatSurfaces(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr obstaclesCloudWithoutFlatSurfaces(new pcl::PointCloud<pcl::PointXYZ>);
if(originalCloud->size()) if(inputCloud->size())
{ {
originalCloud = rtabmap::util3d::transformPointCloud(originalCloud, localTransform); inputCloud = rtabmap::util3d::transformPointCloud(inputCloud, localTransform);
if(maxObstaclesHeight_ > 0)
{
// std::numeric_limits<float>::lowest() exists only for c++11
originalCloud = rtabmap::util3d::passThrough(originalCloud, "z", std::numeric_limits<int>::min(), maxObstaclesHeight_);
}
if(originalCloud->size()) pcl::IndicesPtr flatObstacles(new std::vector<int>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = grid_.segmentCloud<pcl::PointXYZ>(
inputCloud,
pcl::IndicesPtr(new std::vector<int>),
pose,
cv::Point3f(localTransform.x(), localTransform.y(), localTransform.z()),
ground,
obstacles,
&flatObstacles);
if(cloud->size() && (ground->size() || obstacles->size()))
{ {
if(!optimizeForCloseObjects_) if(groundPub_.getNumSubscribers() &&
ground.get() && ground->size())
{ {
// This is the default strategy pcl::copyPointCloud(*cloud, *ground, *groundCloud);
pcl::IndicesPtr flatObstacles(new std::vector<int>);
rtabmap::util3d::segmentObstaclesFromGround<pcl::PointXYZ>(
originalCloud,
ground,
obstacles,
normalKSearch_,
groundNormalAngle_,
clusterRadius_,
minClusterSize_,
segmentFlatObstacles_,
maxGroundHeight_,
&flatObstacles);
if(groundPub_.getNumSubscribers() &&
ground.get() && ground->size())
{
pcl::copyPointCloud(*originalCloud, *ground, *groundCloud);
}
if((obstaclesPub_.getNumSubscribers() || projObstaclesPub_.getNumSubscribers()) &&
obstacles.get() && obstacles->size())
{
// remove flat obstacles from obstacles
std::set<int> flatObstaclesSet;
if(projObstaclesPub_.getNumSubscribers())
{
flatObstaclesSet.insert(flatObstacles->begin(), flatObstacles->end());
}
obstaclesCloud->resize(obstacles->size());
obstaclesCloudWithoutFlatSurfaces->resize(obstacles->size());
int oi=0;
for(unsigned int i=0; i<obstacles->size(); ++i)
{
obstaclesCloud->points[i] = originalCloud->at(obstacles->at(i));
if(flatObstaclesSet.size() == 0 ||
flatObstaclesSet.find(obstacles->at(i))==flatObstaclesSet.end())
{
obstaclesCloudWithoutFlatSurfaces->points[oi] = obstaclesCloud->points[i];
obstaclesCloudWithoutFlatSurfaces->points[oi].z = 0;
++oi;
}
}
obstaclesCloudWithoutFlatSurfaces->resize(oi);
if(obstaclesCloudWithoutFlatSurfaces->size() && projVoxelSize_ > 0.0)
{
obstaclesCloudWithoutFlatSurfaces = rtabmap::util3d::voxelize(obstaclesCloudWithoutFlatSurfaces, projVoxelSize_);
}
}
} }
else
if((obstaclesPub_.getNumSubscribers() || projObstaclesPub_.getNumSubscribers()) &&
obstacles.get() && obstacles->size())
{ {
// in this case optimizeForCloseObject_ is true: // remove flat obstacles from obstacles
// we divide the floor point cloud into two subsections, one for all potential floor points up to 1m std::set<int> flatObstaclesSet;
// one for potential floor points further away than 1m. if(projObstaclesPub_.getNumSubscribers())
// For the points at closer range, we use a smaller normal estimation radius and ground normal angle,
// which allows to detect smaller objects, without increasing the number of false positive.
// For all other points, we use a bigger normal estimation radius (* 3.) and tolerance for the
// grond normal angle (* 2.).
pcl::PointCloud<pcl::PointXYZ>::Ptr originalCloud_near = rtabmap::util3d::passThrough(originalCloud, "x", std::numeric_limits<int>::min(), 1.);
pcl::PointCloud<pcl::PointXYZ>::Ptr originalCloud_far = rtabmap::util3d::passThrough(originalCloud, "x", 1., std::numeric_limits<int>::max());
// Part 1: segment floor and obstacles near the robot
rtabmap::util3d::segmentObstaclesFromGround<pcl::PointXYZ>(
originalCloud_near,
ground,
obstacles,
normalKSearch_,
groundNormalAngle_,
clusterRadius_,
minClusterSize_,
segmentFlatObstacles_,
maxGroundHeight_);
if(groundPub_.getNumSubscribers() && ground.get() && ground->size())
{ {
pcl::copyPointCloud(*originalCloud_near, *ground, *groundCloud); flatObstaclesSet.insert(flatObstacles->begin(), flatObstacles->end());
ground->clear();
} }
if((obstaclesPub_.getNumSubscribers() || projObstaclesPub_.getNumSubscribers()) && obstacles.get() && obstacles->size()) obstaclesCloud->resize(obstacles->size());
obstaclesCloudWithoutFlatSurfaces->resize(obstacles->size());
int oi=0;
for(unsigned int i=0; i<obstacles->size(); ++i)
{ {
pcl::copyPointCloud(*originalCloud_near, *obstacles, *obstaclesCloud); obstaclesCloud->points[i] = cloud->at(obstacles->at(i));
obstacles->clear(); if(flatObstaclesSet.size() == 0 ||
flatObstaclesSet.find(obstacles->at(i))==flatObstaclesSet.end())
{
obstaclesCloudWithoutFlatSurfaces->points[oi] = obstaclesCloud->points[i];
obstaclesCloudWithoutFlatSurfaces->points[oi].z = 0;
++oi;
}
} }
// Part 2: segment floor and obstacles far from the robot obstaclesCloudWithoutFlatSurfaces->resize(oi);
rtabmap::util3d::segmentObstaclesFromGround<pcl::PointXYZ>( }
originalCloud_far,
ground,
obstacles,
normalKSearch_,
2.*groundNormalAngle_,
3.*clusterRadius_,
minClusterSize_,
segmentFlatObstacles_,
maxGroundHeight_);
if(groundPub_.getNumSubscribers() && ground.get() && ground->size()) if(!localTransform.isIdentity())
{
//transform back in topic frame
rtabmap::Transform localTransformInv = localTransform.inverse();
if(groundCloud->size())
{ {
pcl::PointCloud<pcl::PointXYZ>::Ptr groundCloud2 (new pcl::PointCloud<pcl::PointXYZ>); groundCloud = rtabmap::util3d::transformPointCloud(groundCloud, localTransformInv);
pcl::copyPointCloud(*originalCloud_far, *ground, *groundCloud2);
*groundCloud += *groundCloud2;
} }
if(obstaclesCloud->size())
if((obstaclesPub_.getNumSubscribers() || projObstaclesPub_.getNumSubscribers()) && obstacles.get() && obstacles->size())
{ {
pcl::PointCloud<pcl::PointXYZ>::Ptr obstacles2(new pcl::PointCloud<pcl::PointXYZ>); obstaclesCloud = rtabmap::util3d::transformPointCloud(obstaclesCloud, localTransformInv);
pcl::copyPointCloud(*originalCloud_far, *obstacles, *obstacles2);
*obstaclesCloud += *obstacles2;
} }
} }
} }
@@ -300,8 +346,7 @@ private:
{ {
sensor_msgs::PointCloud2 rosCloud; sensor_msgs::PointCloud2 rosCloud;
pcl::toROSMsg(*groundCloud, rosCloud); pcl::toROSMsg(*groundCloud, rosCloud);
rosCloud.header.stamp = cloudMsg->header.stamp; rosCloud.header = cloudMsg->header;
rosCloud.header.frame_id = frameId_;
//publish the message //publish the message
groundPub_.publish(rosCloud); groundPub_.publish(rosCloud);
@@ -311,8 +356,7 @@ private:
{ {
sensor_msgs::PointCloud2 rosCloud; sensor_msgs::PointCloud2 rosCloud;
pcl::toROSMsg(*obstaclesCloud, rosCloud); pcl::toROSMsg(*obstaclesCloud, rosCloud);
rosCloud.header.stamp = cloudMsg->header.stamp; rosCloud.header = cloudMsg->header;
rosCloud.header.frame_id = frameId_;
//publish the message //publish the message
obstaclesPub_.publish(rosCloud); obstaclesPub_.publish(rosCloud);
@@ -334,16 +378,10 @@ private:
private: private:
std::string frameId_; std::string frameId_;
int normalKSearch_; std::string mapFrameId_;
double groundNormalAngle_;
double clusterRadius_;
int minClusterSize_;
double maxObstaclesHeight_;
double maxGroundHeight_;
bool segmentFlatObstacles_;
bool waitForTransform_; bool waitForTransform_;
bool optimizeForCloseObjects_;
double projVoxelSize_; rtabmap::OccupancyGrid grid_;
tf::TransformListener tfListener_; tf::TransformListener tfListener_;
@@ -357,3 +395,4 @@ private:
PLUGINLIB_EXPORT_CLASS(rtabmap_ros::ObstaclesDetection, nodelet::Nodelet); PLUGINLIB_EXPORT_CLASS(rtabmap_ros::ObstaclesDetection, nodelet::Nodelet);
} }
+357
View File
@@ -0,0 +1,357 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <ros/ros.h>
#include <pluginlib/class_list_macros.h>
#include <nodelet/nodelet.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl_conversions/pcl_conversions.h>
#include <tf/transform_listener.h>
#include <sensor_msgs/PointCloud2.h>
#include <rtabmap_ros/MsgConversion.h>
#include "rtabmap/core/util3d.h"
#include "rtabmap/core/util3d_filtering.h"
#include "rtabmap/core/util3d_mapping.h"
#include "rtabmap/core/util3d_transforms.h"
namespace rtabmap_ros
{
class ObstaclesDetectionOld : public nodelet::Nodelet
{
public:
ObstaclesDetectionOld() :
frameId_("base_link"),
normalKSearch_(20),
groundNormalAngle_(M_PI_4),
clusterRadius_(0.05),
minClusterSize_(20),
maxObstaclesHeight_(0.0), // if<=0.0 -> disabled
maxGroundHeight_(0.0), // if<=0.0 -> disabled, used only if detect_flat_obstacles is true
segmentFlatObstacles_(false),
waitForTransform_(false),
optimizeForCloseObjects_(false),
projVoxelSize_(0.01)
{}
virtual ~ObstaclesDetectionOld()
{}
private:
virtual void onInit()
{
ros::NodeHandle & nh = getNodeHandle();
ros::NodeHandle & pnh = getPrivateNodeHandle();
int queueSize = 10;
pnh.param("queue_size", queueSize, queueSize);
pnh.param("frame_id", frameId_, frameId_);
pnh.param("normal_k", normalKSearch_, normalKSearch_);
pnh.param("ground_normal_angle", groundNormalAngle_, groundNormalAngle_);
if(pnh.hasParam("normal_estimation_radius") && !pnh.hasParam("cluster_radius"))
{
NODELET_WARN("Parameter \"normal_estimation_radius\" has been renamed "
"to \"cluster_radius\"! Your value is still copied to "
"corresponding parameter. Instead of normal radius, nearest neighbors count "
"\"normal_k\" is used instead (default 20).");
pnh.param("normal_estimation_radius", clusterRadius_, clusterRadius_);
}
else
{
pnh.param("cluster_radius", clusterRadius_, clusterRadius_);
}
pnh.param("min_cluster_size", minClusterSize_, minClusterSize_);
pnh.param("max_obstacles_height", maxObstaclesHeight_, maxObstaclesHeight_);
pnh.param("max_ground_height", maxGroundHeight_, maxGroundHeight_);
pnh.param("detect_flat_obstacles", segmentFlatObstacles_, segmentFlatObstacles_);
pnh.param("wait_for_transform", waitForTransform_, waitForTransform_);
pnh.param("optimize_for_close_objects", optimizeForCloseObjects_, optimizeForCloseObjects_);
pnh.param("proj_voxel_size", projVoxelSize_, projVoxelSize_);
cloudSub_ = nh.subscribe("cloud", 1, &ObstaclesDetectionOld::callback, this);
groundPub_ = nh.advertise<sensor_msgs::PointCloud2>("ground", 1);
obstaclesPub_ = nh.advertise<sensor_msgs::PointCloud2>("obstacles", 1);
projObstaclesPub_ = nh.advertise<sensor_msgs::PointCloud2>("proj_obstacles", 1);
}
void callback(const sensor_msgs::PointCloud2ConstPtr & cloudMsg)
{
ros::WallTime time = ros::WallTime::now();
if (groundPub_.getNumSubscribers() == 0 && obstaclesPub_.getNumSubscribers() == 0 && projObstaclesPub_.getNumSubscribers() == 0)
{
// no one wants the results
return;
}
rtabmap::Transform localTransform;
try
{
if(waitForTransform_)
{
if(!tfListener_.waitForTransform(frameId_, cloudMsg->header.frame_id, cloudMsg->header.stamp, ros::Duration(1)))
{
NODELET_ERROR("Could not get transform from %s to %s after 1 second!", frameId_.c_str(), cloudMsg->header.frame_id.c_str());
return;
}
}
tf::StampedTransform tmp;
tfListener_.lookupTransform(frameId_, cloudMsg->header.frame_id, cloudMsg->header.stamp, tmp);
localTransform = rtabmap_ros::transformFromTF(tmp);
}
catch(tf::TransformException & ex)
{
NODELET_ERROR("%s",ex.what());
return;
}
pcl::PointCloud<pcl::PointXYZ>::Ptr originalCloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(*cloudMsg, *originalCloud);
//Common variables for all strategies
pcl::IndicesPtr ground, obstacles;
pcl::PointCloud<pcl::PointXYZ>::Ptr obstaclesCloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr groundCloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr obstaclesCloudWithoutFlatSurfaces(new pcl::PointCloud<pcl::PointXYZ>);
if(originalCloud->size())
{
originalCloud = rtabmap::util3d::transformPointCloud(originalCloud, localTransform);
if(maxObstaclesHeight_ > 0)
{
// std::numeric_limits<float>::lowest() exists only for c++11
originalCloud = rtabmap::util3d::passThrough(originalCloud, "z", std::numeric_limits<int>::min(), maxObstaclesHeight_);
}
if(originalCloud->size())
{
if(!optimizeForCloseObjects_)
{
// This is the default strategy
pcl::IndicesPtr flatObstacles(new std::vector<int>);
rtabmap::util3d::segmentObstaclesFromGround<pcl::PointXYZ>(
originalCloud,
ground,
obstacles,
normalKSearch_,
groundNormalAngle_,
clusterRadius_,
minClusterSize_,
segmentFlatObstacles_,
maxGroundHeight_,
&flatObstacles);
if(groundPub_.getNumSubscribers() &&
ground.get() && ground->size())
{
pcl::copyPointCloud(*originalCloud, *ground, *groundCloud);
}
if((obstaclesPub_.getNumSubscribers() || projObstaclesPub_.getNumSubscribers()) &&
obstacles.get() && obstacles->size())
{
// remove flat obstacles from obstacles
std::set<int> flatObstaclesSet;
if(projObstaclesPub_.getNumSubscribers())
{
flatObstaclesSet.insert(flatObstacles->begin(), flatObstacles->end());
}
obstaclesCloud->resize(obstacles->size());
obstaclesCloudWithoutFlatSurfaces->resize(obstacles->size());
int oi=0;
for(unsigned int i=0; i<obstacles->size(); ++i)
{
obstaclesCloud->points[i] = originalCloud->at(obstacles->at(i));
if(flatObstaclesSet.size() == 0 ||
flatObstaclesSet.find(obstacles->at(i))==flatObstaclesSet.end())
{
obstaclesCloudWithoutFlatSurfaces->points[oi] = obstaclesCloud->points[i];
obstaclesCloudWithoutFlatSurfaces->points[oi].z = 0;
++oi;
}
}
obstaclesCloudWithoutFlatSurfaces->resize(oi);
if(obstaclesCloudWithoutFlatSurfaces->size() && projVoxelSize_ > 0.0)
{
obstaclesCloudWithoutFlatSurfaces = rtabmap::util3d::voxelize(obstaclesCloudWithoutFlatSurfaces, projVoxelSize_);
}
}
}
else
{
// in this case optimizeForCloseObject_ is true:
// we divide the floor point cloud into two subsections, one for all potential floor points up to 1m
// one for potential floor points further away than 1m.
// For the points at closer range, we use a smaller normal estimation radius and ground normal angle,
// which allows to detect smaller objects, without increasing the number of false positive.
// For all other points, we use a bigger normal estimation radius (* 3.) and tolerance for the
// grond normal angle (* 2.).
pcl::PointCloud<pcl::PointXYZ>::Ptr originalCloud_near = rtabmap::util3d::passThrough(originalCloud, "x", std::numeric_limits<int>::min(), 1.);
pcl::PointCloud<pcl::PointXYZ>::Ptr originalCloud_far = rtabmap::util3d::passThrough(originalCloud, "x", 1., std::numeric_limits<int>::max());
// Part 1: segment floor and obstacles near the robot
rtabmap::util3d::segmentObstaclesFromGround<pcl::PointXYZ>(
originalCloud_near,
ground,
obstacles,
normalKSearch_,
groundNormalAngle_,
clusterRadius_,
minClusterSize_,
segmentFlatObstacles_,
maxGroundHeight_);
if(groundPub_.getNumSubscribers() && ground.get() && ground->size())
{
pcl::copyPointCloud(*originalCloud_near, *ground, *groundCloud);
ground->clear();
}
if((obstaclesPub_.getNumSubscribers() || projObstaclesPub_.getNumSubscribers()) && obstacles.get() && obstacles->size())
{
pcl::copyPointCloud(*originalCloud_near, *obstacles, *obstaclesCloud);
obstacles->clear();
}
// Part 2: segment floor and obstacles far from the robot
rtabmap::util3d::segmentObstaclesFromGround<pcl::PointXYZ>(
originalCloud_far,
ground,
obstacles,
normalKSearch_,
2.*groundNormalAngle_,
3.*clusterRadius_,
minClusterSize_,
segmentFlatObstacles_,
maxGroundHeight_);
if(groundPub_.getNumSubscribers() && ground.get() && ground->size())
{
pcl::PointCloud<pcl::PointXYZ>::Ptr groundCloud2 (new pcl::PointCloud<pcl::PointXYZ>);
pcl::copyPointCloud(*originalCloud_far, *ground, *groundCloud2);
*groundCloud += *groundCloud2;
}
if((obstaclesPub_.getNumSubscribers() || projObstaclesPub_.getNumSubscribers()) && obstacles.get() && obstacles->size())
{
pcl::PointCloud<pcl::PointXYZ>::Ptr obstacles2(new pcl::PointCloud<pcl::PointXYZ>);
pcl::copyPointCloud(*originalCloud_far, *obstacles, *obstacles2);
*obstaclesCloud += *obstacles2;
}
}
if(!localTransform.isIdentity())
{
//transform back in topic frame
rtabmap::Transform localTransformInv = localTransform.inverse();
if(groundCloud->size())
{
groundCloud = rtabmap::util3d::transformPointCloud(groundCloud, localTransformInv);
}
if(obstaclesCloud->size())
{
obstaclesCloud = rtabmap::util3d::transformPointCloud(obstaclesCloud, localTransformInv);
}
}
}
}
if(groundPub_.getNumSubscribers())
{
sensor_msgs::PointCloud2 rosCloud;
pcl::toROSMsg(*groundCloud, rosCloud);
rosCloud.header = cloudMsg->header;
//publish the message
groundPub_.publish(rosCloud);
}
if(obstaclesPub_.getNumSubscribers())
{
sensor_msgs::PointCloud2 rosCloud;
pcl::toROSMsg(*obstaclesCloud, rosCloud);
rosCloud.header = cloudMsg->header;
//publish the message
obstaclesPub_.publish(rosCloud);
}
if(projObstaclesPub_.getNumSubscribers())
{
sensor_msgs::PointCloud2 rosCloud;
pcl::toROSMsg(*obstaclesCloudWithoutFlatSurfaces, rosCloud);
rosCloud.header.stamp = cloudMsg->header.stamp;
rosCloud.header.frame_id = frameId_;
//publish the message
projObstaclesPub_.publish(rosCloud);
}
NODELET_DEBUG("Obstacles segmentation time = %f s", (ros::WallTime::now() - time).toSec());
}
private:
std::string frameId_;
int normalKSearch_;
double groundNormalAngle_;
double clusterRadius_;
int minClusterSize_;
double maxObstaclesHeight_;
double maxGroundHeight_;
bool segmentFlatObstacles_;
bool waitForTransform_;
bool optimizeForCloseObjects_;
double projVoxelSize_;
tf::TransformListener tfListener_;
ros::Publisher groundPub_;
ros::Publisher obstaclesPub_;
ros::Publisher projObstaclesPub_;
ros::Subscriber cloudSub_;
};
PLUGINLIB_EXPORT_CLASS(rtabmap_ros::ObstaclesDetectionOld, nodelet::Nodelet);
}
+244 -233
View File
@@ -25,7 +25,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "OdometryROS.h" #include <rtabmap_ros/OdometryROS.h>
#include <pluginlib/class_list_macros.h> #include <pluginlib/class_list_macros.h>
#include <nodelet/nodelet.h> #include <nodelet/nodelet.h>
@@ -49,6 +49,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/core/util2d.h> #include <rtabmap/core/util2d.h>
#include <rtabmap/utilite/ULogger.h> #include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UConversion.h> #include <rtabmap/utilite/UConversion.h>
#include <rtabmap/utilite/UStl.h>
using namespace rtabmap; using namespace rtabmap;
@@ -59,16 +60,18 @@ class RGBDOdometry : public rtabmap_ros::OdometryROS
{ {
public: public:
RGBDOdometry() : RGBDOdometry() :
OdometryROS(false), OdometryROS(false, true, false),
approxSync_(0), approxSync_(0),
exactSync_(0), exactSync_(0),
sync2_(0), approxSync2_(0),
exactSync2_(0),
queueSize_(5) queueSize_(5)
{ {
} }
virtual ~RGBDOdometry() virtual ~RGBDOdometry()
{ {
rgbdSub_.shutdown();
if(approxSync_) if(approxSync_)
{ {
delete approxSync_; delete approxSync_;
@@ -77,9 +80,13 @@ public:
{ {
delete exactSync_; delete exactSync_;
} }
if(sync2_) if(approxSync2_)
{ {
delete sync2_; delete approxSync2_;
}
if(exactSync2_)
{
delete exactSync2_;
} }
} }
@@ -90,66 +97,65 @@ private:
ros::NodeHandle & nh = getNodeHandle(); ros::NodeHandle & nh = getNodeHandle();
ros::NodeHandle & pnh = getPrivateNodeHandle(); ros::NodeHandle & pnh = getPrivateNodeHandle();
int depthCameras = 1; int rgbdCameras = 1;
bool approxSync = true; bool approxSync = true;
bool subscribeRGBD = false;
pnh.param("approx_sync", approxSync, approxSync); pnh.param("approx_sync", approxSync, approxSync);
pnh.param("queue_size", queueSize_, queueSize_); pnh.param("queue_size", queueSize_, queueSize_);
pnh.param("depth_cameras", depthCameras, depthCameras); pnh.param("subscribe_rgbd", subscribeRGBD, subscribeRGBD);
if(depthCameras <= 0) if(pnh.hasParam("depth_cameras"))
{ {
depthCameras = 1; ROS_ERROR("\"depth_cameras\" parameter doesn't exist anymore. It is replaced by \"rgbd_cameras\" with the \"rgbd_image\" input topics. \"subscribe_rgbd\" should be also set to true.");
} }
if(depthCameras > 2) pnh.param("rgbd_cameras", rgbdCameras, rgbdCameras);
if(rgbdCameras <= 0)
{
rgbdCameras = 1;
}
if(rgbdCameras > 2)
{ {
NODELET_FATAL("Only 2 cameras maximum supported yet."); NODELET_FATAL("Only 2 cameras maximum supported yet.");
} }
if(depthCameras == 2) std::string subscribedTopicsMsg;
if(subscribeRGBD)
{ {
ros::NodeHandle rgb0_nh(nh, "rgb0"); if(rgbdCameras == 2)
ros::NodeHandle depth0_nh(nh, "depth0"); {
ros::NodeHandle rgb0_pnh(pnh, "rgb0"); rgbd_image1_sub_.subscribe(nh, "rgbd_image0", 1);
ros::NodeHandle depth0_pnh(pnh, "depth0"); rgbd_image2_sub_.subscribe(nh, "rgbd_image1", 1);
image_transport::ImageTransport rgb0_it(rgb0_nh);
image_transport::ImageTransport depth0_it(depth0_nh);
image_transport::TransportHints hintsRgb0("raw", ros::TransportHints(), rgb0_pnh);
image_transport::TransportHints hintsDepth0("raw", ros::TransportHints(), depth0_pnh);
image_mono_sub_.subscribe(rgb0_it, rgb0_nh.resolveName("image"), 1, hintsRgb0); if(approxSync)
image_depth_sub_.subscribe(depth0_it, depth0_nh.resolveName("image"), 1, hintsDepth0); {
info_sub_.subscribe(rgb0_nh, "camera_info", 1); approxSync2_ = new message_filters::Synchronizer<MyApproxSync2Policy>(
MyApproxSync2Policy(queueSize_),
rgbd_image1_sub_,
rgbd_image2_sub_);
approxSync2_->registerCallback(boost::bind(&RGBDOdometry::callbackRGBD2, this, _1, _2));
}
else
{
exactSync2_ = new message_filters::Synchronizer<MyExactSync2Policy>(
MyExactSync2Policy(queueSize_),
rgbd_image1_sub_,
rgbd_image2_sub_);
exactSync2_->registerCallback(boost::bind(&RGBDOdometry::callbackRGBD2, this, _1, _2));
}
subscribedTopicsMsg = uFormat("\n%s subscribed to (%s sync):\n %s,\n %s",
getName().c_str(),
approxSync?"approx":"exact",
rgbd_image1_sub_.getTopic().c_str(),
rgbd_image2_sub_.getTopic().c_str());
}
else
{
rgbdSub_ = nh.subscribe("rgbd_image", queueSize_, &RGBDOdometry::callbackRGBD, this);
ros::NodeHandle rgb1_nh(nh, "rgb1"); subscribedTopicsMsg =
ros::NodeHandle depth1_nh(nh, "depth1"); uFormat("\n%s subscribed to:\n %s",
ros::NodeHandle rgb1_pnh(pnh, "rgb1"); getName().c_str(),
ros::NodeHandle depth1_pnh(pnh, "depth1"); rgbdSub_.getTopic().c_str());
image_transport::ImageTransport rgb1_it(rgb1_nh); }
image_transport::ImageTransport depth1_it(depth1_nh);
image_transport::TransportHints hintsRgb1("raw", ros::TransportHints(), rgb1_pnh);
image_transport::TransportHints hintsDepth1("raw", ros::TransportHints(), depth1_pnh);
image_mono2_sub_.subscribe(rgb1_it, rgb1_nh.resolveName("image"), 1, hintsRgb1);
image_depth2_sub_.subscribe(depth1_it, depth1_nh.resolveName("image"), 1, hintsDepth1);
info2_sub_.subscribe(rgb1_nh, "camera_info", 1);
NODELET_INFO("\n%s subscribed to:\n %s,\n %s,\n %s,\n %s,\n %s,\n %s",
ros::this_node::getName().c_str(),
image_mono_sub_.getTopic().c_str(),
image_depth_sub_.getTopic().c_str(),
info_sub_.getTopic().c_str(),
image_mono2_sub_.getTopic().c_str(),
image_depth2_sub_.getTopic().c_str(),
info2_sub_.getTopic().c_str());
sync2_ = new message_filters::Synchronizer<MySync2Policy>(
MySync2Policy(queueSize_),
image_mono_sub_,
image_depth_sub_,
info_sub_,
image_mono2_sub_,
image_depth2_sub_,
info2_sub_);
sync2_->registerCallback(boost::bind(&RGBDOdometry::callback2, this, _1, _2, _3, _4, _5, _6));
} }
else else
{ {
@@ -177,13 +183,136 @@ private:
exactSync_->registerCallback(boost::bind(&RGBDOdometry::callback, this, _1, _2, _3)); exactSync_->registerCallback(boost::bind(&RGBDOdometry::callback, this, _1, _2, _3));
} }
NODELET_INFO("\n%s subscribed to (%s sync):\n %s,\n %s,\n %s", subscribedTopicsMsg = uFormat("\n%s subscribed to (%s sync):\n %s,\n %s,\n %s",
ros::this_node::getName().c_str(), getName().c_str(),
approxSync?"approx":"exact", approxSync?"approx":"exact",
image_mono_sub_.getTopic().c_str(), image_mono_sub_.getTopic().c_str(),
image_depth_sub_.getTopic().c_str(), image_depth_sub_.getTopic().c_str(),
info_sub_.getTopic().c_str()); info_sub_.getTopic().c_str());
} }
this->startWarningThread(subscribedTopicsMsg, approxSync);
}
virtual void updateParameters(ParametersMap & parameters)
{
//make sure we are using Reg/Strategy=0
ParametersMap::iterator iter = parameters.find(Parameters::kRegStrategy());
if(iter != parameters.end() && iter->second.compare("0") != 0)
{
ROS_WARN("RGBD odometry works only with \"Reg/Strategy\"=0. Ignoring value %s.", iter->second.c_str());
}
uInsert(parameters, ParametersPair(Parameters::kRegStrategy(), "0"));
}
void commonCallback(
const std::vector<cv_bridge::CvImageConstPtr> & rgbImages,
const std::vector<cv_bridge::CvImageConstPtr> & depthImages,
const std::vector<sensor_msgs::CameraInfo>& cameraInfos)
{
ROS_ASSERT(rgbImages.size() > 0 && rgbImages.size() == depthImages.size() && rgbImages.size() == cameraInfos.size());
ros::Time higherStamp;
int imageWidth = rgbImages[0]->image.cols;
int imageHeight = rgbImages[0]->image.rows;
int cameraCount = rgbImages.size();
cv::Mat rgb;
cv::Mat depth;
pcl::PointCloud<pcl::PointXYZ> scanCloud;
std::vector<CameraModel> cameraModels;
for(unsigned int i=0; i<rgbImages.size(); ++i)
{
if(!(rgbImages[i]->encoding.compare(sensor_msgs::image_encodings::TYPE_8UC1) ==0 ||
rgbImages[i]->encoding.compare(sensor_msgs::image_encodings::MONO8) ==0 ||
rgbImages[i]->encoding.compare(sensor_msgs::image_encodings::MONO16) ==0 ||
rgbImages[i]->encoding.compare(sensor_msgs::image_encodings::BGR8) == 0 ||
rgbImages[i]->encoding.compare(sensor_msgs::image_encodings::RGB8) == 0) ||
!(depthImages[i]->encoding.compare(sensor_msgs::image_encodings::TYPE_16UC1) == 0 ||
depthImages[i]->encoding.compare(sensor_msgs::image_encodings::TYPE_32FC1) == 0 ||
depthImages[i]->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0))
{
NODELET_ERROR("Input type must be image=mono8,mono16,rgb8,bgr8 and image_depth=32FC1,16UC1,mono16");
return;
}
UASSERT_MSG(rgbImages[i]->image.cols == imageWidth && rgbImages[i]->image.rows == imageHeight,
uFormat("imageWidth=%d vs %d imageHeight=%d vs %d",
imageWidth,
rgbImages[i]->image.cols,
imageHeight,
rgbImages[i]->image.rows).c_str());
UASSERT_MSG(depthImages[i]->image.cols == imageWidth && depthImages[i]->image.rows == imageHeight,
uFormat("imageWidth=%d vs %d imageHeight=%d vs %d",
imageWidth,
depthImages[i]->image.cols,
imageHeight,
depthImages[i]->image.rows).c_str());
ros::Time stamp = rgbImages[i]->header.stamp>depthImages[i]->header.stamp?rgbImages[i]->header.stamp:depthImages[i]->header.stamp;
if(i == 0)
{
higherStamp = stamp;
}
else if(stamp > higherStamp)
{
higherStamp = stamp;
}
Transform localTransform = getTransform(this->frameId(), rgbImages[i]->header.frame_id, stamp);
if(localTransform.isNull())
{
return;
}
cv_bridge::CvImageConstPtr ptrImage = rgbImages[i];
if(rgbImages[i]->encoding.compare(sensor_msgs::image_encodings::TYPE_8UC1) !=0 &&
rgbImages[i]->encoding.compare(sensor_msgs::image_encodings::MONO8) != 0)
{
ptrImage = cv_bridge::cvtColor(rgbImages[i], "mono8");
}
cv_bridge::CvImageConstPtr ptrDepth = depthImages[i];
cv::Mat subDepth = ptrDepth->image;
// initialize
if(rgb.empty())
{
rgb = cv::Mat(imageHeight, imageWidth*cameraCount, ptrImage->image.type());
}
if(depth.empty())
{
depth = cv::Mat(imageHeight, imageWidth*cameraCount, subDepth.type());
}
if(ptrImage->image.type() == rgb.type())
{
ptrImage->image.copyTo(cv::Mat(rgb, cv::Rect(i*imageWidth, 0, imageWidth, imageHeight)));
}
else
{
NODELET_ERROR("Some RGB images are not the same type!");
return;
}
if(subDepth.type() == depth.type())
{
subDepth.copyTo(cv::Mat(depth, cv::Rect(i*imageWidth, 0, imageWidth, imageHeight)));
}
else
{
NODELET_ERROR("Some Depth images are not the same type!");
return;
}
cameraModels.push_back(rtabmap_ros::cameraModelFromROS(cameraInfos[i], localTransform));
}
rtabmap::SensorData data(
rgb,
depth,
cameraModels,
0,
rtabmap_ros::timestampFromROS(higherStamp));
this->processData(data, higherStamp);
} }
void callback( void callback(
@@ -191,179 +320,52 @@ private:
const sensor_msgs::ImageConstPtr& depth, const sensor_msgs::ImageConstPtr& depth,
const sensor_msgs::CameraInfoConstPtr& cameraInfo) const sensor_msgs::CameraInfoConstPtr& cameraInfo)
{ {
callbackCalled();
if(!this->isPaused()) if(!this->isPaused())
{ {
if(!(image->encoding.compare(sensor_msgs::image_encodings::TYPE_8UC1) ==0 || std::vector<cv_bridge::CvImageConstPtr> imageMsgs(1);
image->encoding.compare(sensor_msgs::image_encodings::MONO8) ==0 || std::vector<cv_bridge::CvImageConstPtr> depthMsgs(1);
image->encoding.compare(sensor_msgs::image_encodings::MONO16) ==0 || std::vector<sensor_msgs::CameraInfo> infoMsgs;
image->encoding.compare(sensor_msgs::image_encodings::BGR8) == 0 || imageMsgs[0] = cv_bridge::toCvShare(image);
image->encoding.compare(sensor_msgs::image_encodings::RGB8) == 0) || depthMsgs[0] = cv_bridge::toCvShare(depth);
!(depth->encoding.compare(sensor_msgs::image_encodings::TYPE_16UC1)==0 || infoMsgs.push_back(*cameraInfo);
depth->encoding.compare(sensor_msgs::image_encodings::TYPE_32FC1)==0 ||
depth->encoding.compare(sensor_msgs::image_encodings::MONO16)==0))
{
NODELET_ERROR("Input type must be image=mono8,mono16,rgb8,bgr8 (mono8 "
"recommended) and image_depth=16UC1,32FC1,mono16. Types detected: %s %s",
image->encoding.c_str(), depth->encoding.c_str());
return;
}
ros::Time stamp = image->header.stamp>depth->header.stamp?image->header.stamp:depth->header.stamp; this->commonCallback(imageMsgs, depthMsgs, infoMsgs);
Transform localTransform = getTransform(this->frameId(), image->header.frame_id, stamp);
if(localTransform.isNull())
{
return;
}
if(image->data.size() && depth->data.size() && cameraInfo->K[4] != 0)
{
rtabmap::CameraModel rtabmapModel = rtabmap_ros::cameraModelFromROS(*cameraInfo, localTransform);
cv_bridge::CvImagePtr ptrImage = cv_bridge::toCvCopy(image, image->encoding.compare(sensor_msgs::image_encodings::TYPE_8UC1)==0?"":"mono8");
cv_bridge::CvImagePtr ptrDepth = cv_bridge::toCvCopy(depth);
rtabmap::SensorData data(
ptrImage->image,
ptrDepth->image,
rtabmapModel,
0,
rtabmap_ros::timestampFromROS(stamp));
this->processData(data, stamp);
}
} }
} }
void callback2( void callbackRGBD(
const sensor_msgs::ImageConstPtr& image, const rtabmap_ros::RGBDImageConstPtr& image)
const sensor_msgs::ImageConstPtr& depth,
const sensor_msgs::CameraInfoConstPtr& cameraInfo,
const sensor_msgs::ImageConstPtr& image2,
const sensor_msgs::ImageConstPtr& depth2,
const sensor_msgs::CameraInfoConstPtr& cameraInfo2)
{ {
callbackCalled();
if(!this->isPaused()) if(!this->isPaused())
{ {
std::vector<sensor_msgs::ImageConstPtr> imageMsgs; std::vector<cv_bridge::CvImageConstPtr> imageMsgs(1);
std::vector<sensor_msgs::ImageConstPtr> depthMsgs; std::vector<cv_bridge::CvImageConstPtr> depthMsgs(1);
std::vector<sensor_msgs::CameraInfoConstPtr> infoMsgs; std::vector<sensor_msgs::CameraInfo> infoMsgs;
imageMsgs.push_back(image); rtabmap_ros::toCvShare(image, imageMsgs[0], depthMsgs[0]);
imageMsgs.push_back(image2); infoMsgs.push_back(image->cameraInfo);
depthMsgs.push_back(depth);
depthMsgs.push_back(depth2);
infoMsgs.push_back(cameraInfo);
infoMsgs.push_back(cameraInfo2);
ros::Time higherStamp; this->commonCallback(imageMsgs, depthMsgs, infoMsgs);
int imageWidth = imageMsgs[0]->width; }
int imageHeight = imageMsgs[0]->height; }
int cameraCount = imageMsgs.size();
cv::Mat rgb;
cv::Mat depth;
pcl::PointCloud<pcl::PointXYZ> scanCloud;
std::vector<CameraModel> cameraModels;
for(unsigned int i=0; i<imageMsgs.size(); ++i)
{
if(!(imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::TYPE_8UC1) ==0 ||
imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::MONO8) ==0 ||
imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::MONO16) ==0 ||
imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::BGR8) == 0 ||
imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::RGB8) == 0) ||
!(depthMsgs[i]->encoding.compare(sensor_msgs::image_encodings::TYPE_16UC1) == 0 ||
depthMsgs[i]->encoding.compare(sensor_msgs::image_encodings::TYPE_32FC1) == 0 ||
depthMsgs[i]->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0))
{
NODELET_ERROR("Input type must be image=mono8,mono16,rgb8,bgr8 and image_depth=32FC1,16UC1,mono16");
return;
}
UASSERT_MSG(imageMsgs[i]->width == imageWidth && imageMsgs[i]->height == imageHeight,
uFormat("imageWidth=%d vs %d imageHeight=%d vs %d",
imageWidth,
imageMsgs[i]->width,
imageHeight,
imageMsgs[i]->height).c_str());
UASSERT_MSG(depthMsgs[i]->width == imageWidth && depthMsgs[i]->height == imageHeight,
uFormat("imageWidth=%d vs %d imageHeight=%d vs %d",
imageWidth,
depthMsgs[i]->width,
imageHeight,
depthMsgs[i]->height).c_str());
ros::Time stamp = imageMsgs[i]->header.stamp>depthMsgs[i]->header.stamp?imageMsgs[i]->header.stamp:depthMsgs[i]->header.stamp; void callbackRGBD2(
const rtabmap_ros::RGBDImageConstPtr& image,
const rtabmap_ros::RGBDImageConstPtr& image2)
{
callbackCalled();
if(!this->isPaused())
{
std::vector<cv_bridge::CvImageConstPtr> imageMsgs(2);
std::vector<cv_bridge::CvImageConstPtr> depthMsgs(2);
std::vector<sensor_msgs::CameraInfo> infoMsgs;
rtabmap_ros::toCvShare(image, imageMsgs[0], depthMsgs[0]);
rtabmap_ros::toCvShare(image2, imageMsgs[1], depthMsgs[1]);
infoMsgs.push_back(image->cameraInfo);
infoMsgs.push_back(image2->cameraInfo);
if(i == 0) this->commonCallback(imageMsgs, depthMsgs, infoMsgs);
{
higherStamp = stamp;
}
else if(stamp > higherStamp)
{
higherStamp = stamp;
}
Transform localTransform = getTransform(this->frameId(), imageMsgs[i]->header.frame_id, stamp);
if(localTransform.isNull())
{
return;
}
cv_bridge::CvImageConstPtr ptrImage;
if(imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::TYPE_8UC1)==0)
{
ptrImage = cv_bridge::toCvShare(imageMsgs[i]);
}
else if(imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::MONO8) == 0 ||
imageMsgs[i]->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0)
{
ptrImage = cv_bridge::toCvShare(imageMsgs[i], "mono8");
}
else
{
ptrImage = cv_bridge::toCvShare(imageMsgs[i], "bgr8");
}
cv_bridge::CvImageConstPtr ptrDepth = cv_bridge::toCvShare(depthMsgs[i]);
cv::Mat subDepth = ptrDepth->image;
// initialize
if(rgb.empty())
{
rgb = cv::Mat(imageHeight, imageWidth*cameraCount, ptrImage->image.type());
}
if(depth.empty())
{
depth = cv::Mat(imageHeight, imageWidth*cameraCount, subDepth.type());
}
if(ptrImage->image.type() == rgb.type())
{
ptrImage->image.copyTo(cv::Mat(rgb, cv::Rect(i*imageWidth, 0, imageWidth, imageHeight)));
}
else
{
NODELET_ERROR("Some RGB images are not the same type!");
return;
}
if(subDepth.type() == depth.type())
{
subDepth.copyTo(cv::Mat(depth, cv::Rect(i*imageWidth, 0, imageWidth, imageHeight)));
}
else
{
NODELET_ERROR("Some Depth images are not the same type!");
return;
}
cameraModels.push_back(rtabmap_ros::cameraModelFromROS(*infoMsgs[i], localTransform));
}
rtabmap::SensorData data(
rgb,
depth,
cameraModels,
0,
rtabmap_ros::timestampFromROS(higherStamp));
this->processData(data, higherStamp);
} }
} }
@@ -383,18 +385,23 @@ protected:
exactSync_ = new message_filters::Synchronizer<MyExactSyncPolicy>(MyExactSyncPolicy(queueSize_), image_mono_sub_, image_depth_sub_, info_sub_); exactSync_ = new message_filters::Synchronizer<MyExactSyncPolicy>(MyExactSyncPolicy(queueSize_), image_mono_sub_, image_depth_sub_, info_sub_);
exactSync_->registerCallback(boost::bind(&RGBDOdometry::callback, this, _1, _2, _3)); exactSync_->registerCallback(boost::bind(&RGBDOdometry::callback, this, _1, _2, _3));
} }
if(sync2_) if(approxSync2_)
{ {
delete sync2_; delete approxSync2_;
sync2_ = new message_filters::Synchronizer<MySync2Policy>( approxSync2_ = new message_filters::Synchronizer<MyApproxSync2Policy>(
MySync2Policy(queueSize_), MyApproxSync2Policy(queueSize_),
image_mono_sub_, rgbd_image1_sub_,
image_depth_sub_, rgbd_image2_sub_);
info_sub_, approxSync2_->registerCallback(boost::bind(&RGBDOdometry::callbackRGBD2, this, _1, _2));
image_mono2_sub_, }
image_depth2_sub_, if(exactSync2_)
info2_sub_); {
sync2_->registerCallback(boost::bind(&RGBDOdometry::callback2, this, _1, _2, _3, _4, _5, _6)); delete exactSync2_;
exactSync2_ = new message_filters::Synchronizer<MyExactSync2Policy>(
MyExactSync2Policy(queueSize_),
rgbd_image1_sub_,
rgbd_image2_sub_);
exactSync2_->registerCallback(boost::bind(&RGBDOdometry::callbackRGBD2, this, _1, _2));
} }
} }
@@ -402,15 +409,19 @@ private:
image_transport::SubscriberFilter image_mono_sub_; image_transport::SubscriberFilter image_mono_sub_;
image_transport::SubscriberFilter image_depth_sub_; image_transport::SubscriberFilter image_depth_sub_;
message_filters::Subscriber<sensor_msgs::CameraInfo> info_sub_; message_filters::Subscriber<sensor_msgs::CameraInfo> info_sub_;
image_transport::SubscriberFilter image_mono2_sub_;
image_transport::SubscriberFilter image_depth2_sub_; ros::Subscriber rgbdSub_;
message_filters::Subscriber<sensor_msgs::CameraInfo> info2_sub_; message_filters::Subscriber<rtabmap_ros::RGBDImage> rgbd_image1_sub_;
message_filters::Subscriber<rtabmap_ros::RGBDImage> rgbd_image2_sub_;
typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo> MyApproxSyncPolicy; typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo> MyApproxSyncPolicy;
message_filters::Synchronizer<MyApproxSyncPolicy> * approxSync_; message_filters::Synchronizer<MyApproxSyncPolicy> * approxSync_;
typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo> MyExactSyncPolicy; typedef message_filters::sync_policies::ExactTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo> MyExactSyncPolicy;
message_filters::Synchronizer<MyExactSyncPolicy> * exactSync_; message_filters::Synchronizer<MyExactSyncPolicy> * exactSync_;
typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo> MySync2Policy; typedef message_filters::sync_policies::ApproximateTime<rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage> MyApproxSync2Policy;
message_filters::Synchronizer<MySync2Policy> * sync2_; message_filters::Synchronizer<MyApproxSync2Policy> * approxSync2_;
typedef message_filters::sync_policies::ExactTime<rtabmap_ros::RGBDImage, rtabmap_ros::RGBDImage> MyExactSync2Policy;
message_filters::Synchronizer<MyExactSync2Policy> * exactSync2_;
int queueSize_; int queueSize_;
}; };
+165
View File
@@ -0,0 +1,165 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <ros/ros.h>
#include <pluginlib/class_list_macros.h>
#include <nodelet/nodelet.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/CompressedImage.h>
#include <sensor_msgs/image_encodings.h>
#include <sensor_msgs/CameraInfo.h>
#include <image_transport/image_transport.h>
#include <image_transport/subscriber_filter.h>
#include <message_filters/sync_policies/approximate_time.h>
#include <message_filters/sync_policies/exact_time.h>
#include <message_filters/subscriber.h>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/highgui/highgui.hpp>
#include "rtabmap_ros/RGBDImage.h"
#include "rtabmap/core/Compression.h"
namespace rtabmap_ros
{
class RGBDSync : public nodelet::Nodelet
{
public:
RGBDSync() :
approxSyncDepth_(0),
exactSyncDepth_(0)
{}
virtual ~RGBDSync()
{
if(approxSyncDepth_)
delete approxSyncDepth_;
if(exactSyncDepth_)
delete exactSyncDepth_;
}
private:
virtual void onInit()
{
ros::NodeHandle & nh = getNodeHandle();
ros::NodeHandle & pnh = getPrivateNodeHandle();
int queueSize = 10;
bool approxSync = true;
pnh.param("approx_sync", approxSync, approxSync);
pnh.param("queue_size", queueSize, queueSize);
NODELET_INFO("Approximate time sync = %s", approxSync?"true":"false");
rgbdImagePub_ = nh.advertise<rtabmap_ros::RGBDImage>("rgbd_image", 1);
rgbdImageCompressedPub_ = nh.advertise<rtabmap_ros::RGBDImage>("rgbd_image/compressed", 1);
if(approxSync)
{
approxSyncDepth_ = new message_filters::Synchronizer<MyApproxSyncDepthPolicy>(MyApproxSyncDepthPolicy(queueSize), imageSub_, imageDepthSub_, cameraInfoSub_);
approxSyncDepth_->registerCallback(boost::bind(&RGBDSync::callback, this, _1, _2, _3));
}
else
{
exactSyncDepth_ = new message_filters::Synchronizer<MyExactSyncDepthPolicy>(MyExactSyncDepthPolicy(queueSize), imageSub_, imageDepthSub_, cameraInfoSub_);
exactSyncDepth_->registerCallback(boost::bind(&RGBDSync::callback, this, _1, _2, _3));
}
ros::NodeHandle rgb_nh(nh, "rgb");
ros::NodeHandle depth_nh(nh, "depth");
ros::NodeHandle rgb_pnh(pnh, "rgb");
ros::NodeHandle depth_pnh(pnh, "depth");
image_transport::ImageTransport rgb_it(rgb_nh);
image_transport::ImageTransport depth_it(depth_nh);
image_transport::TransportHints hintsRgb("raw", ros::TransportHints(), rgb_pnh);
image_transport::TransportHints hintsDepth("raw", ros::TransportHints(), depth_pnh);
imageSub_.subscribe(rgb_it, rgb_nh.resolveName("image"), 1, hintsRgb);
imageDepthSub_.subscribe(depth_it, depth_nh.resolveName("image"), 1, hintsDepth);
cameraInfoSub_.subscribe(rgb_nh, "camera_info", 1);
}
void callback(
const sensor_msgs::ImageConstPtr& image,
const sensor_msgs::ImageConstPtr& depth,
const sensor_msgs::CameraInfoConstPtr& cameraInfo)
{
if(rgbdImagePub_.getNumSubscribers() || rgbdImageCompressedPub_.getNumSubscribers())
{
rtabmap_ros::RGBDImage msg;
msg.header.frame_id = cameraInfo->header.frame_id;
msg.header.stamp = image->header.stamp>depth->header.stamp?image->header.stamp:depth->header.stamp;
msg.cameraInfo = *cameraInfo;
if(rgbdImageCompressedPub_.getNumSubscribers())
{
rtabmap_ros::RGBDImage msgCompressed = msg;
cv_bridge::CvImageConstPtr imagePtr = cv_bridge::toCvShare(image);
imagePtr->toCompressedImageMsg(msgCompressed.rgbCompressed, cv_bridge::JPG);
cv_bridge::CvImageConstPtr imageDepthPtr = cv_bridge::toCvShare(depth);
ROS_ASSERT(imageDepthPtr->image.type() == CV_32FC1 || imageDepthPtr->image.type() == CV_16UC1);
msgCompressed.depthCompressed.header = imageDepthPtr->header;
msgCompressed.depthCompressed.data = rtabmap::compressImage(imageDepthPtr->image, ".png");
msgCompressed.depthCompressed.format = "png";
rgbdImageCompressedPub_.publish(msgCompressed);
}
if(rgbdImagePub_.getNumSubscribers())
{
msg.rgb = *image;
msg.depth = *depth;
rgbdImagePub_.publish(msg);
}
}
}
private:
ros::Publisher rgbdImagePub_;
ros::Publisher rgbdImageCompressedPub_;
image_transport::SubscriberFilter imageSub_;
image_transport::SubscriberFilter imageDepthSub_;
message_filters::Subscriber<sensor_msgs::CameraInfo> cameraInfoSub_;
typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo> MyApproxSyncDepthPolicy;
message_filters::Synchronizer<MyApproxSyncDepthPolicy> * approxSyncDepth_;
typedef message_filters::sync_policies::ExactTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo> MyExactSyncDepthPolicy;
message_filters::Synchronizer<MyExactSyncDepthPolicy> * exactSyncDepth_;
};
PLUGINLIB_EXPORT_CLASS(rtabmap_ros::RGBDSync, nodelet::Nodelet);
}
+406
View File
@@ -0,0 +1,406 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtabmap_ros/OdometryROS.h>
#include <pluginlib/class_list_macros.h>
#include <nodelet/nodelet.h>
#include <message_filters/subscriber.h>
#include <message_filters/time_synchronizer.h>
#include <message_filters/sync_policies/approximate_time.h>
#include <image_transport/image_transport.h>
#include <image_transport/subscriber_filter.h>
#include <image_geometry/stereo_camera_model.h>
#include <laser_geometry/laser_geometry.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/image_encodings.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/LaserScan.h>
#include <sensor_msgs/PointCloud2.h>
#include <pcl_conversions/pcl_conversions.h>
#include "rtabmap_ros/MsgConversion.h"
#include <rtabmap/core/util3d.h>
#include <rtabmap/core/util3d_surface.h>
#include <rtabmap/core/util3d_transforms.h>
#include <rtabmap/core/util2d.h>
#include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UConversion.h>
#include <rtabmap/utilite/UStl.h>
using namespace rtabmap;
namespace rtabmap_ros
{
class RGBDICPOdometry : public rtabmap_ros::OdometryROS
{
public:
RGBDICPOdometry() :
OdometryROS(false, true, true),
approxScanSync_(0),
exactScanSync_(0),
approxCloudSync_(0),
exactCloudSync_(0),
queueSize_(5),
scanCloudMaxPoints_(0),
scanCloudNormalK_(0)
{
}
virtual ~RGBDICPOdometry()
{
if(approxScanSync_)
{
delete approxScanSync_;
}
if(exactScanSync_)
{
delete exactScanSync_;
}
if(approxCloudSync_)
{
delete approxCloudSync_;
}
if(exactCloudSync_)
{
delete exactCloudSync_;
}
}
private:
virtual void onOdomInit()
{
ros::NodeHandle & nh = getNodeHandle();
ros::NodeHandle & pnh = getPrivateNodeHandle();
bool approxSync = true;
bool subscribeScanCloud = false;
pnh.param("approx_sync", approxSync, approxSync);
pnh.param("queue_size", queueSize_, queueSize_);
pnh.param("subscribe_scan_cloud", subscribeScanCloud, subscribeScanCloud);
pnh.param("scan_cloud_max_points", scanCloudMaxPoints_, scanCloudMaxPoints_);
pnh.param("scan_cloud_normal_k", scanCloudNormalK_, scanCloudNormalK_);
ros::NodeHandle rgb_nh(nh, "rgb");
ros::NodeHandle depth_nh(nh, "depth");
ros::NodeHandle rgb_pnh(pnh, "rgb");
ros::NodeHandle depth_pnh(pnh, "depth");
image_transport::ImageTransport rgb_it(rgb_nh);
image_transport::ImageTransport depth_it(depth_nh);
image_transport::TransportHints hintsRgb("raw", ros::TransportHints(), rgb_pnh);
image_transport::TransportHints hintsDepth("raw", ros::TransportHints(), depth_pnh);
image_mono_sub_.subscribe(rgb_it, rgb_nh.resolveName("image"), 1, hintsRgb);
image_depth_sub_.subscribe(depth_it, depth_nh.resolveName("image"), 1, hintsDepth);
info_sub_.subscribe(rgb_nh, "camera_info", 1);
std::string subscribedTopicsMsg;
if(subscribeScanCloud)
{
cloud_sub_.subscribe(nh, "scan_cloud", 1);
if(approxSync)
{
approxCloudSync_ = new message_filters::Synchronizer<MyApproxCloudSyncPolicy>(MyApproxCloudSyncPolicy(queueSize_), image_mono_sub_, image_depth_sub_, info_sub_, cloud_sub_);
approxCloudSync_->registerCallback(boost::bind(&RGBDICPOdometry::callbackCloud, this, _1, _2, _3, _4));
}
else
{
exactCloudSync_ = new message_filters::Synchronizer<MyExactCloudSyncPolicy>(MyExactCloudSyncPolicy(queueSize_), image_mono_sub_, image_depth_sub_, info_sub_, cloud_sub_);
exactCloudSync_->registerCallback(boost::bind(&RGBDICPOdometry::callbackCloud, this, _1, _2, _3, _4));
}
subscribedTopicsMsg = uFormat("\n%s subscribed to (%s sync):\n %s,\n %s,\n %s, \n %s",
getName().c_str(),
approxSync?"approx":"exact",
image_mono_sub_.getTopic().c_str(),
image_depth_sub_.getTopic().c_str(),
info_sub_.getTopic().c_str(),
cloud_sub_.getTopic().c_str());
}
else
{
scan_sub_.subscribe(nh, "scan", 1);
if(approxSync)
{
approxScanSync_ = new message_filters::Synchronizer<MyApproxScanSyncPolicy>(MyApproxScanSyncPolicy(queueSize_), image_mono_sub_, image_depth_sub_, info_sub_, scan_sub_);
approxScanSync_->registerCallback(boost::bind(&RGBDICPOdometry::callbackScan, this, _1, _2, _3, _4));
}
else
{
exactScanSync_ = new message_filters::Synchronizer<MyExactScanSyncPolicy>(MyExactScanSyncPolicy(queueSize_), image_mono_sub_, image_depth_sub_, info_sub_, scan_sub_);
exactScanSync_->registerCallback(boost::bind(&RGBDICPOdometry::callbackScan, this, _1, _2, _3, _4));
}
subscribedTopicsMsg = uFormat("\n%s subscribed to (%s sync):\n %s,\n %s,\n %s, \n %s",
getName().c_str(),
approxSync?"approx":"exact",
image_mono_sub_.getTopic().c_str(),
image_depth_sub_.getTopic().c_str(),
info_sub_.getTopic().c_str(),
scan_sub_.getTopic().c_str());
}
this->startWarningThread(subscribedTopicsMsg, approxSync);
}
virtual void updateParameters(ParametersMap & parameters)
{
//make sure we are using Reg/Strategy=0
ParametersMap::iterator iter = parameters.find(Parameters::kRegStrategy());
if(iter != parameters.end() && iter->second.compare("0") != 0)
{
ROS_WARN("RGBDICP odometry works only with \"Reg/Strategy\"=2. Ignoring value %s.", iter->second.c_str());
}
uInsert(parameters, ParametersPair(Parameters::kRegStrategy(), "2"));
}
void callback(
const sensor_msgs::ImageConstPtr& image,
const sensor_msgs::ImageConstPtr& depth,
const sensor_msgs::CameraInfoConstPtr& cameraInfo)
{
sensor_msgs::LaserScanConstPtr scanMsg;
sensor_msgs::PointCloud2ConstPtr cloudMsg;
callbackCommon(image, depth, cameraInfo, scanMsg, cloudMsg);
}
void callbackScan(
const sensor_msgs::ImageConstPtr& image,
const sensor_msgs::ImageConstPtr& depth,
const sensor_msgs::CameraInfoConstPtr& cameraInfo,
const sensor_msgs::LaserScanConstPtr& scanMsg)
{
sensor_msgs::PointCloud2ConstPtr cloudMsg;
callbackCommon(image, depth, cameraInfo, scanMsg, cloudMsg);
}
void callbackCloud(
const sensor_msgs::ImageConstPtr& image,
const sensor_msgs::ImageConstPtr& depth,
const sensor_msgs::CameraInfoConstPtr& cameraInfo,
const sensor_msgs::PointCloud2ConstPtr& cloudMsg)
{
sensor_msgs::LaserScanConstPtr scanMsg;
callbackCommon(image, depth, cameraInfo, scanMsg, cloudMsg);
}
void callbackCommon(
const sensor_msgs::ImageConstPtr& image,
const sensor_msgs::ImageConstPtr& depth,
const sensor_msgs::CameraInfoConstPtr& cameraInfo,
const sensor_msgs::LaserScanConstPtr& scanMsg,
const sensor_msgs::PointCloud2ConstPtr& cloudMsg)
{
callbackCalled();
if(!this->isPaused())
{
if(!(image->encoding.compare(sensor_msgs::image_encodings::TYPE_8UC1) ==0 ||
image->encoding.compare(sensor_msgs::image_encodings::MONO8) ==0 ||
image->encoding.compare(sensor_msgs::image_encodings::MONO16) ==0 ||
image->encoding.compare(sensor_msgs::image_encodings::BGR8) == 0 ||
image->encoding.compare(sensor_msgs::image_encodings::RGB8) == 0) ||
!(depth->encoding.compare(sensor_msgs::image_encodings::TYPE_16UC1)==0 ||
depth->encoding.compare(sensor_msgs::image_encodings::TYPE_32FC1)==0 ||
depth->encoding.compare(sensor_msgs::image_encodings::MONO16)==0))
{
NODELET_ERROR("Input type must be image=mono8,mono16,rgb8,bgr8 (mono8 "
"recommended) and image_depth=16UC1,32FC1,mono16. Types detected: %s %s",
image->encoding.c_str(), depth->encoding.c_str());
return;
}
// use the highest stamp to make sure that there will be no future interpolation required when synchronized with another node
ros::Time stamp = image->header.stamp > depth->header.stamp? image->header.stamp : depth->header.stamp;
if(scanMsg.get() != 0)
{
if(stamp < scanMsg->header.stamp)
{
stamp = scanMsg->header.stamp;
}
}
else if(cloudMsg.get() != 0)
{
if(stamp < cloudMsg->header.stamp)
{
stamp = cloudMsg->header.stamp;
}
}
Transform localTransform = getTransform(this->frameId(), image->header.frame_id, stamp);
if(localTransform.isNull())
{
return;
}
if(image->data.size() && depth->data.size() && cameraInfo->K[4] != 0)
{
rtabmap::CameraModel rtabmapModel = rtabmap_ros::cameraModelFromROS(*cameraInfo, localTransform);
cv_bridge::CvImagePtr ptrImage = cv_bridge::toCvCopy(image, image->encoding.compare(sensor_msgs::image_encodings::TYPE_8UC1)==0?"":"mono8");
cv_bridge::CvImagePtr ptrDepth = cv_bridge::toCvCopy(depth);
cv::Mat scan;
Transform localScanTransform = Transform::getIdentity();
if(scanMsg.get() != 0)
{
// make sure the frame of the laser is updated too
localScanTransform = getTransform(this->frameId(),
scanMsg->header.frame_id,
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());
return;
}
//transform in frameId_ frame
sensor_msgs::PointCloud2 scanOut;
laser_geometry::LaserProjection projection;
projection.transformLaserScanToPointCloud(scanMsg->header.frame_id, *scanMsg, scanOut, this->tfListener());
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(scanOut, *pclScan);
scan = util3d::laserScan2dFromPointCloud(*pclScan);
}
else if(cloudMsg.get() != 0)
{
bool containNormals = false;
for(unsigned int i=0; i<cloudMsg->fields.size(); ++i)
{
if(cloudMsg->fields[i].name.compare("normal_x") == 0)
{
containNormals = true;
break;
}
}
localScanTransform = getTransform(this->frameId(), cloudMsg->header.frame_id, cloudMsg->header.stamp);
if(localScanTransform.isNull())
{
ROS_ERROR("TF of received scan cloud at time %fs is not set, aborting rtabmap update.", cloudMsg->header.stamp.toSec());
return;
}
if(containNormals)
{
pcl::PointCloud<pcl::PointNormal>::Ptr pclScan(new pcl::PointCloud<pcl::PointNormal>);
pcl::fromROSMsg(*cloudMsg, *pclScan);
scan = util3d::laserScanFromPointCloud(*pclScan);
}
else
{
pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(*cloudMsg, *pclScan);
if(scanCloudNormalK_ > 0)
{
//compute normals
pcl::PointCloud<pcl::Normal>::Ptr normals = util3d::computeNormals(pclScan, scanCloudNormalK_);
pcl::PointCloud<pcl::PointNormal>::Ptr pclScanNormal(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*pclScan, *normals, *pclScanNormal);
scan = util3d::laserScanFromPointCloud(*pclScanNormal);
}
else
{
scan = util3d::laserScanFromPointCloud(*pclScan);
}
}
}
rtabmap::SensorData data(
scan,
LaserScanInfo(
scanMsg.get() != 0?(int)scanMsg->ranges.size():cloudMsg.get() != 0?scanCloudMaxPoints_:0,
scanMsg.get() != 0?scanMsg->range_max:0,
localScanTransform),
ptrImage->image,
ptrDepth->image,
rtabmapModel,
0,
rtabmap_ros::timestampFromROS(stamp));
this->processData(data, stamp);
}
}
}
protected:
virtual void flushCallbacks()
{
// flush callbacks
if(approxScanSync_)
{
delete approxScanSync_;
approxScanSync_ = new message_filters::Synchronizer<MyApproxScanSyncPolicy>(MyApproxScanSyncPolicy(queueSize_), image_mono_sub_, image_depth_sub_, info_sub_, scan_sub_);
approxScanSync_->registerCallback(boost::bind(&RGBDICPOdometry::callbackScan, this, _1, _2, _3, _4));
}
if(exactScanSync_)
{
delete exactScanSync_;
exactScanSync_ = new message_filters::Synchronizer<MyExactScanSyncPolicy>(MyExactScanSyncPolicy(queueSize_), image_mono_sub_, image_depth_sub_, info_sub_, scan_sub_);
exactScanSync_->registerCallback(boost::bind(&RGBDICPOdometry::callbackScan, this, _1, _2, _3, _4));
}
if(approxCloudSync_)
{
delete approxCloudSync_;
approxCloudSync_ = new message_filters::Synchronizer<MyApproxCloudSyncPolicy>(MyApproxCloudSyncPolicy(queueSize_), image_mono_sub_, image_depth_sub_, info_sub_, cloud_sub_);
approxCloudSync_->registerCallback(boost::bind(&RGBDICPOdometry::callbackCloud, this, _1, _2, _3, _4));
}
if(exactCloudSync_)
{
delete exactCloudSync_;
exactCloudSync_ = new message_filters::Synchronizer<MyExactCloudSyncPolicy>(MyExactCloudSyncPolicy(queueSize_), image_mono_sub_, image_depth_sub_, info_sub_, cloud_sub_);
exactCloudSync_->registerCallback(boost::bind(&RGBDICPOdometry::callbackCloud, this, _1, _2, _3, _4));
}
}
private:
image_transport::SubscriberFilter image_mono_sub_;
image_transport::SubscriberFilter image_depth_sub_;
message_filters::Subscriber<sensor_msgs::CameraInfo> info_sub_;
message_filters::Subscriber<sensor_msgs::LaserScan> scan_sub_;
message_filters::Subscriber<sensor_msgs::PointCloud2> cloud_sub_;
typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::LaserScan> MyApproxScanSyncPolicy;
message_filters::Synchronizer<MyApproxScanSyncPolicy> * approxScanSync_;
typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::LaserScan> MyExactScanSyncPolicy;
message_filters::Synchronizer<MyExactScanSyncPolicy> * exactScanSync_;
typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::PointCloud2> MyApproxCloudSyncPolicy;
message_filters::Synchronizer<MyApproxCloudSyncPolicy> * approxCloudSync_;
typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::PointCloud2> MyExactCloudSyncPolicy;
message_filters::Synchronizer<MyExactCloudSyncPolicy> * exactCloudSync_;
int queueSize_;
int scanCloudMaxPoints_;
int scanCloudNormalK_;
};
PLUGINLIB_EXPORT_CLASS(rtabmap_ros::RGBDICPOdometry, nodelet::Nodelet);
}
+18 -5
View File
@@ -25,7 +25,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "OdometryROS.h" #include "rtabmap_ros/OdometryROS.h"
#include "pluginlib/class_list_macros.h" #include "pluginlib/class_list_macros.h"
#include "nodelet/nodelet.h" #include "nodelet/nodelet.h"
@@ -47,6 +47,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rtabmap/utilite/ULogger.h> #include <rtabmap/utilite/ULogger.h>
#include <rtabmap/utilite/UTimer.h> #include <rtabmap/utilite/UTimer.h>
#include <rtabmap/utilite/UStl.h>
using namespace rtabmap; using namespace rtabmap;
@@ -57,7 +58,7 @@ class StereoOdometry : public rtabmap_ros::OdometryROS
{ {
public: public:
StereoOdometry() : StereoOdometry() :
rtabmap_ros::OdometryROS(true), rtabmap_ros::OdometryROS(true, true, false),
approxSync_(0), approxSync_(0),
exactSync_(0), exactSync_(0),
queueSize_(5) queueSize_(5)
@@ -85,7 +86,6 @@ private:
bool approxSync = false; bool approxSync = false;
pnh.param("approx_sync", approxSync, approxSync); pnh.param("approx_sync", approxSync, approxSync);
pnh.param("queue_size", queueSize_, queueSize_); pnh.param("queue_size", queueSize_, queueSize_);
NODELET_INFO("Approximate time sync = %s", approxSync?"true":"false");
ros::NodeHandle left_nh(nh, "left"); ros::NodeHandle left_nh(nh, "left");
ros::NodeHandle right_nh(nh, "right"); ros::NodeHandle right_nh(nh, "right");
@@ -113,13 +113,25 @@ private:
} }
NODELET_INFO("\n%s subscribed to (%s sync):\n %s,\n %s,\n %s,\n %s", std::string subscribedTopicsMsg = uFormat("\n%s subscribed to (%s sync):\n %s,\n %s,\n %s,\n %s",
ros::this_node::getName().c_str(), getName().c_str(),
approxSync?"approx":"exact", approxSync?"approx":"exact",
imageRectLeft_.getTopic().c_str(), imageRectLeft_.getTopic().c_str(),
imageRectRight_.getTopic().c_str(), imageRectRight_.getTopic().c_str(),
cameraInfoLeft_.getTopic().c_str(), cameraInfoLeft_.getTopic().c_str(),
cameraInfoRight_.getTopic().c_str()); cameraInfoRight_.getTopic().c_str());
this->startWarningThread(subscribedTopicsMsg, approxSync);
}
virtual void updateParameters(ParametersMap & parameters)
{
//make sure we are using Reg/Strategy=0
ParametersMap::iterator iter = parameters.find(Parameters::kRegStrategy());
if(iter != parameters.end() && iter->second.compare("0") != 0)
{
ROS_WARN("Stereo odometry works only with \"Reg/Strategy\"=0. Ignoring value %s.", iter->second.c_str());
}
uInsert(parameters, ParametersPair(Parameters::kRegStrategy(), "0"));
} }
void callback( void callback(
@@ -128,6 +140,7 @@ private:
const sensor_msgs::CameraInfoConstPtr& cameraInfoLeft, const sensor_msgs::CameraInfoConstPtr& cameraInfoLeft,
const sensor_msgs::CameraInfoConstPtr& cameraInfoRight) const sensor_msgs::CameraInfoConstPtr& cameraInfoRight)
{ {
callbackCalled();
if(!this->isPaused()) if(!this->isPaused())
{ {
if(!(imageRectLeft->encoding.compare(sensor_msgs::image_encodings::MONO8) ==0 || if(!(imageRectLeft->encoding.compare(sensor_msgs::image_encodings::MONO8) ==0 ||
+123
View File
@@ -0,0 +1,123 @@
/*
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Universite de Sherbrooke nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <ros/ros.h>
#include <pluginlib/class_list_macros.h>
#include <nodelet/nodelet.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/image_encodings.h>
#include <image_transport/image_transport.h>
#include <image_transport/subscriber.h>
#include <image_transport/publisher.h>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/highgui/highgui.hpp>
#include "rtabmap/core/clams/discrete_depth_distortion_model.h"
#include "rtabmap/utilite/UConversion.h"
namespace rtabmap_ros
{
class UndistortDepth : public nodelet::Nodelet
{
public:
UndistortDepth()
{}
virtual ~UndistortDepth()
{
}
private:
virtual void onInit()
{
ros::NodeHandle & nh = getNodeHandle();
ros::NodeHandle & pnh = getPrivateNodeHandle();
int queueSize = 10;
std::string modelPath;
pnh.param("queue_size", queueSize, queueSize);
pnh.param("model", modelPath, modelPath);
if(modelPath.empty())
{
NODELET_ERROR("undistort_depth: \"model\" parameter should be set!");
}
model_.load(modelPath);
if(!model_.isValid())
{
NODELET_ERROR("Loaded distortion model from \"%s\" is not valid!", modelPath.c_str());
}
else
{
image_transport::ImageTransport it(nh);
sub_ = it.subscribe("depth", queueSize, &UndistortDepth::callback, this);
pub_ = it.advertise(uFormat("%s_undistorted", nh.resolveName("depth").c_str()), 1);
}
}
void callback(const sensor_msgs::ImageConstPtr& depth)
{
if(depth->encoding.compare(sensor_msgs::image_encodings::TYPE_16UC1)!=0 &&
depth->encoding.compare(sensor_msgs::image_encodings::TYPE_32FC1)!=0 &&
depth->encoding.compare(sensor_msgs::image_encodings::MONO16)!=0)
{
NODELET_ERROR("Input type depth=32FC1,16UC1,MONO16");
return;
}
if(pub_.getNumSubscribers())
{
if(depth->width == model_.getWidth() && depth->width == model_.getWidth())
{
cv_bridge::CvImagePtr imageDepthPtr = cv_bridge::toCvCopy(depth);
model_.undistort(imageDepthPtr->image);
pub_.publish(imageDepthPtr->toImageMsg());
}
else
{
NODELET_ERROR("Input depth image size (%dx%d) and distortion model "
"size (%dx%d) don't match! Cannot undistort image.",
depth->width, depth->height,
model_.getWidth(), model_.getHeight());
}
}
}
private:
clams::DiscreteDepthDistortionModel model_;
image_transport::Publisher pub_;
image_transport::Subscriber sub_;
};
PLUGINLIB_EXPORT_CLASS(rtabmap_ros::UndistortDepth, nodelet::Nodelet);
}
+52 -49
View File
@@ -272,58 +272,60 @@ void MapCloudDisplay::processMapData(const rtabmap_ros::MapData& map)
for(unsigned int i=0; i<map.nodes.size() && i<map.nodes.size(); ++i) for(unsigned int i=0; i<map.nodes.size() && i<map.nodes.size(); ++i)
{ {
int id = map.nodes[i].id; int id = map.nodes[i].id;
if(poses.find(id) != poses.end() &&
cloud_infos_.find(id) == cloud_infos_.end()) // Always refresh the cloud if there are data
rtabmap::Signature s = rtabmap_ros::nodeDataFromROS(map.nodes[i]);
if(!s.sensorData().imageCompressed().empty() &&
!s.sensorData().depthOrRightCompressed().empty() &&
(s.sensorData().cameraModels().size() || s.sensorData().stereoCameraModel().isValidForProjection()))
{ {
// Cloud not added to RVIZ, add it! cv::Mat image, depth;
rtabmap::Signature s = rtabmap_ros::nodeDataFromROS(map.nodes[i]); s.sensorData().uncompressData(&image, &depth, 0);
if(!s.sensorData().imageCompressed().empty() &&
!s.sensorData().depthOrRightCompressed().empty() &&
(s.sensorData().cameraModels().size() || s.sensorData().stereoCameraModel().isValidForProjection())) if(!s.sensorData().imageRaw().empty() && !s.sensorData().depthOrRightRaw().empty())
{ {
cv::Mat image, depth; pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
s.sensorData().uncompressData(&image, &depth, 0); pcl::IndicesPtr validIndices(new std::vector<int>);
cloud = rtabmap::util3d::cloudRGBFromSensorData(
s.sensorData(),
cloud_decimation_->getInt(),
cloud_max_depth_->getFloat(),
cloud_min_depth_->getFloat(),
validIndices.get());
if(cloud_voxel_size_->getFloat())
if(!s.sensorData().imageRaw().empty() && !s.sensorData().depthOrRightRaw().empty())
{ {
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud; cloud = rtabmap::util3d::voxelize(cloud, validIndices, cloud_voxel_size_->getFloat());
pcl::IndicesPtr validIndices(new std::vector<int>); }
cloud = rtabmap::util3d::cloudRGBFromSensorData(
s.sensorData(),
cloud_decimation_->getInt(),
cloud_max_depth_->getFloat(),
cloud_min_depth_->getFloat(),
validIndices.get());
if(cloud_voxel_size_->getFloat()) if(cloud->size())
{
if(cloud_filter_floor_height_->getFloat() > 0.0f || cloud_filter_ceiling_height_->getFloat() > 0.0f)
{ {
cloud = rtabmap::util3d::voxelize(cloud, validIndices, cloud_voxel_size_->getFloat()); // convert in /odom frame
cloud = rtabmap::util3d::transformPointCloud(cloud, s.getPose());
cloud = rtabmap::util3d::passThrough(cloud, "z",
cloud_filter_floor_height_->getFloat()>0.0f?cloud_filter_floor_height_->getFloat():-999.0f,
cloud_filter_ceiling_height_->getFloat()>0.0f && (cloud_filter_floor_height_->getFloat()<=0.0f || cloud_filter_ceiling_height_->getFloat()>cloud_filter_floor_height_->getFloat())?cloud_filter_ceiling_height_->getFloat():999.0f);
// convert back in /base_link frame
cloud = rtabmap::util3d::transformPointCloud(cloud, s.getPose().inverse());
} }
if(cloud->size()) sensor_msgs::PointCloud2::Ptr cloudMsg(new sensor_msgs::PointCloud2);
pcl::toROSMsg(*cloud, *cloudMsg);
cloudMsg->header = map.header;
CloudInfoPtr info(new CloudInfo);
info->message_ = cloudMsg;
info->pose_ = rtabmap::Transform::getIdentity();
info->id_ = id;
if (transformCloud(info, true))
{ {
if(cloud_filter_floor_height_->getFloat() > 0.0f || cloud_filter_ceiling_height_->getFloat() > 0.0f) boost::mutex::scoped_lock lock(new_clouds_mutex_);
{ new_cloud_infos_.erase(id);
cloud = rtabmap::util3d::passThrough(cloud, "z", new_cloud_infos_.insert(std::make_pair(id, info));
cloud_filter_floor_height_->getFloat()>0.0f?cloud_filter_floor_height_->getFloat():-999.0f,
cloud_filter_ceiling_height_->getFloat()>0.0f && (cloud_filter_floor_height_->getFloat()<=0.0f || cloud_filter_ceiling_height_->getFloat()>cloud_filter_floor_height_->getFloat())?cloud_filter_ceiling_height_->getFloat():999.0f);
}
sensor_msgs::PointCloud2::Ptr cloudMsg(new sensor_msgs::PointCloud2);
pcl::toROSMsg(*cloud, *cloudMsg);
cloudMsg->header = map.header;
CloudInfoPtr info(new CloudInfo);
info->message_ = cloudMsg;
info->pose_ = rtabmap::Transform::getIdentity();
info->id_ = id;
if (transformCloud(info, true))
{
boost::mutex::scoped_lock lock(new_clouds_mutex_);
new_cloud_infos_.insert(std::make_pair(id, info));
}
} }
} }
} }
@@ -485,7 +487,7 @@ void MapCloudDisplay::downloadMap()
ros::NodeHandle nh; ros::NodeHandle nh;
QMessageBox * messageBox = new QMessageBox( QMessageBox * messageBox = new QMessageBox(
QMessageBox::NoIcon, QMessageBox::NoIcon,
tr("Calling \"%1\" service...").arg(nh.resolveName("rtabmap/get_map").c_str()), tr("Calling \"%1\" service...").arg(nh.resolveName("rtabmap/get_map_data").c_str()),
tr("Downloading the map... please wait (rviz could become gray!)"), tr("Downloading the map... please wait (rviz could become gray!)"),
QMessageBox::NoButton); QMessageBox::NoButton);
messageBox->setAttribute(Qt::WA_DeleteOnClose, true); messageBox->setAttribute(Qt::WA_DeleteOnClose, true);
@@ -493,18 +495,18 @@ void MapCloudDisplay::downloadMap()
QApplication::processEvents(); QApplication::processEvents();
uSleep(100); // hack make sure the text in the QMessageBox is shown... uSleep(100); // hack make sure the text in the QMessageBox is shown...
QApplication::processEvents(); QApplication::processEvents();
if(!ros::service::call("rtabmap/get_map", getMapSrv)) if(!ros::service::call("rtabmap/get_map_data", getMapSrv))
{ {
ROS_ERROR("MapCloudDisplay: Can't call \"%s\" service. " ROS_ERROR("MapCloudDisplay: Can't call \"%s\" service. "
"Tip: if rtabmap node is not in rtabmap namespace, you can remap the service " "Tip: if rtabmap node is not in rtabmap namespace, you can remap the service "
"to \"get_map\" in the launch " "to \"get_map\" in the launch "
"file like: <remap from=\"rtabmap/get_map\" to=\"get_map\"/>.", "file like: <remap from=\"rtabmap/get_map_data\" to=\"get_map_data\"/>.",
nh.resolveName("rtabmap/get_map").c_str()); nh.resolveName("rtabmap/get_map_data").c_str());
messageBox->setText(tr("MapCloudDisplay: Can't call \"%1\" service. " messageBox->setText(tr("MapCloudDisplay: Can't call \"%1\" service. "
"Tip: if rtabmap node is not in rtabmap namespace, you can remap the service " "Tip: if rtabmap node is not in rtabmap namespace, you can remap the service "
"to \"get_map\" in the launch " "to \"get_map\" in the launch "
"file like: <remap from=\"rtabmap/get_map\" to=\"get_map\"/>."). "file like: <remap from=\"rtabmap/get_map_data\" to=\"get_map_data\"/>.").
arg(nh.resolveName("rtabmap/get_map").c_str())); arg(nh.resolveName("rtabmap/get_map_data").c_str()));
} }
else else
{ {
@@ -633,6 +635,7 @@ void MapCloudDisplay::update( float wall_dt, float ros_dt )
cloud_info->scene_node_->attachObject( cloud_info->cloud_.get() ); cloud_info->scene_node_->attachObject( cloud_info->cloud_.get() );
cloud_info->scene_node_->setVisible(false); cloud_info->scene_node_->setVisible(false);
cloud_infos_.erase(it->first);
cloud_infos_.insert(*it); cloud_infos_.insert(*it);
} }