42 #include <boost/thread/mutex.hpp> 43 #include "boost/thread.hpp" 45 #include <tf/tfMessage.h> 47 #include <geometry_msgs/TransformStamped.h> 50 #include <tf2_web_republisher/TFSubscriptionAction.h> 52 #include <tf2_web_republisher/RepublishTFs.h> 53 #include <tf2_web_republisher/TFArray.h> 63 typedef tf2_web_republisher::RepublishTFs::Request
Request;
64 typedef tf2_web_republisher::RepublishTFs::Response
Response;
69 TFTransformServer
as_;
102 #if ROS_VERSION_MINOR < 10 124 tf_listener_(tf_buffer_),
139 boost::mutex::scoped_lock l(goals_mutex_);
149 it = active_goals_.erase(it);
161 if ( frame_id[0] ==
'/' )
163 return frame_id.substr(1);
173 const std::vector<std::string>& source_frames,
174 const std::string& target_frame_,
176 float trans_thres)
const 178 std::size_t request_size_ = source_frames.size();
179 info->tf_subscriptions_.resize(request_size_);
181 for (std::size_t i=0; i<request_size_; ++i )
183 TFPair& tf_pair = info->tf_subscriptions_[i];
185 std::string source_frame =
cleanTfFrame(source_frames[i]);
197 ROS_DEBUG(
"GoalHandle request received");
203 const tf2_web_republisher::TFSubscriptionGoal::ConstPtr& goal = gh.
getGoal();
207 goal_info->handle = gh;
208 goal_info->client_ID_ = client_ID_count_++;
221 boost::mutex::scoped_lock l(goals_mutex_);
223 active_goals_.push_back(goal_info);
230 ROS_DEBUG(
"RepublishTF service request received");
235 std::stringstream topicname;
236 topicname <<
"tf_repub_" << client_ID_count_++;
238 request_info->pub_ = priv_nh_.
advertise<tf2_web_republisher::TFArray>(topicname.str(), 10,
true);
247 request_info->unsub_timeout_ = req.timeout;
248 request_info->unsub_timer_ = nh_.
createTimer(request_info->unsub_timeout_,
256 boost::mutex::scoped_lock l(requests_mutex_);
258 active_requests_.push_back(request_info);
260 res.topic_name = request_info->pub_.getTopic();
261 ROS_INFO_STREAM(
"Publishing requested TFs on topic " << res.topic_name);
269 << request_info->client_ID_
270 <<
" for " << request_info->unsub_timeout_.toSec()
271 <<
" seconds. Unadvertising topic:" 272 << request_info->pub_.getTopic());
273 request_info->pub_.shutdown();
274 request_info->unsub_timer_.stop();
275 request_info->timer_.stop();
281 if(info.
pub_ == request_info->pub_)
283 active_requests_.erase(it);
290 std::vector<geometry_msgs::TransformStamped>& transforms)
293 std::vector<TFPair>::iterator it ;
294 std::vector<TFPair>::const_iterator end = tf_subscriptions.end();
296 for (it=tf_subscriptions.begin(); it!=end; ++it)
298 geometry_msgs::TransformStamped transform;
303 boost::mutex::scoped_lock lock (tf_buffer_mutex_);
307 it->getSourceFrame(),
316 << it->getSourceFrame()
318 << it->getTargetFrame()
319 <<
" is working again at time " 320 << transform.header.stamp.toSec());
323 it->updateTransform(transform);
336 if (it->updateNeeded())
339 transform.header.frame_id = it->getTargetFrame();
340 transform.child_frame_id = it->getSourceFrame();
343 it->transmissionTriggered();
346 transforms.push_back(transform);
353 tf2_web_republisher::TFSubscriptionFeedback feedback;
356 feedback.transforms);
358 if (feedback.transforms.size() > 0)
361 goal_info->handle.publishFeedback(feedback);
362 ROS_DEBUG(
"Client %d: TF feedback published:", goal_info->client_ID_);
365 ROS_DEBUG(
"Client %d: No TF frame update needed:", goal_info->client_ID_);
371 if (request_info->pub_.getNumSubscribers() == 0)
373 request_info->unsub_timer_.start();
377 request_info->unsub_timer_.stop();
380 tf2_web_republisher::TFArray array_msg;
382 array_msg.transforms);
384 if (array_msg.transforms.size() > 0)
387 request_info->pub_.publish(array_msg);
388 ROS_DEBUG(
"Request %d: TFs published:", request_info->client_ID_);
392 ROS_DEBUG(
"Request %d: No TF frame update needed:", request_info->client_ID_);
397 int main(
int argc,
char **argv)
399 ros::init(argc, argv,
"tf2_web_republisher");
unsigned int client_ID_count_
TFTransformServer::GoalHandle GoalHandle
void goalCB(GoalHandle gh)
int main(int argc, char **argv)
void setTargetFrame(const std::string &target_frame)
boost::mutex goals_mutex_
void setSourceFrame(const std::string &source_frame)
void setSubscriptions(boost::shared_ptr< ClientInfo > info, const std::vector< std::string > &source_frames, const std::string &target_frame_, float angular_thres, float trans_thres) const
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
bool requestCB(Request &req, Response &res)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
boost::shared_ptr< const Goal > getGoal() const
ROSCPP_DECL const std::string & getName()
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
tf2::TransformListener tf_listener_
boost::mutex requests_mutex_
tf2_web_republisher::RepublishTFs::Request Request
void setCanceled(const Result &result=Result(), const std::string &text=std::string(""))
ros::Duration unsub_timeout_
ROSCPP_DECL void spin(Spinner &spinner)
void setAccepted(const std::string &text=std::string(""))
void unadvertiseCB(boost::shared_ptr< ClientRequestInfo > request_info, const ros::TimerEvent &)
TFRepublisher(const std::string &name)
void processRequest(boost::shared_ptr< ClientRequestInfo > request_info, const ros::TimerEvent &)
void processGoal(boost::shared_ptr< ClientGoalInfo > goal_info, const ros::TimerEvent &)
std::list< boost::shared_ptr< ClientGoalInfo > > active_goals_
boost::mutex tf_buffer_mutex_
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
void setTransThres(float trans_thres)
void updateSubscriptions(std::vector< TFPair > &tf_subscriptions, std::vector< geometry_msgs::TransformStamped > &transforms)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void setAngularThres(float angular_thres)
std::list< boost::shared_ptr< ClientRequestInfo > > active_requests_
#define ROS_INFO_STREAM(args)
ros::ServiceServer tf_republish_service_
actionlib::ActionServer< tf2_web_republisher::TFSubscriptionAction > TFTransformServer
void cancelCB(GoalHandle gh)
const std::string cleanTfFrame(const std::string frame_id) const
std::vector< TFPair > tf_subscriptions_
tf2_web_republisher::RepublishTFs::Response Response