Apollo学习笔记(1) 百度 Apollo Cyber RT简介、基本概念以及与 ROS 对照

本文转载其他大神的博客,再此声明,转载仅仅为了自己学习方便,无其他用途。

一、背景

ROS 应用于自动驾驶领域的不足:

  • 调度的不确定性:各节点以独立进程运行,节点运行顺序无法确定,因而业务逻辑的调度顺序无法保证;
  • 运行效率:ROS 为分布式系统,存在通信开销

二、Cyber RT 框架

Apollo学习笔记(1) 百度 Apollo Cyber RT简介、基本概念以及与 ROS 对照_第1张图片

从下到上依次为:

  • 基础库:高性能,无锁队列;
  • 通信层:Publish/Subscribe机制,Service/Client机制,服务自发现,自适应的通信机制(共享内存、Socket、进程内);
  • 数据层:数据缓存与融合。多路传感器之间数据需要融合,而且算法可能需要缓存一定的数据。比如典型的仿真应用,不同算法模块之间需要有一个数据桥梁,数据层起到了这个模块间通信的桥梁的作用;
  • 计算层:计算模型,任务以及任务调度;

三、运行流程

Apollo学习笔记(1) 百度 Apollo Cyber RT简介、基本概念以及与 ROS 对照_第2张图片

算法模块通过有向无环图(DAG),配置任务间的逻辑关系。对于每个算法可以进行优先级、运行时间、使用资源等方面的配置。
系统启动时,结合DAG、调度配置等,创建相应的任务,从框架内部来讲,就是协程(coroutine)
调度器把任务放到各个 Processor 的队列中。
然后,由 Sensor 输入的数据,驱动整个系统运转。

四、基本概念以及与 ROS 对照

Cyber ROS 注释
Component 组件之间通过 Cyber channel 通信。
Channel Topic channel 用于管理数据通信,用户可以通过 publish/subscribe 相同的 channel 来通信。
Node Node 每一个模块包含 Node 并通过 Node 来通信。一个模块通过定义 read/write 和/或 service/client 使用不同的通信模式。
Reader/Writer Publish/Subscribe 订阅者模式。往 channel 读写消息的类。 通常作为 Node 主要的消息传输接口。
Service/Client Service/Client 请求/响应模式,支持节点间双向通信。
Message Message Cyber RT 中用于模块间通信的数据单元。其实现基于 protobuf
Parameter Parameter Parameter 服务提供全局参数访问接口。该服务基于 service/client 模式。
Record file Bag file 用于记录从 channel 发送或接收的消息。 回放 record file 可以重现之前的操作行为。
Launch file Launch file 提供一种启动模块的便利途径。通过在 launch file 中定义一个或多个 dag 文件,可以同时启动多个 modules。
Task 异步计算任务
CRoutine 协程,优化线程使用与系统资源分配
Scheduler 任务调度器,用户空间。
Dag file 定义模块拓扑结构的配置文件。

五、特色

  • 高性能:无锁对象,协程(coroutine),自适应通信机制;
  • 确定性:可配置的任务以及任务调度,通过协程将调度从内核空间转移到用户空间;
  • 模块化:在框架内实现组件以及节点,即可完成系统任务;
  • 便利性:创建和使用任务

六、示例

Writer/Reader

Message:

syntax = "proto2";
package apollo.cyber.examples.proto;
message Chatter 
{
    optional uint64 timestamp = 1;
    optional uint64 lidar_timestamp = 2;
    optional uint64 seq = 3;
    optional bytes content = 4;
};

Writer:

#include "cyber/cyber.h"
#include "cyber/examples/proto/examples.pb.h"
#include "cyber/time/rate.h"
#include "cyber/time/time.h"

using apollo::cyber::Rate;
using apollo::cyber::Time;
using apollo::cyber::examples::proto::Chatter;

int main(int argc, char *argv[]) 
{
    // init cyber framework
    apollo::cyber::Init(argv[0]);
    // create talker node
    auto talker_node = apollo::cyber::CreateNode("talker");
    // create talker
    auto talker = talker_node->CreateWriter<Chatter>("channel/chatter");
    Rate rate(1.0);
    while (apollo::cyber::OK()) 
    {
        static uint64_t seq = 0;
        auto msg = std::make_shared<Chatter>();
        msg->set_timestamp(Time::Now().ToNanosecond());
        msg->set_lidar_timestamp(Time::Now().ToNanosecond());
        msg->set_seq(seq++);
        msg->set_content("Hello, apollo!");
        talker->Write(msg);
        AINFO << "talker sent a message!";
        rate.Sleep();
    }
  return 0;
}

Reader:

#include "cyber/cyber.h"
#include "cyber/examples/proto/examples.pb.h"

void MessageCallback(const std::shared_ptr<apollo::cyber::examples::proto::Chatter>& msg) 
{
    AINFO << "Received message seq-> " << msg->seq();
    AINFO << "msgcontent->" << msg->content();
}

int main(int argc, char* argv[]) 
{
    // init cyber framework
    apollo::cyber::Init(argv[0]);
    // create listener node
    auto listener_node = apollo::cyber::CreateNode("listener");
    // create listener
    auto listener = listener_node->CreateReader<apollo::cyber::examples::proto::Chatter>("channel/chatter", MessageCallback);
    apollo::cyber::WaitForShutdown();
    
    return 0;
}

Service/Client

Message:

syntax = "proto2";

package apollo.cyber.examples.proto;

message Driver 
{
    optional string content = 1;
    optional uint64 msg_id = 2;
    optional uint64 timestamp = 3;
};

Service/client:

#include "cyber/cyber.h"
#include "cyber/examples/proto/examples.pb.h"

using apollo::cyber::examples::proto::Driver;

int main(int argc, char* argv[]) 
{
 	apollo::cyber::Init(argv[0]);
 	std::shared_ptr<apollo::cyber::Node> node(apollo::cyber::CreateNode("start_node"));
	 auto server = node->CreateService<Driver, Driver>("test_server", [](const std::shared_ptr<Driver>& request,
	                       std::shared_ptr<Driver>& response) {
								AINFO << "server: i am driver server";
								static uint64_t id = 0;
								++id;
								response->set_msg_id(id);
								response->set_timestamp(0);
							});
	auto client = node->CreateClient<Driver, Driver>("test_server");
	auto driver_msg = std::make_shared<Driver>();
	driver_msg->set_msg_id(0);
	driver_msg->set_timestamp(0);
  
	while (apollo::cyber::OK()) 
	{
		auto res = client->SendRequest(driver_msg);
		if (res != nullptr) 
		{
			AINFO << "client: responese: " << res->ShortDebugString();
		} 
		else 
		{
			AINFO << "client: service may not ready.";
		}
		sleep(1);
	}

	apollo::cyber::WaitForShutdown();
	return 0;
}

七、Apollo 整体框架

Apollo学习笔记(1) 百度 Apollo Cyber RT简介、基本概念以及与 ROS 对照_第3张图片

你可能感兴趣的:(Apollo)