00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <ros/ros.h>
00042 #include <opencv2/core/core.hpp>
00043 #include <ros/duration.h>
00044 #include <ros/time.h>
00045
00046 #include <image_transport/image_transport.h>
00047 #include <image_transport/subscriber_filter.h>
00048 #include <message_filters/time_synchronizer.h>
00049 #include <cv_bridge/cv_bridge.h>
00050 #include <sensor_msgs/image_encodings.h>
00051 #include <geometry_msgs/Pose.h>
00052 #include <dynamic_reconfigure/server.h>
00053
00054 #include <blort_ros/TrackerConfig.h>
00055 #include <blort_ros/TrackerCommand.h>
00056 #include <blort_ros/RecoveryCall.h>
00057 #include <blort_ros/EstimatePose.h>
00058 #include <blort_ros/SetCameraInfo.h>
00059 #include <blort/GLWindow/glxhidingwindow.h>
00060 #include <blort/blort/pal_util.h>
00061 #include "../gltracker.h"
00062 #include <boost/noncopyable.hpp>
00063
00064 class TrackerNode : boost::noncopyable
00065 {
00066 private:
00067 class Mode;
00068 class TrackingMode;
00069 class SingleShotMode;
00070
00071 private:
00072 ros::NodeHandle nh_;
00073 image_transport::ImageTransport it_;
00074 image_transport::Publisher image_pub;
00075 image_transport::Publisher image_debug_pub;
00076 ros::Publisher detection_result;
00077 ros::Publisher confidences_pub;
00078
00079
00080
00081 const std::string root_;
00082 ros::ServiceServer control_service;
00083 std::auto_ptr<dynamic_reconfigure::Server<blort_ros::TrackerConfig> > server_;
00084 dynamic_reconfigure::Server<blort_ros::TrackerConfig>::CallbackType f_;
00085 ros::ServiceClient recovery_client;
00086 blort_ros::GLTracker* tracker;
00087 std::string launch_mode;
00088
00089 Mode* mode;
00090 public:
00091
00092 TrackerNode(std::string root = ".")
00093 : nh_("blort_tracker"), it_(nh_), root_(root), tracker(0)
00094 {
00095 nh_.param<std::string>("launch_mode", launch_mode, "tracking");
00096 detection_result = nh_.advertise<geometry_msgs::Pose>("detection_result", 100);
00097 confidences_pub = nh_.advertise<blort_ros::TrackerConfidences>("confidences", 100);
00098 image_pub = it_.advertise("image_result", 1);
00099
00100 if(launch_mode == "tracking")
00101 {
00102 mode = new TrackingMode(this);
00103 }else if(launch_mode == "singleshot")
00104 {
00105 mode = new SingleShotMode(this);
00106 } else {
00107 ROS_FATAL("Invalid launch_mode parameter passed to blort_tracker.");
00108 }
00109 }
00110
00111 ~TrackerNode()
00112 {
00113 if(tracker != 0)
00114 delete(tracker);
00115 delete mode;
00116 }
00117
00118 void imageCb(const sensor_msgs::ImageConstPtr& detectorImgMsg, const sensor_msgs::ImageConstPtr& trackerImgMsg )
00119 {
00120 if(tracker != 0)
00121 {
00122 cv_bridge::CvImagePtr cv_detector_ptr, cv_tracker_ptr;
00123 try
00124 {
00125 cv_detector_ptr = cv_bridge::toCvCopy(detectorImgMsg, sensor_msgs::image_encodings::BGR8);
00126 cv_tracker_ptr = cv_bridge::toCvCopy(trackerImgMsg, sensor_msgs::image_encodings::BGR8);
00127 }
00128 catch (cv_bridge::Exception& e)
00129 {
00130 ROS_ERROR("cv_bridge exception: %s", e.what());
00131 return;
00132 }
00133
00134 if(tracker->getMode() == blort_ros::TRACKER_RECOVERY_MODE)
00135 {
00136 blort_ros::RecoveryCall srv = mode->recovery(detectorImgMsg);
00137
00138 ROS_INFO("tracker_node in TRACKER_RECOVERY_MODE: calling detector_node recovery service ...");
00139 if(recovery_client.call(srv))
00140 {
00141
00142 ROS_INFO("reseting tracker with pose from detector\n");
00143 tracker->resetWithPose(srv.response.Pose);
00144 ROS_INFO("AFTER reseting tracker with pose from detector\n");
00145 }
00146 else
00147 {
00148 ROS_WARN("Detector not confident enough.\n");
00149 }
00150 }
00151 else
00152 {
00153 ROS_INFO("\n----------------------------------------------\n");
00154 ROS_INFO("TrackerNode::imageCb: calling tracker->process");
00155 tracker->process(cv_tracker_ptr->image);
00156
00157 confidences_pub.publish(tracker->getConfidences());
00158 if(tracker->getConfidence() == blort_ros::TRACKER_CONF_GOOD)
00159 {
00160 geometry_msgs::Pose target_pose = pal_blort::blortPosesToRosPose(tracker->getCameraReferencePose(),
00161 tracker->getDetections()[0]);
00162
00163 detection_result.publish(target_pose);
00164 }
00165
00166 cv_bridge::CvImage out_msg;
00167 out_msg.header = trackerImgMsg->header;
00168 out_msg.header.stamp = ros::Time::now();
00169
00170 out_msg.encoding = sensor_msgs::image_encodings::BGR8;
00171 out_msg.image = tracker->getImage();
00172 image_pub.publish(out_msg.toImageMsg());
00173 }
00174 }
00175 }
00176
00177 bool trackerControlServiceCb(blort_ros::TrackerCommand::Request &req,
00178 blort_ros::TrackerCommand::Response &)
00179 {
00180 if(tracker != 0)
00181 {
00182 tracker->trackerControl(req.code, req.param);
00183 return true;
00184 } else {
00185 ROS_WARN("Please publish camera_info for the tracker initialization.");
00186 return false;
00187 }
00188 }
00189
00190
00191
00192 private:
00193 class Mode
00194 {
00195 public:
00196 virtual void reconf_callback(blort_ros::TrackerConfig &config, uint32_t level) = 0;
00197 virtual blort_ros::RecoveryCall recovery(const sensor_msgs::ImageConstPtr& msg) = 0;
00198 };
00199
00200 class TrackingMode : public Mode
00201 {
00202 private:
00203 ros::Subscriber cam_info_sub;
00204 boost::shared_ptr<image_transport::SubscriberFilter> detector_image_sub, tracker_image_sub;
00205 boost::shared_ptr< message_filters::TimeSynchronizer<sensor_msgs::Image, sensor_msgs::Image > > imageSynchronizer;
00206 TrackerNode* parent_;
00207 public:
00208 TrackingMode(TrackerNode* parent) : parent_(parent)
00209 {
00210 ROS_INFO("Blort tracker launched in tracking mode.");
00211 cam_info_sub = parent_->nh_.subscribe("/detector_camera_info", 10, &TrackerNode::TrackingMode::cam_info_callback, this);
00212 }
00213
00214 virtual void reconf_callback(blort_ros::TrackerConfig &config, uint32_t level)
00215 {
00216 if(parent_->tracker != 0)
00217 {
00218 parent_->tracker->reconfigure(config);
00219 } else {
00220 ROS_WARN("Please publish camera_info for the tracker initialization.");
00221 }
00222 }
00223
00224 virtual blort_ros::RecoveryCall recovery(const sensor_msgs::ImageConstPtr& msg)
00225 {
00226 blort_ros::RecoveryCall srv;
00227 srv.request.Image = *msg;
00228 return srv;
00229 }
00230
00231
00232 void cam_info_callback(const sensor_msgs::CameraInfo &msg)
00233 {
00234 if(parent_->tracker == 0)
00235 {
00236 ROS_INFO("Camera parameters received, ready to run.");
00237
00238 cam_info_sub.shutdown();
00239 parent_->tracker = new blort_ros::GLTracker(msg, parent_->root_, true);
00240 parent_->tracker->setVisualizeObjPose(true);
00241
00242 image_transport::TransportHints transportHint("raw");
00243
00244 detector_image_sub.reset( new image_transport::SubscriberFilter(parent_->it_, "/detector_image", 1, transportHint) );
00245 tracker_image_sub.reset( new image_transport::SubscriberFilter(parent_->it_, "/tracker_image", 1, transportHint) );
00246
00247 imageSynchronizer.reset( new message_filters::TimeSynchronizer<sensor_msgs::Image,
00248 sensor_msgs::Image>(*detector_image_sub, *tracker_image_sub, 1) );
00249
00250 imageSynchronizer->registerCallback(boost::bind(&TrackerNode::imageCb, parent_, _1, _2));
00251
00252 parent_->control_service = parent_->nh_.advertiseService("tracker_control", &TrackerNode::trackerControlServiceCb, parent_);
00253 parent_->server_ = std::auto_ptr<dynamic_reconfigure::Server<blort_ros::TrackerConfig> >
00254 (new dynamic_reconfigure::Server<blort_ros::TrackerConfig>());
00255 parent_->f_ = boost::bind(&TrackerNode::TrackingMode::reconf_callback, this, _1, _2);
00256 parent_->server_->setCallback(parent_->f_);
00257 parent_->recovery_client = parent_->nh_.serviceClient<blort_ros::RecoveryCall>("/blort_detector/pose_service");
00258 }
00259 }
00260 };
00261
00262 class SingleShotMode : public Mode
00263 {
00264 private:
00265 ros::ServiceServer singleshot_service;
00266 double time_to_run_singleshot;
00267 ros::ServiceClient detector_set_caminfo_service;
00268 bool inServiceCall;
00269 TrackerNode* parent_;
00270 std::list<geometry_msgs::Pose> results;
00271
00272 ros::Subscriber cam_info_sub;
00273 image_transport::Subscriber image_sub;
00274 sensor_msgs::ImageConstPtr lastImage;
00275 sensor_msgs::CameraInfoConstPtr lastCameraInfo;
00276 public:
00277 SingleShotMode(TrackerNode* parent) : parent_(parent)
00278 {
00279 ROS_INFO("Blort tracker launched in singleshot mode.");
00280 detector_set_caminfo_service = parent_->nh_.serviceClient<blort_ros::SetCameraInfo>("/blort_detector/set_camera_info");
00281 singleshot_service = parent_->nh_.advertiseService("singleshot_service", &TrackerNode::SingleShotMode::singleShotService, this);
00282 image_sub = parent_->it_.subscribe("/blort_image_rect_masked", 10, &TrackerNode::SingleShotMode::imageCallback, this);
00283 cam_info_sub = parent_->nh_.subscribe("/detector_camera_info", 10, &TrackerNode::SingleShotMode::cameraCallback, this);
00284
00285 parent_->control_service = parent_->nh_.advertiseService("tracker_control", &TrackerNode::trackerControlServiceCb, parent_);
00286 parent_->server_ = std::auto_ptr<dynamic_reconfigure::Server<blort_ros::TrackerConfig> >
00287 (new dynamic_reconfigure::Server<blort_ros::TrackerConfig>());
00288 parent_->f_ = boost::bind(&SingleShotMode::reconf_callback, this, _1, _2);
00289 parent_->server_->setCallback(parent_->f_);
00290
00291 time_to_run_singleshot = 10.;
00292 inServiceCall = false;
00293 }
00294
00295 void imageCallback(const sensor_msgs::ImageConstPtr &image)
00296 {
00297 if(!inServiceCall)
00298 {
00299
00300
00301 lastImage = image;
00302 }
00303 }
00304
00305 void cameraCallback(const sensor_msgs::CameraInfoConstPtr &camera_info)
00306 {
00307 if(!inServiceCall)
00308 {
00309
00310
00311 lastCameraInfo = camera_info;
00312 }
00313 }
00314
00315 virtual void reconf_callback(blort_ros::TrackerConfig &config, uint32_t level)
00316 {
00317 time_to_run_singleshot = config.time_to_run_singleshot;
00318 }
00319
00320 virtual blort_ros::RecoveryCall recovery(const sensor_msgs::ImageConstPtr& msg)
00321 {
00322 blort_ros::RecoveryCall srv;
00323 if(!inServiceCall)
00324 {
00325 srv.request.Image = *msg;
00326
00327
00328 inServiceCall = true;
00329 }
00330 return srv;
00331 }
00332
00333 bool singleShotService(blort_ros::EstimatePose::Request &req,
00334 blort_ros::EstimatePose::Response &resp)
00335 {
00336 if(lastImage.use_count() < 1 && lastCameraInfo.use_count() < 1)
00337 {
00338 ROS_ERROR("Service called but there was no data on the input topics!");
00339 return false;
00340 } else {
00341
00342 ROS_INFO("Singleshot service has been called with a timeout of %f seconds.", time_to_run_singleshot);
00343 results.clear();
00344
00345 if(parent_->tracker == 0)
00346 {
00347 parent_->tracker = new blort_ros::GLTracker(*lastCameraInfo, parent_->root_, true);
00348 parent_->recovery_client = parent_->nh_.serviceClient<blort_ros::RecoveryCall>("/blort_detector/poseService");
00349 } else {
00350 parent_->tracker->reset();
00351 }
00352 parent_->tracker->setPublisMode(blort_ros::TRACKER_PUBLISH_GOOD);
00353 parent_->tracker->setVisualizeObjPose(true);
00354 blort_ros::SetCameraInfo camera_info;
00355 camera_info.request.CameraInfo = *lastCameraInfo;
00356 if(!detector_set_caminfo_service.call(camera_info))
00357 ROS_ERROR("blort_tracker failed to call blort_detector/set_camera_info service");
00358
00359 double start_secs = ros::Time::now().toSec();
00360 while(ros::Time::now().toSec()-start_secs < time_to_run_singleshot)
00361 {
00362 ROS_INFO("Remaining time %f", time_to_run_singleshot+start_secs-ros::Time::now().toSec());
00363 parent_->imageCb(lastImage, lastImage);
00364 if(parent_->tracker->getConfidence() == blort_ros::TRACKER_CONF_GOOD)
00365 {
00366
00367
00368 results.push_back(parent_->tracker->getDetections()[0]);
00369 } else if(parent_->tracker->getConfidence() == blort_ros::TRACKER_CONF_LOST)
00370 {
00371 results.clear();
00372 }
00373 }
00374
00375 inServiceCall = false;
00376 if(!results.empty())
00377 {
00378
00379
00380 resp.Pose = pal_blort::blortPosesToRosPose(parent_->tracker->getCameraReferencePose(),
00381 results.back());
00382
00383
00384 ROS_INFO_STREAM("PUBLISHED POSE: \n" << resp.Pose.position << "\n" <<
00385 pal_blort::quaternionTo3x3cvMat(resp.Pose.orientation) << "\n");
00386 return true;
00387 } else {
00388
00389 return false;
00390 }
00391 }
00392 }
00393 };
00394 };
00395
00396 int main(int argc, char *argv[] )
00397 {
00398 if(argc < 2)
00399 {
00400 ROS_ERROR("The first command line argument should be the package root!");
00401 return -1;
00402 }
00403 ros::init(argc, argv, "blort_tracker");
00404
00405
00406 pal_blort::GLXHidingWindow window(656, 492, "Tracker");
00407
00408 TrackerNode node(argv[1]);
00409 ros::spin();
00410 return 0;
00411 }
00412