按照我的步骤一步步来,实现订阅与发布的功能。
一、搭建基本的东西(工作空间与功能包)
1、工作空间
mkdir -p 自定义空间名称/src
cd 自定义空间名称
catkin_make
2.进入 src 创建 ros 包并添加依赖
cd src
catkin_create_pkg 自定义ROS包名 roscpp rospy std_msgs
在我们这个例子中用plumbing_pub_sub
所以
catkin_create_pkg plumbing_pub_sub roscpp rospy std_msgs
然后在src下创建一个demo01_pub.cpp
#include "ros/ros.h"
#include "std_msgs/String.h"
/*
发布方实现:
1、包含头文件
ROS中文本类型 ---> std_msgs/String.h
2、初始化ROS节点
3、创建节点句柄
4、创建发布者对象
5、编写发布逻辑并发布数据
*/
int main(int argc, char *argv[])
{
// 2、初始化 ROS 节点;
ros::init(argc,argv,"erGouZi");
// 3、创建节点句柄 ;
ros::NodeHandle nh;
// 4、茶ungjian发布者对象
ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10);
// 5、编写发布逻辑并发布数据
//先创建被发布的消息
std_msgs::String msg;
//编写循环,循环中发布数据
while (ros::ok())
{
msg.data = "hello";
pub.publish(msg);
}
return 0;
}
-
ros::init(argc,argv,"erGouZi");
: 初始化ROS节点,节点名为"erGouZi"。 -
ros::NodeHandle nh;
: 创建一个节点句柄,用于创建发布者和订阅者。 -
ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10);
: 创建一个发布者对象,用于发布std_msgs::String
类型的消息到"fang"话题,第二个参数10表示消息队列的大小。 -
std_msgs::String msg;
: 创建一个std_msgs::String
类型的消息实例。 -
while (ros::ok())
: 一个无限循环,只要节点没有被关闭,循环就会继续。 -
msg.data = "hello";
: 设置消息的数据字段为字符串"hello"。 -
pub.publish(msg);
: 使用发布者对象发布消息。
接着来到这个文件
改这两个
一切准备就绪!
接着打开一个终端输入roscore,开启核心
然后开启另一个终端,输入
再另一终端去订阅发布,fang是话题名
效果如下:
案例二
我们现在要换成
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
/*
发布方实现:
1、包含头文件
ROS中文本类型 ---> std_msgs/String.h
2、初始化ROS节点
3、创建节点句柄
4、创建发布者对象
5、编写发布逻辑并发布数据
*/
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
// 2、初始化 ROS 节点;
ros::init(argc,argv,"erGouZi");
// 3、创建节点句柄 ;
ros::NodeHandle nh;
// 4、茶ungjian发布者对象
ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10);
// 5、编写发布逻辑并发布数据
//要求以 10HZ 的频率发布数据,并且文本后添加编码
//先创建被发布的消息
std_msgs::String msg;
//发布频率
ros::Rate rate(10);
//编写循环,循环中发布数据
//设置编号、
int count = 0;
while (ros::ok())
{
count++;
// msg.data = "hello";
//实现字符串拼接数字
std::stringstream ss;
ss << "hello ---> " << count;
msg.data = ss.str();
pub.publish(msg);
//添加日志
ROS_INFO("发布的数据是:%s",ss.str().c_str());
rate.sleep();
}
return 0;
}
记住!每次重新编写cpp文件都得catkin_make一下,否则根本就不会刷新数据。
重新运行一下,发布方按照代码执行日志输出
订阅方订阅到数据
PS:复习一下一些重要的概念:
ROS中,节点句柄(Node Handle)是一个对象,它提供了对ROS节点的控制与访问,以下是节点句柄的一些主要功能:
1、初始化节点:节点句柄用于初始化节点,使其成为ROS通信系统中的一部分。
2、创建发布者和订阅者:节点句柄允许你创建发布者(Publisher)和订阅者(Subscriber),用于发布和接收消息。
3、访问参数服务器:节点句柄提供了访问参数服务器(Parameter Server)的功能,你可以使用它来设置或获取参数。
4、获取节点名称:节点句柄可以获取当前节点的名称。
5、管理回调队列:节点句柄可以设置回调队列(Callback Queue),用于控制回调函数的执行顺序。
6、获取时间信息:节点句柄可以获取ROS时间(包括当前时间、时间戳等)。
7、获取节点的URI:节点句柄可以获取节点的URI,这在分布式系统中非常有用。
C++ 示例
#include "ros/ros.h"
int main(int argc, char **argv)
{
// 初始化节点
ros::init(argc, argv, "my_node");
// 创建节点句柄
ros::NodeHandle nh;
// 使用节点句柄创建发布者
ros::Publisher pub = nh.advertise<std_msgs::String>("topic", 10);
// ... 其他操作 ...
return 0;
}
Python 示例
#!/usr/bin/env python
import rospy
def main():
# 初始化节点
rospy.init_node('my_node')
# 获取节点句柄
nh = rospy.get_node_handle()
# 使用节点句柄创建发布者
pub = nh.advertise(std_msgs.msg.String, 'topic', 10)
# ... 其他操作 ...
if __name__ == '__main__':
main()