1、通信原理
整个通信过程分为六步,0-4步采用RPC协议,5-6步采用TCP协议。此外,第一步和第二步不分先后,但由于talker注册需要花费时间,可能导致订阅者无法接收到前几条消息,可通过设置延迟进行解决。
0、talker注册
talker通过RPC协议向master注册节点信息:
1、listener注册
listener通过RPC协议向master注册自身信息:
2、ROS Master实现信息匹配
ROS Master根据注册表进行信息匹配,并通过RPC协议向listener发送talker的RPC地址
3、Listener向Talker发送连接请求
listener根据master提供的RPC地址,向talker发送连接请求:
4、Talker确认请求
talker接收到连接请求连接后,通过RPC协议向listener确认连接:
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
|