moved stereo stuff from rgbd_sync to stereo_sync

This commit is contained in:
matlabbe
2018-05-02 12:29:45 -04:00
parent 30eabe93f1
commit a39ffe382c
11 changed files with 277 additions and 86 deletions
+1 -1
View File
@@ -184,7 +184,7 @@ SET(rtabmap_ros_lib_src
)
IF(${cv_bridge_VERSION_MAJOR} GREATER 1 OR ${cv_bridge_VERSION_MINOR} GREATER 10)
SET(rtabmap_ros_lib_src ${rtabmap_ros_lib_src} src/nodelets/rgbd_sync.cpp)
SET(rtabmap_ros_lib_src ${rtabmap_ros_lib_src} src/nodelets/rgbd_sync.cpp src/nodelets/stereo_sync.cpp)
ELSE()
ADD_DEFINITIONS("-DCV_BRIDGE_HYDRO")
ENDIF()
+18 -6
View File
@@ -18,6 +18,7 @@
<arg name="rviz" default="true" />
<arg name="rtabmapviz" default="false" />
<arg name="local_bundle" default="true" />
<arg name="stereo_sync" default="false" />
<param name="use_sim_time" type="bool" value="True"/>
@@ -27,8 +28,6 @@
<!-- Run the ROS package stereo_image_proc for image rectification -->
<group ns="/stereo_camera" >
<node pkg="nodelet" type="nodelet" name="stereo_nodelet" args="manager"/>
<node pkg="stereo_image_proc" type="stereo_image_proc" name="stereo_image_proc">
<remap from="left/image_raw" to="left/image_raw_throttle_relay"/>
<remap from="left/camera_info" to="left/camera_info_throttle"/>
@@ -36,6 +35,13 @@
<remap from="right/camera_info" to="right/camera_info_throttle"/>
<param name="disparity_range" value="128"/>
</node>
<node if="$(arg stereo_sync)" pkg="nodelet" type="nodelet" name="stereo_sync" args="standalone rtabmap_ros/stereo_sync">
<remap from="left/image_rect" to="left/image_rect_color"/>
<remap from="right/image_rect" to="right/image_rect"/>
<remap from="left/camera_info" to="left/camera_info_throttle"/>
<remap from="right/camera_info" to="right/camera_info_throttle"/>
</node>
</group>
<group ns="rtabmap">
@@ -46,10 +52,12 @@
<remap from="right/image_rect" to="/stereo_camera/right/image_rect"/>
<remap from="left/camera_info" to="/stereo_camera/left/camera_info_throttle"/>
<remap from="right/camera_info" to="/stereo_camera/right/camera_info_throttle"/>
<remap from="rgbd_image" to="/stereo_camera/rgbd_image"/>
<remap from="odom" to="/stereo_odometry"/>
<param name="frame_id" type="string" value="base_footprint"/>
<param name="odom_frame_id" type="string" value="odom"/>
<param name="subscribe_rgbd" type="bool" value="$(arg stereo_sync)"/>
<param name="frame_id" type="string" value="base_footprint"/>
<param name="odom_frame_id" type="string" value="odom"/>
<param name="Odom/Strategy" type="string" value="0"/> <!-- 0=Frame-to-Map, 1=Frame=to=Frame -->
<param name="Vis/EstimationType" type="string" value="1"/> <!-- 0=3D->3D 1=3D->2D (PnP) -->
@@ -66,13 +74,15 @@
<!-- Visual SLAM: args: "delete_db_on_start" and "udebug" -->
<node name="rtabmap" pkg="rtabmap_ros" type="rtabmap" output="screen" args="--delete_db_on_start">
<param name="frame_id" type="string" value="base_footprint"/>
<param name="subscribe_stereo" type="bool" value="true"/>
<param unless="$(arg stereo_sync)" name="subscribe_stereo" type="bool" value="true"/>
<param name="subscribe_depth" type="bool" value="false"/>
<param name="subscribe_rgbd" type="bool" value="$(arg stereo_sync)"/>
<remap from="left/image_rect" to="/stereo_camera/left/image_rect_color"/>
<remap from="right/image_rect" to="/stereo_camera/right/image_rect"/>
<remap from="left/camera_info" to="/stereo_camera/left/camera_info_throttle"/>
<remap from="right/camera_info" to="/stereo_camera/right/camera_info_throttle"/>
<remap from="rgbd_image" to="/stereo_camera/rgbd_image"/>
<remap from="odom" to="/stereo_odometry"/>
@@ -92,8 +102,9 @@
<!-- 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">
<param name="subscribe_stereo" type="bool" value="true"/>
<param unless="$(arg stereo_sync)" name="subscribe_stereo" type="bool" value="true"/>
<param name="subscribe_odom_info" type="bool" value="true"/>
<param name="subscribe_rgbd" type="bool" value="$(arg stereo_sync)"/>
<param name="queue_size" type="int" value="10"/>
<param name="frame_id" type="string" value="base_footprint"/>
@@ -101,6 +112,7 @@
<remap from="right/image_rect" to="/stereo_camera/right/image_rect"/>
<remap from="left/camera_info" to="/stereo_camera/left/camera_info_throttle"/>
<remap from="right/camera_info" to="/stereo_camera/right/camera_info_throttle"/>
<remap from="rgbd_image" to="/stereo_camera/rgbd_image"/>
<remap from="odom_info" to="odom_info"/>
<remap from="odom" to="/stereo_odometry"/>
<remap from="mapData" to="mapData"/>
-2
View File
@@ -53,7 +53,6 @@
<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"/>
<remap from="depth/camera_info" to="depth_registered/camera_info"/>
</node>
</group>
<group ns="camera2">
@@ -61,7 +60,6 @@
<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"/>
<remap from="depth/camera_info" to="depth_registered/camera_info"/>
</node>
</group>
+11 -37
View File
@@ -29,27 +29,9 @@
<arg name="rtabmapviz_cfg" default="-d $(find rtabmap_ros)/launch/config/rgbd_gui.ini" />
<arg name="rviz_cfg" default="-d $(find rtabmap_ros)/launch/config/rgbd.rviz" />
<!-- ODOMETRY MAIN ARGUMENTS:
-"strategy" : Strategy: Frame-to-Map 1=Frame-To-Frame
-"feature" : Feature type: 0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK
-"nn" : Nearest neighbor strategy : 0=Linear, 1=FLANN_KDTREE, 2=FLANN_LSH, 3=BRUTEFORCE
Set to 1 for float descriptor like SIFT/SURF
Set to 3 for binary descriptor like ORB/FREAK/BRIEF/BRISK
-"max_depth" : Maximum features depth (m)
-"min_inliers" : Minimum visual correspondences to accept a transformation (m)
-"inlier_distance" : RANSAC maximum inliers distance (m)
-"local_map" : Local map size: number of unique features to keep track
-"odom_info_data" : Fill odometry info messages with inliers/outliers data.
-->
<arg name="strategy" default="0" />
<arg name="feature" default="6" />
<arg name="nn" default="3" />
<arg name="max_depth" default="10.0" />
<arg name="min_inliers" default="20" />
<arg name="inlier_distance" default="0.02" />
<arg name="local_map" default="1000" />
<arg name="gftt_max_corners" default="1000" />
<arg name="gftt_min_distance" default="7" />
<!-- slightly increase default parameters for larger images (qhd=720p) -->
<arg name="gftt_block_size" default="5" />
<arg name="gftt_min_distance" default="5" />
<group ns="rtabmap">
@@ -60,17 +42,9 @@
<remap from="rgb/camera_info" to="/kinect2/$(arg resolution)/camera_info"/>
<param name="frame_id" type="string" value="$(arg frame_id)"/>
<param name="approx_sync" type="bool" value="true"/>
<param name="approx_sync" type="bool" value="false"/>
<param name="Odom/Strategy" type="string" value="$(arg strategy)"/>
<param name="Vis/FeatureType" type="string" value="$(arg feature)"/>
<param name="Vis/CorNNType" type="string" value="$(arg nn)"/>
<param name="Vis/MaxDepth" type="string" value="$(arg max_depth)"/>
<param name="Vis/MinInliers" type="string" value="$(arg min_inliers)"/>
<param name="Vis/InlierDistance" type="string" value="$(arg inlier_distance)"/>
<param name="OdomF2M/MaxSize" type="string" value="$(arg local_map)"/>
<param name="Odom/FillInfoData" type="string" value="$(arg rtabmapviz)"/>
<param name="Vis/MaxFeatures" type="string" value="$(arg gftt_max_corners)"/>
<param name="GFTT/BlockSize" type="string" value="$(arg gftt_block_size)"/>
<param name="GFTT/MinDistance" type="string" value="$(arg gftt_min_distance)"/>
</node>
@@ -84,17 +58,17 @@
<remap from="depth/image" to="/kinect2/$(arg resolution)/image_depth_rect"/>
<remap from="rgb/camera_info" to="/kinect2/$(arg resolution)/camera_info"/>
<param name="approx_sync" type="bool" value="true"/>
<param name="Vis/MinInliers" type="string" value="$(arg min_inliers)"/>
<param name="Vis/InlierDistance" type="string" value="$(arg inlier_distance)"/>
<param name="approx_sync" type="bool" value="false"/>
<param name="GFTT/BlockSize" type="string" value="$(arg gftt_block_size)"/>
<param name="GFTT/MinDistance" type="string" value="$(arg gftt_min_distance)"/>
</node>
<!-- Visualisation RTAB-Map -->
<node if="$(arg rtabmapviz)" pkg="rtabmap_ros" type="rtabmapviz" name="rtabmapviz" args="$(arg rtabmapviz_cfg)" output="screen">
<param name="subscribe_depth" type="bool" value="true"/>
<param name="subscribe_odom_info" type="bool" value="true"/>
<param name="approx_sync" type="bool" value="true"/>
<param name="approx_sync" type="bool" value="false"/>
<param name="frame_id" type="string" value="$(arg frame_id)"/>
<remap from="rgb/image" to="/kinect2/$(arg resolution)/image_color_rect"/>
@@ -115,7 +89,7 @@
<remap from="odom_in" to="rtabmap/odom"/>
<param name="approx_sync" type="bool" value="true"/>
<param name="approx_sync" type="bool" value="false"/>
<remap from="rgb/image_out" to="data_odom_sync/image"/>
<remap from="depth/image_out" to="data_odom_sync/depth"/>
+5 -6
View File
@@ -119,7 +119,6 @@
<remap from="rgb/image" to="$(arg rgb_topic_relay)"/>
<remap from="depth/image" to="$(arg depth_topic_relay)"/>
<remap from="rgb/camera_info" to="$(arg camera_info_topic)"/>
<remap from="depth/camera_info" to="$(arg depth_camera_info_topic)"/>
<remap from="rgbd_image" to="$(arg rgbd_topic)"/>
<param name="approx_sync" type="bool" value="$(arg approx_rgbd_sync)"/>
<param name="queue_size" type="int" value="$(arg queue_size)"/>
@@ -130,11 +129,11 @@
<node if="$(arg compressed)" name="republish_left" type="republish" pkg="image_transport" args="compressed in:=$(arg left_image_topic) raw out:=$(arg left_image_topic_relay)" />
<node if="$(arg compressed)" name="republish_right" type="republish" pkg="image_transport" args="compressed in:=$(arg right_image_topic) raw out:=$(arg right_image_topic_relay)" />
<node if="$(arg rgbd_sync)" pkg="nodelet" type="nodelet" name="rgbd_sync" args="standalone rtabmap_ros/rgbd_sync" output="$(arg output)">
<remap from="rgb/image" to="$(arg left_image_topic)"/>
<remap from="depth/image" to="$(arg right_image_topic)"/>
<remap from="rgb/camera_info" to="$(arg left_camera_info_topic)"/>
<remap from="depth/camera_info" to="$(arg right_camera_info_topic)"/>
<node if="$(arg rgbd_sync)" pkg="nodelet" type="nodelet" name="rgbd_sync" args="standalone rtabmap_ros/stereo_sync" output="$(arg output)">
<remap from="left/image_rect" to="$(arg left_image_topic)"/>
<remap from="right/image_rect" to="$(arg right_image_topic)"/>
<remap from="left/camera_info" to="$(arg left_camera_info_topic)"/>
<remap from="right/camera_info" to="$(arg right_camera_info_topic)"/>
<remap from="rgbd_image" to="$(arg rgbd_topic)"/>
<param name="approx_sync" type="bool" value="$(arg approx_rgbd_sync)"/>
<param name="queue_size" type="int" value="$(arg queue_size)"/>
+2 -4
View File
@@ -13,7 +13,6 @@
<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"/>
<remap from="depth/camera_info" to="depth_registered/camera_info"/>
</node>
</group>
@@ -22,9 +21,8 @@
<!-- 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="subscribe_rgbd" type="bool" value="true"/>
<remap from="rgbd_image" to="/camera/rgbd_image"/>
<param name="Odom/AlignWithGround" type="string" value="true"/>
<param name="frame_id" type="string" value="camera_link"/>
@@ -22,7 +22,6 @@
<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)"/>
<remap from="depth/camera_info" to="$(arg camera_info_topic)"/>
</node>
<!-- RGB-D Odometry -->
+8
View File
@@ -128,6 +128,14 @@
</description>
</class>
<class name="rtabmap_ros/stereo_sync"
type="rtabmap_ros::StereoSync"
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">
+15 -27
View File
@@ -101,13 +101,13 @@ private:
if(approxSync)
{
approxSyncDepth_ = new message_filters::Synchronizer<MyApproxSyncDepthPolicy>(MyApproxSyncDepthPolicy(queueSize), imageSub_, imageDepthSub_, cameraInfoSub_, cameraDepthInfoSub_);
approxSyncDepth_->registerCallback(boost::bind(&RGBDSync::callback, this, _1, _2, _3, _4));
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_, cameraDepthInfoSub_);
exactSyncDepth_->registerCallback(boost::bind(&RGBDSync::callback, this, _1, _2, _3, _4));
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");
@@ -122,15 +122,13 @@ private:
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);
cameraDepthInfoSub_.subscribe(depth_nh, "camera_info", 1);
std::string subscribedTopicsMsg = uFormat("\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",
getName().c_str(),
approxSync?"approx":"exact",
imageSub_.getTopic().c_str(),
imageDepthSub_.getTopic().c_str(),
cameraInfoSub_.getTopic().c_str(),
cameraDepthInfoSub_.getTopic().c_str());
cameraInfoSub_.getTopic().c_str());
warningThread_ = new boost::thread(boost::bind(&RGBDSync::warningLoop, this, subscribedTopicsMsg, approxSync));
NODELET_INFO("%s", subscribedTopicsMsg.c_str());
@@ -158,8 +156,7 @@ private:
void callback(
const sensor_msgs::ImageConstPtr& image,
const sensor_msgs::ImageConstPtr& depth,
const sensor_msgs::CameraInfoConstPtr& cameraInfo,
const sensor_msgs::CameraInfoConstPtr& cameraDepthInfo)
const sensor_msgs::CameraInfoConstPtr& cameraInfo)
{
callbackCalled_ = true;
if(rgbdImagePub_.getNumSubscribers() || rgbdImageCompressedPub_.getNumSubscribers())
@@ -168,7 +165,7 @@ private:
msg.header.frame_id = cameraInfo->header.frame_id;
msg.header.stamp = image->header.stamp>depth->header.stamp?image->header.stamp:depth->header.stamp;
msg.rgbCameraInfo = *cameraInfo;
msg.depthCameraInfo = *cameraDepthInfo;
msg.depthCameraInfo = *cameraInfo;
if(rgbdImageCompressedPub_.getNumSubscribers())
{
@@ -178,24 +175,16 @@ private:
imagePtr->toCompressedImageMsg(msgCompressed.rgbCompressed, cv_bridge::JPG);
cv_bridge::CvImageConstPtr imageDepthPtr = cv_bridge::toCvShare(depth);
if(imageDepthPtr->image.type() == CV_32FC1 || imageDepthPtr->image.type() == CV_16UC1)
msgCompressed.depthCompressed.header = imageDepthPtr->header;
if(depthScale_ != 1.0)
{
msgCompressed.depthCompressed.header = imageDepthPtr->header;
if(depthScale_ != 1.0)
{
msgCompressed.depthCompressed.data = rtabmap::compressImage(imageDepthPtr->image*depthScale_, ".png");
}
else
{
msgCompressed.depthCompressed.data = rtabmap::compressImage(imageDepthPtr->image, ".png");
}
msgCompressed.depthCompressed.format = "png";
msgCompressed.depthCompressed.data = rtabmap::compressImage(imageDepthPtr->image*depthScale_, ".png");
}
else
{
// Assume right stereo image
imageDepthPtr->toCompressedImageMsg(msgCompressed.depthCompressed, cv_bridge::JPG);
msgCompressed.depthCompressed.data = rtabmap::compressImage(imageDepthPtr->image, ".png");
}
msgCompressed.depthCompressed.format = "png";
rgbdImageCompressedPub_.publish(msgCompressed);
}
@@ -229,12 +218,11 @@ private:
image_transport::SubscriberFilter imageSub_;
image_transport::SubscriberFilter imageDepthSub_;
message_filters::Subscriber<sensor_msgs::CameraInfo> cameraInfoSub_;
message_filters::Subscriber<sensor_msgs::CameraInfo> cameraDepthInfoSub_;
typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::CameraInfo> MyApproxSyncDepthPolicy;
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, sensor_msgs::CameraInfo> MyExactSyncDepthPolicy;
typedef message_filters::sync_policies::ExactTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo> MyExactSyncDepthPolicy;
message_filters::Synchronizer<MyExactSyncDepthPolicy> * exactSyncDepth_;
};
+4 -2
View File
@@ -172,7 +172,8 @@ private:
imageRectRight->encoding.compare(sensor_msgs::image_encodings::BGR8) == 0 ||
imageRectRight->encoding.compare(sensor_msgs::image_encodings::RGB8) == 0))
{
NODELET_ERROR("Input type must be image=mono8,mono16,rgb8,bgr8 (mono8 recommended)");
NODELET_ERROR("Input type must be image=mono8,mono16,rgb8,bgr8 (mono8 recommended), received types are %s (left) and %s (right)",
imageRectLeft->encoding.c_str(), imageRectRight->encoding.c_str());
return;
}
@@ -250,7 +251,8 @@ private:
imageRectRight->encoding.compare(sensor_msgs::image_encodings::BGR8) == 0 ||
imageRectRight->encoding.compare(sensor_msgs::image_encodings::RGB8) == 0))
{
NODELET_ERROR("Input type must be image=mono8,mono16,rgb8,bgr8 (mono8 recommended)");
NODELET_ERROR("Input type must be image=mono8,mono16,rgb8,bgr8 (mono8 recommended), received types are %s (left) and %s (right)",
imageRectLeft->encoding.c_str(), imageRectRight->encoding.c_str());
return;
}
+213
View File
@@ -0,0 +1,213 @@
/*
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 <boost/thread.hpp>
#include "rtabmap_ros/RGBDImage.h"
#include "rtabmap/core/Compression.h"
#include "rtabmap/utilite/UConversion.h"
namespace rtabmap_ros
{
class StereoSync : public nodelet::Nodelet
{
public:
StereoSync() :
warningThread_(0),
callbackCalled_(false),
approxSync_(0),
exactSync_(0)
{}
virtual ~StereoSync()
{
if(approxSync_)
delete approxSync_;
if(exactSync_)
delete exactSync_;
if(warningThread_)
{
callbackCalled_=true;
warningThread_->join();
delete warningThread_;
}
}
private:
virtual void onInit()
{
ros::NodeHandle & nh = getNodeHandle();
ros::NodeHandle & pnh = getPrivateNodeHandle();
int queueSize = 10;
bool approxSync = false;
pnh.param("approx_sync", approxSync, approxSync);
pnh.param("queue_size", queueSize, queueSize);
NODELET_INFO("%s: approx_sync = %s", getName().c_str(), approxSync?"true":"false");
NODELET_INFO("%s: queue_size = %d", getName().c_str(), queueSize);
rgbdImagePub_ = nh.advertise<rtabmap_ros::RGBDImage>("rgbd_image", 1);
rgbdImageCompressedPub_ = nh.advertise<rtabmap_ros::RGBDImage>("rgbd_image/compressed", 1);
if(approxSync)
{
approxSync_ = new message_filters::Synchronizer<MyApproxSyncPolicy>(MyApproxSyncPolicy(queueSize), imageLeftSub_, imageRightSub_, cameraInfoLeftSub_, cameraInfoRightSub_);
approxSync_->registerCallback(boost::bind(&StereoSync::callback, this, _1, _2, _3, _4));
}
else
{
exactSync_ = new message_filters::Synchronizer<MyExactSyncPolicy>(MyExactSyncPolicy(queueSize), imageLeftSub_, imageRightSub_, cameraInfoLeftSub_, cameraInfoRightSub_);
exactSync_->registerCallback(boost::bind(&StereoSync::callback, this, _1, _2, _3, _4));
}
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 rgb_it(left_nh);
image_transport::ImageTransport depth_it(right_nh);
image_transport::TransportHints hintsRgb("raw", ros::TransportHints(), left_pnh);
image_transport::TransportHints hintsDepth("raw", ros::TransportHints(), right_pnh);
imageLeftSub_.subscribe(rgb_it, left_nh.resolveName("image_rect"), 1, hintsRgb);
imageRightSub_.subscribe(depth_it, right_nh.resolveName("image_rect"), 1, hintsDepth);
cameraInfoLeftSub_.subscribe(left_nh, "camera_info", 1);
cameraInfoRightSub_.subscribe(right_nh, "camera_info", 1);
std::string subscribedTopicsMsg = uFormat("\n%s subscribed to (%s sync):\n %s,\n %s,\n %s,\n %s",
getName().c_str(),
approxSync?"approx":"exact",
imageLeftSub_.getTopic().c_str(),
imageRightSub_.getTopic().c_str(),
cameraInfoLeftSub_.getTopic().c_str(),
cameraInfoRightSub_.getTopic().c_str());
warningThread_ = new boost::thread(boost::bind(&StereoSync::warningLoop, this, subscribedTopicsMsg, approxSync));
NODELET_INFO("%s", subscribedTopicsMsg.c_str());
}
void 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());
}
}
}
void callback(
const sensor_msgs::ImageConstPtr& imageLeft,
const sensor_msgs::ImageConstPtr& imageRight,
const sensor_msgs::CameraInfoConstPtr& cameraInfoLeft,
const sensor_msgs::CameraInfoConstPtr& cameraInfoRight)
{
callbackCalled_ = true;
if(rgbdImagePub_.getNumSubscribers() || rgbdImageCompressedPub_.getNumSubscribers())
{
rtabmap_ros::RGBDImage msg;
msg.header.frame_id = cameraInfoLeft->header.frame_id;
msg.header.stamp = imageLeft->header.stamp>imageRight->header.stamp?imageLeft->header.stamp:imageRight->header.stamp;
msg.rgbCameraInfo = *cameraInfoLeft;
msg.depthCameraInfo = *cameraInfoRight;
if(rgbdImageCompressedPub_.getNumSubscribers())
{
rtabmap_ros::RGBDImage msgCompressed = msg;
cv_bridge::CvImageConstPtr imagePtr = cv_bridge::toCvShare(imageLeft);
imagePtr->toCompressedImageMsg(msgCompressed.rgbCompressed, cv_bridge::JPG);
cv_bridge::CvImageConstPtr imageDepthPtr = cv_bridge::toCvShare(imageRight);
imageDepthPtr->toCompressedImageMsg(msgCompressed.depthCompressed, cv_bridge::JPG);
rgbdImageCompressedPub_.publish(msgCompressed);
}
if(rgbdImagePub_.getNumSubscribers())
{
msg.rgb = *imageLeft;
msg.depth = *imageRight;
rgbdImagePub_.publish(msg);
}
}
}
private:
boost::thread * warningThread_;
bool callbackCalled_;
ros::Publisher rgbdImagePub_;
ros::Publisher rgbdImageCompressedPub_;
image_transport::SubscriberFilter imageLeftSub_;
image_transport::SubscriberFilter imageRightSub_;
message_filters::Subscriber<sensor_msgs::CameraInfo> cameraInfoLeftSub_;
message_filters::Subscriber<sensor_msgs::CameraInfo> cameraInfoRightSub_;
typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::CameraInfo> MyApproxSyncPolicy;
message_filters::Synchronizer<MyApproxSyncPolicy> * approxSync_;
typedef message_filters::sync_policies::ExactTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::CameraInfo> MyExactSyncPolicy;
message_filters::Synchronizer<MyExactSyncPolicy> * exactSync_;
};
PLUGINLIB_EXPORT_CLASS(rtabmap_ros::StereoSync, nodelet::Nodelet);
}