ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

In the end, I've found a solution. Using a global variable std::weak_ptr<MyNode> MyNode::instance_;, I've initialized it in the main and registered it as a signal handler:

// Set the instance pointer to the shared pointer of the main node
MyNode::setInstance(node);
// Register the signal handler for SIGINT (CTRL+C)
signal(SIGINT, MyNode::signalHandler);

before adding and spinning the node.

I had to add some function to the node, of course:

class MyNode : public rclcpp::Node {
    public:
        std::atomic<bool> is_terminated_ {false};
        void stopThread();
        void startThread();
        static void signalHandler(int signum);
        static std::shared_ptr<MyNode> getInstance();
        static void setInstance(rclcpp::Node::SharedPtr instance);
    private:
        std::thread helping_thread_;
        static std::weak_ptr<MyNode> instance_; // Weak pointer to the instance of the node
}

void MyNode::setInstance(rclcpp::Node::SharedPtr instance) {
    instance_ = std::static_pointer_cast<MyNode>(instance);
}

std::shared_ptr<MyNode> MyNode::getInstance() {
    return instance_.lock();
}

void MyNode::signalHandler(int signum) {
    // Stop the thread gracefully
    std::shared_ptr<MyNode> node = getInstance();
        if (node) {
            node->stopThread();
        }

    rclcpp::shutdown();
}

void MyNode::startThread() {
    if (!this->helping_thread_.joinable()) {
        this->helping_thread_ = std::thread(&MyNode::spawnedThread, this);
    }
}

void MyNode::stopThread() {
    if (this->helping_thread_.joinable()) {
        this->is_terminated_ = true;
        this->helping_thread_.join();
    }
}

where spawnedThread is the main function used in the additional thread.

I don't really like using global variables and such, but for now this works as intended.