Cyber之talker-listener通信
1、实验简介
假设我们想要一直获取车的速度,该需求不需要向发送方返回什么消息,也不需要发送方对消息进行进一步处理。该种情况下,我们可以选择Listener-Talker通信方式实现该功能。
Listener-Talker通信一方主动送消息,一方被动接收。Listener-Talker通信首先创建了两个Node,分别是Talker Node和 Listener Node。每个Node实例化Writer类和Reader类对Channel进行消息的读写。Writer和Reader通过Topic连接,对同一块共享内存(Channel)进行读写处理。在这里,Talker Node 为了实现其“诉说”的功能,选择实例化Writer,通过Writer来对Channel进行消息写操作。而Listener Node为了实现其“聆听”功能,选择实例化reader类,通过Reader来对channel进行读操作。该通信方式适合于持续性通信的应用场景,比如雷达信号,摄像头图像信息这类数据的传输。数据交互路径如下图所示:
2、实验步骤
2.1 编写代码
1、在/apollo_workspace/examples/proto下创建car1.proto文件,用于保存车的车身信息。
vim /apollo_workspace/examples/proto/car1.proto
在car1.proto中输入自定义的车身信息。
syntax = "proto2";//定义包名,在cc文件中调用package apollo.cyber.examples.proto;//定义一个车的消息,车的型号,车主,车的车牌号,已跑公里数,车速message Car1{optional string plate = 1;optional string type = 2;optional string owner = 3;optional uint64 kilometers = 4;optional uint64 speed = 5;};
2、打开 BUILD文件,在BUILD文件末尾补充car1.proto信息,以便系统能正常编译car1.proto。
vim /apollo_workspace/examples/proto/BUILD
在BUILD文件末尾补充car1.proto信息。
proto_library(name = "car1_proto",srcs = ["car1.proto"],)cc_proto_library(name = "car1_cc_proto",deps = [":car1_proto",],)
3、进入到/apollo_workspace/examples/communication目录下,创建编写talker1.cc来实现主动对话
vim /apollo_workspace//examples/communication/talker1.cc
在talker1.cc中输入以下代码
//头文件引用#include "examples/proto/car1.pb.h"#include "cyber/cyber.h"#include "cyber/time/rate.h"//car数据定义的引用,可以看出其定义来源于一个protousing apollo::cyber::examples::proto::Car1;int main(int argc, char *argv[]) {// 初始化一个cyber框架apollo::cyber::Init(argv[0]);// 创建talker节点auto talker_node = apollo::cyber::CreateNode("talker");// 从节点创建一个Topic,来实现对车速的查看auto talker = talker_node->CreateWriter<Car1>("car_speed");AINFO << "I'll start telling you the current speed of the car.";//设置初始速度为0,然后速度每秒增加5km/huint64_t speed = 0;while (apollo::cyber::OK()) {auto msg = std::make_shared<Car1>();msg->set_speed(speed);//假设车速持续增加speed += 5;talker->Write(msg);sleep(1);}return 0;}
4、在同目录下,创建编写一个listener1.cc来实现对talker1发送过来的内容进行接收
vim /apollo_workspace//examples/communication/listener1.cc
在talker1.cc中输入以下代码
#include "examples/proto/car1.pb.h"#include "cyber/cyber.h"using apollo::cyber::examples::proto::Car1;//接收到消息后的响应函数void message_callback(const std::shared_ptr<Car1>& msg) {AINFO << "now speed is: " << msg->speed();}int main(int argc, char* argv[]) {//初始化cyber框架apollo::cyber::Init(argv[0]);//创建监听节点auto listener_node = apollo::cyber::CreateNode("listener");//创建监听响应进行消息读取auto listener = listener_node->CreateReader<Car1>("car_speed", message_callback);apollo::cyber::WaitForShutdown();return 0;}
5、修改同目录下的BUILD文件,将刚刚创建的talker1.cc和listener1.cc加入到编译文件中
vim /apollo_workspace/examples/communication/BUILD
在BUILD文件中补充内容
//添加两个cc_binarycc_binary(name = "talker1",srcs = ["talker1.cc"],deps = ["//cyber","//examples/proto:car1_cc_proto",],linkstatic = True,)cc_binary(name = "listener1",srcs = ["listener1.cc"],deps = ["//cyber","//examples/proto:car1_cc_proto",],linkstatic = True,)//在install中将自己创建的talker1和listener1程序加入进去install(name = "install",runtime_dest = "examples/bin",targets = [":talker",":listener",":server",":client",":param_client",":param_server",":talker1", //添加":listener1" //添加],)
2.2编译程序
//回到 /apollo_workspace目录下编译cd /apollo_workspacebash scripts/apollo_neo.sh build --packages examples/communication
编译成功后显示如下信息
2.3运行通信程序
2.3.1 运行talker1程序
打开新的终端,执行以下命令。
//设置将输出结果到控制台export GLOG_alsologtostderr=1//编译产生的可执行文件在 /opt/apollo/neo/packages/examples-dev/local/bincd /opt/apollo/neo/packages/examples-dev/local/bin//执行talker1./talker1
2.3.2 运行listener1程序
再次打开一个新的终端,执行以下命令。
//设置将输出结果到控制台export GLOG_alsologtostderr=1//编译产生的可执行文件在 /opt/apollo/neo/packages/examples-dev/local/bincd /opt/apollo/neo/packages/examples-dev/local/bin//执行listener1./listener1
2.4 运行结果
talker1会一直给listener1发送实时速度信息。
listener1收到后会将速度输出到控制台