botamochi6277
botamochi6277

Reputation: 33

ROS 2 Subscriber Callback with a method of member class

I'd like to use member class method in callback function. The following C++ code is a simple subscriber with a callback using a member class method hello().

#include <functional>
#include <memory>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

using std::placeholders::_1;

class Subclass
{
private:
public:
    Subclass(/* args */);
    ~Subclass();
    std::string hello(std::string &s)
    {
        return "Hello " + s;
    }
};

class MinimalSubscriber : public rclcpp::Node
{
public:
    MinimalSubscriber()
        : Node("minimal_subscriber")
    {
        subscription_ = this->create_subscription<std_msgs::msg::String>(
            "topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));
    }

private:
    Subclass subclass_;
    void topic_callback(const std_msgs::msg::String::SharedPtr msg) const
    {
        std::string s = subclass_.hello(msg->data);
        RCLCPP_INFO(this->get_logger(), "I heard: '%s'", s.c_str());
    }
    rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};

int main(int argc, char *argv[])
{
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<MinimalSubscriber>());
    rclcpp::shutdown();
    return 0;
}

I build the C++ code and I catch below message. How I fix the code? ROS2 Foxy in Ubuntu LTS 20.04 is used to build.

/home/ubuntu/dev_ws/src/ros2_pigpio/src/subclass.cpp: In member function ‘void MinimalSubscriber::topic_callback(std_msgs::msg::String_<std::allocator<void> >::SharedPtr) const’:
/home/ubuntu/dev_ws/src/ros2_pigpio/src/subclass.cpp:35:50: error: passing ‘const Subclass’ as ‘this’ argument discards qualifiers [-fpermissive]
   35 |         std::string s = subclass_.hello(msg->data);
      |                                                  ^
/home/ubuntu/dev_ws/src/ros2_pigpio/src/subclass.cpp:15:17: note:   in call to std::string Subclass::hello(std::string&)’
   15 |     std::string hello(std::string &s)
      |                 ^~~~~
make[2]: *** [CMakeFiles/subclass.dir/build.make:63: CMakeFiles/subclass.dir/src/subclass.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:84: CMakeFiles/subclass.dir/all] Error 2
make: *** [Makefile:141: all] Error 2

Upvotes: 0

Views: 6779

Answers (3)

aurelia
aurelia

Reputation: 687

You were getting an error because MinimalSubscriber::topic_callback was marked as const - that is, calling will not change any of the member variables.

Subclass::hello was not marked as const - that means that member variables could be changed after calling it. So, it could change this - a Subclass instance.

So, MinimalSubscriber::topic_callback guarantees that none of the member variables will change during its execution, but Subclass::hello doesn't.

Upvotes: 0

botamochi6277
botamochi6277

Reputation: 33

I could build following one.

#include <functional>
#include <memory>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

using std::placeholders::_1;

class Subclass
{
private:
public:
    Subclass(/* args */){};
    ~Subclass(){};
    std::string hello(std::string &s) const
    {
        return "Hello " + s;
    }
};

class MinimalSubscriber : public rclcpp::Node
{
public:
    MinimalSubscriber()
        : Node("minimal_subscriber")
    {
        subscription_ = this->create_subscription<std_msgs::msg::String>(
            "topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));
    }

private:
    Subclass subclass_;
    void topic_callback(const std_msgs::msg::String::SharedPtr msg) const
    {
        std::string s = subclass_.hello(msg->data);
        RCLCPP_INFO(this->get_logger(), "I heard: '%s'", s.c_str());
    }
    rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};

int main(int argc, char *argv[])
{
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<MinimalSubscriber>());
    rclcpp::shutdown();
    return 0;
}

Upvotes: 1

dawnb
dawnb

Reputation: 84

First of all if you pass the msg->data as a string use msg->data.c_str(). Thereupon, i believe your std::string hello(std::string &s) method has to be static in this context or you have to create an instance of the subclass with the constructor.

Upvotes: -1

Related Questions