39 #include <sensor_msgs/Image.h> 89 bool approxSync =
false;
90 bool subscribeRGBD =
false;
91 pnh.
param(
"approx_sync", approxSync, approxSync);
92 pnh.
param(
"queue_size", queueSize_, queueSize_);
93 pnh.
param(
"subscribe_rgbd", subscribeRGBD, subscribeRGBD);
94 pnh.
param(
"keep_color", keepColor_, keepColor_);
96 NODELET_INFO(
"StereoOdometry: approx_sync = %s", approxSync?
"true":
"false");
97 NODELET_INFO(
"StereoOdometry: queue_size = %d", queueSize_);
98 NODELET_INFO(
"StereoOdometry: subscribe_rgbd = %s", subscribeRGBD?
"true":
"false");
99 NODELET_INFO(
"StereoOdometry: keep_color = %s", keepColor_?
"true":
"false");
101 std::string subscribedTopicsMsg;
104 rgbdSub_ = nh.
subscribe(
"rgbd_image", 1, &StereoOdometry::callbackRGBD,
this);
106 subscribedTopicsMsg =
107 uFormat(
"\n%s subscribed to:\n %s",
109 rgbdSub_.getTopic().c_str());
122 imageRectLeft_.subscribe(left_it, left_nh.
resolveName(
"image_rect"), 1, hintsLeft);
123 imageRectRight_.subscribe(right_it, right_nh.
resolveName(
"image_rect"), 1, hintsRight);
124 cameraInfoLeft_.subscribe(left_nh,
"camera_info", 1);
125 cameraInfoRight_.subscribe(right_nh,
"camera_info", 1);
139 subscribedTopicsMsg =
uFormat(
"\n%s subscribed to (%s sync):\n %s \\\n %s \\\n %s \\\n %s",
141 approxSync?
"approx":
"exact",
142 imageRectLeft_.getTopic().c_str(),
143 imageRectRight_.getTopic().c_str(),
144 cameraInfoLeft_.getTopic().c_str(),
145 cameraInfoRight_.getTopic().c_str());
148 this->startWarningThread(subscribedTopicsMsg, approxSync);
154 ParametersMap::iterator iter = parameters.find(Parameters::kRegStrategy());
155 if(iter != parameters.end() && iter->second.compare(
"0") != 0)
157 ROS_WARN(
"Stereo odometry works only with \"Reg/Strategy\"=0. Ignoring value %s.", iter->second.c_str());
163 const sensor_msgs::ImageConstPtr& imageRectLeft,
164 const sensor_msgs::ImageConstPtr& imageRectRight,
165 const sensor_msgs::CameraInfoConstPtr& cameraInfoLeft,
166 const sensor_msgs::CameraInfoConstPtr& cameraInfoRight)
169 if(!this->isPaused())
184 NODELET_ERROR(
"Input type must be image=mono8,mono16,rgb8,bgr8,rgba8,bgra8 (mono8 recommended), received types are %s (left) and %s (right)",
185 imageRectLeft->encoding.c_str(), imageRectRight->encoding.c_str());
189 ros::Time stamp = imageRectLeft->header.stamp>imageRectRight->header.stamp?imageRectLeft->header.stamp:imageRectRight->header.stamp;
192 if(localTransform.
isNull())
198 if(imageRectLeft->data.size() && imageRectRight->data.size())
200 bool alreadyRectified =
true;
201 Parameters::parse(parameters(), Parameters::kRtabmapImagesAlreadyRectified(), alreadyRectified);
203 if(!alreadyRectified)
206 cameraInfoRight->header.frame_id,
207 cameraInfoLeft->header.frame_id,
208 cameraInfoLeft->header.stamp);
209 if(stereoTransform.
isNull())
211 NODELET_ERROR(
"Parameter %s is false but we cannot get TF between the two cameras!", Parameters::kRtabmapImagesAlreadyRectified().c_str());
218 if(stereoModel.
baseline() == 0 && alreadyRectified)
221 cameraInfoLeft->header.frame_id,
222 cameraInfoRight->header.frame_id,
223 cameraInfoLeft->header.stamp);
225 if(!stereoTransform.
isNull() && stereoTransform.
x()>0)
227 static bool warned =
false;
230 ROS_WARN(
"Right camera info doesn't have Tx set but we are assuming that stereo images are already rectified (see %s parameter). While not " 231 "recommended, we used TF to get the baseline (%s->%s = %fm) for convenience (e.g., D400 ir stereo issue). It is preferred to feed " 232 "a valid right camera info if stereo images are already rectified. This message is only printed once...",
233 rtabmap::Parameters::kRtabmapImagesAlreadyRectified().c_str(),
234 cameraInfoRight->header.frame_id.c_str(), cameraInfoLeft->header.frame_id.c_str(), stereoTransform.
x());
248 if(alreadyRectified && stereoModel.
baseline() <= 0)
250 NODELET_ERROR(
"The stereo baseline (%f) should be positive (baseline=-Tx/fx). We assume a horizontal left/right stereo " 251 "setup where the Tx (or P(0,3)) is negative in the right camera info msg.", stereoModel.
baseline());
257 static bool shown =
false;
260 NODELET_WARN(
"Detected baseline (%f m) is quite large! Is your " 261 "right camera_info P(0,3) correctly set? Note that " 262 "baseline=-P(0,3)/P(0,0). This warning is printed only once.",
278 ptrImageRight->image,
283 this->processData(data, stamp, imageRectLeft->header.frame_id);
293 const rtabmap_ros::RGBDImageConstPtr& image)
296 if(!this->isPaused())
314 NODELET_ERROR(
"Input type must be image=mono8,mono16,rgb8,bgr8,rgba8,bgra8 (mono8 recommended), received types are %s (left) and %s (right)",
315 imageRectLeft->encoding.c_str(), imageRectRight->encoding.c_str());
319 ros::Time stamp = imageRectLeft->header.stamp>imageRectRight->header.stamp?imageRectLeft->header.stamp:imageRectRight->header.stamp;
322 if(localTransform.
isNull())
330 if(!imageRectLeft->image.empty() && !imageRectRight->image.empty())
332 bool alreadyRectified =
true;
333 Parameters::parse(parameters(), Parameters::kRtabmapImagesAlreadyRectified(), alreadyRectified);
335 if(!alreadyRectified)
338 image->depth_camera_info.header.frame_id,
339 image->rgb_camera_info.header.frame_id,
340 image->rgb_camera_info.header.stamp);
341 if(stereoTransform.
isNull())
343 NODELET_ERROR(
"Parameter %s is false but we cannot get TF between the two cameras!", Parameters::kRtabmapImagesAlreadyRectified().c_str());
350 if(stereoModel.
baseline() == 0 && alreadyRectified)
353 image->rgb_camera_info.header.frame_id,
354 image->depth_camera_info.header.frame_id,
355 image->rgb_camera_info.header.stamp);
357 if(!stereoTransform.
isNull() && stereoTransform.
x()>0)
359 static bool warned =
false;
362 ROS_WARN(
"Right camera info doesn't have Tx set but we are assuming that stereo images are already rectified (see %s parameter). While not " 363 "recommended, we used TF to get the baseline (%s->%s = %fm) for convenience (e.g., D400 ir stereo issue). It is preferred to feed " 364 "a valid right camera info if stereo images are already rectified. This message is only printed once...",
365 rtabmap::Parameters::kRtabmapImagesAlreadyRectified().c_str(),
366 image->depth_camera_info.header.frame_id.c_str(), image->rgb_camera_info.header.frame_id.c_str(), stereoTransform.
x());
380 if(alreadyRectified && stereoModel.
baseline() <= 0)
382 NODELET_ERROR(
"The stereo baseline (%f) should be positive (baseline=-Tx/fx). We assume a horizontal left/right stereo " 383 "setup where the Tx (or P(0,3)) is negative in the right camera info msg.", stereoModel.
baseline());
389 static bool shown =
false;
392 NODELET_WARN(
"Detected baseline (%f m) is quite large! Is your " 393 "right camera_info P(0,3) correctly set? Note that " 394 "baseline=-P(0,3)/P(0,0). This warning is printed only once.",
420 ptrImageRight->image,
425 this->processData(data, stamp, image->header.frame_id);
static bool parse(const ParametersMap ¶meters, const std::string &key, bool &value)
std::string uFormat(const char *fmt,...)
#define NODELET_ERROR(...)
const cv::Size & imageSize() const
#define NODELET_WARN(...)
virtual void flushCallbacks()
image_transport::SubscriberFilter imageRectLeft_
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
std::pair< std::string, std::string > ParametersPair
std::string resolveName(const std::string &name, bool remap=true) const
void callback(const sensor_msgs::ImageConstPtr &imageRectLeft, const sensor_msgs::ImageConstPtr &imageRectRight, const sensor_msgs::CameraInfoConstPtr &cameraInfoLeft, const sensor_msgs::CameraInfoConstPtr &cameraInfoRight)
std::string getName(void *handle)
const std::string TYPE_8UC1
virtual ~StereoOdometry()
rtabmap::Transform getTransform(const std::string &fromFrameId, const std::string &toFrameId, const ros::Time &stamp, tf::TransformListener &listener, double waitForTransform)
message_filters::Subscriber< sensor_msgs::CameraInfo > cameraInfoLeft_
PLUGINLIB_EXPORT_CLASS(rtabmap_ros::StereoOdometry, nodelet::Nodelet)
const CameraModel & left() const
image_transport::SubscriberFilter imageRectRight_
Connection registerCallback(C &callback)
message_filters::sync_policies::ExactTime< sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::CameraInfo > MyExactSyncPolicy
CvImagePtr cvtColor(const CvImageConstPtr &source, const std::string &encoding)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
CvImagePtr toCvCopy(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
QMap< QString, QVariant > ParametersMap
message_filters::Synchronizer< MyExactSyncPolicy > * exactSync_
message_filters::Subscriber< sensor_msgs::CameraInfo > cameraInfoRight_
virtual void updateParameters(ParametersMap ¶meters)
void callback(rtabmap_ros::CameraConfig &config, uint32_t level)
#define NODELET_INFO(...)
void toCvShare(const rtabmap_ros::RGBDImageConstPtr &image, cv_bridge::CvImageConstPtr &rgb, cv_bridge::CvImageConstPtr &depth)
rtabmap::StereoCameraModel stereoCameraModelFromROS(const sensor_msgs::CameraInfo &leftCamInfo, const sensor_msgs::CameraInfo &rightCamInfo, const rtabmap::Transform &localTransform=rtabmap::Transform::getIdentity(), const rtabmap::Transform &stereoTransform=rtabmap::Transform())
double timestampFromROS(const ros::Time &stamp)
void callbackRGBD(const rtabmap_ros::RGBDImageConstPtr &image)
virtual void onOdomInit()
const Transform & localTransform() const
message_filters::sync_policies::ApproximateTime< sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::CameraInfo > MyApproxSyncPolicy
message_filters::Synchronizer< MyApproxSyncPolicy > * approxSync_
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)