为何下述ROS代码仅发布一条消息?是否为ROS Noetic已知Bug?
问题描述
在Ubuntu 20.04系统上运行ROS Noetic版本,编写测试代码调用两次publish()方法,但实际仅发布一条消息。首次调用publish()时出现调试日志:
[DEBUG] [1707520305.010403219]: Trying to publish message of type [std_msgs/String/992ce8a1687cec8c8bd883ec73ca41d1] on a publisher with type [std_msgs/String/992ce8a1687cec8c8bd883ec73ca41d1]
通过在另一终端执行rostopic echo test_topic验证确实仅收到一条消息,测试代码如下:
#include <ros/ros.h> #include <iostream> #include "std_msgs/String.h" int main(int argc, char *argv[]) { ros::init(argc, argv, "test_pub_node"); ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Debug); ros::NodeHandle nh; auto pub = nh.advertise<std_msgs::String>("test_topic", 1); auto msg = boost::make_shared<std_msgs::String>(); msg->data = "hello"; usleep(1.0e6); pub.publish(msg); ros::spinOnce(); usleep(1.0e6); pub.publish(msg); ros::spinOnce(); return 0; }
请问这是否是ROS的已知Bug?
解答
这不是ROS的已知Bug,问题源于代码实现和ROS发布队列的机制:
- 队列大小限制:创建Publisher时设置的队列大小为
1,ROS最多只会缓存1条待发送的消息。 - 重复消息优化:两次发布的是同一个
boost::shared_ptr指向的相同内容的消息,ROS会判定为重复消息,当队列已满时,直接丢弃第二次的发布请求,不会将其加入队列。 - 节点退出时机:第二次
publish后仅调用一次ros::spinOnce()就立即退出节点,ROS的后台发送线程可能还没来得及处理第二次发布请求就被终止。
修复方案
- 增大队列大小:将
nh.advertise<std_msgs::String>("test_topic", 1)改为nh.advertise<std_msgs::String>("test_topic", 2),让队列能容纳多条待发送消息。 - 修改消息内容:每次发布不同的消息内容,比如第二次发布前修改
msg->data = "hello second",ROS会识别为新消息,即使队列大小为1,也会处理该发布请求。 - 延长节点存活时间:在最后一次
ros::spinOnce()后添加短暂延迟,比如usleep(500000),确保ROS有足够时间发送完所有消息再退出。
修复后的示例代码:
#include <ros/ros.h> #include <iostream> #include "std_msgs/String.h" int main(int argc, char *argv[]) { ros::init(argc, argv, "test_pub_node"); ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Debug); ros::NodeHandle nh; // 增大队列大小到2 auto pub = nh.advertise<std_msgs::String>("test_topic", 2); auto msg = boost::make_shared<std_msgs::String>(); msg->data = "hello first"; usleep(1.0e6); pub.publish(msg); ros::spinOnce(); // 修改消息内容 msg->data = "hello second"; usleep(1.0e6); pub.publish(msg); ros::spinOnce(); // 延长存活时间,确保消息发送完成 usleep(500000); return 0; }
内容的提问来源于stack exchange,提问作者Guilty Spark
相关产品推荐
相关产品推荐

