ROS通信机制
创始人
2024-05-31 22:38:22

参考:
bilibili@Autolabor官方

回调函数:!

由外部中断激发而执行的函数,函数执行的时间不由函数本身控制,而是由外部激发

1、话题通信

​ publisher发布者,和subscriber订阅者通过topic相互连接,在同一个话题进行数据交换

publish一个0/1的信号,表示急停信号,推送到mobile_base/sensors/switch

1.1 使用场景

​ 不断更新,逻辑处理少

1.2 作用

​ 发布方以固定频率发送文本,订阅方接收文本并输出

1.3 话题通信的角色及其功能

​ master:管理者

​ 可以根据话题建立发布者和订阅者之间的连接

​ listener:订阅者

​ talker:发布者

1.4 话题通信的流程,涉及RPC与TCP协议

​ 1、talker在master注册一个话题advertise("话题名",RPC地址)

​ 2、listener在master申请订阅话题subscribe("话题名")

​ 3、若话题名匹配成功,master向listener提供话题的RPC地址

​ 4、listener通过RPC地址远程访问talker

​ 5、talker给listener发送响应,包含talker的TCP地址

​ 6、listener根据TCP地址访问talker

​ 7、talker给listener发送数据

​ 注:注册和订阅话题没有先后顺序

1.5 发布方实现 视频040

/*1.包含头文件2.初始化ROS节点3.创建节点句柄4.创建发布者对象5.编写发布逻辑并发布数据
*/
#include   //实现字符串拼接
#include "ros.h"
#include "stc_msgs/String.h"int main(int argc, char *argv[])
{setlocale(LC_ALL,""); //避免中文乱码ros::init(argc,argv,"pub"); //初始化节点ros::NodeHandle nh; //创建Node句柄ros::Publisher pub = nh.advertise("em_state",10); //创建发布者对象std_msgs::String msg; //创建发布消息ros::Rate rate(10); // 创建发布速率为10Hzint cnt=0;//ros::ok()若节点存活while(ros::ok()) //创建发布逻辑,循环发布数据{cnt++;//msg.data = "hello" ;std::stringstream ss;ss << "hello --->" << count;msg.data = ss.str(); //将stringstream中的数据转换成字符串pub.publish(msg);rate.sleep();//和ros::Rate rate(10) 配合实现每秒10次}return 0;
}

1.6 订阅方实现 视频42

/*1.包含头文件2.初始化ROS节点3.创建节点句柄4.创建订阅者对象5.处理订阅到的数据6.声明spin函数
*/
#include   //实现字符串拼接
#include "ros.h"
#include "stc_msgs/String.h"void doMsg(const std_msgs::String::ConstPtr &mas)
{//通过msg获取并操作订阅到的数据ROS_INFO("订阅的数据是:%s",msg->data.c_str()); //以日志形式输出订阅到的数据
}int main(int argc, char *argv[])
{setlocale(LC_ALL,""); //避免中文乱码ros::init(argc,argv,"sub"); //初始化节点ros::NodeHandle nh; //创建Node句柄//ros::Subscriber sub = nh.subscribe("话题名",队列长度,回调函数名)ros::Subscriber sub = nh.subscribe("em_state",10,doMsg); //创建订阅者对象ros::spin(); //字面意思:回头,再次调用回调函数doMsg   return 0;
}

2 自定义msg的实现

​ 原因:msgs只是简单的文本文件,无法对数据进行复合

​ 特殊类型:Header包含时间戳以及ROS中常用的坐标帧信息

1.6.1 编写msg文件

//在src/package下新建msg文件夹,放入msg文件
//Person.msg
string name
int32 age
float32 height

1.6.2 编写配置文件



smessage_generation
message_runtime
# cmake 修改find_package(#添加message_generation
)#添加
add_message_files(FILESPerson.msg#文件名2
)#添加
generate_messages(DEPENDENCIESstd_msgs
)#添加
catkin_package(CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
)add_dependencies(包名 ${PROJECT_NAME}_generate_message_cpp)

1.6.3 发布方 视频 注意预先设置vscode

/*发布person.msg格式的消息1.包含头文件2.初始化ROS节点3.创建节点句柄4.创建发布者对象5.编写发布逻辑并发布数据
*/
#include "包名/Person.h" //导入包
#include "ros.h"
#include "stc_msgs/String.h"int main(int argc, char *argv[])
{setlocale(LC_ALL,""); //避免中文乱码ros::init(argc,argv,"pub"); //初始化节点ros::NodeHandle nh; //创建Node句柄ros::Publisher pub = nh.advertise<包名::Person>("em_state",10); //创建发布者对象包名::Person msg; //创建发布消息msg.name = "张三";msg.age = 1;msg.height = 1.65;ros::Rate rate(1); // 创建发布速率为10Hzwhile(ros::ok()) //创建发布逻辑,循环发布数据{msg.age+=1; // 修改数据pub.publish(msg);rate.sleep();//和ros::Rate rate(10) 配合实现每秒10次ros::spinOnce(); //官方建议,目前不用}return 0;
}
1.6.6 订阅方
/*发布person.msg格式的消息1.包含头文件2.初始化ROS节点3.创建节点句柄4.创建订阅者对象5.处理订阅到的数据6.调用spin()函数
*/
#include "包名/Person.h" //导入包
#include "ros.h"
#include "stc_msgs/String.h"void doMsg(const 包名::Person::ConstPtr &person)
{//通过msg获取并操作订阅到的数据ROS_INFO("订阅的数据是:%s,%d,%.2f",person->name.c_str(),person->age,person->height); //以日志形式输出订阅到的数据
}int main(int argc, char *argv[])
{setlocale(LC_ALL,""); //避免中文乱码ros::init(argc,argv,"sub"); //初始化节点ros::NodeHandle nh; //创建Node句柄ros::Subscriber sub = nh.Subscribe("em_state",10,doMsg); //创建发布者对象ros::spin();return 0;
}

2、服务通信 srv文件

​ server和client进行请求和相应

适用性:对实时性有要求,需要一定的逻辑处理

2.1理论模型

​ 角色:

​ Master

​ Server

​ Client

​ 流程:

​ master根据话题实现server和client的连接

​ 1、server向master注册信息,话题与地址

​ 2、client向master注册话题

​ 3、master向client返回ROSRPC格式的地址

​ 4、建立TCP连接,实现Clinet和Server的通信

​ 注:必须是服务端(server)先启动和注册,之后client发送请求才有效

// 创建srv文件夹
//编写请求与响应内容int32 num1
int32 num2
//请求跟响应隔3个-
---
int32 sum

message_generation
message_runtime
## 修改cmakelist.txt
find_package(catkin REQUIRED COMPONENTSroscpprospystd_msgsmessage_generation
)
## 添加
add_service_files(FILES文件名.srv
)## 添加
generate_messages(DEPENDENCIESstd_msgs
)
## 添加
catkin_package(CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
)

编译完成后生成 请求名.h、响应名.h 头文件

c++实现 ?(查看topic是否存在,检验是话题名还是服务名)

  1. 配置文件

    devel/include路径查看

    添加到 c_cpp_properties.json中的includePath中

  2. server.cpp 服务端:解析处理客户端的数据并给出响应

    //1. 头文件
    #include "ros/ros.h"
    #include "包名/srv文件夹下的名称.h"bool doSums(包名::功能名::Request &request,包名::功能名::Response &response){//处理请求:解析数字int num1 = request.num1;int num2 = request.num2;//查看解析结果ROS_INFO("num1=%d, num2=%d",num1,num2);//组织响应:求和输出int sum = num1+num2;response.sum = sum;return true;
    }
    int main(int argc, char *argv[])
    {//节点初始化ros::init(argc,argv,"节点名");//创建节点句柄ros::NodeHandler nh;//创建服务对象ros::serviceServer 服务端名 = nh.advertiseService("话题名",回调函数(doSums));//spinros::spin()
    }
    

    添加配置文件 CmakeList.txt

    add_executable(名称 src/被执行的文件.cpp)
    ## 防止编译顺序引发的异常
    add_dependencies(名称 ${PROJECT_NAME}_gencpp)
    target_link_libraries(名称${catkin_LIBRARIES}
    )
    
  3. client.cpp 客户端

    //1. 头文件
    #include "ros/ros.h"
    #include "包名/srv文件夹下的名称.h"// main传递的是,参数数量和参数值
    int main(int argc, char *argv[])
    {//节点初始化ros::init(argc,argv,"节点名");//创建节点句柄ros::NodeHandler nh;//创建客户端对象ros::ServiceClient 客户端名 = nh.serverce<客户端名称::服务名>("话题名");//组织请求(固定请求)客户端名::服务名 ai;ai.request.num1 = 100;ai.request.num2 = 200;//组织请求(自定义传值)if(argc !=3){ROS_INFO("args num error");}else{ai.request.num1 = atoi(argv[1]);ai.request.num2 = atoi(argv[2]);}//处理响应bool flag = client.call(servise对象(ai));if(flag){ROS_INFO("Response TRUE");ROS_INFO("SUM=%d",ai.response.sum);}else{ROS_INFO("G");}//spinros::spin()
    }
    

    添加配置文件 CmakeList.txt

    add_executable(名称 src/被执行的文件.cpp)## 防止编译顺序引发的异常
    add_dependencies(名称 ${PROJECT_NAME}_gencpp)target_link_libraries(名称${catkin_LIBRARIES}
    )

    客户端优化

    先启动客户端时,若服务端未开启,则抛出异常,

    设定:在客户端发请求时,若服务端未开启,则挂起等待服务端启动,而不是直接退出抛异常

    在调用call之前加入下面命令之一

    1、client.waitForExistence()

    2、ros::service::waitForService("服务名")

3、参数服务器通信

​ 开辟空间存放data,各个节点都可以从data中存取数据,共享模式。

image-20230308100531766

相关内容

热门资讯

苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
阿西吧是什么意思 阿西吧相当于... 即使你没有受到过任何外语培训,你也懂四国语言。汉语:你好英语:Shit韩语:阿西吧(아,씨발! )日...