以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子類中的初始化方法和處理方法。