Apollo cyber 源碼解析—— launch 詳解

以scripts/camera.sh腳本為例,若要啟用camera,只需要執(zhí)行該腳本即可
查看內(nèi)容,在start()中調(diào)用了cyber_launch start /apollo/modules/drivers/camera/launch/camera.launch
cyber_launch就是cyber\tools\cyber_launch\cyber_launch py腳本文件,它是何時加載的呢?

在camera.sh Line24, source "${DIR}/apollo_base.sh"
配置了基本的環(huán)境,而且執(zhí)行了source /apollo/cyber/setup.bash,其中就把cyber_launch加入了PATH中,這樣就可找到了

先看camera.launch文件里的內(nèi)容有哪些:

<cyber>
    <module>
        <name>camera</name>
        <dag_conf>/apollo/modules/drivers/camera/dag/camera.dag</dag_conf>
        <process_name>usb_cam</process_name>
    </module>
</cyber>

沿用了ros1的xml格式,自定義了模塊名,以及配置文件dag_conf
cyber\tools\cyber_launch\cyber_launch中的start方法中,關(guān)鍵代碼:

if process_name not in process_list:
    if process_type == 'binary':
        pw = ProcessWrapper(
            process_name.split()[0], 0, [
                ""], process_name, process_type,
            exception_handler)
    # Default is library
    else:
        pw = ProcessWrapper(
            g_binary_name, 0, dag_dict[
                str(process_name)], process_name,
            process_type, sched_name, exception_handler)
    result = pw.start()
    pmon.register(pw)
    process_list.append(process_name)

如果時可執(zhí)行文件,就用py的多進(jìn)程直接調(diào)起來,如果是lib文件,要通過g_binary_name="mainboard"這個程序來動態(tài)加載lib庫文件
也就是說,mainboard可執(zhí)行文件是通用的程序,按照制定的標(biāo)準(zhǔn)api來加載運(yùn)行l(wèi)ib

源碼位置: cyber\mainboard\mainboard.cc
邏輯比較簡單,主要是解析參數(shù),然后將參數(shù)傳入ModuleController的對象,在ModuleController::Init()中會調(diào)用ModuleController::LoadAll() -> ModuleController::LoadModule
看下關(guān)鍵代碼:

bool ModuleController::LoadModule(const DagConfig& dag_config) {
    class_loader_manager_.LoadLibrary(load_path);
    for (auto& component : module_config.components()) {
      const std::string& class_name = component.class_name();
      std::shared_ptr<ComponentBase> base =
          class_loader_manager_.CreateClassObj<ComponentBase>(class_name);
      if (base == nullptr || !base->Initialize(component.config())) {
        return false;
      }
      component_list_.emplace_back(std::move(base));
    }

    for (auto& component : module_config.timer_components()) {
      const std::string& class_name = component.class_name();
      std::shared_ptr<ComponentBase> base =
          class_loader_manager_.CreateClassObj<ComponentBase>(class_name);
      if (base == nullptr || !base->Initialize(component.config())) {
        return false;
      }
      component_list_.emplace_back(std::move(base));
    }
  }
  return true;
}

首先會解析出lib的路徑,然后通過class_loader_manager_加載動態(tài)庫,拿到基類指針,并調(diào)用基類方法base->Initialize(component.config()),在基類方法中,調(diào)用虛函數(shù)Init()和Pross(),利用繼承的特性調(diào)用到實(shí)際加載的lib子類中的初始化方法和處理方法。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容