百度apollo - Apollo代码解析:4. control模块

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的地方就是这了,和ROScallback函数实现开始不一样,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_;
};

猜你喜欢

转载自blog.csdn.net/dinnerhowe/article/details/79957589