Cyber RT中最为核心实现:通信机制。
所谓通信机制就是如何在不同的单元或模块之间传输数据,比如:雷达、摄像头、GPs(、地图、车辆控制、车辆参数、车辆目的地…这些消息是以何种方式在不同模块之间传输的,不同传输方式又有怎样的应用场景等等。
话题通信
场景: 无人车上整合了诸多传感器,比如:雷达,雷达驱动被启动后,就会不间断的感知环境并实时产生相关数据,产生的数据需要被接收然后继续处理转换成业务所需的障碍物信息。
在这一过程中,传感器的数据发布;用于实现二次处理的程序接收数据;同理,像摄像头、GPS、imu、车辆控制…相关的消息的发布和接收…
上述场景下便可以使用话题通信实现数据传输。
概念: 以发布订阅的方式实现不同节点之间数据交互的通信模式。
作用: 用于不断更新的,少逻辑处理的数据传输场景。
需求: 实现发布订阅模型,要求发布方可以循环发送消息,订阅方可以订阅到发布方的消息,并解析将结果在终端输出。
流程:
大致基本步骤:
1.编写消息载体(protobuf文件)并配置;
2.编写发布方并配置;
3.编写订阅方并配置;
4.编译执行。
C++ 实现
1.发布方实现
1.demo_cc 目录下新建C++文件 demo01_talker.cc,输入如下内容:
/*
1.包含头文件
2.初始化 cyber 框架
3.创建节点
4.创建发布者
5.组织数据并发布
6.等待关闭
*/
#include "cyber/cyber.h"
#include "cyber/demo_base_proto/student.pb.h"
using apollo::cyber::demo_base_proto::Student;
int main(int argc, char const *argv[])
{
apollo::cyber::Init(argv[0]);
//创建节点
auto talker_node = apollo::cyber::CreateNode("ergou");
//创建发布者
auto talker = talker_node->CreateWriter<Student>("chatter");
//组织相关数据并发布
uint64_t seq = 0;//计时器
apollo::cyber::Rate rate(0.5);
while (apollo::cyber::OK){ //判断节点是否正在运行
seq++;
AINFO <<"发布第"<<seq<<"条数据!"<<std::endl;
//组织数据
auto msg=std::make_shared<Student>();
msg->set_name("feng");
msg->set_age(seq);
msg->set_height(120.0);
msg->add_books("chinese");
msg->add_books("math");
msg->add_books("english");
//发布
talker->Write(msg);
rate.Sleep();
}
//等待关闭
apollo::cyber::WaitForShutdown();
return 0;
}
2.编写 BUILD 文件
cc_binary(
name="demo01_talker",
srcs=["demo01_talker.cc"],
deps=[
"//cyber",
"//cyber/demo_base_proto:student_cc"
]
)
3.编译与执行
使用工具进行监听:
cyber_channel echo chatter
2.订阅方实现
1.demo_cc目录下新建 demo02_listener.cc,输入如下内容:
/*
1.包含头文件
2.初始化
3.创建节点
4.创建订阅方
5.回调函数处理数据
6.等待关闭
*/
#include "cyber/cyber.h"
#include "cyber/demo_base_proto/student.pb.h"
using apollo::cyber::demo_base_proto::Student;
void cb(const std::shared_ptr<Student>& stu){
AINFO << "name:"<<stu->name();
AINFO << "age:"<<stu->age();
AINFO << "height:"<<stu->height();
for(int i=0;i<stu->books_size();i++){
AINFO <<" books: "<< stu->books(i);
}
AINFO <<"------------------------------------";
}
int main(int argc, char const *argv[])
{
//初始化
apollo::cyber::Init(argv[0]);
AINFO <<"订阅方创建......";
//创建节点
auto listener_node = apollo::cyber::CreateNode("fei");
//订阅方
auto listener = listener_node->CreateReader<Student>("chatter",cb);
//回调函数处理数据
//等待关闭
apollo::cyber::WaitForShutdown();
return 0;
}
2.BUILD 文件
cc_binary(
name="demo02_listener",
srcs=["demo02_listener.cc"],
deps=[
"//cyber",
"//cyber/demo_base_proto:student_cc"
]
)
3.编译与执行
python 实现
1.发布方实现
1.demo_py 目录下创建 python 文件 demo01_talker_py.py,输入以下内容:
#!/usr/bin/env python3
"""
1.导包
2.初始化
3.创建节点
4.创建发布方
5.组织并发送数据
6.等待关闭
"""
from cyber.python.cyber_py3 import cyber
from cyber.demo_base_proto.student_pb2 import Student
import time
def talk():
# 创建节点
talker_node = cyber.Node("ergou_py")
# 创建发布方
talker = talker_node.create_writer("chatter",Student)
# 组织并发送数据
seq = 0
while not cyber.is_shutdown():
seq += 1
print("send message %d" % seq)
stu = Student()
stu.name = "Feng"
stu.age = seq
stu.height = 120.0
stu.books.append("Chinese")
stu.books.append("Math")
stu.books.append("English")
talker.write(stu)
time.sleep(1.0)
if __name__ == "__main__":
cyber.init()
talk()
cyber.shutdown()
2.BUILD 文件
py_binary(
name = "demo01_talker_py",
srcs = ["demo01_talker_py.py"],
deps = [
"//cyber/python/cyber_py3:cyber",
"//cyber/demo_base_proto:student_py"
],
)
3.编译并执行
2.订阅方实现
1.demo_py 目录下创建 python 文件 demo02_listener_py.py,输入以下内容:
#!/usr/bin/env python3
"""
1.导包
2.初始化
3.创建节点
4.创建订阅方
5.处理数据
6.等待关闭
"""
from cyber.python.cyber_py3 import cyber
from cyber.demo_base_proto.student_pb2 import Student
def cb(stu):
print("name = %s age = %d height = %.2f" % (stu.name,stu.age,stu.height))
for book in stu.books:
print("books: %s" %book)
print("-"*30)
def listen():
listener_node = cyber.Node("Feng_py")
listener = listener_node.create_reader("chatter",Student,cb)
listener_node.spin()
if __name__ == "__main__":
cyber.init()
listen()
cyber.shutdown()
2.BUILD
py_binary(
name = "demo02_listener_py",
srcs = ["demo02_listener_py.py"],
deps = [
"//cyber/python/cyber_py3:cyber",
"//cyber/demo_base_proto:student_py"
],
)
3.编译与执行
解耦合:可以使用C++的listener 和 python 的 talker,反之亦可