CanbusComponent主要对象分析
CanClient
can客户端CanClient
用于开启can设备、接收与发送can报文,其作为基类接口,可以派生不同种类的can。目前Apollo支持的can类型有EsdCanClient
、HermesCanClient
、SocketCanClientRaw
以及一个用于调试的FakeCanClient
。其最主要的方法有:
Start
。开启can设备SendSingleFrame
发送单个的can报文数据Send
发送指定数目的can报文数据Receive
接收指定数目的can报文数据
AbstractVehicleFactory
车辆抽象工厂AbstractVehicleFactory
用于创建VehicleController
和MessageManager
,其作为基类接口,可以派生不同种类车型的抽象工厂,从而可以创建车型各种的VehicleController
和MessageManager
,目前Apollo支持的车型可以在modules/canbus/vehicle
文件夹中查看。
ProtocolData
不同的车型有不同的can协议,ProtocolData
是can协议的基类接口,不同的协议继承于该基类接口,每个协议类都在数据成员中定义所需的物理量以及描述协议类型的ID,并定义相关setter和修改和解析规则can报文的方法,不同车型的协议类源文件在相关车型的protocol
文件夹下。其主要的方法有:
UpdateData
,根据该协议的物理量更新can报文数据Parse
通过解析规则,将can报文数据解析为消息类型
can协议分为发送和接收两种类型,以lincoln的Brake60
和 Brake61
协议为例,前者是发送给车辆底层的协议,后者是从车辆底层接收的协议。具体的物理量以及can协议可在每个协议的源文件注释中找到,具体实现不再赘述。
MessageManager
MessageManager
是所有车型协议管理类的基类接口,不同的车型继承于该基类接口。
MessageManager
用于管理该车型所需要的协议对象,其拥有分别保存发送和接收协议的容器 send_protocol_data_
和recv_protocol_data_
,在不同车型MessageManager
的派生类的构造函数当中,需要通过方法AddSendProtocolData
和AddRecvProtocolData
创建该车型需要所有的发送和接收协议。以lincoln的MessageManager
为例:
LincolnMessageManager::LincolnMessageManager() {
// TODO(Authors): verify which one is recv/sent
AddSendProtocolData<Brake60, true>();
AddSendProtocolData<Throttle62, true>();
AddSendProtocolData<Steering64, true>();
AddSendProtocolData<Gear66, true>();
AddSendProtocolData<Turnsignal68, true>();
AddRecvProtocolData<Brake61, true>();
AddRecvProtocolData<Throttle63, true>();
AddRecvProtocolData<Steering65, true>();
AddRecvProtocolData<Gear67, true>();
AddRecvProtocolData<Misc69, true>();
AddRecvProtocolData<Wheelspeed6a, true>();
AddRecvProtocolData<Accel6b, true>();
AddRecvProtocolData<Gyro6c, true>();
AddRecvProtocolData<Gps6d, true>();
AddRecvProtocolData<Gps6e, true>();
AddRecvProtocolData<Gps6f, true>();
AddRecvProtocolData<Tirepressure71, true>();
AddRecvProtocolData<Fuellevel72, true>();
AddRecvProtocolData<Surround73, true>();
AddRecvProtocolData<Brakeinfo74, true>();
AddRecvProtocolData<Throttleinfo75, true>();
AddRecvProtocolData<Version7f, true>();
AddRecvProtocolData<License7e, true>();
}
注意,在canbus模块当中,所有的协议类对象都通过MessageManager
在堆上创建,可以通过GetMutableProtocolDataById
方法根据协议ID返回对应的协议类堆堆对象的指针。
MessageManager
还负责调用相关接收协议对象,通过Parse
方法,将从底层接收的can报文的数据解析为消息类型,并保存在其数据成员sensor_data_
当中
CanFrame
CanFrame
定义了can报文数据,其中最主要的是uint8_t data[8]
,代表can报文的数据
SenderMessage
发送can报文SenderMessage
定义了发送给底层的can报文,其主要包含了:
ProtocolData
用于描述该can报文的协议类型CanFrame
用于描述该can报文的数据period_
描述发送的间隔message_id_
描述该can报文的协议类型的ID
通过SenderMessage<SensorType>::Update
方法,可以根据协议类对象的物理量,根据该更新can报文数据CanFrame
CanReceiver
CanReceiver
开启一个线程,其入口函数为RecvThreadFunc
,不断接收底盘的can报文,根据其协议ID将can报文的数据解析为消息类型并保存至MessageManager
的数据成员sensor_data_
中。
CanSender
CanSender
有一个包含所有发送协议的can报文容器send_messages_
,通过方法AddMessage
向其添加发送can报文。
开启一个线程,入口函数为PowerSendThreadFunc
,不断循环以对应的协议的间隔将容器当中的can报文发送至can网络。
通过CanSender<SensorType>::Update
,可以更新所有发送协议can报文的数据
VehicleController
VehicleController
是所有车型控制器的基类接口,可以派生出不同的车型的的控制器。在派生类的初始化函数当中,会获得该车型所有需要的发送协议,并在CanSender
的发送协议的can报文容器send_messages_
当中创建发送协议can报文,并且会开启一个线程,不断检查错误信息。
VehicleController
的主要功能是通过Update
方法,接收控制消息control::ControlCommand
,更新发送协议can报文的物理量,修改协议相关的方法有:
- Gear
- Brake
- Throttle
- Acceleration
- Steer
- …
有趣的是,Update
方法会根据车辆的驾驶模式修改不同的发送协议报文物理量,驾驶模式有以下五种类型:
- COMPLETE_AUTO_DRIVE
- COMPLETE_MANUAL
- AUTO_STEER_ONLY
- AUTO_SPEED_ONLY
- EMERGENCY_MODE