20#include "rclcpp/qos.hpp"
21#include "behaviortree_cpp/condition_node.h"
32template <
class MessageT>
35 using Publisher =
typename rclcpp::Publisher<MessageT>;
43 const rclcpp::QoS& qos = { 10 });
56 BT::PortsList basic = { BT::InputPort<std::string>(
"topic_name",
"",
"Topic name") };
57 basic.insert(addition.begin(), addition.end());
70 BT::NodeStatus
tick() override final;
91 const rclcpp::QoS qos_;
92 std::
string topic_name_;
93 bool topic_name_should_be_checked_ = false;
94 std::shared_ptr<Publisher> publisher_;
96 bool createPublisher(const std::
string& topic_name);
103template <class MessageT>
105 const
Context& context, const rclcpp::QoS& qos)
106 : BT::ConditionNode(instance_name, config),
logger_(context.getLogger()), context_(context), qos_{ qos }
109 auto portIt = config.input_ports.find(
"topic_name");
110 if (portIt != config.input_ports.end())
112 const std::string& bb_topic_name = portIt->second;
114 if (isBlackboardPointer(bb_topic_name))
117 topic_name_should_be_checked_ =
true;
119 else if (!bb_topic_name.empty())
122 createPublisher(bb_topic_name);
132template <
class MessageT>
133inline bool RosPublisherNode<MessageT>::createPublisher(
const std::string& topic_name)
135 if (topic_name.empty())
137 throw exceptions::RosNodeError(
getFullName() +
" - Argument topic_name is empty when trying to create a client.");
144 " - The shared pointer to the ROS node went out of scope. The tree node doesn't "
145 "take the ownership of the node.");
148 publisher_ = node->template create_publisher<MessageT>(topic_name, qos_);
149 topic_name_ = topic_name;
150 RCLCPP_DEBUG(
logger_,
"%s - Created publisher for topic '%s'.",
getFullName().c_str(), topic_name.c_str());
154template <
class MessageT>
160 if (!publisher_ || (status() == BT::NodeStatus::IDLE && topic_name_should_be_checked_))
162 std::string topic_name;
163 getInput(
"topic_name", topic_name);
164 if (topic_name_ != topic_name)
166 createPublisher(topic_name);
173 " - You must specify a service name either by using a default value or by "
174 "passing a value to the corresponding dynamic input port.");
180 return BT::NodeStatus::FAILURE;
182 publisher_->publish(msg);
183 return BT::NodeStatus::SUCCESS;
186template <
class MessageT>
192template <
class MessageT>
197 if (registrationName().empty())
199 if (this->name() == this->registrationName())
201 return this->name() +
" (Type: " + this->registrationName() +
")";
204template <
class MessageT>
Abstract class to wrap a ROS publisher.
std::string getFullName() const
const Context & getRosContext()
RosPublisherNode(const std::string &instance_name, const Config &config, const Context &context, const rclcpp::QoS &qos={ 10 })
virtual ~RosPublisherNode()=default
virtual bool setMessage(MessageT &msg)
setMessage is a callback invoked in tick to allow the user to pass the message to be published.
static BT::PortsList providedBasicPorts(BT::PortsList addition)
Any subclass of RosPublisherNode that has additinal ports must provide a providedPorts method and cal...
BT::NodeStatus tick() override final
static BT::PortsList providedPorts()
Creates list of BT ports.
const rclcpp::Logger logger_
std::weak_ptr< rclcpp::Node > nh
Handle for the ROS2 node.
std::string default_port_name
Default port name of the corresponding ROS 2 communication interface.