1

我有一个关于 ROS2 中 rclcpp 的 CallbackGroups 的问题。我正在尝试让 rclcpp::TimerBase 以指定的更新速率运行更新周期,同时节点应侦听订阅中的传入消息。据我了解,这样做的方法是将 MultiThreadExceutor 与 CallbackGroups 一起使用。因此,我创建了一个可重入类型 CallbackGroup,我在其中添加了计时器和订阅。但是,一旦我将计时器添加到 CallbackGroup,计时器就会停止工作。也许我忘记了什么?CallbackGroups 或 Node 是否需要在指定的上下文中?还是我完全误解了 CallbackGroups 的概念?很高兴得到您的任何帮助!

到目前为止我尝试了什么:SingleThreadExecutor 显示了同样的问题,删除 CallbackGroup 显示了预期的行为,计时器正在运行并调用了 update()。试图隔离问题并发现,它是在 MTE 的 run(...) 方法期间,在 wait_for_work( ...) 第 447-448 行中 Executor 的功能:

    rcl_ret_t status = rcl_wait(&wait_set_, std::chrono::duration_cast<std::chrono::nanoseconds>(timeout).count());

如果我放弃

    memory_strategy_->number_of_ready_timers()

在 MultiThreadedExecutor 中它向我显示 1,所以计时器似乎已注册,对吧?

头文件:controller_node_test/controller_node_test.h:

#ifndef CONTROLLER_NODE_H
#define CONTROLLER_NODE_H

#include "rclcpp/rclcpp.hpp"
#include "controller_node_test/multi_threaded_executor.hpp"
#include "chrono"
#include <ctime>

using std::placeholders::_1;

namespace controller_node
{
    class ControllerNode : public rclcpp::Node {
        public:
        ControllerNode();
        ~ControllerNode();

        private:

        rclcpp::TimerBase::SharedPtr update_timer_;

        void update();

    };
} // namespace controller_node

源文件:controller_node_test.cpp

#include "controller_node_test/controller_node_test.h"

namespace controller_node
{

    ControllerNode::ControllerNode() : rclcpp::Node("controller_node"){
        rclcpp::callback_group::CallbackGroup::SharedPtr update_group = this->create_callback_group(rclcpp::callback_group::CallbackGroupType::Reentrant);
        update_timer_ = this->create_wall_timer(
                                                                    std::chrono::milliseconds(100),
                                                                    std::bind(&ControllerNode::update, this),
                                                                    update_group);
    }

    ControllerNode::~ControllerNode(){

    }

    void ControllerNode::update(){
        std::cout << "Timer: " << std::this_thread::get_id() << std::endl;
    }
} // namespace controller_node

int main(int argc, char * argv[])
{
    rclcpp::init(argc, argv);
    rclcpp::executors::MultiThreadedExecutor exec;
    auto controller_node = std::make_shared<controller_node::ControllerNode>();
    exec.add_node(controller_node);
    exec.spin();
    rclcpp::shutdown();
    return 0;
}

问题是,那

    std::cout << "Timer: " << std::this_thread::get_id() << std::endl;

永远不会被调用,所以计时器根本不工作。

我删除了代码中所有不必要的部分,以使您更清楚,所以如果它没有编译,请告诉我。非常感谢任何帮助!我只是不明白那里到底发生了什么,现在我需要你的帮助......谢谢!

4

1 回答 1

1

您对如何使用 CallbackGroups 有了正确的认识。

您发布的示例不起作用的原因:在 ControllerNode 构造函数中,您声明了一个局部变量rclcpp::callback_group::CallbackGroup::SharedPtr cbg

当构造函数返回时,指针的引用计数变为 0 并被CallbackGroup销毁。您需要保留对 CallbackGroup 的引用,并且您的示例应该可以工作。

例如

class ControllerNode : public rclcpp::Node {
public:
  ControllerNode() : rclcpp::Node("controller_node") {
    cbg_ = create_callback_group(rclcpp::callback_group::CallbackGroupType::Reentrant);
    update_timer_ = create_wall_timer(
      100ms, std::bind(&ControllerNode::update, this), cbg_);
  }

private:
  rclcpp::TimerBase::SharedPtr update_timer_;
  rclcpp::callback_group::CallbackGroup::SharedPtr cbg_;
  void update() {
    std::cout << "Timer: " << std::this_thread::get_id() << std::endl;
  }
};
于 2019-10-04T22:22:09.733 回答