tracker-viewer.cpp
Go to the documentation of this file.
00001 #include <cstdlib>
00002 #include <fstream>
00003 #include <sstream>
00004 
00005 #include <boost/bind.hpp>
00006 #include <boost/filesystem.hpp>
00007 #include <boost/filesystem/fstream.hpp>
00008 #include <boost/filesystem/path.hpp>
00009 #include <boost/format.hpp>
00010 #include <boost/optional.hpp>
00011 
00012 #include <ros/ros.h>
00013 #include <ros/param.h>
00014 #include <image_transport/image_transport.h>
00015 
00016 #include <visp/vpDisplayX.h>
00017 
00018 #include "conversion.hh"
00019 #include "callbacks.hh"
00020 #include "file.hh"
00021 #include "names.hh"
00022 
00023 #include "tracker-viewer.hh"
00024 
00025 namespace visp_tracker
00026 {
00027   namespace
00028   {
00029     static void increment(unsigned int* value)
00030     {
00031       ++(*value);
00032     }
00033   } // end of anonymous namespace.
00034 
00035   TrackerViewer::TrackerViewer(ros::NodeHandle& nh,
00036                                ros::NodeHandle& privateNh,
00037                                volatile bool& exiting,
00038                                unsigned queueSize)
00039     : exiting_ (exiting),
00040       queueSize_(queueSize),
00041       nodeHandle_(nh),
00042       nodeHandlePrivate_(privateNh),
00043       imageTransport_(nodeHandle_),
00044       rectifiedImageTopic_(),
00045       cameraInfoTopic_(),
00046       checkInputs_(nodeHandle_, ros::this_node::getName()),
00047       tracker_(),
00048       cameraParameters_(),
00049       image_(),
00050       info_(),
00051       cMo_(boost::none),
00052       sites_(),
00053       imageSubscriber_(),
00054       cameraInfoSubscriber_(),
00055       trackingResultSubscriber_(),
00056       movingEdgeSitesSubscriber_(),
00057       kltPointsSubscriber_(),
00058       synchronizer_(syncPolicy_t(queueSize_)),
00059       timer_(),
00060       countAll_(0u),
00061       countImages_(0u),
00062       countCameraInfo_(0u),
00063       countTrackingResult_(0u),
00064       countMovingEdgeSites_(0u),
00065       countKltPoints_(0u)
00066   {
00067     // Compute topic and services names.
00068     std::string cameraPrefix;
00069 
00070     ros::Rate rate (1);
00071     while (cameraPrefix.empty ())
00072       {
00073         if (!nodeHandle_.getParam ("camera_prefix", cameraPrefix))
00074           {
00075             ROS_WARN
00076               ("the camera_prefix parameter does not exist.\n"
00077                "This may mean that:\n"
00078                "- the tracker is not launched,\n"
00079                "- the tracker and viewer are not running in the same namespace."
00080                );
00081           }
00082         else if (cameraPrefix.empty ())
00083           {
00084             ROS_INFO
00085               ("tracker is not yet initialized, waiting...\n"
00086                "You may want to launch the client to initialize the tracker.");
00087           }
00088         if (this->exiting())
00089           return;
00090         rate.sleep ();
00091       }
00092 
00093     rectifiedImageTopic_ =
00094       ros::names::resolve(cameraPrefix + "/image_rect");
00095     cameraInfoTopic_ =
00096       ros::names::resolve(cameraPrefix + "/camera_info");
00097 
00098     boost::filesystem::ofstream modelStream;
00099     std::string path;
00100 
00101     while (!nodeHandle_.hasParam(visp_tracker::model_description_param))
00102       {
00103         if (!nodeHandle_.hasParam(visp_tracker::model_description_param))
00104           {
00105             ROS_WARN
00106               ("the model_description parameter does not exist.\n"
00107                "This may mean that:\n"
00108                "- the tracker is not launched or not initialized,\n"
00109                "- the tracker and viewer are not running in the same namespace."
00110                );
00111           }
00112         if (this->exiting())
00113           return;
00114         rate.sleep ();
00115       }
00116 
00117     if (!makeModelFile(modelStream, path))
00118       throw std::runtime_error
00119         ("failed to load the model from the parameter server");
00120     ROS_INFO_STREAM("Model loaded from the parameter server.");
00121     vrmlPath_ = path;
00122 
00123     initializeTracker();
00124     if (this->exiting())
00125       return;
00126 
00127     checkInputs();
00128     if (this->exiting())
00129       return;
00130 
00131     // Subscribe to camera and tracker synchronously.
00132     imageSubscriber_.subscribe
00133       (imageTransport_, rectifiedImageTopic_, queueSize_);
00134     cameraInfoSubscriber_.subscribe
00135       (nodeHandle_, cameraInfoTopic_, queueSize_);
00136     trackingResultSubscriber_.subscribe
00137       (nodeHandle_, visp_tracker::object_position_covariance_topic,
00138        queueSize_);
00139     movingEdgeSitesSubscriber_.subscribe
00140       (nodeHandle_, visp_tracker::moving_edge_sites_topic, queueSize_);
00141     kltPointsSubscriber_.subscribe
00142       (nodeHandle_, visp_tracker::klt_points_topic, queueSize_);
00143 
00144     synchronizer_.connectInput
00145       (imageSubscriber_, cameraInfoSubscriber_,
00146        trackingResultSubscriber_, movingEdgeSitesSubscriber_, kltPointsSubscriber_);
00147     synchronizer_.registerCallback(boost::bind(&TrackerViewer::callback,
00148                  this, _1, _2, _3, _4, _5));
00149 
00150     // Check for synchronization every 30s.
00151     synchronizer_.registerCallback(boost::bind(increment, &countAll_));
00152     imageSubscriber_.registerCallback(boost::bind(increment, &countImages_));
00153     cameraInfoSubscriber_.registerCallback
00154       (boost::bind(increment, &countCameraInfo_));
00155     trackingResultSubscriber_.registerCallback
00156       (boost::bind(increment, &countTrackingResult_));
00157     movingEdgeSitesSubscriber_.registerCallback
00158       (boost::bind(increment, &countMovingEdgeSites_));
00159     kltPointsSubscriber_.registerCallback
00160       (boost::bind(increment, &countKltPoints_));
00161 
00162     timer_ = nodeHandle_.createWallTimer
00163       (ros::WallDuration(30.),
00164        boost::bind(&TrackerViewer::timerCallback, this));
00165 
00166     // Wait for image.
00167     waitForImage();
00168     if (this->exiting())
00169       return;
00170     if (!image_.getWidth() || !image_.getHeight())
00171       throw std::runtime_error("failed to retrieve image");
00172 
00173     // Load camera parameters.
00174     initializeVpCameraFromCameraInfo(cameraParameters_, info_);
00175     tracker_.setCameraParameters(cameraParameters_);
00176   }
00177 
00178   void
00179   TrackerViewer::spin()
00180   {
00181     boost::format fmtWindowTitle ("ViSP MBT tracker viewer - [ns: %s]");
00182     fmtWindowTitle % ros::this_node::getNamespace ();
00183 
00184     vpDisplayX d(image_,
00185                  image_.getWidth(), image_.getHeight(),
00186                  fmtWindowTitle.str().c_str());
00187     vpImagePoint point (10, 10);
00188     vpImagePoint pointTime (22, 10);
00189     vpImagePoint pointCameraTopic (34, 10);
00190     ros::Rate loop_rate(80);
00191 
00192     boost::format fmt("tracking (x=%f y=%f z=%f)");
00193     boost::format fmtTime("time = %f");
00194 
00195     boost::format fmtCameraTopic("camera topic = %s");
00196     fmtCameraTopic % rectifiedImageTopic_;
00197     while (!exiting())
00198       {
00199         vpDisplay::display(image_);
00200   displayMovingEdgeSites();
00201   displayKltPoints();
00202   if (cMo_)
00203           {
00204             try
00205               {
00206                 tracker_.initFromPose(image_, *cMo_);
00207                 tracker_.display(image_, *cMo_,
00208                                  cameraParameters_, vpColor::red);
00209               }
00210             catch(...)
00211               {
00212                 ROS_DEBUG_STREAM_THROTTLE(10, "failed to display cmo");
00213               }
00214 
00215         ROS_DEBUG_STREAM_THROTTLE(10, "cMo viewer:\n" << *cMo_);
00216 
00217             fmt % (*cMo_)[0][3] % (*cMo_)[1][3] % (*cMo_)[2][3];
00218             vpDisplay::displayCharString
00219               (image_, point, fmt.str().c_str(), vpColor::red);
00220             fmtTime % info_->header.stamp.toSec();
00221             vpDisplay::displayCharString
00222               (image_, pointTime, fmtTime.str().c_str(), vpColor::red);
00223             vpDisplay::displayCharString
00224               (image_, pointCameraTopic, fmtCameraTopic.str().c_str(),
00225                vpColor::red);
00226           }
00227         else
00228           vpDisplay::displayCharString
00229             (image_, point, "tracking failed", vpColor::red);
00230         vpDisplay::flush(image_);
00231     ros::spinOnce();
00232         loop_rate.sleep();
00233       }
00234   }
00235 
00236   void
00237   TrackerViewer::waitForImage()
00238   {
00239     ros::Rate loop_rate(10);
00240     while (!exiting()
00241            && (!image_.getWidth() || !image_.getHeight()))
00242       {
00243         ROS_INFO_THROTTLE(1, "waiting for a rectified image...");
00244         ros::spinOnce();
00245         loop_rate.sleep();
00246       }
00247   }
00248 
00249   void
00250   TrackerViewer::checkInputs()
00251   {
00252     ros::V_string topics;
00253     topics.push_back(rectifiedImageTopic_);
00254     topics.push_back(cameraInfoTopic_);
00255     topics.push_back(visp_tracker::object_position_topic);
00256     topics.push_back(visp_tracker::moving_edge_sites_topic);
00257     topics.push_back(visp_tracker::klt_points_topic);
00258     checkInputs_.start(topics, 60.0);
00259   }
00260 
00261   void
00262   TrackerViewer::initializeTracker()
00263   {
00264     try
00265       {
00266         ROS_DEBUG_STREAM("Trying to load the model " << vrmlPath_);
00267         tracker_.loadModel(vrmlPath_.native().c_str());
00268       }
00269     catch(...)
00270       {
00271         boost::format fmt("failed to load the model %1%");
00272         fmt % vrmlPath_;
00273         throw std::runtime_error(fmt.str());
00274       }
00275     ROS_INFO("Model has been successfully loaded.");
00276   }
00277 
00278   void
00279   TrackerViewer::callback
00280   (const sensor_msgs::ImageConstPtr& image,
00281    const sensor_msgs::CameraInfoConstPtr& info,
00282    const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& trackingResult,
00283    const visp_tracker::MovingEdgeSites::ConstPtr& sites,
00284    const visp_tracker::KltPoints::ConstPtr& klt)
00285   {
00286     // Copy image.
00287     try
00288       {
00289         rosImageToVisp(image_, image);
00290       }
00291     catch(std::exception& e)
00292       {
00293         ROS_ERROR_STREAM("dropping frame: " << e.what());
00294       }
00295 
00296     // Copy moving camera infos, edges sites and optional KLT points.
00297     info_ = info;
00298     sites_ = sites;
00299     klt_ = klt;
00300 
00301     // Copy cMo.
00302     cMo_ = vpHomogeneousMatrix();
00303     transformToVpHomogeneousMatrix(*cMo_, trackingResult->pose.pose);
00304   }
00305 
00306   void
00307   TrackerViewer::displayMovingEdgeSites()
00308   {
00309     if (!sites_)
00310       return;
00311     for (unsigned i = 0; i < sites_->moving_edge_sites.size(); ++i)
00312       {
00313         double x = sites_->moving_edge_sites[i].x;
00314         double y = sites_->moving_edge_sites[i].y;
00315         int suppress = sites_->moving_edge_sites[i].suppress;
00316         vpColor color = vpColor::black;
00317 
00318         switch(suppress)
00319           {
00320           case 0:
00321             color = vpColor::green;
00322             break;
00323           case 1:
00324             color = vpColor::blue;
00325             break;
00326           case 2:
00327             color = vpColor::purple;
00328             break;
00329           case 4:
00330             color = vpColor::red;
00331             break;
00332           default:
00333             ROS_ERROR_THROTTLE(10, "bad suppress value");
00334           }
00335 
00336         vpDisplay::displayCross(image_, vpImagePoint(x, y), 3, color, 1);
00337       }
00338   }
00339 
00340 
00341   void
00342   TrackerViewer::displayKltPoints()
00343   {
00344     if (!klt_)
00345       return;
00346     vpImagePoint pos;
00347 
00348     for (unsigned i = 0; i < klt_->klt_points_positions.size(); ++i)
00349     {
00350       double ii = klt_->klt_points_positions[i].i;
00351       double jj = klt_->klt_points_positions[i].j;
00352       int id = klt_->klt_points_positions[i].id;
00353       vpColor color = vpColor::red;
00354 
00355       vpDisplay::displayCross(image_, vpImagePoint(ii, jj), 15, color, 1);
00356 
00357       pos.set_i( vpMath::round( ii + 7 ) );
00358       pos.set_j( vpMath::round( jj + 7 ) );
00359       char ide[10];
00360       sprintf(ide, "%d", id);
00361       vpDisplay::displayCharString(image_, pos, ide, vpColor::red);
00362     }
00363   }
00364 
00365   void
00366   TrackerViewer::timerCallback()
00367   {
00368     const unsigned threshold = 3 * countAll_;
00369 
00370     if (countImages_ < threshold
00371         || countCameraInfo_ < threshold
00372         || countTrackingResult_ < threshold
00373   || countMovingEdgeSites_ < threshold
00374   || countKltPoints_ < threshold)
00375       {
00376         boost::format fmt
00377           ("[visp_tracker] Low number of synchronized tuples received.\n"
00378            "Images: %d\n"
00379            "Camera info: %d\n"
00380            "Tracking result: %d\n"
00381            "Moving edge sites: %d\n"
00382            "Synchronized tuples: %d\n"
00383            "Possible issues:\n"
00384            "\t* The network is too slow.");
00385         fmt % countImages_ % countCameraInfo_
00386           % countTrackingResult_ % countMovingEdgeSites_ % countAll_;
00387         ROS_WARN_STREAM_THROTTLE(10, fmt.str());
00388       }
00389   }
00390 } // end of namespace visp_tracker.


visp_tracker
Author(s): Thomas Moulard
autogenerated on Mon Oct 6 2014 08:40:35