01_apollo_cyber子模块整体软件架构深入分析文档

1. 概述

Apollo Cyber RT是专为自动驾驶场景设计的高性能开源运行时框架。该框架基于集中式计算模型,针对自动驾驶领域的高并发、低延迟和高吞吐量需求进行了深度优化。Cyber RT提供了高效的模块间通信机制、灵活的任务调度系统以及便捷的开发工具集,支持实时数据处理和任务调度,为自动驾驶系统提供了稳定可靠的技术基础。

2. 软件架构图

graph TB subgraph "应用层" A1[感知组件] A2[预测组件] A3[规划组件] A4[控制组件] A5[定位组件] A6[地图组件] A7[诊断组件] A8[监控组件] end subgraph "Cyber RT中间件" subgraph "通信框架" C1[发布订阅机制] C2[服务调用机制] C3[参数服务] C4[记录回放] end subgraph "任务调度" C5[Choreography调度器] C6[Fair调度器] C7[Classic调度器] C8[任务管理] end subgraph "数据管理" C9[共享内存管理] C10[数据缓存] C11[QoS控制] C12[消息序列化] end subgraph "服务发现" C13[节点管理] C14[通道管理] C15[服务管理] C16[拓扑管理] end subgraph "基础工具" C17[日志系统] C18[时间管理] C19[定时器] C20[协程] end end subgraph "基础设施层" I1[基础工具库] I2[内存管理] I3[错误处理] I4[原子操作] I5[类型转换] I6[字符串处理] end subgraph "传输层" T1[进程内传输] T2[共享内存传输] T3[RTPS网络传输] T4[消息序列化] T5[QoS策略] T6[传输控制] end subgraph "服务发现层" S1[节点注册] S2[通道注册] S3[服务注册] S4[拓扑变化通知] S5[节点生命周期管理] S6[服务生命周期管理] end subgraph "运行时环境" R1[主控板] R2[组件框架] R3[服务框架] R4[参数服务器] R5[记录器] R6[播放器] end A1 --> C1 A2 --> C1 A3 --> C1 A4 --> C1 A5 --> C1 A6 --> C1 A7 --> C1 A8 --> C1 C1 --> T1 C1 --> T2 C1 --> T3 C1 --> T4 C1 --> T5 C1 --> T6 C2 --> S1 C2 --> S2 C2 --> S3 C2 --> S4 C2 --> S5 C2 --> S6 C5 --> R1 C6 --> R2 C7 --> R3 C8 --> R4 C8 --> R5 C8 --> R6 I1 --> C1 I2 --> C1 I3 --> C1 I4 --> C1 I5 --> C1 I6 --> C1 R1 --> I1 R2 --> I1 R3 --> I1 R4 --> I1 R5 --> I1 R6 --> I1 S1 --> I1 S2 --> I1 S3 --> I1 S4 --> I1 S5 --> I1 S6 --> I1 style C1 fill:#e1f5fe style A1 fill:#f3e5f5 style T1 fill:#fff3e0 style I1 fill:#e8f5e8 style C5 fill:#ffebee style C13 fill:#e8f5e8

3. 调用流程图

sequenceDiagram participant App as 应用程序 participant Mainboard as 主控板 participant Component as 组件 participant Node as 节点 participant Writer as 消息写入器 participant Reader as 消息读取器 participant Trans as 传输层 participant SD as 服务发现 participant Scheduler as 调度器 participant Executor as 执行器 participant CRoutine as 协程 Note over App, CRoutine: 初始化阶段 App->>Mainboard: 加载组件配置 Mainboard->>Component: 创建组件实例 Component->>Node: 初始化节点 Node->>SD: 注册节点信息 SD-->>Node: 返回注册结果 Component->>Node: 创建写入器 Node->>Writer: 创建Writer实例 Writer->>Trans: 注册传输通道 Trans->>SD: 更新拓扑信息 Component->>Node: 创建读取器 Node->>Reader: 创建Reader实例 Reader->>SD: 订阅话题 SD->>Reader: 匹配生产者 Component->>Scheduler: 注册任务 Scheduler->>Executor: 分配执行器 Executor->>CRoutine: 创建协程 Note over App, CRoutine: 运行阶段 loop 消息处理循环 App->>Writer: 发布消息 Writer->>Trans: 传输消息 Trans->>Reader: 投递消息 Reader->>Component: 调用处理函数 Component->>App: 处理结果 end loop 服务调用 App->>Node: 创建服务客户端 Node->>SD: 查找服务 SD->>Node: 返回服务地址 Node->>App: 创建客户端 App->>Node: 发送服务请求 Node->>SD: 路由请求 SD->>服务节点: 转发请求 服务节点->>App: 返回响应 end Note over App, CRoutine: 关闭阶段 App->>Scheduler: 注销任务 Scheduler->>CRoutine: 停止协程 CRoutine->>Component: 关闭组件 Component->>Node: 清理节点资源 Node->>SD: 注销节点

4. 详细UML类图

4.1. 核心框架类图

classDiagram class CyberRT { +Initialize(): bool +Shutdown(): void +CreateNode(name): shared_ptr~Node~ +CreateComponent(config): shared_ptr~ComponentBase~ +CreateService(name): shared_ptr~ServiceBase~ +CreateClient(name): shared_ptr~ClientBase~ -initialized: bool -scheduler: unique_ptr~Scheduler~ -transport: unique_ptr~transport::Transport~ -service_discovery: unique_ptr~service_discovery::TopologyManager~ -parameter: unique_ptr~Parameter~ -timer_scheduler: unique_ptr~TimerScheduler~ -black_board: unique_ptr~BlackBoard~ } class Node { <> +Node(name) +CreateWriter~T~(const RoleAttributes&): shared_ptr~Writer~T~~ +CreateReader~T~(const RoleAttributes&, Callback): shared_ptr~Reader~T~~ +CreateService~Req, Res~(const string&, ServiceCallback): shared_ptr~Service~Req,Res~~ +CreateClient~Req, Res~(const string&): shared_ptr~Client~Req,Res~~ +GetName(): const string& +GetServiceAttr(const string&, ServiceAttribute*): bool +ListServices(vector~ServiceAttribute~*): bool -ReadParameter(const string&, string*): bool -WriteParameter(const string&, const string&): void -node_name_: string -name_space_: string -writers_: vector~WriterBase*~ -readers_: vector~ReaderBase*~ -servers_: vector~ServiceBase*~ -clients_: vector~ClientBase*~ -rw_mutex_: mutex -role_attr_: proto::RoleAttributes } class ComponentBase { <> +Initialize(): bool +Process(const std::shared_ptr~Message~&): bool +Shutdown(): void +FillInChannelNames(const MultiSubOpt~M0,M1,M2~&): void #node_: std::shared_ptr~Node~ #readers_: vector~ReaderBase*~ #attrs_: vector~RoleAttributes~ } class Component~M0, M1, M2~ { +Component() +Init(const MultiSubOpt~M0, M1, M2~&, std::shared_ptr~Node~): bool +Shutdown(): void -ProcByCaller(uint64_t, const std::shared_ptr~Data~&): bool -RegisterReaders(std::shared_ptr~Node~): bool -Proc(const std::shared_ptr~M0~&, const std::shared_ptr~M1~&, const std::shared_ptr~M2~&): bool #callers_: vector~CallbackCaller~M0,M1,M2~*~ } class WriterBase { <> +WriterBase() +Shutdown(): void +HasReader(): bool +GetReaderCount(): size_t +GetChannelName(): string -init_: bool -attr_: proto::RoleAttributes } class Writer~T~ { +Writer(const proto::RoleAttributes&, const proto::QosProfile&) +Write(const std::shared_ptr~T~&): bool +TryWrite(const std::shared_ptr~T~&): bool +Enable(): bool -message_writer_: transport::MessageWriter~T~ } class ReaderBase { <> +ReaderBase() +Shutdown(): void +GetCachedMessageSize(): uint64_t +GetChannelConnSize(): uint64_t -init_: bool -attr_: proto::RoleAttributes } class Reader~T~ { +Reader(const proto::RoleAttributes&, const Callback&): void +Observe(): void +GetLatestObserved(): shared_ptr~T~ +GetOldestObserved(): shared_ptr~T~ -message_listener_: shared_ptr~transport::MessageListener~T~~ -cache_size_: uint64_t } class ServiceBase { <> +ServiceBase() +ServiceType(): string +GetServiceName(): const string& -service_name_: string } class Service~Req, Res~ { +Service(const string&, const ServiceCall&): void +RegisterService(const ServiceCall&): void +HandleRequest(const std::shared_ptr~Req~&, std::shared_ptr~Res~&): void -service_call_: ServiceCall } class ClientBase { <> +ClientBase() +ServiceType(): string +GetServiceName(): const string& -service_name_: string } class Client~Req, Res~ { +Client(const string&): void +SendRequest(std::shared_ptr~Req~&, std::shared_ptr~Res~&, double): bool -requester_: shared_ptr~transport::Requester~Req, Res~~ } class Scheduler { +CreateTask(const std::function~void()~&, const std::string&): bool +CreateTask(std::shared_ptr~Node~, const std::string&): bool +RemoveTask(const std::string&): bool +NotifyStart(): bool +NotifyStop(): bool +DispatchTask(Task*): bool +SetSchedPolicy(const string&): bool +Shutdown(): void -policy_: unique_ptr~Policy~ -tasks_: base::AtomicHashMap~TaskID, TaskExe~ -task_pool_: base::CCObjectPool~Task~ -cr_pool_: base::CCObjectPool~CRoutine~ } class Transport { +transport::Transport() +Join(const RoleAttributes&): void +Leave(const RoleAttributes&): void +EnableTransport(const Identity&, const OptionalMode&): void +DisableTransport(const Identity&, const OptionalMode&): void -transport_mutex_: mutex -participant_: shared_ptr~rtps::Participant~ -- Intra -- -intra_transmitter_factory_: unique_ptr~IntraTransmitterFactory~ -intra_receiver_factory_: unique_ptr~IntraReceiverFactory~ -- SHM -- -shm_transmitter_factory_: unique_ptr~ShmTransmitterFactory~ -shm_receiver_factory_: unique_ptr~ShmReceiverFactory~ -- RTPS -- -rtps_transmitter_factory_: unique_ptr~RtpsTransmitterFactory~ -rtps_receiver_factory_: unique_ptr~RtpsReceiverFactory~ } class TopologyManager { +TopologyManager() +Init(): bool +Shutdown(): bool +Join(const RoleAttributes&): bool +Leave(const RoleAttributes&): bool +AddNode(const RoleAttributes&): bool +RemoveNode(const RoleAttributes&): bool +AddChannel(const RoleAttributes&): bool +RemoveChannel(const RoleAttributes&): bool +GetNodes(vector~RoleAttributes~*): bool +GetChannels(vector~RoleAttributes~*): bool -node_manager_: shared_ptr~NodeManager~ -channel_manager_: shared_ptr~ChannelManager~ -service_manager_: shared_ptr~ServiceProviderManager~ -change_listener_: shared_ptr~ChangeListener~ -participation_: shared_ptr~rtps::Participation~ } class Parameter { +Parameter(std::shared_ptr~Node~) +Set(const std::string&, const Parameter&) +Get(const std::string&, Parameter*) +List(std::vector~ParameterPair~*) -node_: std::weak_ptr~Node~ -param_client_: std::shared_ptr~ParameterClient~ -param_server_: std::shared_ptr~ParameterServer~ -param_map_: std::unordered_map~std::string, Parameter~ -param_mutex_: std::mutex } CyberRT ..> Node CyberRT ..> ComponentBase CyberRT ..> ServiceBase CyberRT ..> ClientBase CyberRT ..> Scheduler CyberRT ..> Transport CyberRT ..> TopologyManager CyberRT ..> Parameter Node <|-- ComponentBase ComponentBase <|-- Component WriterBase <|-- Writer ReaderBase <|-- Reader ServiceBase <|-- Service ClientBase <|-- Client Scheduler ..> Transport Transport ..> TopologyManager Node ..> Parameter

4.2. 传输层类图

classDiagram class TransmitterBase { <> +TransmitterBase(const RoleAttributes&): void +TransmitterBase(const RoleAttributes&, const proto::QosProfile&): void +virtual ~TransmitterBase() +Transmit(const std::shared_ptr~DataT~&, const MessageInfo&): bool +GetMsgType(): const string& +GetProtoDesc(): const string& +GetSerializedType(): const string& +HasReader(): bool +GetReaderCount(): size_t +AddReader(const RoleAttributes&): void +RemoveReader(const RoleAttributes&): void +GetReaderSize(): size_t -role_attr_: RoleAttributes -msg_type_: string -proto_desc_: string -readers_: Container~RoleAttributes~ } class ReceiverBase { <> +ReceiverBase(const RoleAttributes&, const typename Transmitter~T~::MessageListener&): void +virtual ~ReceiverBase() +Shutdown(): void +HasNewMessage(): bool -role_attr_: RoleAttributes -msg_listener_: typename Transmitter~T~::MessageListener -enabled_: bool } class IntraTransmitter~T~ { +IntraTransmitter(const RoleAttributes&, const proto::QosProfile&): void +Transmit(const std::shared_ptr~T~&, const MessageInfo&): bool +AddListener(const typename Transmitter~T~::MessageListener&): void -readers_: Connection~T~ -receiver_container_: Container~IntraReceiver~T~~* } class ShmTransmitter~T~ { +ShmTransmitter(const RoleAttributes&, const proto::QosProfile&): void +Transmit(const std::shared_ptr~T~&, const MessageInfo&): bool +AddListener(const typename Transmitter~T~::MessageListener&): void -shm_id_: uint64_t -shm_manager_: shared_ptr~transport::shmem::SegmentManager~ -shm_notifier_: shared_ptr~transport::ConditionNotifier~ -buf_idx_: uint32_t -shm_addr_: char* -msg_buffer_: string } class RtpsTransmitter~T~ { +RtpsTransmitter(const RoleAttributes&, const proto::QosProfile&): void +Transmit(const std::shared_ptr~T~&, const MessageInfo&): bool +AddListener(const typename Transmitter~T~::MessageListener&): void -pub_ : shared_ptr~rtps::Publisher~ -msg_raw_ : transport::MessageInfo -msg_ : std::unique_ptr~T~ } class IntraReceiver~T~ { +IntraReceiver(const RoleAttributes&, const typename Transmitter~T~::MessageListener&, const proto::QosProfile&): void +OnData(std::shared_ptr~T~&&): void -container_: shared_ptr~Container~T~~ } class ShmReceiver~T~ { +ShmReceiver(const RoleAttributes&, const typename Transmitter~T~::MessageListener&, const proto::QosProfile&): void +OnData(uint64_t, uint32_t): void -shm_id_: uint64_t -shm_manager_: shared_ptr~transport::shmem::SegmentManager~ -shm_notifier_: shared_ptr~transport::ConditionNotifier~ -msg_buffer_: string } class RtpsReceiver~T~ { +RtpsReceiver(const RoleAttributes&, const typename Transmitter~T~::MessageListener&, const proto::QosProfile&): void +OnData(std::shared_ptr~T~&&): void -sub_ : shared_ptr~rtps::Subscriber~ } class MessageInfo { +MessageInfo(): void +MessageInfo(const Identity&, uint64_t, uint64_t): void +operator==(const MessageInfo&): bool +operator<(const MessageInfo&): bool +SerializeTo(std::string*): bool +DeserializeFrom(const std::string&): bool -sender_id_: Identity -seq_: uint64_t -timestamp_: uint64_t -status_: MessageStatus } class QosProfile { +QosProfile(): void +static getDefaultQos(): QosProfile +getHistory(): HistoryPolicy +getReliability(): ReliabilityPolicy -history: HistoryPolicy -depth: uint32 -reliability: ReliabilityPolicy -durability: DurabilityPolicy -deadline: Duration -lifespan: Duration } TransmitterBase <|-- IntraTransmitter TransmitterBase <|-- ShmTransmitter TransmitterBase <|-- RtpsTransmitter ReceiverBase <|-- IntraReceiver ReceiverBase <|-- ShmReceiver ReceiverBase <|-- RtpsReceiver IntraTransmitter ..> MessageInfo ShmTransmitter ..> MessageInfo RtpsTransmitter ..> MessageInfo IntraTransmitter ..> IntraReceiver ShmTransmitter ..> ShmReceiver RtpsTransmitter ..> RtpsReceiver IntraTransmitter ..> QosProfile ShmTransmitter ..> QosProfile RtpsTransmitter ..> QosProfile

5. 状态机

5.1. Cyber RT 系统状态机

stateDiagram-v2 [*] --> UNINITIALIZED: 系统启动 UNINITIALIZED --> INITIALIZING: 初始化请求 INITIALIZING --> INITIALIZED: 初始化成功 INITIALIZING --> FAILED: 初始化失败 INITIALIZED --> STARTING: 启动请求 STARTING --> RUNNING: 所有模块启动 RUNNING --> PAUSED: 暂停请求 PAUSED --> RUNNING: 恢复请求 RUNNING --> EMERGENCY_STOP: 紧急停止 EMERGENCY_STOP --> RUNNING: 恢复运行 RUNNING --> STOPPING: 正常停止 STOPPING --> STOPPED: 停止完成 STOPPED --> [*]: 系统关闭 FAILED --> [*]: 系统退出 state INITIALIZING { [*] --> LOADING_CONFIG: 加载配置 LOADING_CONFIG --> INITIALIZING_SCHEDULER: 初始化调度器 INITIALIZING_SCHEDULER --> INITIALIZING_TRANSPORT: 初始化传输层 INITIALIZING_TRANSPORT --> INITIALIZING_TOPOLOGY: 初始化拓扑管理 INITIALIZING_TOPOLOGY --> INITIALIZED: 初始化完成 } state STARTING { [*] --> STARTING_NODES: 启动节点 STARTING_NODES --> STARTING_COMPONENTS: 启动组件 STARTING_COMPONENTS --> STARTING_SERVICES: 启动服务 STARTING_SERVICES --> STARTING_TRANSMITTERS: 启动传输器 STARTING_TRANSMITTERS --> RUNNING: 运行中 } state STOPPING { [*] --> STOPPING_TRANSMITTERS: 停止传输器 STOPPING_TRANSMITTERS --> STOPPING_SERVICES: 停止服务 STOPPING_SERVICES --> STOPPING_COMPONENTS: 停止组件 STOPPING_COMPONENTS --> STOPPING_NODES: 停止节点 STOPPING_NODES --> STOPPED: 停止完成 }

5.2. 节点生命周期状态机

stateDiagram-v2 [*] --> CREATED: 节点创建 CREATED --> INITIALIZING: 初始化请求 INITIALIZING --> INITIALIZED: 初始化成功 INITIALIZING --> ERROR: 初始化失败 INITIALIZED --> STARTING: 启动请求 STARTING --> RUNNING: 启动成功 STARTING --> ERROR: 启动失败 RUNNING --> PAUSED: 暂停请求 PAUSED --> RUNNING: 恢复请求 RUNNING --> STOPPING: 停止请求 STOPPING --> STOPPED: 停止完成 STOPPED --> SHUTDOWN: 关闭请求 SHUTDOWN --> TERMINATED: 关闭完成 ERROR --> SHUTDOWN: 关闭请求 TERMINATED --> [*]: 节点销毁 note right of INITIALIZED 节点已初始化 可创建读写器 可注册服务 end note note right of RUNNING 节点正在运行 可收发消息 服务可用 end note note right of STOPPED 节点停止 暂停消息处理 服务不可用 end note

5.3. 消息传输状态机

stateDiagram-v2 [*] --> IDLE: 初始状态 IDLE --> PREPARING : 准备发送 PREPARING --> SERIALIZING : 序列化消息 SERIALIZING --> READY : 序列化完成 READY --> TRANSMITTING : 开始传输 TRANSMITTING --> SUCCESS : 传输成功 TRANSMITTING --> FAILED : 传输失败 TRANSMITTING --> QUEUED : 队列满,等待 SUCCESS --> IDLE : 传输完成 FAILED --> IDLE : 传输失败 QUEUED --> TRANSMITTING : 缓冲区可用 QUEUED --> FAILED : 超时失败 FAILED --> RETRY : 重试传输 RETRY --> TRANSMITTING : 重新开始传输 state PREPARING { [*] --> VALIDATING_MSG VALIDATING_MSG --> ALLOCATING_BUFFER ALLOCATING_BUFFER --> COPYING_DATA COPYING_DATA --> READY } state TRANSMITTING { [*] --> CHECK_QOS CHECK_QOS --> ENFORCE_QOS_POLICY ENFORCE_QOS_POLICY --> SEND_OVER_CHANNEL SEND_OVER_CHANNEL --> SUCCESS } FAILED --> [*] SUCCESS --> [*]

5.4. 协程状态机

stateDiagram-v2 [*] --> READY: 协程创建 READY --> RUNNING: 调度执行 RUNNING --> SUSPEND: 主动让出 RUNNING --> BLOCKED: 等待资源 SUSPEND --> READY: 被唤醒 BLOCKED --> READY: 资源可用 RUNNING --> FINISHED: 执行完成 READY --> YIELD: 被抢占 YIELD --> READY: 重新就绪 FINISHED --> TERMINATED: 协程结束 TERMINATED --> [*]: 内存回收 state RUNNING { [*] --> PROCESSING PROCESSING --> WAITING_MUTEX PROCESSING --> WAITING_CONDITION PROCESSING --> WAITING_IO WAITING_MUTEX --> PROCESSING WAITING_CONDITION --> PROCESSING WAITING_IO --> PROCESSING } state FINISHED { [*] --> CLEANUP_RESOURCES CLEANUP_RESOURCES --> TERMINATED }

6. 源码分析

6.1. Cyber RT 初始化与启动

6.1.1. 初始化流程

Cyber RT的初始化是整个框架运行的前提,它负责初始化各个子系统并建立协调机制。

cpp 复制代码
// cyber/init.h
bool Init(const std::string& binary_name);

// cyber/init.cc
bool Init(const std::string& binary_name) {
  if (IsInit()) {
    return true;
  }

  SignalHandle::PreventDefault(SIGPIPE);

  if (!::apollo::cyber::common::GlobalData::Instance()->Init()) {
    AERROR << "global data init failed.";
    return false;
  }

  GlobalData::Instance()->SetProcessGroupName(binary_name);

  if (!LogWrapper::Instance()->Init()) {
    AERROR << "log wrapper init failed.";
    return false;
  }

  if (!::apollo::cyber::scheduler::Scheduler::Instance()->Init()) {
    AERROR << "scheduler init failed.";
    return false;
  }

  if (!::apollo::cyber::service_discovery::TopologyManager::Instance()->Init()) {
    AERROR << "topology manager init failed.";
    return false;
  }

  if (!::apollo::cyber::transport::Transport::Instance()->Init()) {
    AERROR << "transport init failed.";
    return false;
  }

  {
    std::lock_guard<std::mutex> lock(global_init_mutex_);
    global_init_.store(true);
  }
  AWARN << "cyber has been initialized successfully.";
  return true;
}

初始化过程主要包括:

  1. 设置信号处理器,阻止SIGPIPE信号的默认行为
  2. 初始化全局数据管理器
  3. 初始化日志系统
  4. 初始化调度器
  5. 初始化拓扑管理器(服务发现)
  6. 初始化传输层

6.1.2. 关闭流程

cpp 复制代码
void Clear() {
  if (!IsInit()) {
    return;
  }

  ::apollo::cyber::service_discovery::TopologyManager::Instance()->Shutdown();
  ::apollo::cyber::scheduler::Scheduler::Instance()->Shutdown();
  ::apollo::cyber::transport::Transport::Instance()->Shutdown();
  LogWrapper::Instance()->Shutdown();

  std::lock_guard<std::mutex> lock(global_init_mutex_);
  global_init_.store(false);
}

6.2. 节点管理机制

6.2.1. 节点基类设计

Node是Cyber RT中最基本的概念之一,它封装了消息收发和服务调用的基本功能。

cpp 复制代码
class Node {
 public:
  explicit Node(const std::string& node_name,
                const std::string& name_space = "");

  virtual ~Node();

  template <typename M0, typename C0>
  auto CreateWriter(const std::string& channel_name)
      -> std::shared_ptr<transport::Writer<M0>>;

  template <typename M0, typename C0>
  auto CreateReader(const std::string& channel_name, const C0& callback)
      -> std::shared_ptr<transport::Reader<M0>>;

  template <typename S0, typename S1>
  auto CreateService(const std::string& service_name,
                     const std::function<void(const S0&, S1*)>& service_call)
      -> std::shared_ptr<Service<S0, S1>>;

  template <typename S0, typename S1>
  auto CreateClient(const std::string& service_name)
      -> std::shared_ptr<Client<S0, S1>>;

  const std::string& Name() const;

  bool GetServiceAttr(const std::string& service_name,
                      proto::ServiceAttribute* service_attr);

  bool ListServices(std::vector<proto::ServiceAttribute>* services);

 private:
  void Init();
  std::string node_name_;
  std::string name_space_;
  std::vector<transport::WriterBasePtr> writers_;
  std::vector<transport::ReaderBasePtr> readers_;
  std::vector<ServiceBasePtr> servers_;
  std::vector<ClientBasePtr> clients_;
  std::mutex rw_mutex_;
  apollo::cyber::proto::RoleAttributes role_attr_;
};

6.2.2. 消息读写器创建

Node提供了创建消息读写器的模板方法,这是实现发布订阅模式的关键。

cpp 复制代码
template <typename M0, typename C0>
auto Node::CreateWriter(const std::string& channel_name)
    -> std::shared_ptr<transport::Writer<M0>> {
  proto::RoleAttributes role_attr;
  role_attr.set_node_name(node_name_);
  role_attr.set_channel_name(channel_name);
  role_attr.set_channel_type(transport::ParseMessageTypeName<M0>());
  
  auto writer = std::make_shared<transport::Writer<M0>>(role_attr);
  {
    std::lock_guard<std::mutex> lock(rw_mutex_);
    writers_.emplace_back(writer);
  }
  return writer;
}

template <typename M0, typename C0>
auto Node::CreateReader(const std::string& channel_name, const C0& callback)
    -> std::shared_ptr<transport::Reader<M0>> {
  proto::RoleAttributes role_attr;
  role_attr.set_node_name(node_name_);
  role_attr.set_channel_name(channel_name);
  role_attr.mutable_qos_profile()->CopyFrom(
      QosProfileConf::QOS_PROFILE_DEFAULT);

  auto reader = std::make_shared<transport::Reader<M0>>(role_attr, callback);
  {
    std::lock_guard<std::mutex> lock(rw_mutex_);
    readers_.emplace_back(reader);
  }
  return reader;
}

6.3. 传输层实现

6.3.1. 传输层架构

Cyber RT的传输层支持多种传输方式,包括进程内传输、共享内存传输和RTPS网络传输。

cpp 复制代码
namespace transport {

class Transport {
 public:
  virtual ~Transport();

  static Transport* Instance();

  void Join(const RoleAttributes& attr);
  void Leave(const RoleAttributes& attr);

  template <typename T>
  auto CreateTransmitter(const proto::RoleAttributes& role_attr,
                         const proto::QosProfile& qos_prof)
      -> std::shared_ptr<Transmitter<T>>;

  template <typename T>
  auto CreateReceiver(const proto::RoleAttributes& role_attr,
                      const typename Transmitter<T>::MessageListener& msg_listener,
                      const proto::QosProfile& qos_prof)
      -> std::shared_ptr<Receiver<T>>;

 private:
  Transport();

  void InitInternalParams();
  void EnableTransport(const Identity& host_id, 
                       const proto::OptionalMode& mode);
  void DisableTransport(const Identity& host_id, 
                        const proto::OptionalMode& mode);

  std::mutex transport_mutex_;
  std::shared_ptr<rtps::Participant> participant_;

  std::unique_ptr<IntraTransmitterFactory> intra_transmitter_factory_;
  std::unique_ptr<IntraReceiverFactory> intra_receiver_factory_;

  std::unique_ptr<ShmTransmitterFactory> shm_transmitter_factory_;
  std::unique_ptr<ShmReceiverFactory> shm_receiver_factory_;

  std::unique_ptr<RtpsTransmitterFactory> rtps_transmitter_factory_;
  std::unique_ptr<RtpsReceiverFactory> rtps_receiver_factory_;
};

}  // namespace transport

6.3.2. 共享内存传输实现

共享内存传输是Cyber RT实现高性能IPC的重要手段:

cpp 复制代码
template <typename T>
bool ShmTransmitter<T>::Transmit(const std::shared_ptr<T>& msg,
                                 const MessageInfo& msg_info) {
  RETURN_VAL_IF_NULL(msg, false);
  if (!shm_manager_->AcquireBuffer(&buf_idx_, &shm_addr_)) {
    AERROR << "acquire buffer failed.";
    return false;
  }

  uint32_t msg_size = 0;
  if (MessageType::SerializeToString(msg.get(), &msg_buffer_)) {
    msg_size = msg_buffer_.size();
  } else {
    AERROR << "serialize message failed.";
    shm_manager_->ReleaseBuffer(buf_idx_);
    return false;
  }

  auto hdr = reinterpret_cast<Header*>(shm_addr_);
  hdr->seq = msg_info.seq_num();
  hdr->hash = msg_info.sender_id().HashValue();
  hdr->size = msg_size;
  hdr->timestamp = msg_info.timestamp();

  memcpy(shm_addr_ + sizeof(Header), msg_buffer_.data(), msg_size);

  if (!shm_notifier_->Notify(shm_id_, buf_idx_)) {
    AERROR << "notify failed.";
    shm_manager_->ReleaseBuffer(buf_idx_);
    return false;
  }

  return true;
}

6.4. 调度系统

6.4.1. 调度器设计

Cyber RT的调度器采用策略模式,支持多种调度算法。

cpp 复制代码
class Scheduler {
 public:
  virtual ~Scheduler() = default;

  static Scheduler* Instance();

  virtual bool CreateTask(const std::function<void()>& func,
                          const std::string& name) = 0;
  virtual bool CreateTask(std::shared_ptr<Node> node,
                          const std::string& name) = 0;
  virtual bool RemoveTask(const std::string& name) = 0;
  virtual bool NotifyStart() = 0;
  virtual bool NotifyStop() = 0;

  virtual bool DispatchTask(Task* task) = 0;

 protected:
  Scheduler() = default;
};

// 具体调度策略实现
class ClassicalScheduler : public Scheduler {
 public:
  bool CreateTask(const std::function<void()>& func,
                  const std::string& name) override;
  bool CreateTask(std::shared_ptr<Node> node,
                  const std::string& name) override;
  bool RemoveTask(const std::string& name) override;
  bool NotifyStart() override;
  bool NotifyStop() override;
  bool DispatchTask(Task* task) override;

 private:
  bool CreateTaskInternal(const std::shared_ptr<Task>& task,
                          const std::string& name);
  bool CreateThreadForChoreography(std::shared_ptr<CRoutine> cr);
  bool CreateClassicThread(std::shared_ptr<CRoutine> cr);

  std::unordered_map<std::string, std::shared_ptr<Task>> tasks_;
  std::unordered_map<uint64_t, std::thread> threads_;
  std::unordered_map<std::string, std::vector<std::string>> node_proc_map_;
  std::unordered_set<std::string> raw_tasks_;
  std::mutex task_mutex_;

  apollo::cyber::base::AtomicHashMap<std::string, std::string> cr_concerned_map_;
};

6.4.2. 协程调度机制

Cyber RT引入了协程机制,提高了并发处理效率:

cpp 复制代码
class CRoutine {
 public:
  explicit CRoutine(const std::function<void()>& func);
  explicit CRoutine(std::shared_ptr<Runnable> runnable);
  virtual ~CRoutine();

  void Resume();
  void Yield();
  void Release();

  // 状态管理
  State GetState() const { return state_; }
  void SetState(State state) { state_ = state; }

  // 获取/设置ID
  uint64_t Id() const { return id_; }

  // 获取/设置优先级
  uint32_t Priority() const { return priority_; }
  void SetPriority(uint32_t priority) { priority_ = priority; }

  // 获取/设置所属处理器
  int64_t ProcessorId() const { return processor_id_; }
  void SetProcessorId(int64_t proc_id) { processor_id_ = proc_id; }

  std::string Name() const { return name_; }
  void SetName(std::string name) { name_ = name; }

 private:
  State state_;
  uint64_t id_;
  uint32_t priority_;
  int64_t processor_id_;
  std::string name_;
  std::shared_ptr<Runnable> runnable_;
};

6.5. 服务发现机制

6.5.1. 拓扑管理

服务发现是Cyber RT中实现模块自动发现和连接的重要机制:

cpp 复制代码
class TopologyManager {
 public:
  TopologyManager();
  virtual ~TopologyManager();

  bool Init();
  bool Shutdown();

  bool Join(const RoleAttributes& self_attr);
  bool Leave(const RoleAttributes& self_attr);

  bool AddNode(const RoleAttributes& self_attr);
  bool RemoveNode(const RoleAttributes& self_attr);

  bool AddChannel(const RoleAttributes& self_attr);
  bool RemoveChannel(const RoleAttributes& self_attr);

  bool GetNodes(std::vector<RoleAttributes>* nodes);
  bool GetChannels(std::vector<RoleAttributes>* channels);

  template <typename M0, typename C0>
  bool Subscribe(const std::string& channel_name, const C0& callback) {
    return change_listener_->Subscribe<M0, C0>(channel_name, callback);
  }

  template <typename M0>
  bool Unsubscribe(const std::string& channel_name) {
    return change_listener_->Unsubscribe<M0>(channel_name);
  }

  template <typename S0, typename S1>
  bool AddService(const std::string& service_name,
                  const std::function<void(const S0&, S1*)>& service_call) {
    return change_listener_->AddService<S0, S1>(service_name, service_call);
  }

  template <typename S0>
  bool RemoveService(const std::string& service_name) {
    return change_listener_->RemoveService<S0>(service_name);
  }

  template <typename S0, typename S1>
  auto GetServiceProxy(const std::string& service_name)
      -> std::shared_ptr<Service<S0, S1>> {
    return change_listener_->GetServiceProxy<S0, S1>(service_name);
  }

 private:
  void OnTopoChange(const TopologyChange& change);

  std::mutex manager_mutex_;
  std::shared_ptr<NodeManager> node_manager_;
  std::shared_ptr<ChannelManager> channel_manager_;
  std::shared_ptr<ServiceProviderManager> service_manager_;
  std::shared_ptr<ChangeListener> change_listener_;
  std::shared_ptr<rtps::Participation> participation_;
};

6.6. 组件框架

6.6.1. 组件基类

Cyber RT提供了组件框架,简化了模块开发:

cpp 复制代码
template <typename M0, typename M1 = NullType, typename M2 = NullType>
class Component : public ComponentBase {
 public:
  Component();
  virtual ~Component() = default;

  bool Init(const MultiSubOpt&M0, M1, M2>& multi_sub_opt,
            std::shared_ptr<Node> node) override;

 protected:
  virtual bool Proc(const std::shared_ptr<M0>& msg0,
                    const std::shared_ptr<M1>& msg1,
                    const std::shared_ptr<M2>& msg2) = 0;

 private:
  bool ProcByCaller(
      uint64_t caller_id, 
      const std::shared_ptr<apollo::cyber::Data>& data) override;

  std::vector<CallbackCaller<M0, M1, M2>*> callers_;
};

template <typename M0, typename M1, typename M2>
bool Component<M0, M1, M2>::Init(
    const MultiSubOpt<M0, M1, M2>& multi_sub_opt,
    std::shared_ptr<Node> node) {
  node_ = node;
  auto channel_ptrs = multi_sub_opt.GetChannelVec();
  for (uint32_t i = 0; i < channel_ptrs.size(); ++i) {
    if (std::get<0>(channel_ptrs[i]) == nullptr) {
      continue;
    }
    auto caller = new CallbackCaller<M0, M1, M2>();
    auto callback = RegisterBindingCallback(
        &CallbackCaller<M0, M1, M2>::TemplateCallback, caller);
    std::string channel = *(std::get<0>(channel_ptrs[i]));
    auto reader = node_->template CreateReader<M0, M1, M2>(
        channel, callback, *(std::get<1>(channel_ptrs[i])));
    callers_.emplace_back(caller);
  }
  return true;
}

7. 设计模式

7.1. 单例模式

Cyber RT的多个核心组件使用了单例模式,确保系统中只有一个实例:

cpp 复制代码
template <typename T>
T* GetSingleton() {
  static T instance;
  return &instance;
}

#define SINGLETON(T)                                    \
 public:                                                \
  static T* Instance() {                                \
    return GetSingleton<T>();                           \
  }                                                     \
  void ConfigReinit() {                                 \
    delete GetSingleton<T>();                           \
    Instance();                                         \
  }                                                     \
 private:                                               \
  T();                                                  \
  ~T();                                                 \
  friend class GetSingleton<T>;

7.2. 策略模式

调度器使用了策略模式,支持不同的调度算法:

cpp 复制代码
class Scheduler {
 public:
  virtual bool CreateTask(const std::function<void()>& func,
                          const std::string& name) = 0;
  virtual bool NotifyStart() = 0;
  virtual bool NotifyStop() = 0;
  // ... 其他纯虚函数
};

class FairScheduler : public Scheduler {
  // 实现公平调度算法
};

class ClassicScheduler : public Scheduler {
  // 实现经典调度算法
};

7.3. 观察者模式

服务发现机制使用观察者模式实现拓扑变化通知:

cpp 复制代码
class TopologyObserver {
 public:
  virtual void OnJoin(const RoleAttributes& attr) = 0;
  virtual void OnLeave(const RoleAttributes& attr) = 0;
  virtual void OnUpdate(const RoleAttributes& attr) = 0;
};

class ChangeListener : public TopologyObserver {
  // 实现拓扑变化监听
};

7.4. 工厂模式

传输层使用工厂模式创建不同类型的传输器:

cpp 复制代码
template <typename M0>
class TransmitterFactory {
 public:
  static auto CreateTransmitter(const proto::RoleAttributes& role_attr,
                                const proto::QosProfile& qos_profile)
      -> std::shared_ptr<Transmitter<M0>> {
    // 根据qos_profile创建相应类型的传输器
  }
};

8. 总结

Apollo Cyber RT是一个高度优化的实时运行时框架,其架构设计充分考虑了自动驾驶场景的特殊需求。通过模块化设计、高效的消息传递机制和灵活的调度策略,Cyber RT为自动驾驶系统提供了强大而稳定的运行环境。其采用的设计模式使系统具有良好的可扩展性和可维护性,为自动驾驶技术的发展提供了坚实基础.

相关推荐
lifallen3 小时前
Agent plantask 的架构推导
人工智能·语言模型·架构
实在智能RPA3 小时前
实在 Agent 支持本地化部署吗?深度解析企业级私有化 AI 智能助理的技术架构与落地实践
人工智能·ai·架构
飞Link3 小时前
LangChain 核心链式架构演进史:从顺序链到企业级路由兜底实战
python·架构·langchain
周淳APP4 小时前
【React Fiber架构+React18知识点+浏览器原生帧流程和React阶段流程相串】
前端·javascript·react.js·架构
一水鉴天4 小时前
智能代理体系 20260325(腾讯元宝)
人工智能·架构
LONGZETECH4 小时前
新能源汽车动力蓄电池仿真教学软件技术解析——职教数字化解决方案
架构·汽车·汽车仿真教学软件·汽车教学软件·新能源汽车仿真教学软件
智慧化智能化数字化方案4 小时前
架构进阶——解读数据中台与业务中台架构设计方案【附全文阅读】
大数据·微服务·架构·数据中台·业务中台架构设计
掘根5 小时前
【微服务即时通讯】消息存储子服务2
微服务·云原生·架构
熊猫钓鱼>_>5 小时前
MinerU的正确使用方式:如何解析PDF成标准化向量数据,以供AI大模型等场景应用
人工智能·阿里云·架构·pdf·ocr·skill·mineru