I have a need to implement a nodelet that subscribes for messages from a topic, process them and then publish to another topic.
Can this be done using a single nodelet?
Edit: I tried the below demo, but see only publishing msgs. Sub's callback are not invoked.
#include <chrono>
#include <iostream>
#include <memory>
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
using namespace std::chrono_literals;
namespace composition
{
// Create a Talker "component" that subclasses the generic rclcpp::Node base class.
// Components get built into shared libraries and as such do not write their own main functions.
// The process using the component's shared library will instantiate the class as a ROS node.
Peter::Peter()
: Node("peter"), count_(0)
{
// Create a publisher of "std_mgs/String" messages on the "chatter" topic.
pub_ = create_publisher<std_msgs::msg::String>("chatter");
// Use a timer to schedule periodic message publishing.
timer_ = create_wall_timer(1s, std::bind(&Peter::on_timer, this));
// Create a callback function for when messages are received.
// Variations of this function also exist using, for example, UniquePtr for zero-copy transport.
auto callback =
[this](const typename std_msgs::msg::String::SharedPtr msg) -> void
{
RCLCPP_INFO(this->get_logger(), "I heard: [%s]", msg->data.c_str())
std::flush(std::cout);
};
// Create a subscription to the "chatter" topic which can be matched with one or more
// compatible ROS publishers.
// Note that not all publishers on the same topic with the same type will be compatible:
// they must have compatible Quality of Service policies.
auto sub_ = create_subscription<std_msgs::msg::String>("chatter", callback);
}
void Peter::on_timer()
{
auto msg = std::make_shared<std_msgs::msg::String>();
msg->data = "Peter is here: " + std::to_string(++count_);
RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", msg->data.c_str())
std::flush(std::cout);
// Put the message into a queue to be processed by the middleware.
// This call is non-blocking.
pub_->publish(msg);
}
} // namespace composition
#include "class_loader/class_loader_register_macro.h"
// Register the component with class_loader.
// This acts as a sort of entry point, allowing the component to be discoverable when its library
// is being loaded into a running process.
CLASS_LOADER_REGISTER_CLASS(composition::Peter, rclcpp::Node)
Originally posted by petermp on ROS Answers with karma: 1 on 2018-03-27
Post score: 0
Original comments
Comment by gvdhoorn on 2018-03-28:
I've removed my answer as I'd missed the ros2
tag. The use of the term nodelet
made me think you were asking about the ROS1 concept.
Note: there are no 'nodelets' in ROS2, only nodes.
Comment by petermp on 2018-03-28:
Thanks. I am new to the forum and apparently made some edit mistakes.
I am able to get the code working and confirm that we can do both publishing and subscribing in any order using a single nodelet (in dynamic load composition example).
Peter
Comment by William on 2018-03-28:
What's missing here is the declaration of the class. I believe the bug is that pub_
is member of the class and therefore persists after the constructor, but the subscription sub_
is local to the constructor and is destroyed when it is finished. You must keep the sub_
to get callbacks.