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
我的疑问
- 明明是在单线程的定时器回调里调用
trylock(),为什么还会频繁出现锁失败?难道RealtimePublisher的锁还会和ROS2的其他线程产生竞争? - 1ms的发布周期是不是太密集了?如果是,有没有什么办法可以优化,既保证发布频率又减少锁失败?
- 是不是我对
RealtimePublisher的使用姿势不对?有没有更规范的用法可以避免这个问题?
麻烦各位大佬帮忙看看,谢谢啦!
内容来源于stack exchange
相关产品推荐
相关产品推荐

