Apollo详解之canbus模块——代码简要分析2

CanbusComponent主程序分析

CanbusComponent::Init

CanbusComponent::Init是程序的入口函数,其功能是完成CanbusComponent的初始化。
首先通过GetProtoConfig获得配置文件信息,并保存到canbus_conf_当中。默认的配置文件modules/canbus/conf/canbus_conf.pb.txt内容为:

vehicle_parameter {
  brand: LINCOLN_MKZ
  max_enable_fail_attempt: 5
  driving_mode: COMPLETE_AUTO_DRIVE
}

can_card_parameter {
  brand: HERMES_CAN
  type: PCI_CARD
  channel_id: CHANNEL_ID_ZERO
  num_ports: 8
  interface: NATIVE
}

enable_debug_mode: false
enable_receiver_log: false
enable_sender_log: false

通过工厂模式,根据can_card_parameter参数创建指定类型的CanClient

can_client_ = can_factory->CreateCANClient(canbus_conf_.can_card_parameter());

根据vehicle_parameter参数创建指定车型的抽象工厂std::unique_ptr,并根据该工厂创建该车型的MessageManagerVehicleController

auto vehicle_object =
      vehicle_factory.CreateVehicle(canbus_conf_.vehicle_parameter());
...
message_manager_ = vehicle_object->CreateMessageManager();
....
vehicle_controller_ = vehicle_object->CreateVehicleController();

可以看出,使用工厂模式,可以实现程序的松耦合,通过配置文件的参数可以创建的基类接口不同的派生类对象。
当以上对象初始化完成后,会创建该车型需要的所有协议类对象,同时初始化CanReceiverCanSender,并且会在CanSender的容器当中添加所有需要发送的can报文。
根据命令行参数receive_guardian,可以选择是否开启守护进程,从而订阅不同的话题,命令行参数可以在modules/canbus/conf/canbus.conf中定义。
最后会调用CanClientCanReceiverCanSenderVehicleControllerStart方法,会打开can端口,分别创建三个线程:

  • CanReceiver的线程会不断接收一定数目的can报文,并根据该报文的协议将其解析为消息类型,存储在MessageManager的数据成员sensor_data_当中
  • CanSender的线程,会以各can报文规定的间隔,不断循环发送容器当中保存的所有的can报文
  • VehicleController线程会当can_sender_开启,执行发送can帧的线程时,以一定的频率,根据自动驾驶模式不断根据底盘反馈消息,检查底盘模块是否正常,若连续出错的次数超出了阈值,则进入紧急模式

CanbusComponent::Proc

该函数会以一定的频率由Cyber_RT调用,该函数会调用chassis方法,返回在MessageManager的变量sensor_data_中存储的当前时刻从底层接收的类型为Chassis的消息,其类型在modules/canbus/proto/chassis.proto中定义,然后发送给指定的话题。
另外,可根据命令行参数enable_chassis_detail_pub选择是否发送ChassisDetail消息类型至相关话题。

CanbusComponent::OnControlCommand

CanbusComponent::OnControlCommand是订阅者的回调函数,根据形参列表当中的控制消息ControlCommand,通过VehicleController更新所有发送协议的物理量,并通过CanSender更新所有发送can报文的数据

向车辆底层发送数据

CanSender线程当中,所有发送can报文会会不断循环发送给can底层,而发送can报文的更新是根据订阅相关话题得到的控制消息ControlCommand,通过回调函数CanbusComponent::OnControlCommand完成的。
首先,向车辆底层发送的消息类型为ControlCommand,通过订阅者订阅相关话题得到。
然后会调用回调函数CanbusComponent::OnControlCommand,在其中,方法VehicleController::Update会根据控制消息类型ControlCommand更新所有发送协议的物理量,物理量更新完毕后,会调用CanSender::Update,根据各个can报文的协议的物理量,根据协议更新所有发送can报文的数据。
自动驾驶模式COMPLETE_AUTO_DRIVE是通过控制消息当中的control_command.pad_msg().action()控制的,当其为control::DrivingAction::START时,会打开自动驾驶模式。需要主要的是,在打开自动驾驶模式时,canbus模块会在CheckResponse函数中,根据底盘反馈信息检查相关模块的工作情况。
该回调函数调用完成后,所有向车辆底层发送的can报文的数据会根据ControlCommand完成更新。

从车辆底层获取数据

CanReceiver线程当中,不断通过CanClient从底层接收指定数目的can报文,并通过MessageManager,根据该报文的协议ID将所有接收到的can报文解析为ChassisDetail消息类型,存储在MessageManagersensor_data_当中,因此sensor_data_反映了当前时刻从底层获得的底盘数据ChassisDetail
CanbusComponent::Proc当中,通过调用chassis函数,根据MessageManagersensor_data_当中存储的当前时刻从底层获得的底盘数据ChassisDetail,得到底盘消息类型Chassis,并将其通过发布者发布给相关的话题

你可能感兴趣的:(Apollo详解之canbus模块——代码简要分析2)