日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Apollo源码分析:路径规划 (v5.5)

發(fā)布時(shí)間:2023/12/8 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Apollo源码分析:路径规划 (v5.5) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Apollo開源代碼鏈接:https://github.com/ApolloAuto/apollo

本文主要講解Apollo/modules/planning中的路徑規(guī)劃的架構(gòu)和算法。

第一章? ? 架構(gòu)設(shè)計(jì)與實(shí)現(xiàn)

一、架構(gòu)設(shè)計(jì)與實(shí)現(xiàn)

?

引自:https://github.com/ApolloAuto/apollo/blob/master/modules/planning/README_cn.md

?

Apollo FSM(finite state machine):一個(gè)有限狀態(tài)機(jī),與高清地圖確定車輛狀態(tài)給定其位置和路線。

----------------------------------------------------------------------------------------------------------------------------------------

Planning模塊整體框架:

1. 可執(zhí)行程序?qū)?#xff1a; Planning Dispatcher根據(jù)車輛的狀態(tài)和其他相關(guān)信息,調(diào)用合適的Planner。Planner實(shí)現(xiàn)獲取所需的上下文數(shù)據(jù)和其他信息,確定相應(yīng)的車輛意圖,執(zhí)行該意圖所需的規(guī)劃任務(wù)并生成規(guī)劃軌跡。它還將更新未來作業(yè)的上下文。根據(jù)工作模式不同將規(guī)劃任務(wù)分成不同的Planner模式(LatticePlanner\NaviPlanner\PublicRoadPlanner\RTKReplayPlanner)。

2.app層:每種Planner分成多個(gè)場景Scenario(BareIntersectionUnprotectedScenario、EmergencyPullOverScenario、EmergencyStopScenario、LaneFollowScenario、TestLearningModelScenario、NarrowStreetUTurnScenario、PullOverScenario、ValetParkingScenario、ParkAndGoScenario、StopSignUnprotectedScenario、TrafficLightProtectedScenario、TrafficLightUnprotectedLeftTurnScenario、TrafficLightUnprotectedRightTurnScenario、YieldSignScenario)-》每個(gè)場景又分解成多個(gè)Stage(例如ValetParkingScenario包含StageApproachingParkingSpot和StageParking兩個(gè)Stage)

3.lib層:每個(gè)Stage又分解成可執(zhí)行的Task(包括不同的Deciders & Optimizers庫),Task是Deciders & Optimizers :一組實(shí)現(xiàn)決策任務(wù)和各種優(yōu)化的無狀態(tài)庫。優(yōu)化器特別優(yōu)化車輛的軌跡和速度。決策者是基于規(guī)則的分類決策者,他們建議何時(shí)換車道、何時(shí)停車、何時(shí)爬行(慢速行進(jìn))或爬行何時(shí)完成。

-------------------------------------------------------------------------------------------------------------------------------------------

Planning Context: 作業(yè)的上下文。

這種 可執(zhí)行程序?qū)?》app層 -》lib層 的三層分級(jí)架構(gòu)實(shí)質(zhì)與視覺感知模塊類似。

本文路徑規(guī)劃模塊架構(gòu)與視覺感知模塊架構(gòu)( https://blog.csdn.net/Cxiazaiyu/article/details/106256330 區(qū)別:

?

視覺感知模塊中更像是自下而上地設(shè)計(jì)出這種三層結(jié)構(gòu)的,因此,我們也自下而上地講解了這個(gè)結(jié)構(gòu);

路徑規(guī)劃模塊更像是自上而下設(shè)計(jì)出這種架構(gòu)的,因此,我們也自上而下地講解這個(gè)結(jié)構(gòu)。

?

視覺感知模塊命名更直白。

路徑規(guī)劃模塊把接口分散放入各個(gè)層的模塊中了,沒有集中放在一個(gè)文件夾。

?

?1. 可執(zhí)行程序?qū)?/strong>--planning/planner

定義抽象基類PlannerDispatcher,包含了Planner類型的數(shù)據(jù)成員;

class PlannerDispatcher {public:virtual std::unique_ptr<Planner> DispatchPlanner() = 0;protected:common::util::Factory<PlannerType, Planner> planner_factory_; };

NaviPlannerDispatcher和OnLanePlannerDispatcher繼承自PlannerDispatcher,覆蓋了抽象基類中的virtual std::unique_ptr<Planner> DispatchPlanner()方法,實(shí)現(xiàn)通過工廠模式創(chuàng)建配置文件中指定的Planner對(duì)象。

以?NaviPlannerDispatcher為例:

std::unique_ptr<Planner> NaviPlannerDispatcher::DispatchPlanner() {PlanningConfig planning_config;if (!apollo::cyber::common::GetProtoFromFile(FLAGS_planning_config_file,&planning_config)) {return nullptr;}auto planner_type = PlannerType::NAVI;if (planning_config.has_navigation_planning_config()) {planner_type = planning_config.navigation_planning_config().planner_type(0);}return planner_factory_.CreateObject(planner_type); }

Planner為定義的基類接口,Planner中包含了scenario

class Planner { protected:scenario::ScenarioManager scenario_manager_;scenario::Scenario* scenario_ = nullptr; };

?? PlannerWithReferenceLine繼承自 Planner,做了一層抽象:

class PlannerWithReferenceLine : public Planner {};

根據(jù)不同的工作模式定義了4種Planner:

class LatticePlanner : public PlannerWithReferenceLine {};/*** @class NaviPlanner* @brief NaviPlanner is a planner based on real-time relative maps. It uses the* vehicle's FLU (Front-Left-Up) coordinate system to accomplish tasks such as* cruising, following, overtaking, nudging, changing lanes and stopping.* Note that NaviPlanner is only used in navigation mode (turn on navigation* mode by setting "FLAGS_use_navigation_mode" to "true") and do not use it in* standard mode.*/ class NaviPlanner : public PlannerWithReferenceLine {};/*** @class PublicRoadPlanner* @brief PublicRoadPlanner is an expectation maximization planner.*/class PublicRoadPlanner : public PlannerWithReferenceLine{};/*** @class RTKReplayPlanner* @brief RTKReplayPlanner is a derived class of Planner.* It reads a recorded trajectory from a trajectory file and* outputs proper segment of the trajectory according to vehicle* position.*/ class RTKReplayPlanner : public PlannerWithReferenceLine{};

2. app層--planning/scenarios

前面講到Planner中包含scenario::ScenarioManager scenario_manager_和scenario::Scenario* scenario_ = nullptr數(shù)據(jù)成員,

class Scenario {public:/*** Each scenario should define its own stages object's creation* scenario will call stage's Stage::Process function following a configured* order, The return value of Stage::Process function determines the* transition from one stage to another.*/virtual std::unique_ptr<Stage> CreateStage(const ScenarioConfig::StageConfig& stage_config) = 0;// Each scenario should define its own transfer condition, i.e., when it// should allow to transfer from other scenario to itself.virtual bool IsTransferable(const Scenario& other_scenario,const Frame& frame) {return true;}protected:std::unique_ptr<Stage> current_stage_; };

基于scenario派生出BareIntersectionUnprotectedScenario、EmergencyPullOverScenario、EmergencyStopScenario、LaneFollowScenario、TestLearningModelScenario、NarrowStreetUTurnScenario、PullOverScenario、ValetParkingScenario、ParkAndGoScenario、StopSignUnprotectedScenario、TrafficLightProtectedScenario、TrafficLightUnprotectedLeftTurnScenario、TrafficLightUnprotectedRightTurnScenario、YieldSignScenario;

?Scenario類型中又包含Stage類型的數(shù)據(jù)成員。一個(gè)Scenario分解成多個(gè)Stage,不同Stage可能是基于不同規(guī)劃算法實(shí)現(xiàn)的。例如:泊車場景中(Apollo/modules/planning/scenarios/park/valet_parking),劃分成了StageApproachingParkingSpot和StageParking兩個(gè)Stage。

?

Stage中包含Task類型的數(shù)據(jù)成員,依次執(zhí)行Tasklilst上的Task,相當(dāng)于將多個(gè)lib串聯(lián)起來實(shí)現(xiàn)一定功能的app:

class Stage {public:/*** @brief Each stage does its business logic inside Process function.* If the stage want to transit to a different stage after finish,* it should set the type of 'next_stage_'.*/virtual StageStatus Process(const common::TrajectoryPoint& planning_init_point, Frame* frame) = 0;/*** @brief The sequence of tasks inside the stage. These tasks usually will be* executed in order.*/const std::vector<Task*>& TaskList() const { return task_list_; }protected:std::map<TaskConfig::TaskType, std::unique_ptr<Task>> tasks_;std::vector<Task*> task_list_; };

3. lib層--planning/tasks

決策任務(wù)deciders和各種優(yōu)化optimizers的無狀態(tài)庫,都是基于Task基類派生。

決策者是基于規(guī)則的分類決策者,他們建議何時(shí)換車道、何時(shí)停車、何時(shí)爬行(慢速行進(jìn))或爬行何時(shí)完成。

class Decider : public Task {};

Decider又派生出:CreepDecider、LaneChangeDecider、OpenSpaceFallbackDecider、OpenSpacePreStopDecider、OpenSpaceRoiDecider、PathAssessmentDecider、PathBoundsDecider、PathDecider、PathLaneBorrowDecider、PathReuseDecider、RssDecider、RuleBasedStopDecider、SpeedBoundsDecider、SpeedLimitDecider、SpeedDecider、STBoundsDecider

優(yōu)化器特別優(yōu)化車輛的軌跡和速度。

class PathOptimizer : public Task {}; class SpeedOptimizer : public Task {}; class TrajectoryOptimizer : public Task{};

具體包括:

class OpenSpaceTrajectoryProvider : public TrajectoryOptimizer{}; class OpenSpaceTrajectoryPartition : public TrajectoryOptimizer{}; class PathTimeHeuristicOptimizer : public SpeedOptimizer {}; class PiecewiseJerkPathOptimizer : public PathOptimizer{}; class PiecewiseJerkSpeedNonlinearOptimizer : public SpeedOptimizer{}; class PiecewiseJerkSpeedOptimizer : public SpeedOptimizer{};

關(guān)于Apollo路徑規(guī)劃更詳細(xì)的資料可參考:https://blog.csdn.net/davidhopper/article/details/79176505?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control

?

第二章??? 設(shè)計(jì)模式

一、簡單工廠模式

Apollo/modules/planning/scenarios/scenario_manager.cc

std::unique_ptr<Scenario> ScenarioManager::CreateScenario(ScenarioConfig::ScenarioType scenario_type) {std::unique_ptr<Scenario> ptr;switch (scenario_type) {case ScenarioConfig::BARE_INTERSECTION_UNPROTECTED:ptr.reset(new scenario::bare_intersection::BareIntersectionUnprotectedScenario(config_map_[scenario_type], &scenario_context_));break;case ScenarioConfig::EMERGENCY_PULL_OVER:ptr.reset(new emergency_pull_over::EmergencyPullOverScenario(config_map_[scenario_type], &scenario_context_));break;case ScenarioConfig::EMERGENCY_STOP:ptr.reset(new emergency_stop::EmergencyStopScenario(config_map_[scenario_type], &scenario_context_));break;case ScenarioConfig::LANE_FOLLOW:ptr.reset(new lane_follow::LaneFollowScenario(config_map_[scenario_type],&scenario_context_));break;case ScenarioConfig::PARK_AND_GO:ptr.reset(new scenario::park_and_go::ParkAndGoScenario(config_map_[scenario_type], &scenario_context_));break;case ScenarioConfig::PULL_OVER:ptr.reset(new scenario::pull_over::PullOverScenario(config_map_[scenario_type], &scenario_context_));break;case ScenarioConfig::STOP_SIGN_UNPROTECTED:ptr.reset(new scenario::stop_sign::StopSignUnprotectedScenario(config_map_[scenario_type], &scenario_context_));break;case ScenarioConfig::TEST_LEARNING_MODEL:ptr.reset(new scenario::TestLearningModelScenario(config_map_[scenario_type], &scenario_context_));break;case ScenarioConfig::TRAFFIC_LIGHT_PROTECTED:ptr.reset(new scenario::traffic_light::TrafficLightProtectedScenario(config_map_[scenario_type], &scenario_context_));break;case ScenarioConfig::TRAFFIC_LIGHT_UNPROTECTED_LEFT_TURN:ptr.reset(new scenario::traffic_light::TrafficLightUnprotectedLeftTurnScenario(config_map_[scenario_type], &scenario_context_));break;case ScenarioConfig::TRAFFIC_LIGHT_UNPROTECTED_RIGHT_TURN:ptr.reset(new scenario::traffic_light::TrafficLightUnprotectedRightTurnScenario(config_map_[scenario_type], &scenario_context_));break;case ScenarioConfig::VALET_PARKING:ptr.reset(new scenario::valet_parking::ValetParkingScenario(config_map_[scenario_type], &scenario_context_));break;case ScenarioConfig::YIELD_SIGN:ptr.reset(new scenario::yield_sign::YieldSignScenario(config_map_[scenario_type], &scenario_context_));break;default:return nullptr;}if (ptr != nullptr) {ptr->Init();}return ptr;

與視覺感知模塊(https://blog.csdn.net/Cxiazaiyu/article/details/106256330)中使用的簡單工廠模式類似,這里不再贅述。

二、工廠方法模式(基于類模板)

工廠方法模式:調(diào)用抽象工廠的接口,返回抽象產(chǎn)品的指針;根據(jù)輸入配置參數(shù)不同,在抽象工廠接口內(nèi)部調(diào)用相應(yīng)的具體工廠,生產(chǎn)相應(yīng)的具體產(chǎn)品,并將具體產(chǎn)品的指針綁定在抽象產(chǎn)品的指針上作為返回值。Register解決的就是實(shí)現(xiàn)“根據(jù)輸入配置參數(shù)不同,在抽象工廠接口內(nèi)部調(diào)用相應(yīng)的具體工廠”,方法是建立一個(gè)map,根據(jù)配置參數(shù)名稱映射到相應(yīng)的具體工廠。

路徑規(guī)劃模塊(Apollo/modules/planning)主要使用基于類模板實(shí)現(xiàn)工廠方法模式創(chuàng)建對(duì)象。包括在planner_dispatcher中創(chuàng)建planner對(duì)象(?Apollo/modules/planning/planner/planner_dispatcher.h中定義 common::util::Factory<PlannerType, Planner> planner_factory_;),在scenarios中創(chuàng)建stage對(duì)象(Apollo/modules/planning/scenarios/stop_sign/unprotected/stop_sign_unprotected_scenario.cc中定義的? static apollo::common::util::Factory<ScenarioConfig::StageType, Stage, Stage* (*)(const ScenarioConfig::StageConfig& stage_config)> s_stage_factory_;),在stage中創(chuàng)建task(Apollo/modules/planning/scenarios/stage.cc中調(diào)用auto ptr = TaskFactory::CreateTask(*config_map[task_type]);)。

2.1 UML結(jié)構(gòu)

參與者如下(這里以task_factory_一條應(yīng)用鏈路為例,planner_factory_的鏈路與之類似):

參與者作用在Apollo中的示例
抽象工廠類模板,創(chuàng)建對(duì)象調(diào)用的接口和Register的接口由Factory(factory.h中定義)實(shí)例化出的task_factory_
具體工廠實(shí)例化抽象工廠的類模板,負(fù)責(zé)生產(chǎn)具體產(chǎn)品。將抽象工廠的指針綁定在具體工廠指針上,根據(jù)需要調(diào)用相應(yīng)的具體工廠以生產(chǎn)相應(yīng)的具體產(chǎn)品task_factory_中輸入的creator(這里是匿名函數(shù)的形式)
抽象產(chǎn)品抽象工廠返回類型為抽象產(chǎn)品的指針Task
具體產(chǎn)品綁定在基類(抽象產(chǎn)品)指針上的具體派生類指針LaneChangeDecider、SpeedBoundsDecider、OpenSpaceRoiDecider (Decider和PathOptimizer是根據(jù)邏輯需要在抽象產(chǎn)品和具體產(chǎn)品之間抽象的一層)

注意:相比于一般只能創(chuàng)建一種抽象產(chǎn)品的工廠方法模式,這里設(shè)計(jì)的工廠方法模式還支持創(chuàng)建不同的抽象產(chǎn)品(基于類模板,把抽象產(chǎn)品類型作為參數(shù))。

?

2.2 實(shí)現(xiàn)方法

2.2.1 抽象工廠 & 抽象產(chǎn)品 、 map & 創(chuàng)建對(duì)象的接口

  • 類模板的定義

Apollo/modules/common/util/factory.h 中Factory類模板提供了注冊(cè)和創(chuàng)建對(duì)象的接口。

template <typename IdentifierType, class AbstractProduct, //IdentifierType為派生類名的類型(一般可設(shè)為string),AbstractProduct為基類class ProductCreator = AbstractProduct *(*)(),class MapContainer = std::map<IdentifierType, ProductCreator>> class Factory {public:/*** @brief Registers the class given by the creator function, linking it to id.* Registration must happen prior to calling CreateObject.* @param id Identifier of the class being registered* @param creator Function returning a pointer to an instance of* the registered class* @return True if the key id is still available*/bool Register(const IdentifierType &id, ProductCreator creator) { //注冊(cè)的接口return producers_.insert(std::make_pair(id, creator)).second;}/*** @brief Creates and transfers membership of an object of type matching id.* Need to register id before CreateObject is called. May return nullptr* silently.* @param id The identifier of the class we which to instantiate* @param args the object construction arguments*/template <typename... Args>std::unique_ptr<AbstractProduct> CreateObjectOrNull(const IdentifierType &id, //創(chuàng)建對(duì)象的接口,返回的是抽象產(chǎn)品(基類)的指針Args &&... args) { auto id_iter = producers_.find(id);if (id_iter != producers_.end()) {return std::unique_ptr<AbstractProduct>((id_iter->second)(std::forward<Args>(args)...));}return nullptr;}/*** @brief Creates and transfers membership of an object of type matching id.* Need to register id before CreateObject is called.* @param id The identifier of the class we which to instantiate* @param args the object construction arguments*/template <typename... Args>std::unique_ptr<AbstractProduct> CreateObject(const IdentifierType &id, //創(chuàng)建對(duì)象的接口Args &&... args) {auto result = CreateObjectOrNull(id, std::forward<Args>(args)...);AERROR_IF(!result) << "Factory could not create Object of type : " << id;return result;}private:MapContainer producers_; };
  • map定義:

std::map<IdentifierType, ProductCreator>> producers_;

注冊(cè)就是將實(shí)際需要生產(chǎn)的具體產(chǎn)品的名稱和具體工廠插入producers_,在需要?jiǎng)?chuàng)建對(duì)象時(shí)根據(jù)具體產(chǎn)品的名稱索引到具體工廠,調(diào)用具體工廠生產(chǎn)具體產(chǎn)品,并將具體產(chǎn)品的指針綁定在抽象產(chǎn)品的指針上作為具體工廠的返回值。

?

  • 基于抽象工廠類模板+抽象產(chǎn)品作為模板實(shí)參=》實(shí)例化出抽象工廠

在Apollo/modules/planning/tasks/task_factory.h中針對(duì)task基類對(duì)工廠模板類進(jìn)行了實(shí)例化,產(chǎn)生task_factory_抽象工廠,并使用TaskFactory類對(duì)task_factory_抽象工廠做了一層封裝。

class TaskFactory {public:...private:static apollo::common::util::Factory<TaskConfig::TaskType, Task, Task *(*)(const TaskConfig &config),std::unordered_map<TaskConfig::TaskType, Task *(*)(const TaskConfig &config), std::hash<int>>> task_factory_;static std::unordered_map<TaskConfig::TaskType, TaskConfig, std::hash<int>>default_task_configs_; };

上文已經(jīng)講過Task為基類(抽象產(chǎn)品),派生出各種Decider和Optimizer的具體產(chǎn)品。

2.2.2 具體工廠 & 具體產(chǎn)品、 Register(向map中添加元素)

//Register void TaskFactory::Init(const PlanningConfig& config) {task_factory_.Register(TaskConfig::LANE_CHANGE_DECIDER,[](const TaskConfig& config) -> Task* {return new LaneChangeDecider(config); //使用匿名函數(shù)定義具體工廠,具體工廠生產(chǎn)具體產(chǎn)品});task_factory_.Register(TaskConfig::SPEED_BOUNDS_PRIORI_DECIDER,[](const TaskConfig& config) -> Task* {return new SpeedBoundsDecider(config);});task_factory_.Register(TaskConfig::OPEN_SPACE_ROI_DECIDER,[](const TaskConfig& config) -> Task* {return new OpenSpaceRoiDecider(config);}); }std::unique_ptr<Task> TaskFactory::CreateTask(const TaskConfig& task_config) {TaskConfig merged_config;if (default_task_configs_.find(task_config.task_type()) !=default_task_configs_.end()) {merged_config = default_task_configs_[task_config.task_type()];}merged_config.MergeFrom(task_config);return task_factory_.CreateObject(task_config.task_type(), merged_config); }

特點(diǎn):在Apollo/modules/planning/tasks/task_factory.cc定義中對(duì)task的派生類LaneChangeDecider、PATH_LANE_BORROW_DECIDER等集中進(jìn)行注冊(cè)。

2.2.3 Client使用示例:

?Apollo/modules/planning/scenarios/stage.cc中讀入配置參數(shù),調(diào)用抽象工廠的接口,依次生產(chǎn)具體產(chǎn)品:

for (int i = 0; i < config_.task_type_size(); ++i) {auto task_type = config_.task_type(i);ACHECK(config_map.find(task_type) != config_map.end())<< "Task: " << TaskConfig::TaskType_Name(task_type)<< " used but not configured";auto iter = tasks_.find(task_type);if (iter == tasks_.end()) {auto ptr = TaskFactory::CreateTask(*config_map[task_type]); //根據(jù)配置文件的參數(shù)動(dòng)態(tài)地創(chuàng)建具體產(chǎn)品task_list_.push_back(ptr.get());tasks_[task_type] = std::move(ptr);} else {task_list_.push_back(iter->second.get());}}

可參考:https://blog.csdn.net/davidhopper/article/details/79197075

?

下表總結(jié)對(duì)比基于類模板實(shí)現(xiàn)工廠方法模式和視覺感知模塊(https://blog.csdn.net/Cxiazaiyu/article/details/106256330)使用的基于宏定義的工廠方法模式的異同

?基于類模板的工廠方法實(shí)現(xiàn)基于宏定義的工廠方法實(shí)現(xiàn)

可適用不同基類類型的抽象工廠機(jī)理

工廠的類模板只有一個(gè),利用類模板機(jī)理,將抽象產(chǎn)品類型(基類)作為模板參數(shù),根據(jù)抽象產(chǎn)品類型實(shí)例化出不同的抽象工廠只有一個(gè)抽象工廠原型類,使用返回創(chuàng)建對(duì)象的接口使用Any類型機(jī)理(支持代表任意類型)保證可以返回任意抽象產(chǎn)品
實(shí)現(xiàn)方法的區(qū)別

直接將Register和CreateObject作為工廠類模板的兩個(gè)方法,使用類模板Factory實(shí)例化出的對(duì)象調(diào)用Register和CreateObject方法

?

?

?

CreateObject: 為每一個(gè)基類宏展開一個(gè)伴隨的Register類(實(shí)際作用是CreateObject),該Register類中給出創(chuàng)建對(duì)象的接口;

Register: 為每一個(gè)派生類宏展開一個(gè)伴隨的Register函數(shù),該Register函數(shù)建立配置參數(shù)名稱到具體工廠的map。

?

Register的map的區(qū)別

(相同點(diǎn):都基于Register添加一個(gè)map,建立根據(jù)輸入配置文件參數(shù)映射到對(duì)應(yīng)的具體工廠)

無論是基于宏定義還是類模板,在抽象工廠和具體工廠之間需要實(shí)現(xiàn)怎么基于抽象工廠的接口調(diào)用具體工廠(Register機(jī)理建立map后,使用map索引到真實(shí)綁定的具體工廠)。?

每一個(gè)基類維護(hù)一個(gè)Local的map

(std::map<IdentifierType, ProductCreator>> producers_;),通過producers_[派生類名]可以調(diào)用對(duì)應(yīng)的具體工廠;

不同基類維護(hù)不同的Local map。

維護(hù)一個(gè)Global的map, (static std::map<string, std::map<std::string, ObjectFactory *>> factory_map;),通過factory_map[基類名][派生類名]可以調(diào)用對(duì)應(yīng)的具體工廠
具體工廠的實(shí)現(xiàn)機(jī)制直接使用匿名函數(shù)在派生類中使用宏定義展開成對(duì)應(yīng)的具體工廠類,繼承自抽象工廠類
Register的方式區(qū)別

在factory的Register方法中集中Register,將派生類名-具體工廠的對(duì)應(yīng)關(guān)系插入到map中;

?

在每個(gè)派生類定義中分布式地Register,將[基類名][派生類名]-具體工廠的對(duì)應(yīng)關(guān)系插入到map中;

?

優(yōu)\缺點(diǎn)

優(yōu)點(diǎn):類模板工廠定義簡單

缺點(diǎn):如果需要添加新的基類,需要重新實(shí)例化factory;如果需要添加新的派生類,需要在實(shí)例化的factory中集中Register。

缺點(diǎn):定義相比類模板實(shí)現(xiàn)略顯復(fù)雜

優(yōu)點(diǎn):如果需要增加新的基類和派生類,不需要修改原來的工廠相關(guān)的代碼,僅需要在新添加的基類和派生類后調(diào)用宏定義。

?

總結(jié)

以上是生活随笔為你收集整理的Apollo源码分析:路径规划 (v5.5)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。