ROS-话题编程Publisher&Subscriber

本文档记录了学习ROS过程中,基于古月老师的教程实现ROS Publisher和Subscriber节点的过程。首先,创建功能包并添加依赖,接着编写发布者和订阅者代码,发布者发送geometry_msgs/Twist消息,订阅者接收turtlesim/Pose消息并进行处理。最后,介绍了编译规则及运行步骤,包括配置CMakeLists.txt,编译代码,设置环境变量以及运行节点。

听了古月老师的ROS入门21讲,对发布者和订阅者的编程实现做一些笔记。

话题模型

ROSMaster在这里插入图片描述
ROS Master管理所有节点,这个话题模型有2个节点,Publisher&Subscriber,Publisher通过Topic总线管道发送Message给Subscriber来建立连接。

创建功能包

把功能包放入catkin_ws的工作空间中才可以,并且要添加依赖(c++库,python库,标准消息库,几何库等)。

$ cd~/catkin_ws/src
$ catkin_create_pkg learning_topic roscpp rospy std_msgs geometry_msgs turtlesim
创建Publisher&Subscriber代码
PublisherSubscriber
1.初始化ROS节点初始化ROS节点
2.向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型订阅需要的话题
3.创建消息数据循环等待话题消息,接收到消息后进入回调函数
4.按照一定频率循环发布消息在回调函数中完成消息处理

在功能包里的/src文件下创建cpp文件。

// 发布者代码
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
int main(int argc, char **argv)
{
	// ROS节点初始化
	ros::init(argc, argv, "velocity_publisher");
	// 创建节点句柄
	ros::NodeHandle n;
	// 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10
	ros::Publisher turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);
	// 设置循环的频率
	ros::Rate loop_rate(10);
	int count = 0;
	while (ros::ok())
	{
	    // 初始化geometry_msgs::Twist类型的消息
		geometry_msgs::Twist vel_msg;
		vel_msg.linear.x = 0.5;
		vel_msg.angular.z = 0.2;
        // 发布消息
		turtle_vel_pub.publish(vel_msg);
		ROS_INFO("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", 
				vel_msg.linear.x, vel_msg.angular.z);
	    // 按照循环频率延时
	    loop_rate.sleep();
	}
	return 0;
}
// 订阅者代码
#include <ros/ros.h>
#include "turtlesim/Pose.h"
// 接收到订阅的消息后,会进入消息回调函数
void poseCallback(const turtlesim::Pose::ConstPtr& msg)
{
    // 将接收到的消息打印出来
    ROS_INFO("Turtle pose: x:%0.6f, y:%0.6f", msg->x, msg->y);
}
int main(int argc, char **argv)
{
    // 初始化ROS节点
    ros::init(argc, argv, "pose_subscriber");
    // 创建节点句柄
    ros::NodeHandle n;
    // 创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallback
    ros::Subscriber pose_sub = n.subscribe("/turtle1/pose", 10, poseCallback);
    // 循环等待回调函数
    ros::spin();
    return 0;
}
编译规则

配置CMakeLists.txt
1.设置需要编译的代码和生成的可执行文件
2.设置链接库

add_executable(velocity_publisher src/velocity_publisher.cpp)
target_link_libraries(velocity_publisher ${catkin_LIBRARIES})

add_executable(pose_subscriber src/pose_subscriber.cpp)
target_link_libraries(pose_subscriber ${catkin_LIBRARIES})
编译&运行

在build文件中生成本地代码。

$ cd~/catkin_ws
$ catkin_make

配置环境变量

$ source devel/setup.bash

如果不想每次都配置,需要把这行工作空间中的环境变量代码键入到 /home下的.bashrc中

source home/<username>/catkin_ws/devel/setup.bash

运行:

$ roscore
$ rosrun turtlesim turtlesim_node
$ rosrun learning_topic velocity_publisher pose_subscriber
### ROS 中的话题编程方法 ROS(Robot Operating System)中的 **topic** 是一种异步通信机制,用于节点之间的消息传递。通过发布者-订阅者的模式,多个节点可以共享数据流。以下是关于如何在 ROS 中实现话题相关编程的方法。 #### 创建 Publisher 和 Subscriber 的基本流程 在 ROS 中创建一个简单的 publisher-subscriber 系统通常涉及以下几个方面: 1. 初始化 ROS 节点并设置名称。 2. 定义要发布的主题以及其对应的消息类型。 3. 编写逻辑以定期发送或接收消息。 对于 Python 用户来说,`rospy` 库提供了必要的功能来处理这些操作;而对于 C++ 开发人员,则会依赖于 `ros::NodeHandle` 类及其关联函数[^1]。 #### 使用 rospy 实现 Topic Communication (Python) 下面展示了一个基于 Python 的简单例子,其中包含了如何定义一个发布器(publisher)和订阅器(subscriber): ```python import rospy from std_msgs.msg import String def callback(data): rospy.loginfo(rospy.get_caller_id() + " I heard %s", data.data) def listener(): # In ROS, nodes are uniquely named. rospy.init_node('listener', anonymous=True) rospy.Subscriber("chatter", String, callback) # spin() simply keeps python from exiting until this node is stopped rospy.spin() if __name__ == '__main__': try: listener() except rospy.ROSInterruptException: pass ``` 上述脚本展示了怎样建立一个监听特定字符串型消息的主题名为 `"chatter"` 的 subscriber 。每当有新消息到达时,回调函数 `callback()` 将被触发执行,并打印接收到的内容到控制台[^2]。 同样地,在同一命名空间下也可以构建相应的 publisher: ```python #!/usr/bin/env python import rospy from std_msgs.msg import String def talker(): pub = rospy.Publisher('chatter', String, queue_size=10) rospy.init_node('talker', anonymous=True) rate = rospy.Rate(10) # 10hz while not rospy.is_shutdown(): hello_str = "hello world %s" % rospy.get_time() rospy.loginfo(hello_str) pub.publish(hello_str) rate.sleep() if __name__ == '__main__': try: talker() except rospy.ROSInterruptException: pass ``` 这段代码片段实现了向同一个主题 `"chatter"` 发送时间戳标记过的问候语句的功能[^3]。 #### 利用 roscpp 进行高级应用开发(C++) 如果偏好使用C++,那么可以通过如下方式快速搭建类似的pub/sub架构: ```cpp #include "ros/ros.h" #include "std_msgs/String.h" void chatterCallback(const std_msgs::String::ConstPtr& msg){ ROS_INFO("I heard: [%s]", msg->data.c_str()); } int main(int argc, char **argv){ ros::init(argc, argv, "listener"); ros::NodeHandle n; ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback); ros::spin(); return 0; } ``` 此 CPP 版本的 Listener 同样注册了对来自 `/chatter` 主题的数据感兴趣,并且每次当新的标准字符串到来的时候都会调用指定好的回调函数来进行日志记录[^4]. 对应的 Talker 可能看起来像这样: ```cpp #include "ros/ros.h" #include "std_msgs/String.h" int main(int argc, char **argv){ ros::init(argc, argv, "talker"); ros::NodeHandle nh; ros::Publisher chatter_pub = nh.advertise<std_msgs::String>("chatter", 1000); ros::Rate loop_rate(10); int count = 0; while (ros::ok()){ std_msgs::String msg; std::stringstream ss; ss << "hello world " << count++; msg.data = ss.str(); ROS_INFO("%s", msg.data.c_str()); chatter_pub.publish(msg); ros::spinOnce(); loop_rate.sleep(); } return 0; } ``` 以上示例说明了如何利用 C++ 来完成与之前 Python 示例相同的工作——即周期性广播带有计数器更新的信息至公共频道上供其他进程消费[^5]。 ### 总结 无论是采用哪种语言编写程序,核心概念都围绕着初始化节点、声明所需服务或者资源访问权限、最后再实际参与到具体业务逻辑当中去展开讨论。希望以上的介绍能够帮助理解有关 ROS Topics Programming Tutorial Or Methods 的基础知识!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值