自动驾驶 Apollo 源码分析系列,系统监控篇:Monitor模块如何监控硬件

Posted frank909

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自动驾驶 Apollo 源码分析系列,系统监控篇:Monitor模块如何监控硬件相关的知识,希望对你有一定的参考价值。

前面的文章有分析,Monitor 模块监控的内容分为 Hardware 和 Software 两位。

本篇分析硬件监控部分。

首先,可以观察一下 Apollo 官方文档给出的硬件连接图。


跟自动驾驶本身相关的无非是传感器和底盘。


当前 Monitor 系统支持的硬件类监控有 4 个:

  • ESD CAN
  • GPS
  • Resource
  • SOCKET CAN

监控 ESD CAN

ESD CAN 是一种 CanCard,在 Apollo 中通过 PCIe 接口连接到 6108 工控机上面,在 Apollo 1.0 版本的官方文档就有介绍过 ESD CAN 型号是 ESD CAN-PCIe/402-1。 它长这个样子:

ESD CAN 接收到的信号有 2 类:

  • 线控底盘 CAN 信号
  • 大陆毫米波雷达 CAN 信号

EsdCanMonitor

我在前面的文章中有写过,各类 xxxMonitor 其实是 RecurrentRunner 子类。


EsdMonitor 也是如此,它和 CameraMonitor 一样也是 RecurrentRunner 子类。


EsdCanMonitor 在初始化的时候设置了自己的模块名字和周期执行间隔,这里时间间隔是 3 秒,也就是 EsdCan 每 3 秒被监控 1 次。


我们也可以看到 EsdCanMonitor 的核心方法其实是 EsdCanTest。


在 EsdCanTest 中检测到的结果,最后会通过 SummaryMonitor.EscalateStatus 方法提升自身状态等级。

当然,如果 ESD CAN 根本不存在,那么就返回 ERROR 错误类型。

EsdCanTest 内部创建了 NT_HANDLE 类型变量 handle,并基于它进行测试。


应该是借助于 EsdCan 厂商自带的驱动测试函数。上面代码很简单,通过调用 3 个函数进行了 5 类测试。

  1. 通过 canOpen 测试设备是否能正常打开
  2. 通过 canStatu 测试设备是否能正常获取状态
  3. 通过 canIoctl 测试是否能获取 CANBUS 的分析数据
  4. 通过 canIoctl 测试是否能获取控制状态
  5. 通过 canIoctl 测试是否能获取波特率

然后根据测试的结果返回。

测试的可能结果还挺多的,就不一一列出了。

NTCAN_SUCCESS:
     
NTCAN_RX_TIMEOUT:
     
NTCAN_TX_TIMEOUT:

NTCAN_TX_ERROR:
 
NTCAN_CONTR_OFF_BUS:
  
NTCAN_CONTR_BUSY:
  
...

然后 EsdCan 的监控的基本逻辑就没有了,它的工作更多借助于厂商的驱动测试API完成。

GpsMonitor


GpsMonitor 的代码更简单。

监控周期也是每隔 3 秒一次。

主要逻辑是接收 GnssBestPose 这个 Topic,获取它的状态,结果有 3 种:

  1. 如果是 SolutionType::NARROW_INT,那么状态是 OK
  2. 如果是 SolutionType::SINGLE,那么状态是 WARN
  3. 其它情况,状态被标志为 ERROR

GnssBestPose 和 SolutionType 的定义都来自 GNSS 驱动,路径在。

modules/drivers/gnss/proto/gnss_best_pose.proto

Socket CAN

Socket CAN 是个什么东西呢?

我们知道 Socket,也知道在汽车行业中广泛通过 CAN 协议传输,那么 Socket CAN 是什么呢?

它是在 Linux 环境下基于 Socket 机制实现 CAN 协议的一套机制。

Apollo 中也支持对它的监控。


可以看到核心方法是 SocketCanTest。


通过 socket 方法得到一个 handler。

注意 socket() 中的参考,PF_CAN 有别于我们常使用的 TCP 类 Socket 开发。

socket(AF_INET,SOCK_STREAM,0)

这说明 SocketCAN 和普通的 TCP/IP 是不一样的。

SocketCanTest() 中通过 SocketCanHandlerTest 执行操作。


检测的逻辑也非常简单:

  1. 通过设置 filter,检测是否正常
  2. 通过尝试 enable CAN Frame 的接收检测是否正常
  3. 通过 bind socket 到网络接口检测是否正常

ResouceMonitor

ResourceMonitor 监控的对象是那些通用的物理资源,当前包含 CPU、内存、磁盘。

上面代码显示并没有多特别之处,下面是这的实现。

ResourceMonitor 每隔 5 秒监控 1 次,它需要从 HMI 中获取受监控的配置项目。

CheckDiskSpace


在代码检测磁盘空间是通过 boost::filesystem 中的 space() 方法。

得到的结果需要和 config 中规定的阈值进行判断,产生 ERROR 和 WARN 两种结果。

CheckCPUUsage


实际执行的是 GetSystemCPUUsage 或者 GetCPUUsage 方法。

核心逻辑无非就是通过代码执行命令行脚本 /proc/stat。这个命令包含了系统内核中很多信息,就如 CPU 信息。比如,我在我的 WIN11 系统中的 WSL 中查看 /proc/stat 信息,出现下面的结果 :


cpu 状态有很多信息,每一列有独特的意义。

cpu 统计时间的单位是 jiffies。
大家可能在想,代码如何拿到 /proc/stat 信息的呢?

因为在 Linux 中,万物皆文件。只要通过 ifstream 读取那个路径,然后 getLine 一行一行解析就好了。
然后,如果要统计单个进程 PID 的CPU 信息,则需要通过 /proc/pid/stat 命令。

有 4 种时间

  • utime 用户态时长
  • stime 内核时长
  • cutime 当前进程等待子进程的 utime
  • cstime 当前进程等待子进程的 stime

最终的 CPU 时长:

cputime = utime+stime+cutime+cstime

CPU 使用率公式:

usage = (time - pretime)/monitor_time

就是在一次监控周期内,两次 cputime 统计值的差占监控时间的比例。

CPU 状态是否报警取决于结果和配置中预设的值的比较。

CheckMemoryUsage

检查内存使用情况的逻辑和 CPU 差不多。

如果没有进程 DAG 则检测 SystemMemoryUsage 否则就通过 pid 一个个获取单个进程的内存信息。


通过命令行 /proc/meminfo 获取内存信息。

得到总共的内存,和当前使用的内存,然后求比例。
单个进程使用的内存信息通过 /proc/pid/statm 命令求得。

内存使用率公式:

usage = usedMem/TotalMem

计算已使用了的内存在整个内存容量的占比。

CheckDiskLoads

字面意思是检测磁盘负载。


需要通过 GetSystemDiskload 获取各个设备的负载值,然后和配置中的阈值做比较,最终得到 Error 或者 WARN 状态。

借助的是 /proc/diskstats 命令,这个命令可以查看磁盘的相关信息。


第2列也就是 ram0、loop0、sda 之类是 devicename。
第12列是 I/O 耗费的时间,单位是 ms。

磁盘负债的比例计算公式是:

usage = (当前I/O时间 - 上一次I/O时间)/监控间隔时长

总结

  1. Apollo 归类到硬件监控的内容不多,只有 4 个,ESD CAN、GPS、SocketCAN、Resource
  2. 监控本身的逻辑代码没有多少,更多借助于硬件本身的测试驱动方法,Monitor负责汇总
  3. SocketCAN 的监控主要是在一个监控周期对它进行常规的 API 调用
  4. System 健康问题被当成一个 Resource 对待
  5. 读取 /proc/stat 计算 cpu 使用率
  6. 读取 /proc/meminfo 计算磁盘使用率
  7. 读取 /proc/diskstats 计算磁盘负载
  8. 通过 Boost::FileSystem 的 space() 方法计算磁盘空间状态

参考

  1. https://esd.eu/en/products/can-pcie-402
  2. https://www.jianshu.com/p/aea52895de5e
  3. https://blog.csdn.net/cybertan/article/details/7596633
  4. https://blog.csdn.net/u011436427/article/details/103394715

以上是关于自动驾驶 Apollo 源码分析系列,系统监控篇:Monitor模块如何监控硬件的主要内容,如果未能解决你的问题,请参考以下文章

自动驾驶 Apollo 源码分析系列,系统监控篇:Monitor模块如何监控硬件

自动驾驶 Apollo 源码分析系列,系统监控篇:Monitor模块如何监控通信中 channel 的时延?

自动驾驶 Apollo 源码分析系列,系统监控篇:Monitor模块如何监控通信中 channel 的时延?

自动驾驶 Apollo 源码分析系列,系统监控篇:Monitor模块如何监控通信中 channel 的时延?

自动驾驶 Apollo 源码分析系列,系统监控篇:Monitor模块如何监控通信中 channel 的时延?

自动驾驶 Apollo 源码分析系列,系统监控篇:简析Monitor模块工作机制