You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ROS2 Humble单线程节点中RealtimePublisher trylock()频繁失败的问题求助

ROS2 Humble单线程节点中RealtimePublisher trylock()频繁失败的问题求助

大家好,我在ROS2 Humble环境里用realtime_tools的RealtimePublisher做测试时碰到了个头疼的问题,想请各位帮忙分析下原因。

我写了一个生命周期节点,实例化了4个RealtimePublisher,然后用1ms周期的定时器在单线程回调里依次调用它们的发布逻辑。结果运行的时候控制台老是弹出Failed to lock publisher的警告,虽然话题的发布频率接近预期的1000Hz,但锁失败的情况太频繁了,我有点搞不懂为啥单线程里还会出现锁竞争?

下面是我的实现细节:


实现代码

src/main.cpp

#include <rclcpp/rclcpp.hpp>
#include <rclcpp_lifecycle/lifecycle_node.hpp>
#include <realtime_tools/realtime_publisher.hpp>
#include <std_msgs/msg/string.hpp>

class MyNode : public rclcpp_lifecycle::LifecycleNode {
public:
  MyNode(rclcpp::NodeOptions &options)
      : rclcpp_lifecycle::LifecycleNode("test_node", options.allow_undeclared_parameters(true).automatically_declare_parameters_from_overrides(true)) {
    rt_pub1_ = std::make_shared<realtime_tools::RealtimePublisher<std_msgs::msg::String>>(this->create_publisher<std_msgs::msg::String>("/test_topic1", 10));
    rt_pub2_ = std::make_shared<realtime_tools::RealtimePublisher<std_msgs::msg::String>>(this->create_publisher<std_msgs::msg::String>("/test_topic2", 10));
    rt_pub3_ = std::make_shared<realtime_tools::RealtimePublisher<std_msgs::msg::String>>(this->create_publisher<std_msgs::msg::String>("/test_topic3", 10));
    rt_pub4_ = std::make_shared<realtime_tools::RealtimePublisher<std_msgs::msg::String>>(this->create_publisher<std_msgs::msg::String>("/test_topic4", 10));

    timer_ = this->create_wall_timer(
        std::chrono::milliseconds(1),
        [this]() {
          publishMessage(rt_pub1_, "Hello from topic 1!");
          publishMessage(rt_pub2_, "Hello from topic 2!");
          publishMessage(rt_pub3_, "Hello from topic 3!");
          publishMessage(rt_pub4_, "Hello from topic 4!");
        });
  }

  ~MyNode() {}

private:
  void publishMessage(realtime_tools::RealtimePublisherSharedPtr<std_msgs::msg::String> &pub, const std::string &message) {
    if (pub->trylock()) {
      pub->msg_.data = message;
      pub->unlockAndPublish();
    } else {
      RCLCPP_WARN(this->get_logger(), "Failed to lock publisher");
    }
  }

  rclcpp::TimerBase::SharedPtr timer_;
  realtime_tools::RealtimePublisherSharedPtr<std_msgs::msg::String> rt_pub1_;
  realtime_tools::RealtimePublisherSharedPtr<std_msgs::msg::String> rt_pub2_;
  realtime_tools::RealtimePublisherSharedPtr<std_msgs::msg::String> rt_pub3_;
  realtime_tools::RealtimePublisherSharedPtr<std_msgs::msg::String> rt_pub4_;
};

int main(int argc, char **argv) {
  rclcpp::init(argc, argv);
  rclcpp::NodeOptions options;
  auto node = std::make_shared<MyNode>(options);
  rclcpp::spin(node->get_node_base_interface());
  rclcpp::shutdown();
  return 0;
}

package.xml

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>rt_test</name>
  <version>0.0.0</version>
  <description>A simple ROS2 lifecycle node using realtime_tools.</description>
  <maintainer email="your_email@example.com">Your Name</maintainer>
  <license>Apache License 2.0</license>

  <buildtool_depend>ament_cmake</buildtool_depend>
  <depend>rclcpp</depend>
  <depend>rclcpp_lifecycle</depend>
  <depend>realtime_tools</depend>
  <depend>std_msgs</depend>

  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>

CMakeLists.txt

cmake_minimum_required(VERSION 3.8)
project(rt_test)

if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_lifecycle REQUIRED)
find_package(realtime_tools REQUIRED)
find_package(std_msgs REQUIRED)

include_directories(
  include
  ${rclcpp_INCLUDE_DIRS}
  ${rclcpp_lifecycle_INCLUDE_DIRS}
  ${realtime_tools_INCLUDE_DIRS}
  ${std_msgs_INCLUDE_DIRS}
)

add_executable(${PROJECT_NAME} src/main.cpp)
ament_target_dependencies(${PROJECT_NAME}
  rclcpp
  rclcpp_lifecycle
  realtime_tools
  std_msgs
)

install(TARGETS ${PROJECT_NAME}
  DESTINATION lib/${PROJECT_NAME})

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()

项目目录结构

realtime_pub_test/
├── CMakeLists.txt
├── package.xml
└── src
    └── main.cpp

1 directory, 3 files

运行结果

启动节点后,控制台持续输出锁失败的警告:

exr@li9htning:~/zxm/ros_ws$ ros2 run rt_test rt_test
[WARN] [1750988390.588930275] [test_node]: Failed to lock publisher
[WARN] [1750988390.859900980] [test_node]: Failed to lock publisher
[WARN] [1750988391.261064491] [test_node]: Failed to lock publisher
[WARN] [1750988391.429071660] [test_node]: Failed to lock publisher

查看其中一个话题的发布频率,接近设定的1000Hz:

exr@li9htning:~$ ros2 topic hz /test_topic1
average rate: 999.633
min: 0.000

我的疑问

  1. 明明是在单线程的定时器回调里调用trylock(),为什么还会频繁出现锁失败?难道RealtimePublisher的锁还会和ROS2的其他线程产生竞争?
  2. 1ms的发布周期是不是太密集了?如果是,有没有什么办法可以优化,既保证发布频率又减少锁失败?
  3. 是不是我对RealtimePublisher的使用姿势不对?有没有更规范的用法可以避免这个问题?

麻烦各位大佬帮忙看看,谢谢啦!

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 10:43:02