I would like to correlate the ROS documentation with its reference examples. This is a nit-picking, but I would like to know if it's ROS specific or generic C++ implementation.
Consider the create_publisher()
function defined in ROS here
template<typename MessageT , typename Alloc , typename PublisherT >
std::shared_ptr< PublisherT > rclcpp::Node::create_publisher ( const std::string & topic_name,
size_t qos_history_depth,
std::shared_ptr< Alloc > allocator = nullptr
)
Create and return a Publisher.
Parameters
[in] topic_name The topic for this publisher to publish on.
[in] qos_history_depth The depth of the publisher message queue.
[in] allocator Optional custom allocator.
Returns
Shared pointer to the created publisher.
Now, consider the code sample in its example for Creating a Publisher - here
class MinimalPublisher : public rclcpp::Node { public:
MinimalPublisher()
: Node("minimal_publisher"), count_(0)
{
publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);
timer_ = this->create_wall_timer(
500ms, std::bind(&MinimalPublisher::timer_callback, this));
}
}
Here, if we look at the definition of publisher_ shared pointer, it takes template parameter std_msgs::msg::String
as input, and parameters- topic name
and size_t
as non-type parameters. Based on some of my findings, this is a template function. So, is the right way to define such functions something like-
create_publisher<typename MessageT , typename Alloc , typename PublisherT > ( const std::string & topic_name,
size_t qos_history_depth,
std::shared_ptr< Alloc > allocator = nullptr
)
Also, that would mean Node is the template class. Then how do we access the member function without initializing the class? Does it take place in the background?
I think I am bit confused with the whole template implementation, as it doesn't follow the syntax from the template tutorials that I have seen till now.
The doxygen autogenerated docs are missing some details. If you look at the implementation:
template<
typename MessageT,
typename AllocatorT = std::allocator<void>,
typename PublisherT = rclcpp::Publisher<MessageT, AllocatorT>>
std::shared_ptr<PublisherT>
create_publisher(
const std::string & topic_name,
const rclcpp::QoS & qos,
const PublisherOptionsWithAllocator<AllocatorT> & options =
PublisherOptionsWithAllocator<AllocatorT>()
);
you see that second and third template parameters have default values, so you only need to specify the MessageT
, that will imply the publisher returned type. So, if you call
auto pub = _myNode->create_publisher<String>("chatter", 10);
the pub
will have a type std::shared_ptr<rclcpp::Publisher<String, std::allocator<void>>>
.
class Node
itself is not a template, it just has templated create_publisher
method.
In MinimalPublisher
example authors suggest to subclass rclcpp::Node
, probably for convenience - to be able to pass it directly to rclcpp::spin
function, and to make sure that publishers/timers lifetime do not exceed the lifetime of provided callback. But in principle you could achieve similar behavior by working directly with std::make_shared<rclcpp::Node>(...)
.