Apollo7.0_CyberRT调度框架思维导图及该模块注释代码 , Apollo 7.0为Apollo最新版本,自Apollo3.5版本开始摒弃原来的ROS调度方式改用自研的CyberRT调度架构以来,截止至7.0版本的CyberRT也最为成熟。

Apollo 7.0版本的发布,标志着自2017年Apollo 3.5版本以来自研CyberRT调度框架的进一步成熟。CyberRT作为Apollo的核心调度架构,经历了从无到有,从学习ROS到完全自主研发的蜕变。在这个过程中,CyberRT不仅解决了ROS架构在实时性和资源利用率上的诸多问题,还为Apollo平台的性能优化和扩展性打下了坚实的基础。

那么,CyberRT到底是什么?它是如何工作的?它的核心模块有哪些?让我们一起来深入探讨一下。


1. CyberRT的发展背景

在Apollo 3.5版本之前,Apollo平台采用的是ROS(Robot Operating System)作为调度框架。ROS虽然功能强大,但在实时性和资源利用效率上表现一般。这在车规级应用中尤其明显,自动驾驶系统对实时性的要求极高, ROS的调度机制常常显得力不从心。

Apollo7.0_CyberRT调度框架思维导图及该模块注释代码 , Apollo 7.0为Apollo最新版本,自Apollo3.5版本开始摒弃原来的ROS调度方式改用自研的CyberRT调度架构以来,截止至7.0版本的CyberRT也最为成熟。

CyberRT的诞生,就是为了解决这些问题。从3.5版本开始,Apollo团队逐步抛弃了ROS,转而使用自研的CyberRT调度框架。经过多个版本的迭代,到7.0版本,CyberRT已经非常成熟,成为Apollo平台的核心调度架构。


2. CyberRT的核心模块

CyberRT的架构设计非常模块化,核心模块包括:

  1. Scheduler(调度器):用来管理任务的执行顺序和周期。
  2. Publisher/Subscriber(发布/订阅机制):负责节点间的消息传输。
  3. Timer Manager(定时器管理器):用于管理周期性任务的执行。
  4. Node(节点):任务的基本执行单元。
核心模块代码示例

以下是一段CyberRT调度框架的核心模块代码,展示了CyberRT节点的基本初始化过程:

#include "cyber/kit/node.h"

int main(int argc, char **argv) {
  // 初始化节点
  cyber::Node node("example_node");
  
  // 注册回调函数
  node.RegisterCallback(
      "example_topic",
      std::bind(&ExampleClass::OnMessage, &example_object), 
      nullptr);

  // 启动节点
  node.Start();
  
  // 进入主循环
  while(running) {
    // 任务执行
    node.Run();
  }

  // 停止节点
  node.Stop();
  return 0;
}

代码分析:

  • 节点初始化cyber::Node node("examplenode"); 这行代码创建了一个名为examplenode的节点。CyberRT的节点是任务的基本执行单位,每个节点可以注册多个回调函数,处理不同的消息。
  • 回调函数注册node.RegisterCallback(...) 这里注册了一个回调函数,表示当节点接收到example_topic主题的消息时,会调用OnMessage方法。
  • 节点启动和主循环node.Start()用于启动节点,node.Run()进入主循环,处理所有注册的任务。

3. CyberRT的工作原理

CyberRT采用了一种更加高效的任务调度方式,主要包括以下几个步骤:

  1. 任务初始化:节点初始化时,会注册任务相关的回调函数。
  2. 任务调度:调度器根据任务的优先级和执行周期,为每个任务分配执行时间。
  3. 消息传输:发布者节点将消息发布到指定主题,订阅者节点通过订阅主题获取消息。
  4. 任务执行:每个任务在调度器分配的时间窗口内执行,并通过回调函数处理消息。
定时任务实现示例

以下是一段CyberRT实现定时任务的代码示例:

#include "cyber/timer/timer_manager.h"

class TimerExample {
 public:
  TimerExample() {
    timer_manager_.SetInterval(std::bind(&TimerExample::OnTimer, this), 1000); // 1秒间隔
    timer_manager_.Start();
  }

 private:
  void OnTimer() {
    // 定时任务执行的代码
    std::cout << "Timer tick!" << std::endl;
  }

  cyber::timer::TimerManager timer_manager_;
};

代码分析:

  • 定时器初始化timermanager.SetInterval(...) 设置了定时器的间隔时间为1秒,并绑定回调函数OnTimer
  • 定时器启动timermanager.Start()启动定时器,定时任务开始执行。
  • 回调函数OnTimer函数会在每隔1秒时被调用,执行相应的任务。

4. CyberRT的性能优势

相比ROS,CyberRT在性能上有以下几个显著优势:

  1. 更低的延迟:CyberRT采用更高效的调度算法,任务间的切换更加迅速。
  2. 更高的吞吐量:通过优化消息传输机制,CyberRT能够处理更多的消息。
  3. 更好的实时性:CyberRT支持硬实时任务调度,能够确保任务在规定的时间内完成。
高性能消息传输示例

以下是一段CyberRT高效消息传输的代码示例:

#include "cyber/publisher.h"
#include "cyber/subscriber.h"

// 发布消息
void PublishMessage() {
  auto message = std::make_shared<ExampleMessage>();
  message->data = "Hello, CyberRT!";
  publisher_->Publish(message);
}

// 订阅消息
void OnSubscribe(const std::shared_ptr<ExampleMessage>& message) {
  std::cout << "Received message: " << message->data << std::endl;
}

int main() {
  // 创建发布者和订阅者
  cyber::Publisher<ExampleMessage> publisher("example_topic");
  cyber::Subscriber<ExampleMessage> subscriber("example_topic", std::bind(&OnSubscribe, std::placeholders::_1));

  // 发布消息
  PublishMessage();

  return 0;
}

代码分析:

  • 消息发布publisher->Publish(message); 这行代码将消息发布到exampletopic主题。
  • 消息订阅subscriber绑定了一个回调函数OnSubscribe,当有消息发布到example_topic时,OnSubscribe会被调用,处理接收到的消息。

5. 总结

CyberRT作为Apollo 7.0版本的核心调度框架,经过长期的优化和迭代,已经成为一个高效、可靠的实时任务调度系统。无论是任务调度、消息传输,还是定时任务管理,CyberRT都表现出了强大的性能和灵活性。

对于开发者来说,深入了解CyberRT的架构和实现方式,不仅能够帮助我们更好地使用Apollo平台,还能为我们在实时系统开发中提供宝贵的参考经验。

如果你对CyberRT的更多细节感兴趣,不妨进一步阅读Apollo的官方文档或源码,相信会有更多的收获!

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐