@@ -93,6 +93,18 @@ class TransformListener
9393 TF2_ROS_PUBLIC
9494 explicit TransformListener (tf2::BufferCore & buffer, bool spin_thread = true );
9595
96+ /* * \brief Simplified constructor for transform listener with static_only option.
97+ *
98+ * This constructor will create a new ROS 2 node under the hood.
99+ * If you already have access to a ROS 2 node and you want to associate the TransformListener
100+ * to it, then it's recommended to use one of the other constructors.
101+ */
102+ TF2_ROS_PUBLIC
103+ explicit TransformListener (
104+ tf2::BufferCore & buffer,
105+ bool spin_thread,
106+ bool static_only);
107+
96108 /* * \brief Node constructor */
97109 template <class NodeT , class AllocatorT = std::allocator<void >>
98110 TransformListener (
@@ -118,6 +130,31 @@ class TransformListener
118130 static_options)
119131 {}
120132
133+ /* * \brief Node constructor with static_only option */
134+ template <class NodeT , class AllocatorT = std::allocator<void >>
135+ TransformListener (
136+ tf2::BufferCore & buffer,
137+ NodeT && node,
138+ bool spin_thread,
139+ const rclcpp::QoS & qos,
140+ const rclcpp::QoS & static_qos,
141+ const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options,
142+ const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & static_options,
143+ bool static_only)
144+ : TransformListener(
145+ buffer,
146+ node->get_node_base_interface (),
147+ node->get_node_logging_interface(),
148+ node->get_node_parameters_interface(),
149+ node->get_node_topics_interface(),
150+ spin_thread,
151+ qos,
152+ static_qos,
153+ options,
154+ static_options,
155+ static_only)
156+ {}
157+
121158 /* * \brief Node interface constructor */
122159 template <class AllocatorT = std::allocator<void >>
123160 TransformListener (
@@ -147,6 +184,35 @@ class TransformListener
147184 static_options);
148185 }
149186
187+ /* * \brief Node interface constructor with static_only option */
188+ template <class AllocatorT = std::allocator<void >>
189+ TransformListener (
190+ tf2::BufferCore & buffer,
191+ rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
192+ rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
193+ rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters,
194+ rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics,
195+ bool spin_thread,
196+ const rclcpp::QoS & qos,
197+ const rclcpp::QoS & static_qos,
198+ const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options,
199+ const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & static_options,
200+ bool static_only)
201+ : buffer_(buffer)
202+ {
203+ init (
204+ node_base,
205+ node_logging,
206+ node_parameters,
207+ node_topics,
208+ spin_thread,
209+ qos,
210+ static_qos,
211+ options,
212+ static_options,
213+ static_only);
214+ }
215+
150216 TF2_ROS_PUBLIC
151217 virtual ~TransformListener ();
152218
@@ -216,6 +282,71 @@ class TransformListener
216282 }
217283 }
218284
285+ // Overload of init() with the static_only flag
286+ template <class AllocatorT = std::allocator<void >>
287+ void init (
288+ rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
289+ rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
290+ rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters,
291+ rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics,
292+ bool spin_thread,
293+ const rclcpp::QoS & qos,
294+ const rclcpp::QoS & static_qos,
295+ const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options,
296+ const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & static_options,
297+ bool static_only)
298+ {
299+ if (!static_only) {
300+ init (
301+ node_base,
302+ node_logging,
303+ node_parameters,
304+ node_topics,
305+ spin_thread,
306+ qos,
307+ static_qos,
308+ options,
309+ static_options);
310+ return ;
311+ }
312+
313+ spin_thread_ = spin_thread;
314+ node_base_interface_ = node_base;
315+ node_logging_interface_ = node_logging;
316+
317+ using callback_t = std::function<void (tf2_msgs::msg::TFMessage::ConstSharedPtr)>;
318+ callback_t static_cb = std::bind (
319+ &TransformListener::subscription_callback, this , std::placeholders::_1, true );
320+
321+ if (spin_thread_) {
322+ callback_group_ = node_base_interface_->create_callback_group (
323+ rclcpp::CallbackGroupType::MutuallyExclusive, false );
324+ rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> tf_static_options = static_options;
325+ tf_static_options.callback_group = callback_group_;
326+
327+ message_subscription_tf_static_ = rclcpp::create_subscription<tf2_msgs::msg::TFMessage>(
328+ node_parameters,
329+ node_topics,
330+ " /tf_static" ,
331+ static_qos,
332+ std::move (static_cb),
333+ tf_static_options);
334+
335+ executor_ = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
336+ executor_->add_callback_group (callback_group_, node_base_interface_);
337+ dedicated_listener_thread_ = std::make_unique<std::thread>([&]() {executor_->spin ();});
338+ buffer_.setUsingDedicatedThread (true );
339+ } else {
340+ message_subscription_tf_static_ = rclcpp::create_subscription<tf2_msgs::msg::TFMessage>(
341+ node_parameters,
342+ node_topics,
343+ " /tf_static" ,
344+ static_qos,
345+ std::move (static_cb),
346+ static_options);
347+ }
348+ }
349+
219350 bool spin_thread_{false };
220351 std::unique_ptr<std::thread> dedicated_listener_thread_ {nullptr };
221352 rclcpp::Executor::SharedPtr executor_ {nullptr };
@@ -231,6 +362,78 @@ class TransformListener
231362 rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface_ {nullptr };
232363 rclcpp::CallbackGroup::SharedPtr callback_group_{nullptr };
233364};
365+
366+ /* * \brief Convenience class for subscribing to static-only transforms
367+ *
368+ * While users can achieve the same thing with a normal TransformListener, the number of parameters that must be
369+ * provided is unwieldy.
370+ */
371+ class StaticTransformListener : public TransformListener
372+ {
373+ public:
374+ /* * \brief Simplified constructor for a static transform listener
375+ * \see the simplified TransformListener documentation
376+ */
377+ TF2_ROS_PUBLIC
378+ explicit StaticTransformListener (tf2::BufferCore & buffer, bool spin_thread = true )
379+ : TransformListener(buffer, spin_thread, true )
380+ {
381+ }
382+
383+ /* * \brief Node constructor */
384+ template <class NodeT , class AllocatorT = std::allocator<void >>
385+ StaticTransformListener (
386+ tf2::BufferCore & buffer,
387+ NodeT && node,
388+ bool spin_thread = true ,
389+ const rclcpp::QoS & static_qos = StaticListenerQoS(),
390+ const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & static_options =
391+ detail::get_default_transform_listener_static_sub_options<AllocatorT>())
392+ : TransformListener(
393+ buffer,
394+ node,
395+ spin_thread,
396+ rclcpp::QoS (1 ),
397+ static_qos,
398+ rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>(),
399+ static_options,
400+ true)
401+ {
402+ }
403+
404+ /* * \brief Node interface constructor */
405+ template <class AllocatorT = std::allocator<void >>
406+ StaticTransformListener (
407+ tf2::BufferCore & buffer,
408+ rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
409+ rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
410+ rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters,
411+ rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics,
412+ bool spin_thread = true ,
413+ const rclcpp::QoS & static_qos = StaticListenerQoS(),
414+ const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & static_options =
415+ detail::get_default_transform_listener_static_sub_options<AllocatorT>())
416+ : TransformListener(
417+ buffer,
418+ node_base,
419+ node_logging,
420+ node_parameters,
421+ node_topics,
422+ spin_thread,
423+ rclcpp::QoS (1 ),
424+ static_qos,
425+ rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>(),
426+ static_options,
427+ true)
428+ {
429+ }
430+
431+ TF2_ROS_PUBLIC
432+ virtual ~StaticTransformListener ()
433+ {
434+ }
435+ };
436+
234437} // namespace tf2_ros
235438
236439#endif // TF2_ROS__TRANSFORM_LISTENER_HPP_
0 commit comments