1. 项目结构设计

project/
├── config/                  # 配置文件(定义 Scenario、Stage、Task 的映射)
├── src/
│   ├── base/                # 抽象基类定义
│   │   ├── scenario_base.h/.cpp
│   │   ├── stage_base.h/.cpp
│   │   └── task_base.h/.cpp
│   ├── scenarios/           # 不同样本架地图的 Scenario 实现
│   │   ├── map_a_scenario.cpp
│   │   └── map_b_scenario.cpp
│   ├── stages/              # 阶段(Stage)实现
│   │   ├── stage1.cpp
│   │   ├── stage2.cpp
│   │   └── ...
│   ├── tasks/               # 任务(Task)实现
│   │   ├── task1.cpp
│   │   ├── task2.cpp
│   │   └── ...
│   └── main.cpp             # 入口逻辑
└── include/                 # 头文件

 

2. 抽象基类定义

(1) Scenario 基类
// base/scenario_base.h
class ScenarioBase {public:virtual ~ScenarioBase() = default;// 初始化 Scenario(如加载配置、初始化 Stage 列表)virtual bool Init(const std::string& config_file) = 0;// 执行当前 Stage 的 Taskvirtual void Process() = 0;// 状态机切换接口:根据条件判断是否切换 Stage 或 Scenariovirtual ScenarioStatus UpdateStatus() = 0;// 获取当前 Stage 名称virtual std::string GetCurrentStageName() const = 0;protected:std::string name_;                      // Scenario 名称(如 MapA/MapB)std::vector<std::shared_ptr<StageBase>> stages_;  // 当前 Scenario 的 Stage 列表size_t current_stage_index_ = 0;        // 当前 Stage 的索引
};
(2) Stage 基类
// base/stage_base.h
class StageBase {public:virtual ~StageBase() = default;// 执行当前 Stage 的所有 Taskvirtual StageStatus Run() = 0;// 获取下一 Stage 名称(根据 Task 返回状态决定)virtual std::string NextStage() const = 0;// 获取 Stage 名称virtual std::string Name() const = 0;protected:std::string name_;                      // Stage 名称(如 Stage1/Stage2)std::vector<std::shared_ptr<TaskBase>> tasks_;  // 当前 Stage 的 Task 列表
};
(3) Task 基类
// base/task_base.h
class TaskBase {public:virtual ~TaskBase() = default;// 执行单个 Task 的逻辑virtual TaskStatus Execute() = 0;// 获取 Task 名称virtual std::string Name() const = 0;
};

3. 状态机实现原理

(1) 状态定义
// base/status.h
enum class ScenarioStatus {SUCCESS,      // 当前 Scenario 成功完成RUNNING,      // 当前 Scenario 继续执行ERROR,        // 当前 Scenario 出错TRANSITION    // 需要切换到其他 Scenario
};enum class StageStatus {SUCCESS,      // 当前 Stage 成功完成RUNNING,      // 当前 Stage 继续执行ERROR         // 当前 Stage 出错
};enum class TaskStatus {SUCCESS,      // 当前 Task 成功完成RUNNING,      // 当前 Task 继续执行ERROR         // 当前 Task 出错
};
(2) 状态机切换逻辑
  • Scenario 状态机
    • 在 UpdateStatus() 中根据感知数据(如样本架地图类型、任务完成状态)决定是否切换 Scenario。
    • 示例:如果检测到地图类型从 MapA 切换为 MapB,则调用 SetScenario("MapB")
  • Stage 状态机
    • 在 Run() 中依次执行所有 Task,根据 Task 返回的 TaskStatus 决定是否继续或切换 Stage。
    • 示例:如果某个 Task 返回 SUCCESS,则执行下一个 Task;如果返回 ERROR,则触发 Scenario 的重规划。

4. 样本架地图的实现示例

(1) 地图 A 的 Scenario 实现
// scenarios/map_a_scenario.cpp
class MapAScenario : public ScenarioBase {public:std::string Name() const override { return "MapA"; }bool Init(const std::string& config_file) override {// 加载 Stage 列表(如 Stage1 -> Stage2)stages_.push_back(std::make_shared<Stage1>());stages_.push_back(std::make_shared<Stage2>());return true;}void Process() override {auto& current_stage = stages_[current_stage_index_];auto status = current_stage->Run();if (status == StageStatus::SUCCESS) {// 切换到下一 Stagecurrent_stage_index_++;} else if (status == StageStatus::ERROR) {// 触发 Scenario 重规划ResetStageIndex();}}ScenarioStatus UpdateStatus() override {// 根据感知数据判断是否需要切换 Scenarioif (CheckMapTypeChangedToB()) {return ScenarioStatus::TRANSITION;}return ScenarioStatus::RUNNING;}
};
(2) 地图 B 的 Scenario 实现
// scenarios/map_b_scenario.cpp
class MapBScenario : public ScenarioBase {public:std::string Name() const override { return "MapB"; }bool Init(const std::string& config_file) override {// 加载 Stage 列表(如 Stage3 -> Stage4)stages_.push_back(std::make_shared<Stage3>());stages_.push_back(std::make_shared<Stage4>());return true;}// ... 其他方法类似
};

5. 配置文件示例

# config/scenario_config.yaml
scenarios:- name: MapAstages:- name: Stage1tasks:- name: Task1- name: Task2- name: Stage2tasks:- name: Task3- name: MapBstages:- name: Stage3tasks:- name: Task4- name: Task5

6. 状态机管理器(主逻辑)

// main.cpp
int main() {// 1. 加载配置文件std::string config_file = "config/scenario_config.yaml";ScenarioConfig config = LoadScenarioConfig(config_file);// 2. 创建初始 Scenariostd::shared_ptr<ScenarioBase> current_scenario = CreateScenario("MapA");// 3. 初始化 Scenarioif (!current_scenario->Init(config_file)) {return -1;}// 4. 主循环while (true) {// 4.1 执行当前 Scenario 的 Stagecurrent_scenario->Process();// 4.2 更新 Scenario 状态auto status = current_scenario->UpdateStatus();if (status == ScenarioStatus::SUCCESS) {break;} else if (status == ScenarioStatus::TRANSITION) {// 切换到新的 Scenariostd::string new_scenario_name = GetNextScenarioName();  // 通过感知数据获取current_scenario = CreateScenario(new_scenario_name);current_scenario->Init(config_file);}}return 0;
}

7. 关键设计原则

  1. 解耦与扩展性

    • 通过抽象基类和工厂模式(CreateScenario)实现模块解耦。
    • 新增 Scenario/Stage/Task 时无需修改现有代码,只需扩展配置文件和实现类。
  2. 状态驱动

    • 每个组件(Scenario/Stage/Task)通过返回状态(SUCCESS/RUNNING/ERROR)驱动状态机切换。
  3. 配置化

    • 通过 YAML 文件定义 Scenario、Stage、Task 的映射关系,支持快速调整流程。
  4. 容错性

    • 每个 Stage/Task 的错误状态会触发上层重规划或降级策略。

8. 总结

  • 架构层级Scenario → Stage → Task,符合 Apollo 的分层设计。
  • 状态机实现:通过 Status 枚举和 NextStage() 方法实现动态切换。
  • 灵活性:支持两种样本架地图的差异化处理,通过配置文件灵活扩展。

你可以根据实际需求补充具体的 Task 逻辑(如路径规划、障碍物避让等),并结合感知模块的数据驱动状态机切换。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/90374.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/90374.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/90374.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

动手学深度学习13.6. 目标检测数据集-笔记练习(PyTorch)

以下内容为结合李沐老师的课程和教材补充的学习笔记&#xff0c;以及对课后练习的一些思考&#xff0c;自留回顾&#xff0c;也供同学之人交流参考。 本节课程地址&#xff1a;数据集_哔哩哔哩_bilibili 本节教材地址&#xff1a;13.6. 目标检测数据集 — 动手学深度学习 2.0…

Unity3D游戏内存优化指南

前言 Unity3D 游戏的内存控制是保证游戏流畅运行&#xff08;尤其在移动端和主机平台&#xff09;和避免崩溃的关键挑战。以下是核心策略和常见问题的解决方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&#xff0c;希望大家可以点击进来一起交流一下开发经验…

git学习:首次创建仓库

文章目录前言&#xff1a;1、首次创建仓库并上传数据1.1 创建仓库&#xff0c;1.2 命令上传1.3 首次代码上传至仓库的步骤&#xff1a;2、分支操作2.1 分支的删除2.2 切换分支2.3 查看分支2.4 同步其他分支的修改3、查看电脑的配置文件4、远程仓库命令 git remote5、其他后语前…

C++并行计算:OpenMP与MPI全解析

在高性能计算领域&#xff0c;充分利用硬件资源的并行计算技术已成为刚需。从单节点多核到跨节点集群&#xff0c;开发者需要掌握不同的并行编程模型。本文将系统讲解两种主流并行技术&#xff1a;OpenMP&#xff08;共享内存多核并行&#xff09;与MPI&#xff08;分布式内存集…

TCP 动态选路协议全面研究:OSPF、BGP 与 IS-IS 的比较与应用分析

一、引言&#xff1a;动态选路协议概述 在现代计算机网络中&#xff0c;路由选择是数据传输的核心功能&#xff0c;它决定了数据包从源到目的地的路径选择。随着网络规模的不断扩大和复杂性的增加&#xff0c;静态路由已经无法满足网络动态变化的需求&#xff0c;动态路由协议…

OpenCV 图像哈希类cv::img_hash::AverageHash

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::img_hash::AverageHash是OpenCV中用于图像哈希&#xff08;Image Hashing&#xff09;的一个类&#xff0c;属于opencv_img_hash模块。它实现了…

【Python-网络爬虫】爬虫的基础概念介绍

目录 一、爬虫的介绍 1.1 爬虫的概念 1.2 爬虫的作用 1. 搜索引擎数据索引 2. 商业数据采集与分析 3. 舆情监控与社交分析 4. 学术研究与数据挖掘 5. 信息聚合与服务优化 二、爬虫的分类 三、爬虫的基本流程 3.1 基本流程 3.2 Robots协议 一、爬虫的介绍 1.1 爬虫的…

力扣-31.下一个排列

题目链接 31.下一个排列 class Solution {public void nextPermutation(int[] nums) {//1.从右往左找第一个非逆序的数aint left nums.length - 2; //这里是为了找不到顺序对的时候正好停在-1while (left > 0 && nums[left] > nums[left 1]) { //一定要取等号…

Python爬虫实战:研究python-nameparser库相关技术

1. 引言 在当今数字化时代,姓名作为个人身份的重要标识,在许多领域都有着广泛的应用需求。例如,在客户关系管理系统中,准确解析姓名可以帮助企业更好地了解客户背景;在学术研究中,分析作者姓名分布有助于发现研究团队的地域特征;在社交网络分析中,姓名信息可以辅助进行…

Android中MVI架构详解

博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家 👉点击跳转到教程 什么是 MVI 架构? MVI (Model-View-Intent) 是一种单向数据流的架构模式,它源于响应式编程思想。在 MVI 中: 架构图: 1、Model: 代表的是UI 状态,它包含了…

AutoGen-AgentChat-3-人机交互

import os from dotenv import load_dotenvload_dotenv()True人机交互 在上一节“团队”中&#xff0c;我们了解了如何创建、观察和控制代理团队。本节将重点介绍如何在应用程序中与团队进行交互&#xff0c;并向团队提供人工反馈。 您可以通过两种主要方式从您的应用程序与团队…

Flink Db2 CDC 环境配置与验证

一、DB2 数据库核心配置 1. 启用数据库日志记录与CDC支持 -- 以DB2管理员身份连接数据库 CONNECT TO mydb USER db2inst1 USING password;-- 启用数据库归档日志模式&#xff08;CDC依赖&#xff09; UPDATE DATABASE CONFIGURATION USING LOGARCHMETH1 DISK:/db2log/archive…

初识单例模式

文章目录场景通点定义实现思路六种 Java 实现饿汉式懒汉式synchronized 方法双重检查锁 Double Check Lock Volatile静态内部类 Singleton Holder枚举单例单例运用场景破解单例模式参考场景通点 资源昂贵&#xff1a;数据库连接池、线程池、日志组件&#xff0c;只需要一份全…

音乐抢单源码(连单卡单/叠加组规则/打针/多语言)

简介&#xff1a; 测试环境&#xff1a;Nginx、PHP7.2、MySQL5.6&#xff0c;运行目录设置为public&#xff0c;伪静态thinkphp&#xff0c;建议开启SSL 测试语言&#xff1a;11种 不知道谁给我的一套&#xff0c;说是买来的&#xff0c;我看了一下功能感觉也一般&#…

分类树查询性能优化:从 2 秒到 0.1 秒的技术蜕变之路

在电商系统中&#xff0c;分类树查询是一个基础且高频的功能&#xff0c;然而这个看似简单的功能背后却隐藏着不小的性能挑战。本文将分享我们在实际项目中对分类树查询功能进行五次优化的全过程&#xff0c;看如何将查询耗时从 2 秒缩短至 0.1 秒&#xff0c;为用户提供更流畅…

Ansible 介绍及安装

简介 Ansible 是一款开源的自动化工具&#xff0c;广泛应用于配置管理、应用部署、任务自动化以及多节点管理等领域。它由 Michael DeHaan 于 2012 年创建&#xff0c;ansible 目前已经已经被红帽官方收购&#xff0c;是自动化运维工具中大家认可度最高的&#xff0c;并且上手…

超光谱相机的原理和应用场景

超光谱相机是光谱成像技术的尖端形态&#xff0c;具备亚纳米级光谱分辨率与超千波段连续覆盖能力&#xff0c;通过“图谱合一”的三维数据立方体实现物质的精准识别与分析。其核心技术架构、应用场景及发展趋势如下&#xff1a;一、核心技术原理1、‌分光机制‌‌干涉分光‌&am…

掌握MySQL函数:高效数据处理指南

​ 在 MySQL 数据库管理系统中&#xff0c;函数扮演着极为重要的角色。它们就像是数据库操作的得力助手&#xff0c;能够帮助开发者高效地完成各种数据处理任务。本文将深入探讨 MySQL 函数的方方面面&#xff0c;从其基本概念到实际应用&#xff0c;帮助读者全面掌握这一强大的…

10.SpringBoot的统一异常处理详解

文章目录1. 异常处理基础概念1.1 什么是异常处理1.2 为什么需要统一异常处理1.3 Spring异常处理机制2. SpringBoot默认异常处理2.1 默认错误页面2.2 自定义错误页面3. 全局异常处理器3.1 基础全局异常处理器3.2 统一响应格式3.3 使用统一响应格式的异常处理器4. 自定义异常4.1 …