canbus
底层can
CanClient是底层can的抽象类,表示某一种can设备的接口
1 2 3 4 5 6 7 8
| class CanClient { virtual bool Init(const CANCardParameter ¶meter) = 0; virtual apollo::common::ErrorCode Start() = 0; virtual apollo::common::ErrorCode Send(const std::vector<CanFrame> &frames, int32_t *const frame_num) = 0; virtual apollo::common::ErrorCode Receive(std::vector<CanFrame> *const frames, int32_t *const frame_num) = 0; }
|
can client由工厂模式创建,不同参数指定不同 can client
1 2 3
| auto can_factory = CanClientFactory::Instance(); can_factory->RegisterCanClients(); can_client_ = can_factory->CreateCANClient(canbus_conf_.can_card_parameter());
|
以socket为例
1
| class SocketCanClientRaw : public CanClient
|
继承了CanClient,实现了其中的虚函数,主要就是调用linux原生的socket api
底盘数据抽象
不同车辆底盘数据、协议不同,使用了vehicle factory来创建不同车辆的 factory
1 2 3 4
| VehicleFactory vehicle_factory; vehicle_factory.RegisterVehicleFactory(); auto vehicle_object = vehicle_factory.CreateVehicle(canbus_conf_.vehicle_parameter());
|
每一个车型的factory拥有自己的 controller 和 message manager
1 2
| message_manager_ = vehicle_object->CreateMessageManager(); vehicle_controller_ = vehicle_object->CreateVehicleController();
|
其中controller似乎用于填pb等等事情的
message_manager则用于管理各个信号的decode与encode
以”ch vehicle”为例子,
工厂类:
1
| class ChVehicleFactory : public AbstractVehicleFactory
|
controller类:
1
| class ChController final : public VehicleController
|
message manager类:
1
| class ChMessageManager : public MessageManager<::apollo::canbus::ChassisDetail>
|
先看下message manager的构造:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| ChMessageManager::ChMessageManager() { AddSendProtocolData<Brakecommand111, true>(); AddSendProtocolData<Controlcommand115, true>(); AddSendProtocolData<Gearcommand114, true>(); AddSendProtocolData<Steercommand112, true>(); AddSendProtocolData<Throttlecommand110, true>(); AddSendProtocolData<Turnsignalcommand113, true>();
AddRecvProtocolData<Brakestatus511, true>(); AddRecvProtocolData<Ecustatus1515, true>(); AddRecvProtocolData<Ecustatus2516, true>(); AddRecvProtocolData<Ecustatus3517, true>(); AddRecvProtocolData<Gearstatus514, true>(); AddRecvProtocolData<Steerstatus512, true>(); AddRecvProtocolData<Throttlestatus510, true>(); AddRecvProtocolData<Turnsignalstatus513, true>(); }
|
可以看到message manager中添加了该vehicle的各个收发信号
以Brakestatus511信号为例
1 2
| class Brakestatus511 : public ::apollo::drivers::canbus::ProtocolData< ::apollo::canbus::ChassisDetail>
|
实现了 parse函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| void Brakestatus511::Parse(const std::uint8_t* bytes, int32_t length, ChassisDetail* chassis) const { chassis->mutable_ch()->mutable_brake_status__511()->set_brake_pedal_en_sts( brake_pedal_en_sts(bytes, length)); chassis->mutable_ch()->mutable_brake_status__511()->set_brake_pedal_sts( brake_pedal_sts(bytes, length)); chassis->mutable_ch()->mutable_brake_status__511()->set_brake_err( brake_err(bytes, length)); chassis->mutable_ch()->mutable_brake_status__511()->set_emergency_btn_env( emergency_btn_env(bytes, length)); chassis->mutable_ch()->mutable_brake_status__511()->set_front_bump_env( front_bump_env(bytes, length)); chassis->mutable_ch()->mutable_brake_status__511()->set_back_bump_env( back_bump_env(bytes, length)); chassis->mutable_ch()->mutable_brake_status__511()->set_overspd_env( overspd_env(bytes, length)); chassis->mutable_check_response()->set_is_esp_online( brake_pedal_en_sts(bytes, length) == 1); }
|
某个信号的解析如下,这里就是从can frame中按照dbc定义的信号格式解析了
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
Brake_status__511::Brake_pedal_en_stsType Brakestatus511::brake_pedal_en_sts( const std::uint8_t* bytes, int32_t length) const { Byte t0(bytes + 0); int32_t x = t0.get_byte(0, 8); Brake_status__511::Brake_pedal_en_stsType ret = static_cast<Brake_status__511::Brake_pedal_en_stsType>(x); return ret; }
|
再来看看controller类的实现,有一个重要函数
1 2 3 4 5
|
Chassis chassis() override;
|
主要做的事情就是从message_manager中获得sensor data,然后填到自己的Chassis chassis_;变量中并返回,后面可以看到sensor data其实是前面parse函数填的内容
1 2
| ChassisDetail chassis_detail; message_manager_->GetSensorData(&chassis_detail);
|
总结一下,单以接收can信号为例,几个关键点
一种车型对应一个factory,该facotry会产生controller和message manager对象
其中 message manager封装了车身信号的decode和encode函数
controller则负责从message manager中获取解析后的数据,并存到Chassis chassis_(这是一个pb 结构体),然后提供API给外部使用
真正的报文接收处理流程
can报文的接收处理由CanReceiver类管理
CanReceiver由can_client和message manager初始化
并维护一个接收线程
1 2
| template <typename SensorType> void CanReceiver<SensorType>::RecvThreadFunc()
|
在这个线程loop中
使用can_client类的接口接收can frame,这里实际就会调用到socket api
1
| can_client_->Receive(&buf, &frame_num)
|
使用message manager 解析刚刚收到的can frame,这里实际就会调用到对应message manager中的信号解析函数
1
| pt_manager_->Parse(uid, data, len);
|
在这步parse之后,数据已经填到sensor data了
数据的发布
CanBusComponent类:
1 2 3 4 5 6
| void CanbusComponent::PublishChassis() { Chassis chassis = vehicle_controller_->chassis(); common::util::FillHeader(node_->Name(), &chassis); chassis_writer_->Write(chassis); ADEBUG << chassis.ShortDebugString(); }
|
从controller中调用chassis接口,得到chassis数据,然后就使用protobuf writer发布出去了