Apollo程式碼解析:4. control模組
阿新 • • 發佈:2019-02-06
0. 簡介:
閱讀本章之前預設已經閱讀了:
首先來看看整體的邏輯圖:
由此可知planning和control是整個Apollo的核心,由於個人喜好的原因先看control模組。
開啟control模組:
可見整個模組是由main.cc開始的,直接看程式碼:
#include "modules/common/apollo_app.h"
#include "modules/control/common/control_gflags.h"
#include "modules/control/control.h"
APOLLO_MAIN(apollo::control::Control);
程式用了一個巨集APOLLO_MAIN
來實現的,該巨集傳入的是control類,APOLLO_MAIN
的實現在modules/common/apollo_app.h
中實現的,直接看程式:
//巨集定義
#define APOLLO_MAIN(APP)
int main(int argc, char **argv) {
google::InitGoogleLogging(argv[0]);
google::ParseCommandLineFlags(&argc, &argv, true);
signal(SIGINT, apollo::common::apollo_app_sigint_handler);
APP apollo_app_;
ros::init(argc, argv, apollo_app_.Name());
apollo_app_.Spin();
return 0;
}
其中:
google::InitGoogleLogging
:是google glog
的初始化函式,作用是初始化glog
google::ParseCommandLineFlags
:是google gflags
的初始化函式,作用是解析命令列引數,一般都放在 main 函式中開始位置。APP apollo_app_
:是例項化函式,例項化control類。ros::init(argc, argv, apollo_app_.Name())
:註冊節點,這是程式開始的地方,apollo_app_.Name()
將以gflags命令列引數形式
傳入node name
,在c++中命令列引數就是字串,因此apollo_app_.Name()
apollo_app_.Spin()
:在apollo_app.cc中實現,control初始化Control::Init
,開始函式Control::Start
在這執行。個人認為整個程式最tricky的地方就是這了,和ROS
在callback函式
實現開始不一樣,Apollo把程式開始放到了spin()
中。
在看apollo_app_.Spin()
這個函式之前,先要了解一下在Apollo被廣泛引用的apollo::common::Status類
該函式載modules/common/status/status.h
定義:
class Status {
public:
/**
* @brief Create a success status.
*/
Status() : code_(ErrorCode::OK), msg_() {}
~Status() = default;
/**
* @brief Create a status with the specified error code and msg as a
* human-readable string containing more detailed information.
* @param code the error code.
* @param msg the message associated with the error.
*/
//過載建構函式Status()
Status(ErrorCode code, const std::string &msg) : code_(code), msg_(msg) {}
/**
* @brief Create a status with the specified error code and empty msg
* @param code the error code.
*/
//過載Status()+防止隱式呼叫(一個引數的`建構函式`(或者除了第一個引數外其餘引數都有預設值的`多參建構函式`))
explicit Status(ErrorCode code) : code_(code), msg_("") {}
/**
* @brief generate a success status.
* @returns a success status
*/
static Status OK() { return Status(); }
/**
* @brief check whether the return status is OK.
* @returns true if the code is ErrorCode::OK
* false otherwise
*/
//預設true, 因為初始化列表:Status() : "code_(ErrorCode::OK)", msg_() {}
bool ok() const { return code_ == ErrorCode::OK; }
/**
* @brief get the error code
* @returns the error code
*/
ErrorCode code() const { return code_; }
/**
* @brief defines the logic of testing if two Status are equal
*/
//過載運算子`==`
bool operator==(const Status &rh) const {
return (this->code_ == rh.code_) && (this->msg_ == rh.msg_);
}
/**
* @brief defines the logic of testing if two Status are unequal
*/
//過載運算子`!=`
bool operator!=(const Status &rh) const { return !(*this == rh); }
/**
* @brief returns the error message of the status, empty if the status is OK.
* @returns the error message
*/
const std::string &error_message() const { return msg_; }
/**
* @brief returns a string representation in a readable format.
* @returns the string "OK" if success.
* the internal error message otherwise.
*/
std::string ToString() const {
if (ok()) {
return "OK";
}
return ErrorCode_Name(code_) + ": " + msg_;
}
/**
* @brief save the error_code and error message to protobuf
* @param the Status protobuf that will store the message.
*/
void Save(StatusPb *status_pb) {
if (!status_pb) {
return;
}
status_pb->set_error_code(code_);
if (!msg_.empty()) {
status_pb->set_msg(msg_);
}
}
private:
ErrorCode code_;
std::string msg_;
};