百度apollo - Apollo代码解析:4. control模块
程序员文章站
2022-04-16 10:08:12
...
0. 简介:
阅读本章之前默认已经阅读了:
PS: 代码注释github:https://github.com/DinnerHowe/apollo_read
首先来看看整体的逻辑图:
由此可知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_;
};
上一篇: DirectSound---音效使用
下一篇: 对十二个一(追求者)的feeling