FakeObjectRecognizer.cpp
Go to the documentation of this file.
00001 #include <gazebo_test_tools/FakeObjectRecognizer.h>
00002 #include <object_msgs/RegisterObject.h>
00003 #include <boost/thread.hpp>
00004 
00005 #include <iostream>
00006 
00007 #define DEFAULT_OBJECTS_TOPIC "world/objects"
00008 #define DEFAULT_SERVICE_REQUEST_OBJECT_TOPIC "world/request_object"
00009 #define DEFAULT_SERVICE_RECOGNISE_OBJECT_TOPIC "/recognize_object"
00010 #define DEFAULT_SERVICE_REGISTER_OBJECT_TF_TOPIC "/register_object"
00011 #define DEFAULT_PUBLISH_RECOGNISED_OBJECT_RATE 1
00012 
00013 using gazebo_test_tools::FakeObjectRecognizer;
00014 
00015 FakeObjectRecognizer::FakeObjectRecognizer() {
00016 
00017     ros::NodeHandle _node("/gazebo_test_tools");
00018     _node.param<std::string>("objects_topic", OBJECTS_TOPIC, DEFAULT_OBJECTS_TOPIC);
00019     ROS_INFO("Got objects topic name: <%s>", OBJECTS_TOPIC.c_str());
00020 
00021     _node.param<std::string>("request_object_service", SERVICE_REQUEST_OBJECT_TOPIC, DEFAULT_SERVICE_REQUEST_OBJECT_TOPIC);
00022     ROS_INFO("Got object service topic name: <%s>", SERVICE_REQUEST_OBJECT_TOPIC.c_str());
00023     
00024     _node.param<std::string>("recognize_object_service", SERVICE_RECOGNISE_OBJECT_TOPIC, DEFAULT_SERVICE_RECOGNISE_OBJECT_TOPIC);
00025     
00026     _node.param<std::string>("register_object_tf_service", SERVICE_REGISTER_OBJECT_TF_TOPIC, DEFAULT_SERVICE_REGISTER_OBJECT_TF_TOPIC);
00027     ROS_INFO("Got register object tf service topic name: <%s>", SERVICE_REGISTER_OBJECT_TF_TOPIC.c_str());
00028 
00029     int PUBLISH_RECOGNISED_OBJECT_RATE;
00030     _node.param<int>("publish_recognition_rate", PUBLISH_RECOGNISED_OBJECT_RATE, PUBLISH_RECOGNISED_OBJECT_RATE);
00031 
00032     if (!SERVICE_REQUEST_OBJECT_TOPIC.empty()) object_info_client = node.serviceClient<object_msgs::ObjectInfo>(SERVICE_REQUEST_OBJECT_TOPIC);
00033     if (!SERVICE_REGISTER_OBJECT_TF_TOPIC.empty()) register_object_tf_client = node.serviceClient<object_msgs::RegisterObject>(SERVICE_REGISTER_OBJECT_TF_TOPIC);
00034 
00035     recognize_object_srv = node.advertiseService(SERVICE_RECOGNISE_OBJECT_TOPIC, &FakeObjectRecognizer::recognizeObject,this);
00036 
00037     object_pub = node.advertise<object_msgs::Object>(OBJECTS_TOPIC, 100); 
00038 
00039     ros::Rate rate(PUBLISH_RECOGNISED_OBJECT_RATE);
00040     publishTimer=node.createTimer(rate,&FakeObjectRecognizer::publishRecognitionEvent, this);
00041 }
00042 
00043 FakeObjectRecognizer::~FakeObjectRecognizer() {
00044 }
00045 
00046 void FakeObjectRecognizer::publishRecognitionEvent(const ros::TimerEvent& e) {
00047     if (object_pub.getNumSubscribers()==0) return;
00048     
00049     boost::unique_lock<boost::mutex> lock(addedObjectsMtx);
00050     std::set<std::string>::iterator it;
00051     for (it=addedObjects.begin(); it!=addedObjects.end(); ++it )
00052     {
00053         object_msgs::Object object;
00054         // get the object information. Only the pose is required because
00055         // the shape has been published in recognizeObject() already and
00056         // it only needs to be published once when the object is first added.
00057         if (!queryObjectInfo(*it,object,false, true))
00058         {
00059             ROS_ERROR_STREAM("Could not find object "<<*it);
00060             continue;
00061         }
00062         object_pub.publish(object);
00063     }
00064 }
00065     
00066 bool FakeObjectRecognizer::recognizeObject(gazebo_test_tools::RecognizeGazeboObject::Request &req,
00067         gazebo_test_tools::RecognizeGazeboObject::Response &res)
00068 {
00069     ROS_INFO_STREAM("Recognizing object "<<req.name); 
00070     
00071     res.success=true;
00072     boost::unique_lock<boost::mutex> lock(addedObjectsMtx);
00073     std::set<std::string>::iterator it = addedObjects.find(req.name);
00074     if (it!=addedObjects.end())
00075     {
00076         if (req.republish)
00077         { 
00078             ROS_WARN_STREAM("The object "<<req.name<<" was already set to being "
00079                  << "continously published. No need to call FakeObjectRecognizerService again.");
00080             return true; 
00081         }
00082         else  // switch off repbulishing for this object
00083         {
00084             ROS_INFO_STREAM("Removing object "<<req.name<<" from being re-published");
00085             addedObjects.erase(it);
00086             // now, publish the object information one last time, to
00087             // make sure this message is not misunderstood: it could have been
00088             // a caller which wants the message to be published once and wasn't aware
00089             // that the object was actually being re-published.
00090         }
00091     }
00092     if (req.republish) addedObjects.insert(req.name);
00093 
00094     object_msgs::Object object;
00095     // try this for a while, because sometimes when an object has just been
00096     // created / spawned, it may take a while for the service to return
00097     // information about it (before that it can't find it, e.g. if an object
00098     // is spawned in Gazebo and right after the recognition is triggered)
00099     float timeout = 3;
00100     float checkStep = 0.5;
00101     if (!waitForQueryObjectInfo(req.name,object,true, timeout, checkStep, false))
00102     {
00103         ROS_ERROR_STREAM("Could not find object "<<req.name);
00104         res.success=false;
00105         return true;
00106     }
00107 
00108     // ROS_INFO_STREAM("Publishing object "<<object);       
00109     object_pub.publish(object);
00110 
00111     // now, also register this object to be broadcasted in tf:
00112     object_msgs::RegisterObject srv;
00113         srv.request.name = object.name;
00114         if (register_object_tf_client.call(srv))
00115         {
00116                 ROS_INFO("FakeObjectRecogniser: Register tf result:");
00117                 std::cout<<srv.response<<std::endl;
00118         }
00119     return true;
00120 }
00121 
00122 bool FakeObjectRecognizer::waitForQueryObjectInfo(const std::string& name, object_msgs::Object& object,
00123     bool include_geometry, float timeout, float checkStep, bool printErrors)
00124 {
00125     ros::Time startTime=ros::Time::now();
00126     float timeWaited = 0;
00127     while (timeWaited < timeout)
00128     {
00129         if (queryObjectInfo(name, object, include_geometry, printErrors)) return true;
00130         ros::Duration(checkStep).sleep();
00131         ros::Time currTime = ros::Time::now();
00132         timeWaited = (currTime-startTime).toSec();
00133     }
00134     return false;
00135 }
00136 
00137 bool FakeObjectRecognizer::queryObjectInfo(const std::string& name, object_msgs::Object& object, bool include_geometry, bool printErrors){
00138     object_msgs::ObjectInfo srv;
00139     srv.request.name=name;
00140     srv.request.get_geometry=include_geometry;
00141     if (!object_info_client.call(srv)){
00142         if (printErrors) ROS_ERROR("Could not get object %s because service request failed.",name.c_str());
00143         return false;
00144     }
00145     if (!srv.response.success) {
00146         if (printErrors) ROS_ERROR("Could not get object %s because it does not exist.",name.c_str());
00147         return false;
00148     }
00149     object=srv.response.object;
00150     return true;
00151 }
00152 
00153 


gazebo_test_tools
Author(s): Jennifer Buehler
autogenerated on Tue May 7 2019 03:29:23