gltracker.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (Modified BSD License)
00003  *
00004  *  Copyright (c) 2012, PAL Robotics, S.L.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of PAL Robotics, S.L. nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  * @file gltracker.cpp
00035  * @author Bence Magyar
00036  * @date June 2012
00037  * @version 0.1
00038  * @brief Class of GLTracker which wraps the tracker core of BLORT.
00039  */
00040 
00041 #include <blort_ros/gltracker.h>
00042 #include <blort/Tracker/utilities.hpp>
00043 #include <blort/TomGine/tgModelLoader.h>
00044 #include <sstream>
00045 #include <iostream>
00046 #include <blort/blort/pal_util.h>
00047 #include <ros/console.h>
00048 
00049 using namespace blort_ros;
00050 
00051 GLTracker::GLTracker(const sensor_msgs::CameraInfo camera_info,
00052                      const std::string& config_root,
00053                      bool visualize_obj_pose)
00054 {
00055   //this line should force opengl to run software rendering == no GPU
00056   //putenv("LIBGL_ALWAYS_INDIRECT=1");
00057   config_root_ = config_root;
00058   conf_threshold = 0.4;
00059   recovery_conf_threshold = 0.05;
00060   publish_mode = blort_ros::TRACKER_PUBLISH_GOOD_AND_FAIR;
00061   this->visualize_obj_pose = visualize_obj_pose;
00062 
00063   printf("\n Blort detection node\n\n");
00064   printf(" There is a dynamic_reconfigure interface for your convenience. \n");
00065   printf(" Control commands received via ROS service: tracker_control. \n");
00066   printf(" --------------------------\n");
00067   printf(" [0] Lock/Unlock tracking\n");
00068   printf(" [1] Reset tracker to initial pose\n");
00069   printf(" [2] Switch display mode of model\n");
00070   printf(" [3] Show particles\n");
00071   printf(" [4] Texture edge tracking\n");
00072   printf(" [5] Texture color tracking\n");
00073   printf(" [6] Show edges of image\n");
00074   printf(" [7] Print tracking information to console\n");
00075   printf(" \n\n ");
00076 
00077   // File names
00078   pose_cal = blort_ros::addRoot("config/pose.cal", config_root);
00079   //FIXME: make these ROS parameters or eliminate them and use the content as parameters
00080   std::string tracking_ini(blort_ros::addRoot("config/tracking.ini", config_root));
00081 
00082   std::vector<std::string> ply_models(0), sift_files(0), model_names(0);
00083   GetPlySiftFilenames(tracking_ini.c_str(), ply_models, sift_files, model_names);
00084   // Build ModelEntry with these entries
00085   blort::buildFromFiles(ply_models, sift_files, model_names, objects_);
00086 
00087   GetTrackingParameter(track_params, tracking_ini.c_str(), config_root);
00088 
00089   tgcam_params = TomGine::tgCamera::Parameter(camera_info);
00090   getCamPose(pose_cal.c_str(), cam_pose); // should get this from a TF call
00091   setCameraPose(tgcam_params, pose_cal.c_str()); // camPose and tgCamParams share a lot of stuff
00092   track_params.camPar = tgcam_params;
00093 
00094   tracker.init(track_params);
00095 
00096   for(size_t i = 0; i < objects_.size(); ++i)
00097   {
00098     objects_[i].tr_pose = boost::shared_ptr<TomGine::tgPose>(new TomGine::tgPose);
00099     objects_[i].tr_pose->t = vec3(0.0, 0.1, 0.0);
00100     objects_[i].tr_pose->Rotate(0.0f, 0.0f, 0.5f);
00101     model_ids[objects_[i].name] = tracker.addModelFromFile(
00102           blort_ros::addRoot(objects_[i].ply_model, config_root).c_str(),
00103           *(objects_[i].tr_pose), objects_[i].name.c_str(), true);
00104     objects_[i].movement = Tracking::ST_SLOW;
00105     objects_[i].quality = Tracking::ST_LOST;
00106     objects_[i].tracking_conf = Tracking::ST_BAD;
00107     current_modes[objects_[i].name] = blort_ros::TRACKER_RECOVERY_MODE;
00108     current_confs[objects_[i].name] = blort_ros::TRACKER_CONF_LOST;
00109     //tracker_confidences.push_back(boost::shared_ptr<blort_msgs::TrackerConfidences>(new blort_msgs::TrackerConfidences));
00110     //objects_[i].is_tracked = true;
00111   }
00112   //result.resize(objects_.size());
00113   tracker.setLockFlag(true);
00114 
00115   image = cvCreateImage( cvSize(tgcam_params.width, tgcam_params.height), 8, 3 );
00116 
00117   // define the constant cam_pose to be published
00118   fixed_cam_pose = blort_ros::tgPose2RosPose(cam_pose);
00119 }
00120 
00121 //2012-11-27: added by Jordi
00122 void GLTracker::resetParticleFilter(std::string obj_i)
00123 {
00124   //look up object based on name and update(should be changed to nonbusy lookup)
00125   BOOST_FOREACH(blort::ObjectEntry& obj, objects_)
00126   {
00127     if(obj.name == obj_i)
00128     {
00129       tracker.removeModel(model_ids[obj_i]);
00130       model_ids[obj_i] = tracker.addModelFromFile(
00131             blort_ros::addRoot(obj.ply_model, config_root_).c_str(),
00132             *(obj.tr_pose), obj.name.c_str(), true);
00133       obj.movement = Tracking::ST_SLOW;
00134       obj.quality  = Tracking::ST_LOST;
00135       obj.tracking_conf = Tracking::ST_BAD;
00136       obj.is_tracked = true;
00137       break;
00138     }
00139   }
00140 }
00141 
00142 void GLTracker::track()
00143 {
00144   boost::mutex::scoped_lock lock(models_mutex);
00145   *image = last_image;
00146 
00147   // Track object
00148   tracker.image_processing((unsigned char*)image->imageData);
00149 
00150   // turn on tracking for all selected objects
00151   BOOST_FOREACH(const blort::ObjectEntry& obj, objects_)
00152   {
00153     if(obj.is_tracked)
00154       tracker.track(model_ids[obj.name]);
00155   }
00156   tracker.drawImage(0);
00157   tracker.drawCoordinates();
00158   BOOST_FOREACH(const blort::ObjectEntry& obj, objects_)
00159   {
00160     if(obj.is_tracked)
00161     {
00162       tracker.getModelPose(model_ids[obj.name], *(obj.tr_pose));
00163       tracker.drawResult(model_ids[obj.name], 2.0);
00164     }
00165   }
00166   //tracker.drawResult(2.0f);
00167 
00168   // visualize current object pose if needed. moving this piece of code is troublesome,
00169   // has to stay right after drawImage(), because of OpenGL
00170   if( 1 || visualize_obj_pose)
00171   {
00172     for(size_t i = 0; i < objects_.size(); ++i)
00173     {
00174       if(current_modes[objects_[i].name] != TRACKER_RECOVERY_MODE  && objects_[i].is_tracked)
00175       {
00176         objects_[i].tr_pose->Activate();
00177         glBegin(GL_LINES);
00178         glColor3f(1.0f, 0.0f, 0.0f);
00179         glVertex3f(0.0f, 0.0f, 0.0f);
00180         glVertex3f(1.0f, 0.0f, 0.0f);
00181 
00182         glColor3f(0.0f, 1.0f, 0.0f);
00183         glVertex3f(0.0f, 0.0f, 0.0f);
00184         glVertex3f(0.0f, 1.0f, 0.0f);
00185 
00186         glColor3f(0.0f, 0.0f, 1.0f);
00187         glVertex3f(0.0f, 0.0f, 0.0f);
00188         glVertex3f(0.0f, 0.0f, 1.0f);
00189         glEnd();
00190         objects_[i].tr_pose->Deactivate();
00191       }
00192     }
00193   }
00194 
00195   update();
00196 
00197   for(size_t i = 0; i < objects_.size(); ++i)
00198   {
00199     if(objects_[i].is_tracked)
00200     {
00201       if(objects_[i].quality == Tracking::ST_LOCKED)
00202       {
00203         this->current_modes[objects_[i].name] = blort_ros::TRACKER_LOCKED_MODE;
00204       }
00205       else if(objects_[i].quality == Tracking::ST_LOST)
00206       {
00207         ROS_INFO_STREAM("GLTracker::track: switching tracker to RECOVERY_MODE because object " << objects_[i].name << "LOST");
00208         switchToRecovery(objects_[i].name);
00209       }
00210 
00211       if(objects_[i].tracking_conf == Tracking::ST_GOOD
00212          && objects_[i].movement == Tracking::ST_STILL
00213          && objects_[i].quality != Tracking::ST_LOCKED)
00214       {
00215         ROS_DEBUG_STREAM("Tracker is really confident (edge conf: " << objects_[i].edgeConf);
00216       }
00217     }
00218   }
00219 }
00220 
00221 void GLTracker::resetWithPose(std::string id, const geometry_msgs::Pose& new_pose)
00222 {
00223   boost::mutex::scoped_lock lock(models_mutex);
00224   blort::ObjectEntry& obj = getObjEntryByName(id); //TODO: ugly
00225   ConvertCam2World(blort_ros::rosPose2TgPose(new_pose), cam_pose, *(obj.tr_pose));
00226   tracker.setModelInitialPose(model_ids[id], *(obj.tr_pose));
00227   resetParticleFilter(id); // will reset the ModelEntry, particle filter
00228   switchToTracking(id);
00229 
00230   // make sure that the tracker will start tracking after a recovery,
00231   // not standing still in locked mode
00232   tracker.setLockFlag(false);
00233 }
00234 
00235 void GLTracker::reconfigure(blort_ros::TrackerConfig config)
00236 {
00237   tracker.setLockFlag(config.lock);
00238   tracker.setModelModeFlag(config.render_mode);
00239   tracker.setEdgesImageFlag(config.edge);
00240   visualize_obj_pose = config.visualize_obj_pose;
00241   publish_mode = config.publish_mode;
00242 
00243   //only reset the tracker when the checkbox was clicked, not depending on the act value
00244   if(last_reset != config.reset)
00245   {
00246     last_reset = config.reset;
00247     reset();
00248   }
00249 }
00250 
00251 void GLTracker::trackerControl(uint8_t code, const std::vector<std::string> & params)
00252 {
00253   std::string param = "";
00254   if(params.empty())
00255   {
00256     param = objects_.begin()->name;
00257   }
00258   switch(code)
00259   {
00260   case 0: //l
00261     tracker.setLockFlag( !tracker.getLockFlag() );
00262     break;
00263   case 1: //r
00264     //tracker.reset();
00265     this->reset();
00266     break;
00267   case 2: //m
00268     if ( param != "" )
00269       tracker.setModelModeFlag( model_ids[param] );
00270     else
00271       tracker.setModelModeFlag( tracker.getModelModeFlag()+1 );
00272     break;
00273   case 3: //p
00274     tracker.setDrawParticlesFlag( !tracker.getDrawParticlesFlag() );
00275     break;
00276   case 4: //4
00277     tracker.setEdgeShader();
00278     break;
00279   case 5: //5
00280     tracker.setColorShader();
00281     break;
00282   case 6: //e
00283     tracker.setEdgesImageFlag( !tracker.getEdgesImageFlag() );
00284     break;
00285   case 7: //i
00286     tracker.printStatistics();
00287     break;
00288   case 8:
00289     switchTracking(params);
00290     break;
00291   }
00292 }
00293 
00294 void GLTracker::switchTracking(const std::vector<std::string> & params)
00295 {
00296   if(params.size() == 0)
00297   {
00298     BOOST_FOREACH(blort::ObjectEntry& obj, objects_)
00299     {
00300       obj.is_tracked = true;
00301     }
00302   }
00303   else
00304   {
00305     for(size_t i = 0; i < params.size(); ++i)
00306     {
00307       blort::ObjectEntry& obj = getObjEntryByName(params[i]);
00308       obj.is_tracked = !obj.is_tracked;
00309     }
00310   }
00311 }
00312 
00313 cv::Mat GLTracker::getImage()
00314 {
00315   cv::Mat tmp;
00316 
00317   // check if there is a different state then recovery mode
00318   blort_ros::tracker_mode current_mode = TRACKER_RECOVERY_MODE;
00319   typedef std::pair<std::string, blort_ros::tracker_mode> NameModePair_t;
00320   BOOST_FOREACH(NameModePair_t item, current_modes)
00321   {
00322     if(item.second != TRACKER_RECOVERY_MODE)
00323     {
00324       current_mode = item.second;
00325       break;
00326     }
00327   }
00328   switch(current_mode)
00329   {
00330   case TRACKER_RECOVERY_MODE:
00331     // here there is nothing new to publish, copy the last valid one
00332     return last_image.clone(); //TODO: do we need a copy?
00333     break;
00334   case TRACKER_TRACKING_MODE:
00335   case TRACKER_LOCKED_MODE:
00336     // get the last rendered image from the tracker
00337     return tracker.getImage().clone();
00338     break;
00339   default:
00340     break;
00341   }
00342   return tmp;
00343 }
00344 
00345 void GLTracker::updatePoseResult(std::string i)
00346 {
00347   TomGine::tgPose pose;
00348   tracker.getModelPose(model_ids[i], pose);
00349 
00350   geometry_msgs::Pose detection;
00351   detection.position.x = pose.t.x;
00352   detection.position.y = pose.t.y;
00353   detection.position.z = pose.t.z;
00354   //ALERT!!! inverse needed on the rotation quaternion because the blort orientation
00355   //output is computed differently than what rviz expects. they compute the inverse orientation
00356   detection.orientation.x = -pose.q.x;
00357   detection.orientation.y = -pose.q.y;
00358   detection.orientation.z = -pose.q.z;
00359   detection.orientation.w = pose.q.w;
00360 
00361   result[i] = detection;
00362 }
00363 
00364 void GLTracker::update()
00365 {
00366   BOOST_FOREACH(blort::ObjectEntry& obj, objects_)
00367   {
00368     if(obj.is_tracked)
00369     {
00370       //update confidences for output
00371       Tracking::ModelEntry* myModelEntry = tracker.getModelEntry(model_ids[obj.name]);
00372       obj.edgeConf = myModelEntry->c_edge;
00373       obj.confThreshold = myModelEntry->c_th;
00374       obj.lostConf = myModelEntry->c_lost;
00375       obj.distance = myModelEntry->t;
00376 
00377       //update confidences based on the currently tracked model
00378       tracker.getModelMovementState(model_ids[obj.name], obj.movement);
00379       tracker.getModelQualityState(model_ids[obj.name], obj.quality);
00380       ROS_INFO_STREAM("GLTracker::update: the tracked model for " << obj.name << " has set quality to " << obj.quality);
00381       tracker.getModelConfidenceState(model_ids[obj.name], obj.tracking_conf);
00382 
00383       switch(obj.tracking_conf)
00384       {
00385       case Tracking::ST_GOOD:
00386         this->current_confs[obj.name] = blort_ros::TRACKER_CONF_GOOD;
00387         updatePoseResult(obj.name);
00388         break;
00389       case Tracking::ST_FAIR:
00390         this->current_confs[obj.name] = blort_ros::TRACKER_CONF_FAIR;
00391         if(publish_mode == TRACKER_PUBLISH_GOOD_AND_FAIR ||
00392            publish_mode == TRACKER_PUBLISH_ALL)
00393         {
00394           updatePoseResult(obj.name);
00395           this->current_confs[obj.name] = blort_ros::TRACKER_CONF_GOOD;
00396         }
00397         break;
00398       case Tracking::ST_BAD:
00399         this->current_confs[obj.name] = blort_ros::TRACKER_CONF_FAIR;
00400         if(publish_mode == TRACKER_PUBLISH_ALL)
00401           updatePoseResult(obj.name);
00402         break;
00403       default:
00404         ROS_ERROR("Unknown confidence value: %d", obj.tracking_conf);
00405         break;
00406       }
00407     }
00408   }
00409 }
00410 
00411 void GLTracker::reset(const std::vector<std::string> & params)
00412 {
00413   ROS_INFO("GLTracker::reset: switching tracker to RECOVERY_MODE");
00414   if(!params.empty())
00415   {
00416     for(size_t i = 0; i < model_ids.size(); ++i)
00417     {
00418       switchToRecovery(objects_[i].name);
00419     }
00420   }
00421   else
00422   {
00423     for(size_t i = 0; i < params.size(); ++i)
00424     {
00425       //TODO: validate param
00426       switchToRecovery(params[i]);
00427     }
00428   }
00429 }
00430 
00431 void GLTracker::switchToTracking(const std::string& id)
00432 {
00433   TrackerInterface::switchToTracking(id);
00434   tracker.getModelEntry(model_ids[id])->st_quality = Tracking::ST_OK;
00435 }
00436 
00437 void GLTracker::switchToRecovery(const std::string& id)
00438 {
00439   TrackerInterface::switchToRecovery(id);
00440   tracker.getModelEntry(model_ids[id])->st_quality = Tracking::ST_LOST;
00441   getObjEntryByName(id).quality = Tracking::ST_LOST;
00442   typedef std::pair<std::string, blort_ros::tracker_mode> NameModePair_t;
00443   BOOST_FOREACH(NameModePair_t item, current_modes)
00444   {
00445     item.second = blort_ros::TRACKER_RECOVERY_MODE;
00446   }
00447 }
00448 
00449 GLTracker::~GLTracker()
00450 {
00451 }
00452 
00453 blort::ObjectEntry& GLTracker::getObjEntryByName(const std::string& name)
00454 {
00455   BOOST_FOREACH(blort::ObjectEntry& obj, objects_)
00456   {
00457     if(obj.name == name)
00458       return obj;
00459   }
00460   assert(false);
00461   ROS_ERROR_STREAM("GLTracker::reset: No object that coincides with name '" << name << "'', RETURNING FIRST ONE, THIS IS WRONG (but fixes compilation)");
00462   return objects_[0]; // corrects cppcheck: error: control reaches end of non-void function [-Werror=return-type]
00463 }
00464 
00465 const std::vector<blort::ObjectEntry>& GLTracker::getObjects() const
00466 {
00467   return objects_;
00468 }
00469 
00470 bool GLTracker::isTracked(const std::string& id)
00471 {
00472   return getObjEntryByName(id).is_tracked;
00473 }
00474 
00475 void GLTracker::setTracked(const std::string& id, bool tracked)
00476 {
00477   getObjEntryByName(id).is_tracked = tracked;
00478 }
00479 
00480 void GLTracker::enableAllTracking(bool enable)
00481 {
00482   BOOST_FOREACH(blort::ObjectEntry& obj, objects_)
00483   {
00484     obj.is_tracked = enable;
00485   }
00486 }


blort_ros
Author(s): Bence Magyar
autogenerated on Wed Aug 26 2015 15:24:39