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. 關鍵設計原則
解耦與擴展性:
- 通過抽象基類和工廠模式(
CreateScenario
)實現模塊解耦。 - 新增 Scenario/Stage/Task 時無需修改現有代碼,只需擴展配置文件和實現類。
- 通過抽象基類和工廠模式(
狀態驅動:
- 每個組件(Scenario/Stage/Task)通過返回狀態(SUCCESS/RUNNING/ERROR)驅動狀態機切換。
配置化:
- 通過 YAML 文件定義 Scenario、Stage、Task 的映射關系,支持快速調整流程。
容錯性:
- 每個 Stage/Task 的錯誤狀態會觸發上層重規劃或降級策略。
8. 總結
- 架構層級:
Scenario → Stage → Task
,符合 Apollo 的分層設計。 - 狀態機實現:通過?
Status
?枚舉和?NextStage()
?方法實現動態切換。 - 靈活性:支持兩種樣本架地圖的差異化處理,通過配置文件靈活擴展。
你可以根據實際需求補充具體的 Task 邏輯(如路徑規劃、障礙物避讓等),并結合感知模塊的數據驅動狀態機切換。