二、CANBUS代码
1、canbus模块的软件架构如下:
主要输入输出
输入:apollo::control::ControlCommand | 控制指令 输出: /apollo/chassis
| apollo::canbus::Chassis
| 车辆底盘信息接口数据,包括车辆速度、方向盘转角、档位、底盘状态等信息 |
| /apollo/chassis_detail
| apollo::${Vehicle_Type}
| 车辆底盘详细信息,展示发送和接收底盘报文解析数据 |
其中canbus文件夹是canbus模块的主程序入口,构造函数为周期触发的函数,周期执行。
class CanbusComponent final : public apollo::cyber::TimerComponent {
构造函数后进入init函数
bool CanbusComponent::Init() {
AINFO << "CanbusComponent init: ";
// 加载配置文件
if (!GetProtoConfig(&canbus_conf_)) {
AERROR << "Unable to load canbus conf file: " << ConfigFilePath();
return false;
}
AINFO << "The canbus conf file is loaded: " << FLAGS_canbus_conf_file;
ADEBUG << "Canbus_conf:" << canbus_conf_.ShortDebugString();
//加载车辆类型
if (!apollo::cyber::common::PathExists(FLAGS_load_vehicle_library)) {
AERROR << FLAGS_load_vehicle_library << " No such vehicle library";
return false;
}
AINFO << "Load the vehicle factory library: " << FLAGS_load_vehicle_library;
ClassLoader loader(FLAGS_load_vehicle_library);
auto vehicle_object = loader.CreateClassObj<AbstractVehicleFactory>(FLAGS_load_vehicle_class_name);
if (!vehicle_object) {
AERROR << "Failed to create the vehicle factory: " << FLAGS_load_vehicle_class_name;
return false;
}
AINFO << "Successfully create vehicle factory: " << FLAGS_load_vehicle_class_name;
vehicle_object_ = vehicle_object;
if (!vehicle_object_->Init(&canbus_conf_)) {
AERROR << "Fail to init vehicle factory.";
return false;
}
AINFO << "Vehicle factory is successfully initialized.";
// cyber::ReaderConfig guardian_cmd_reader_config;
// guardian_cmd_reader_config.channel_name = FLAGS_guardian_topic;
// guardian_cmd_reader_config.pending_queue_size = FLAGS_guardian_cmd_pending_queue_size;
cyber::ReaderConfig control_cmd_reader_config;
control_cmd_reader_config.channel_name = FLAGS_control_command_topic;
control_cmd_reader_config.pending_queue_size = FLAGS_control_cmd_pending_queue_size;
cyber::ReaderConfig chassis_cmd_reader_config;
chassis_cmd_reader_config.channel_name = FLAGS_chassis_command_topic;
chassis_cmd_reader_config.pending_queue_size = FLAGS_control_cmd_pending_queue_size;
// if (FLAGS_receive_guardian) {
// guardian_cmd_reader_ = node_->CreateReader<GuardianCommand>(
// guardian_cmd_reader_config, [this](const std::shared_ptr<GuardianCommand> &cmd) {
// ADEBUG << "Received guardian data: run canbus callback.";
// OnGuardianCommand(*cmd);
// });
// } else
{
//订阅topic
control_command_reader_ = node_->CreateReader<ControlCommand>(
control_cmd_reader_config, [this](const std::shared_ptr<ControlCommand> &cmd) {
ADEBUG << "Received control data: run canbus callback.";
OnControlCommand(*cmd);
});
chassis_command_reader_ = node_->CreateReader<ChassisCommand>(
chassis_cmd_reader_config, [this](const std::shared_ptr<ChassisCommand> &cmd) {
ADEBUG << "Received control data: run canbus callback.";
OnChassisCommand(*cmd);
});
}
// 发布topic
chassis_writer_ = node_->CreateWriter<Chassis>(FLAGS_chassis_topic);
if (!vehicle_object_->Start()) {
AERROR << "Fail to start canclient, cansender, canreceiver, canclient, "
"vehicle controller.";
Clear();
return false;
}
AINFO << "Start canclient cansender, canreceiver, canclient, vehicle "
"controller successfully.";
monitor_logger_buffer_.INFO("Canbus is started.");
return true;
}
收到控制指令后调用回调函数,将控制指令中的油门、刹车、档位、灯光等指令,转换成对应的报文下发至底盘。vehicle_object_为实例化车辆类型。
void CanbusComponent::OnControlCommand(const ControlCommand &control_command) {
int64_t current_timestamp = Time::Now().ToMicrosecond();
// if command coming too soon, just ignore it.
if (current_timestamp - last_timestamp_ < FLAGS_min_cmd_interval * 1000) {
ADEBUG << "Control command comes too soon. Ignore.\n Required "
"FLAGS_min_cmd_interval["
<< FLAGS_min_cmd_interval << "], actual time interval[" << current_timestamp - last_timestamp_ << "].";
return;
}
last_timestamp_ = current_timestamp;
ADEBUG << "Control_sequence_number:" << control_command.header().sequence_num() << ", Time_of_delay:"
<< current_timestamp - static_cast<int64_t>(control_command.header().timestamp_sec() * 1e6)
<< " micro seconds";
vehicle_object_->UpdateCommand(&control_command);
}
回调函数跳转至所选车型的内部更新控制指令。
void GemVehicleFactory::UpdateCommand(
const apollo::control::ControlCommand *control_command) {
if (vehicle_controller_->Update(*control_command) != ErrorCode::OK) {
AERROR << "Failed to process callback function OnControlCommand because "
"vehicle_controller_->Update error.";
return;
}
can_sender_.Update();
}
更新控制指令,赋值自动驾驶模式,并对对加速度、减速度、档位等进行赋值。
ErrorCode VehicleController<SensorType>::Update(const ControlCommand &control_command) {
if (!is_initialized_) {
AERROR << "Controller is not initialized.";
return ErrorCode::CANBUS_ERROR;
}
// Execute action to transform driving mode
AINFO << " control_command.has_pad_msg() " << control_command.has_pad_msg();
AINFO << " control_command.pad_msg().has_action() " << control_command.pad_msg().has_action();
if (control_command.has_pad_msg() && control_command.pad_msg().has_action()) {
AINFO << "Canbus received pad msg: " << control_command.pad_msg().ShortDebugString();
if (control_command.pad_msg().action() == control::DrivingAction::VIN_REQ) {
if (!VerifyID()) {
AINFO << "Response vid failed, please request again.";
} else {
AINFO << "Response vid success!";
}
} else {
Chassis::DrivingMode mode = Chassis::COMPLETE_MANUAL;
switch (control_command.pad_msg().action()) {
case control::DrivingAction::START: {
mode = Chassis::COMPLETE_AUTO_DRIVE;
break;
}
case control::DrivingAction::RESET: {
break;
}
default: {
AERROR << "No response for this action.";
break;
}
}
auto error_code = SetDrivingMode(mode);
if (error_code != ErrorCode::OK) {
AERROR << "Failed to set driving mode.";
} else {
AINFO << "Set driving mode success.";
}
}
}
if (driving_mode() == Chassis::COMPLETE_AUTO_DRIVE || driving_mode() == Chassis::AUTO_SPEED_ONLY) {
Gear(control_command.gear_location());
Throttle(control_command.throttle());
Acceleration(control_command.acceleration());
Brake(control_command.brake());
SetEpbBreak(control_command);
SetLimits();
}
if (driving_mode() == Chassis::COMPLETE_AUTO_DRIVE || driving_mode() == Chassis::AUTO_STEER_ONLY) {
const double steering_rate_threshold = 1.0;
Steer(control_command.steering_target());
}
if ((driving_mode() == Chassis::COMPLETE_AUTO_DRIVE || driving_mode() == Chassis::AUTO_SPEED_ONLY
|| driving_mode() == Chassis::AUTO_STEER_ONLY)
&& control_command.has_signal()) {
HandleVehicleSignal(ProcessCommandChange(control_command.signal(), &last_control_command_));
}
return ErrorCode::OK;
}