Go to the documentation of this file.00001 #include <object_msgs_tools/ObjectTFBroadcaster.h>
00002 #include <object_msgs_tools/ObjectFunctions.h>
00003 #include <object_msgs/ObjectInfo.h>
00004
00005 using object_msgs_tools::ObjectTFBroadcaster;
00006
00007 ObjectTFBroadcaster::ObjectTFBroadcaster(
00008 ros::NodeHandle& n,
00009 const std::string& register_object_service,
00010 unsigned int publish_tf_rate,
00011 unsigned int query_object_info_rate,
00012 const std::string& object_topic,
00013 const std::string& object_service):
00014 node(n)
00015 {
00016 if (object_service.empty() && object_topic.empty())
00017 {
00018 ROS_ERROR("Can't use ObjetTFBroadcaster if neither service nor object info topic is set");
00019 throw std::runtime_error("Can't use ObjetTFBroadcaster if neither service nor object info topic is set");
00020 }
00021
00022 ros::Rate rate(publish_tf_rate);
00023 publish_tf_timer = node.createTimer(rate, &ObjectTFBroadcaster::publishTFEvent, this);
00024 if (!register_object_service.empty())
00025 {
00026 ROS_INFO_STREAM("Advertising service "<<register_object_service);
00027 register_object_srv = node.advertiseService(register_object_service, &ObjectTFBroadcaster::registerObjectService,this);
00028 }
00029
00030 if (!object_service.empty())
00031 {
00032 ros::Rate qRate(query_object_info_rate);
00033 query_object_info_timer=node.createTimer(qRate,&ObjectTFBroadcaster::queryObjectPoseEvent, this);
00034 query_object_info_timer.start();
00035 object_info_srv = node.serviceClient<object_msgs::ObjectInfo>(object_service);
00036 }
00037 if (!object_topic.empty())
00038 object_info_sub = node.subscribe(object_topic,1000,&ObjectTFBroadcaster::objectCallback, this);
00039 }
00040
00041 bool ObjectTFBroadcaster::isRegistered(const std::string& name) const
00042 {
00043 obj_poses_mutex.lock();
00044 bool exists= obj_poses.find(name) != obj_poses.end();
00045 obj_poses_mutex.unlock();
00046 return exists;
00047 }
00048
00049 bool ObjectTFBroadcaster::registerObjectService(object_msgs::RegisterObject::Request &req,
00050 object_msgs::RegisterObject::Response &res)
00051 {
00052 ROS_INFO_STREAM("Calling ObjectTFBroadcaster service with "<<req.name);
00053 res.success = registerObject(req.name, true);
00054
00055
00056
00057
00058 return true;
00059 }
00060
00061
00062 int ObjectTFBroadcaster::registerObject(const std::string& name, bool printMsgs)
00063 {
00064 object_msgs::Object obj;
00065
00066
00067 queryObjectPose(name,obj, false);
00068 geometry_msgs::PoseStamped pose;
00069 if (!ObjectFunctions::getObjectPose(obj, pose)){
00070 if (printMsgs) ROS_WARN_STREAM("ObjectTFBroadcaster: Could not get pose for object '"<<name<<"'");
00071 return object_msgs::RegisterObject::Response::ERROR_INFO;
00072 }
00073
00074 obj_poses_mutex.lock();
00075 bool success = obj_poses.insert(std::make_pair(name,pose)).second;
00076 obj_poses_mutex.unlock();
00077 if (!success)
00078 {
00079 if (printMsgs)
00080 ROS_WARN_STREAM("Object " << name <<
00081 " could not be added in ObjectTFBroadcaster because it was already registered.");
00082 return object_msgs::RegisterObject::Response::EXISTS;
00083 }
00084 return object_msgs::RegisterObject::Response::SUCCESS;
00085 }
00086
00087
00088 bool ObjectTFBroadcaster::queryObjectPose(const std::string& name, object_msgs::Object& obj, bool printErrors)
00089 {
00090 if (object_info_srv.getService().empty())
00091 {
00092 if (printErrors) ROS_ERROR("ObjectTFBroadcaster: Service to request object_msgs/Object is not running.");
00093 return false;
00094 }
00095 object_msgs::ObjectInfo srv;
00096 srv.request.name = name;
00097 srv.request.get_geometry = false;
00098 if (object_info_srv.call(srv)){
00099
00100
00101 }else{
00102 if (printErrors) ROS_ERROR("ObjectTFBroadcaster: Failed to call service to obtain object info");
00103 return false;
00104 }
00105 obj=srv.response.object;
00106 return true;
00107 }
00108
00109 void ObjectTFBroadcaster::sendTF(const geometry_msgs::PoseStamped& pose, const std::string& frame_name){
00110 tf::Transform transform;
00111 transform.setOrigin( tf::Vector3(pose.pose.position.x, pose.pose.position.y, pose.pose.position.z) );
00112 tf::Quaternion q(pose.pose.orientation.x,pose.pose.orientation.y,pose.pose.orientation.z,pose.pose.orientation.w);
00113 transform.setRotation(q);
00114
00115 tf_broadcaster.sendTransform(tf::StampedTransform(transform, pose.header.stamp, pose.header.frame_id, frame_name));
00116
00117 }
00118
00119
00120 bool ObjectTFBroadcaster::updateObject(const object_msgs::Object& obj)
00121 {
00122
00123 geometry_msgs::PoseStamped pose;
00124 if (!ObjectFunctions::getObjectPose(obj, pose)){
00125 ROS_ERROR("ObjectTFBroadcaster: Could not get pose");
00126 return false;
00127 }
00128 std::map<std::string, geometry_msgs::PoseStamped>::iterator it;
00129 obj_poses_mutex.lock();
00130 it = obj_poses.find(obj.name);
00131 bool success = (it != obj_poses.end());
00132 if (success) it->second=pose;
00133 obj_poses_mutex.unlock();
00134 if (!success)
00135 {
00136 ROS_ERROR_STREAM("ObjectTFBroadcaster: Could not update object "
00137 <<obj.name<<" because it was not registered. Call registerObject() to add it.");
00138 }
00139 return success;
00140 }
00141
00142 void ObjectTFBroadcaster::objectCallback(const object_msgs::Object& obj){
00143 updateObject(obj);
00144 }
00145
00146 void ObjectTFBroadcaster::publishTFEvent(const ros::TimerEvent& e){
00147
00148 obj_poses_mutex.lock();
00149 std::map<std::string, geometry_msgs::PoseStamped>::iterator it;
00150 for (it = obj_poses.begin(); it!=obj_poses.end(); ++it)
00151 {
00152 it->second.header.stamp=ros::Time::now();
00153
00154 sendTF(it->second,it->first);
00155 }
00156 obj_poses_mutex.unlock();
00157 }
00158
00159 void ObjectTFBroadcaster::queryObjectPoseEvent(const ros::TimerEvent& e)
00160 {
00161
00162 obj_poses_mutex.lock();
00163 std::map<std::string, geometry_msgs::PoseStamped>::iterator it;
00164 for (it = obj_poses.begin(); it!=obj_poses.end(); ++it)
00165 {
00166 object_msgs::Object obj;
00167 if (!queryObjectPose(it->first,obj,true)) continue;
00168 updateObject(obj);
00169 }
00170 obj_poses_mutex.unlock();
00171 }