文章目录
1、通信原理
整个通信过程分为六步,0-4步采用RPC协议,5-6步采用TCP协议。此外,第一步和第二步不分先后,但由于talker注册需要花费时间,可能导致订阅者无法接收到前几条消息,可通过设置延迟进行解决。
0、talker注册
talker通过RPC协议向master注册节点信息:
- 话题名:bar
- RPC地址:1234
1、listener注册
listener通过RPC协议向master注册自身信息:
- 需要订阅的话题名:bar
2、ROS Master实现信息匹配
ROS Master根据注册表进行信息匹配,并通过RPC协议向listener发送talker的RPC地址
3、Listener向Talker发送连接请求
listener根据master提供的RPC地址,向talker发送连接请求:
- 订阅的话题名称
- 消息类型
- 通信协议(TCP/UDP)
4、Talker确认请求
talker接收到连接请求连接后,通过RPC协议向listener确认连接:
- TCP地址
5、建立连接
listener根据第四不的TCP地址建立连接,此时,如果ROS Master关闭,二者仍然可以建立连接
6、Talker向Listener发送信息
2、代码实现
1、C++版
- 创建工作空间并编译
mkdir -p workspace/src //创建工作空间 cd workspace //进入工作空间 catkin_make //编译,生成devel和build文件夹
- 创建ROS包并添加依赖
cd src catkin_creat_pkg 功能包名 roscpp rospy std_msgs
- C++源码实现
//1.包含头文件 #include "ros/ros.h" #include "std_msgs/String.h"//用于定义传递信息类型 #include <sstream> int main(int argc, char *argv[]){ setlocale(LC_ALL,"");//防止乱码 //2.节点初始化 //前两个参数用来传递信息,后面哪个为节点名称,在rqt_graph标识唯一 ros::init(argc,argv,"talker"); //3.创建节点句柄 ros::NodeHandle nh; //4.创建发布对象 //第一个参数为发布的话题,第二个参数为最大保存的消息数,超出时,最早进入的消息会被删除 ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",10); //5.组织被发布的数据 std_msgs::String msg;//创建要发布的数据 std::string msg_front = "hello 您好!"; int count = 0; ros::Rate r(1);//设置数据发布速率 while(ros::ok()){ std::stringstream ss; ss << msg_front << count; msg.data = ss.str(); pub.publish(msg);//发布消息 ROS_INFO("发送的消息:%s",msg.data.c_str()); r.sleep(); count++; ros::spinOnce(); } return 0; }
//1.包含头文件 #include "ros/ros.h" #include "std_msgs/String.h" void doMsg(const std_msgs::String::ConstPtr&msg_p){ ROS_INFO("我听见:%s",msg_p->data.c_str()); } int main(int argc, char *argv[]){ setlocale(LC_ALL,""); //2.初始化节点 ros::init(argc,argv,"listener"); //3.创建ROS句柄 ros::NodeHandle nh; //4.实例化订阅对象,包括话题名称,消息长度,回调函数 ros::Subscriber sub = nh.subscribe<std_msgs::String>("chatter",10,doMsg); //5.处理订阅的消息 //6.设置循环调用回调函数 ros::spin(); return 0; }
- 配置文件并编译
add_executable(Hello_pub src/Hello_pub.cpp ) add_executable(Hello_sub src/Hello_sub.cpp ) target_link_libraries(Hello_pub ${catkin_LIBRARIES} ) target_link_libraries(Hello_sub ${catkin_LIBRARIES} )
- 编译并运行
cd 工作空间 catkin_make roscore cd 工作空间 source ./devel/setup.bash rosrun 包名 节点名
2、Python版
- 创建sripts文件夹
- 代码实现
#! /usr/bin/env python #1.导包 import rospy from std_msgs.msg import String #定义数据类型的包 if __name__ == "__main__": #2.初始化ROS节点 rospy.init_node("talker_p")#节点名称唯一,否则会报错 #3.实例化发布者对象 pub = rospy.Publisher("chatter_p",String,queue_size=10) #4.组织发布数据 msg = String() msg_font = "hello python" count = 0 #设置循环频率 rate = rospy.Rate(10) while not rospy.is_shutdown(): msg.data = msg_font + str(count) pub.publish(msg) rate.sleep() rospy.loginfo("data:%s",msg.data) count += 1
#! /usr/bin/env python #1.导包 import rospy from std_msgs.msg import String def doMsg(msg): rospy.loginfo("我听见:%s",msg.data) if __name__ == "__main__": #2.初始化ROS节点 rospy.init_node("listener_p") #3.实例化订阅者 sub = rospy.Subscriber("chatter",String,doMsg,queue_size=10) #4.处理订阅的消息 #5.设置循环调用回调函数 rospy.spin()
- 配置Cmakelists.txt文件
catkin_install_python(PROGRAMS scripts/talker_p.py scripts/listener_p.py DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} )
- 运行代码
cd 工作空间 catkin_make roscore source devel/setup.bash rosrun 包名 .py