rgbd
client_ros_base.cpp
Go to the documentation of this file.
1 #include "rgbd/client_ros.h"
2 #include "rgbd/image.h"
3 
4 // ROS message serialization
5 #include <cv_bridge/cv_bridge.h>
6 #include <message_filters/synchronizer.h>
7 #include <message_filters/subscriber.h>
8 #include <message_filters/sync_policies/approximate_time.h>
9 #include <sensor_msgs/Image.h>
10 #include <sensor_msgs/image_encodings.h>
11 #include <image_geometry/pinhole_camera_model.h>
12 
13 namespace rgbd {
14 
15 // ----------------------------------------------------------------------------------------
16 
17 ClientROSBase::ClientROSBase(ros::NodeHandle nh) : nh_(nh), sync_(nullptr), sub_rgb_sync_(nullptr), sub_depth_sync_(nullptr), image_ptr_(nullptr)
18 {
19 }
20 
21 // ----------------------------------------------------------------------------------------
22 
24 {
25  deinitialize();
26 }
27 
28 // ----------------------------------------------------------------------------------------
29 
30 bool ClientROSBase::initialize(const std::string& rgb_image_topic, const std::string& depth_image_topic, const std::string& cam_info_topic)
31 {
32  sub_cam_info_ = nh_.subscribe(cam_info_topic, 1, &ClientROSBase::camInfoCallback, this);
33 
34  sub_rgb_sync_ = std::unique_ptr<message_filters::Subscriber<sensor_msgs::Image> >(new message_filters::Subscriber<sensor_msgs::Image>(nh_, rgb_image_topic, 1));
35  sub_depth_sync_ = std::unique_ptr<message_filters::Subscriber<sensor_msgs::Image> >(new message_filters::Subscriber<sensor_msgs::Image>(nh_, depth_image_topic, 1));
36 
37  sync_ = std::unique_ptr<message_filters::Synchronizer<RGBDApproxPolicy> >(new message_filters::Synchronizer<RGBDApproxPolicy>(RGBDApproxPolicy(10), *sub_rgb_sync_, *sub_depth_sync_));
38 
39  return true;
40 }
41 
42 // ----------------------------------------------------------------------------------------
43 
45 {
46  nh_.shutdown();
47  sync_.reset();
50  cam_model_ = image_geometry::PinholeCameraModel();
51  return true;
52 }
53 
54 // ----------------------------------------------------------------------------------------
55 
56 void ClientROSBase::camInfoCallback(const sensor_msgs::CameraInfoConstPtr& cam_info_msg)
57 {
58  if (!cam_model_.initialized())
59  {
60  cam_model_.fromCameraInfo(cam_info_msg);
61  sub_cam_info_.shutdown();
62  }
63  else
64  {
65  ROS_ERROR_NAMED("ClientROS", "CameraInfo should unsubsribe after inititializing the camera model");
66  }
67 }
68 
69 // ----------------------------------------------------------------------------------------
70 
72 {
73  if (!cam_model_.initialized())
74  {
75  ROS_ERROR_DELAYED_THROTTLE_NAMED(1, "ClientROS", "ClientROSBase: cam_model not yet initialized");
76  return false;
77  }
78  cv_bridge::CvImagePtr rgb_img_ptr, depth_img_ptr;
79 
80  // Convert RGB image
81  try
82  {
83  rgb_img_ptr = cv_bridge::toCvCopy(rgb_image_msg, sensor_msgs::image_encodings::BGR8);
84  }
85  catch (cv_bridge::Exception& e)
86  {
87  ROS_ERROR_NAMED("ClientROS", "ClientROSBase: Could not deserialize rgb image: %s", e.what());
88  return false;
89  }
90 
91  // Convert depth image
92  try
93  {
94  // cv_bridge doesn't support changing the encoding of depth images, so just creating ImagePtr
95  depth_img_ptr = cv_bridge::toCvCopy(depth_image_msg, depth_image_msg->encoding);
96 
97  if (depth_image_msg->encoding == sensor_msgs::image_encodings::TYPE_16UC1)
98  {
99  // depths are 16-bit unsigned ints, in mm. Convert to 32-bit float (meters)
100  cv::Mat depth_image(depth_img_ptr->image.rows, depth_img_ptr->image.cols, CV_32FC1);
101  for(int x = 0; x < depth_image.cols; ++x)
102  {
103  for(int y = 0; y < depth_image.rows; ++y)
104  {
105  depth_image.at<float>(y, x) = static_cast<float>(depth_img_ptr->image.at<unsigned short>(y, x)) / 1000; // (mm to m)
106  }
107  }
108 
109  depth_img_ptr->image = depth_image;
110  }
111 
112  }
113  catch (cv_bridge::Exception& e)
114  {
115  ROS_ERROR_NAMED("ClientROS", "ClientROSBase: Could not deserialize depth image: %s", e.what());
116  return false;
117  }
118 
119  if (!image_ptr_)
120  // in this case, the pointer will always be wrapped in a shared ptr, so no mem leaks (see nextImage() )
121  image_ptr_ = new Image();
122 
123  image_ptr_->setRGBImage(rgb_img_ptr->image);
124  image_ptr_->setDepthImage(depth_img_ptr->image);
126  image_ptr_->setFrameId(rgb_image_msg->header.frame_id);
127  image_ptr_->setTimestamp(rgb_image_msg->header.stamp.toSec());
128  new_image_ = true;
129 
130  return true;
131 }
132 
133 }
rgbd::ClientROSBase::cam_model_
image_geometry::PinholeCameraModel cam_model_
Definition: client_ros_base.h:79
rgbd::ClientROSBase::sub_rgb_sync_
std::unique_ptr< message_filters::Subscriber< sensor_msgs::Image > > sub_rgb_sync_
Definition: client_ros_base.h:76
std::string
rgbd::ClientROSBase::sync_
std::unique_ptr< message_filters::Synchronizer< RGBDApproxPolicy > > sync_
Definition: client_ros_base.h:75
rgbd::ClientROSBase::sub_cam_info_
ros::Subscriber sub_cam_info_
Definition: client_ros_base.h:78
rgbd::ClientROSBase::~ClientROSBase
virtual ~ClientROSBase()
Destructor.
Definition: client_ros_base.cpp:23
rgbd::Image::setDepthImage
void setDepthImage(const cv::Mat &depth_image)
Set the depth image.
Definition: image.h:105
rgbd::ClientROSBase::camInfoCallback
void camInfoCallback(const sensor_msgs::CameraInfoConstPtr &cam_info_msg)
Callback for CameraInfo, will unsubscribe after succesfully receiving first message.
Definition: client_ros_base.cpp:56
std::unique_ptr::reset
T reset(T... args)
rgbd::ClientROSBase::deinitialize
bool deinitialize()
Clears the subscribers. initialized will now return false.
Definition: client_ros_base.cpp:44
rgbd::Image::setFrameId
void setFrameId(const std::string &frame_id)
Set the frame_id.
Definition: image.h:117
rgbd::Image::setRGBImage
void setRGBImage(const cv::Mat &rgb_image)
Set the BGR color image.
Definition: image.h:111
rgbd::ClientROSBase::nh_
ros::NodeHandle nh_
Definition: client_ros_base.h:73
rgbd::Image
Definition: image.h:43
rgbd::Image::setTimestamp
void setTimestamp(double timestamp)
Set the timestamp.
Definition: image.h:123
rgbd::ClientROSBase::initialize
bool initialize(const std::string &rgb_image_topic, const std::string &depth_image_topic, const std::string &cam_info_topic)
Initialize the subscriber.
Definition: client_ros_base.cpp:30
rgbd::Image::setCameraModel
void setCameraModel(const image_geometry::PinholeCameraModel &cam_model)
Set the camera model. The frame_id and timestamp in the camera info inside the camera model will be e...
Definition: image.cpp:45
rgbd
Definition: client.h:24
rgbd::ImageConstPtr
std::shared_ptr< const Image > ImageConstPtr
Definition: types.h:10
rgbd::ClientROSBase::ClientROSBase
ClientROSBase(ros::NodeHandle nh)
Constructor.
Definition: client_ros_base.cpp:17
image.h
rgbd::ClientROSBase::imageCallback
bool imageCallback(const sensor_msgs::ImageConstPtr &rgb_image_msg, const sensor_msgs::ImageConstPtr &depth_image_msg)
Callback for synched rgb and depth image.
Definition: client_ros_base.cpp:71
rgbd::ClientROSBase::sub_depth_sync_
std::unique_ptr< message_filters::Subscriber< sensor_msgs::Image > > sub_depth_sync_
Definition: client_ros_base.h:77
rgbd::RGBDApproxPolicy
message_filters::sync_policies::ApproximateTime< sensor_msgs::Image, sensor_msgs::Image > RGBDApproxPolicy
Definition: client_ros_base.h:27
client_ros.h
rgbd::ClientROSBase::new_image_
bool new_image_
new_image_ Track if image is updated in a callback.
Definition: client_ros_base.h:84
std::unique_ptr
rgbd::ClientROSBase::image_ptr_
Image * image_ptr_
image_ptr_ Pointer to image. Image could be provided by reference or the pointer will be wrapped in a...
Definition: client_ros_base.h:89