鱼香ROS社区
    • 版块
    • 最新
    • 未解决
    • 已解决
    • 群组
    • 注册
    • 登录
    紧急通知:禁止一切关于政治&VPN翻墙等话题,发现相关帖子会立马删除封号
    提问前必看的发帖注意事项: 社区问答规则(小鱼个人)更新 | 高质量帖子发布指南

    ros2多线程 Callback Groups

    已定时 已固定 已锁定 已移动
    动手学ROS2
    ros2 多线程执行器
    3
    7
    345
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • C
      chenxz
      最后由 编辑

      系统版本:humble
      问题:希望通过多线程同时运行两个回调函数,但是实际上并不运行
      代码:

      #include <chrono>
      #include <memory>
      #include <rclcpp/rclcpp.hpp>
      #include "std_msgs/msg/int32.hpp"
      
      using namespace std::chrono_literals;
      
      class MultiThreadedPublisher : public rclcpp::Node
      {
      public:
        MultiThreadedPublisher() : Node("multi_threaded_publisher")
        {
      
          // // 声明回调组
          rclcpp::CallbackGroup::SharedPtr callback_group;
          rclcpp::CallbackGroup::SharedPtr callback_group_2;
      
          // // 实例化回调组
          callback_group = this->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
          callback_group_2 = this->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
      
          // callback_group = nullptr;
      
          timer1_ = this->create_wall_timer(5000ms, std::bind(&MultiThreadedPublisher::publish_message1, this), callback_group);
      
          timer2_ = this->create_wall_timer(1000ms, std::bind(&MultiThreadedPublisher::publish_message2, this), callback_group_2);
        }
      
      private:
        void publish_message1()
        {
          RCLCPP_INFO(this->get_logger(), "Publishing on topic1: '%d'", 1);
        }
      
        void publish_message2()
        {
          RCLCPP_INFO(this->get_logger(), "Publishing on topic2: '%d'", 2);
        }
      
        rclcpp::TimerBase::SharedPtr timer1_;
        rclcpp::TimerBase::SharedPtr timer2_;
      };
      
      int main(int argc, char *argv[])
      {
        rclcpp::init(argc, argv);
        auto node = std::make_shared<MultiThreadedPublisher>();
      
        // 使用多线程执行器
        rclcpp::executors::MultiThreadedExecutor executor;
        executor.add_node(node);
        executor.spin();
      
        rclcpp::shutdown();
        return 0;
      }
      
      小鱼小 1 条回复 最后回复 回复 引用 0
      • 小伊小
        机器人小伊
        最后由 编辑

        在您的代码中,您已经正确地设置了两个独立的回调组,并将它们分别绑定到不同的定时器回调上。但是,有一些小问题和潜在的误解需要澄清:

        1. 回调组的类型:您使用了rclcpp::CallbackGroupType::MutuallyExclusive,这意味着尽管回调在不同的组中,但它们在同一个线程中顺序执行。如果您希望每个回调在不同的线程中并行执行,应该使用rclcpp::CallbackGroupType::Reentrant或rclcpp::CallbackGroupType::Async。然而,对于定时器和大多数ROS 2节点,通常推荐使用rclcpp::CallbackGroupType::Reentrant,因为它允许回调在多个线程中安全地被调用,但同一个回调组的回调不会并发执行。

        2. 回调的实际执行:您的回调函数实际上是在打印日志,而不是发布消息(尽管函数名暗示了发布消息)。如果您的目的是测试多线程行为,这并不影响,但如果您计划在生产代码中使用,请确保回调执行的是您预期的操作。

        3. 日志输出:由于日志输出可能不是线程安全的(尤其是在不同线程中同时写入同一个日志时),您可能会看到日志输出的顺序与预期不符。这不一定表示多线程执行有问题,而是日志系统的行为。

        让我们修改代码,将回调组类型更改为rclcpp::CallbackGroupType::Reentrant,并稍微调整代码格式:

        #include <chrono>
        #include <memory>
        #include <rclcpp/rclcpp.hpp>
        #include "std_msgs/msg/int32.hpp"
        
        using namespace std::chrono_literals;
        
        class MultiThreadedPublisher : public rclcpp::Node
        {
        public:
          MultiThreadedPublisher() : Node("multi_threaded_publisher")
          {
            // 声明并实例化回调组
            rclcpp::CallbackGroup::SharedPtr callback_group = this->create_callback_group(rclcpp::CallbackGroupType::Reentrant);
            rclcpp::CallbackGroup::SharedPtr callback_group_2 = this->create_callback_group(rclcpp::CallbackGroupType::Reentrant);
        
            timer1_ = this->create_wall_timer(
              5000ms, std::bind(&MultiThreadedPublisher::publish_message1, this), callback_group);
        
            timer2_ = this->create_wall_timer(
              1000ms, std::bind(&MultiThreadedPublisher::publish_message2, this), callback_group_2);
          }
        
        private:
          void publish_message1()
          {
            RCLCPP_INFO(this->get_logger(), "Publishing on topic1: '%d'", 1);
          }
        
          void publish_message2()
          {
            RCLCPP_INFO(this->get_logger(), "Publishing on topic2: '%d'", 2);
          }
        
          rclcpp::TimerBase::SharedPtr timer1_;
          rclcpp::TimerBase::SharedPtr timer2_;
        };
        
        int main(int argc, char *argv[])
        {
          rclcpp::init(argc, argv);
          auto node = std::make_shared<MultiThreadedPublisher>();
        
          // 使用多线程执行器
          rclcpp::executors::MultiThreadedExecutor executor;
          executor.add_node(node);
          executor.spin();
        
          rclcpp::shutdown();
          return 0;
        }
        

        现在,您的回调函数应该在不同的线程中并行执行(具体取决于执行器的线程池大小和执行器的调度策略)。如果您希望进一步控制线程的数量或行为,您可能需要调整执行器的配置。


        以上为生成回答,仅供参考~

        我是小伊,已接入ChatGpt,所有回复,仅供参考~

        C 1 条回复 最后回复 回复 引用 0
        • C
          chenxz @小伊
          最后由 编辑

          @小伊 仍然不能正常输出

          1 条回复 最后回复 回复 引用 0
          • 小伊小
            机器人小伊
            最后由 编辑

            如果你遇到了“仍然不能正常输出”的问题,这通常意味着某个系统、程序或设备没有按预期工作。为了帮助你解决这个问题,我需要更多的具体信息,因为“不能正常输出”可以涉及很多不同的领域和情况。以下是一些可能的情况和相应的解决步骤:

            1. 电脑程序或软件:

              • 检查错误消息:查看程序是否给出了任何错误消息或代码。
              • 更新软件:确保你的软件是最新版本,有时候问题可能由旧版本的bug引起。
              • 重新安装:如果更新后问题依旧,尝试卸载后重新安装软件。
              • 兼容性检查:确保你的操作系统与软件兼容。
              • 查看日志:检查程序的日志文件,可能会有更多关于问题的详细信息。
            2. 打印机:

              • 检查连接:确保打印机与电脑正确连接(USB、Wi-Fi等)。
              • 墨盒/碳粉:检查墨盒或碳粉是否耗尽,需要更换。
              • 打印队列:查看打印队列,确保没有卡住的打印任务。
              • 驱动程序:确保打印机驱动程序是最新的,有时候旧的驱动程序会导致问题。
              • 打印机设置:检查打印机设置,确保没有错误的配置。
            3. 电子设备(如电视、显示器):

              • 检查输入源:确保设备已正确连接到正确的输入源(HDMI、AV、VGA等)。
              • 电源和电缆:检查电源线和所有连接电缆是否牢固连接。
              • 显示设置:在设备的菜单中检查显示设置,确保没有错误的配置。
              • 重启设备:有时候简单的重启可以解决问题。
            4. 网站或在线服务:

              • 网络连接:检查你的网络连接是否稳定。
              • 浏览器问题:尝试使用不同的浏览器访问,看看问题是否依旧。
              • 清除缓存和Cookie:有时候浏览器的缓存和Cookie可能导致显示问题。
              • 服务状态:检查该网站或服务是否正在维护或遇到技术问题。
            5. 编程和代码:

              • 调试信息:使用调试工具查看程序的执行过程和变量值。
              • 日志输出:增加日志输出点,帮助追踪问题发生的位置。
              • 检查代码:仔细检查相关代码,看是否有逻辑错误或遗漏。
              • 编译器/解释器版本:确保你使用的编译器或解释器是支持你的代码的。

            如果你能提供更多的上下文或详细描述你的问题,我可以给出更具体的建议。


            以上为生成回答,仅供参考~

            我是小伊,已接入ChatGpt,所有回复,仅供参考~

            1 条回复 最后回复 回复 引用 0
            • 小鱼小
              小鱼 技术大佬 @chenxz
              最后由 编辑

              @chenxz 在 ros2多线程 Callback Groups 中说:

              // // 声明回调组
              rclcpp::CallbackGroup::SharedPtr callback_group;
              rclcpp::CallbackGroup::SharedPtr callback_group_2;
              

              看起来没什么问题,运行结果看看,另外这两个定义提到成员变量处看看

              新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

              C 1 条回复 最后回复 回复 引用 0
              • C
                chenxz @小鱼
                最后由 编辑

                @小鱼 非常感谢,按照您说的改了一下就可以运行了。方便问一下这是为什么吗,找了很多种方式,没想到改了两个成员变量的位置就行了。😆

                #include <chrono>
                #include <memory>
                #include <rclcpp/rclcpp.hpp>
                #include "std_msgs/msg/int32.hpp"
                #include <thread>
                
                using namespace std::chrono_literals;
                
                class MultiThreadedPublisher : public rclcpp::Node
                {
                public:
                  MultiThreadedPublisher() : Node("multi_threaded_publisher")
                  {
                
                    // // 实例化回调组
                    callback_group = this->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
                    callback_group_2 = this->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
                
                    // callback_group = nullptr;
                
                    timer1_ = this->create_wall_timer(std::chrono::milliseconds(5000), std::bind(&MultiThreadedPublisher::publish_message1, this), callback_group);
                    timer2_ = this->create_wall_timer(std::chrono::milliseconds(1000), std::bind(&MultiThreadedPublisher::publish_message2, this), callback_group_2);
                  }
                
                private:
                  void publish_message1()
                  {
                    RCLCPP_INFO(this->get_logger(), "Publishing on topic1: '%d'", 1);
                  }
                
                  void publish_message2()
                  {
                    RCLCPP_INFO(this->get_logger(), "Publishing on topic2: '%d'", 2);
                  }
                
                  rclcpp::TimerBase::SharedPtr timer1_;
                  rclcpp::TimerBase::SharedPtr timer2_;
                  // // 声明回调组
                  rclcpp::CallbackGroup::SharedPtr callback_group;
                  rclcpp::CallbackGroup::SharedPtr callback_group_2;
                };
                
                int main(int argc, char *argv[])
                {
                  rclcpp::init(argc, argv);
                  rclcpp::executors::MultiThreadedExecutor executor(rclcpp::ExecutorOptions(), 20, true);
                  auto node = std::make_shared<MultiThreadedPublisher>();
                  executor.add_node(node);
                  executor.spin();
                  rclcpp::shutdown();
                  return 0;
                }
                
                小鱼小 1 条回复 最后回复 回复 引用 0
                • 小鱼小
                  小鱼 技术大佬 @chenxz
                  最后由 编辑

                  @chenxz 如果可以就是一个基础问题,构造函数运行完,他们两个被释放了

                  新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

                  1 条回复 最后回复 回复 引用 0
                  • 第一个帖子
                    最后一个帖子
                  皖ICP备16016415号-7
                  Powered by NodeBB | 鱼香ROS