Apollo学习笔记(一):canbus模块与车辆底盘之间的CAN数据传输过程 |
您所在的位置:网站首页 › apollo系统开源代码 › Apollo学习笔记(一):canbus模块与车辆底盘之间的CAN数据传输过程 |
Apollo学习笔记(一):canbus模块与车辆底盘之间的CAN数据传输过程
博主现在从车载自组网信道分配和多跳路由转向了自动驾驶,没啥经验,想快些做出来个Demo还是得站在巨人的肩膀上才行,我选择了Apollo,主要还是支持国产而且它的开发者套件有现成的底盘可以直接跑起来,但是apollo系统结构比较复杂,各种花哨的设计模式(消息适配器、工厂模式等)绕得人头晕。日本那里有个autoware是基于原生ROS的,也用Apollo开发者套件跑了下,就是普通的机器人开发那套,难度适合学生用来做项目,后面继续深入研究一下。(注意代码里面是有我写的注释的) 这次的学习是基于Apollo3.0的,因为3.0还是基于ROS的,后期研究autoware开发自己的系统能用得上,而且那个开发者套件也要用3.0。 canbus模块启动过程参考知行合一2018大佬的Apollo Planning模块源代码分析可以知道canbus模块的主入口为modules/canbus/main.cc: APOLLO_MAIN(apollo::canbus::Canbus);该宏展开后为: #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; \ }这里直接引用知行合一2018大神对于Apollo Planning模块的分析: Main函数完成以下工作:始化Google日志工具,使用Google命令行解析工具解析相关参数,注册接收中止信号“SIGINT”的处理函数:apollo::common::apollo_app_sigint_handler(该函数的功能十分简单,就是收到中止信号“SIGINT”后,调用ros::shutdown()关闭ROS),创建apollo::planning::Planning对象:apollo_app_,初始化ROS环境,调用apollo_app_.Spin()函数开始消息处理循环。 ———————————————— 版权声明:本文为CSDN博主「知行合一2018」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/davidhopper/article/details/79176505 更详细的不再赘述,大家可以去上面链接学习。 在apollo_app_.Spin();函数内会依次调用modules/canbus/canbus.cc的Init()和Start()。 Init()主要过程源码分析 Status Canbus::Init() { AdapterManager::Init(FLAGS_canbus_adapter_config_filename);/*完成AdapterManager的初始化, FLAGS_canbus_adapter_config_filename对应于modules/canbus/common/canbus_gflags.cc中的 DEFINE_string(canbus_adapter_config_filename, "modules/canbus/conf/adapter.conf", "The adapter config file"); adapter.conf中配置了canbus模块订阅和发布的topic 如果改成原生ROS的话,这里的AdapterManager配置删掉,改成ROS的topic订阅和发布*/ AINFO return OnError("Failed to create can client."); } AINFO return OnError("Failed to create message manager."); } AINFO return OnError("Failed to init can sender."); } AINFO return OnError("Failed to init vehicle controller."); } AINFO AdapterManager::AddGuardianCallback(&Canbus::OnGuardianCommand, this); } return Status::OK(); } Init()主要过程流程图(为方便整合不严格按照代码里的顺序)
canbus模块向底盘发送数据的开端在canbus模块接收到上层control_command,因此Canbus::OnControlCommand是发送的开端。 void Canbus::OnControlCommand(const ControlCommand &control_command) { int64_t current_timestamp = apollo::common::time::AsInt64(Clock::Now()); // if command coming too soon, just ignore it. if (current_timestamp - last_timestamp_ AERROR Update流程图(以刹车对应的协议类型数据为例)在canbus Start()的时候,can_receiver_.Start()启动了从底盘接收数据的线程,线程内运行CanReceiver::RecvThreadFunc() // 2. start receive first then send if (can_receiver_.Start() != ErrorCode::OK) { return OnError("Failed to start can receiver."); } AINFO return ::apollo::common::ErrorCode::CANBUS_ERROR; } is_running_ = true; thread_.reset(new std::thread([this] { RecvThreadFunc(); })); if (thread_ == nullptr) { AERROR 10 * 1000}; while (IsRunning()) { std::vector buf; int32_t frame_num = MAX_CAN_RECV_FRAME_LEN; if (can_client_->Receive(&buf, &frame_num) != ::apollo::common::ErrorCode::OK) { /* can_client_为modules/drivers/canbus/can_client/esd/esd_can_client.cc的实例化对象, 其Receive()函数调用了third_party/can_card_library/esd_can/include/ntcan.h的canRead函数从 CAN网络中读取数据并存入buf, const int32_t ret = canRead(dev_handler_, recv_frames_, frame_num, nullptr); buf的定义是std::vector buf; CanFrame在之前can_sender_.Update()流程图内有分析。 */ LOG_IF_EVERY_N(ERROR, receive_error_count++ > ERROR_COUNT_MAX, ERROR_COUNT_MAX) LOG_IF_EVERY_N(ERROR, receive_none_count++ > ERROR_COUNT_MAX, ERROR_COUNT_MAX) ADEBUG |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |