这应该是最后的一篇配适博文了(但愿),如果测试的效果不理想或者存在问题我会继续记录的。
这是一个之前工作的后续收尾,包括对xx_controller.cc中反馈检测(CheckResponse)的补充,也包括对技术文档内剩下的内容的实现。
目录
对tsy_controller.cc的CheckResponse收尾 1
2020年12月23日星期三
对tsy_controller.cc的CheckResponse收尾
添加`CheckResponse`逻辑,Apollo程序内增加了对车辆底层是否在自动驾驶模式的监控,即车辆横向、驱动、制动模块的驾驶模式反馈是否处于自动驾驶状态,如果在一个`CheckResponse`周期内,车辆某个模块驾驶模块反馈处于接管或者手动驾驶模式,则Apollo会控制车辆使能为紧急停车模式(`Emergency`),即各模块均控制为手动模式,确保控制车辆时的安全。不同的车辆`CheckResponse`周期可能不同,需要开发者根据情况通过设置`retry_num`设定`check`周期。
开发者可以不改原check代码方案,将3个驾驶模式反馈报文与apollo内`chassis_detail`做映射:
`is_eps_online->转向模式反馈信号`
`is_vcu_online->驱动模式反馈信号`
`is_esp_online->制动模式反馈信号`
在`apollo/modules/canbus/vehicle/ge3/protocol/scu_eps_311.cc`文件内,增加以下代码:
```
chassis->mutable_check_response()->set_is_eps_online(eps_drvmode(bytes, length) == 3);
```
在`apollo/modules/canbus/vehicle/ge3/protocol/scu_vcu_1_312.cc`文件内,增加以下代码:
```
chassis->mutable_check_response()->set_is_vcu_online(vcu_drvmode(bytes, length) == 3);
```
在`apollo/modules/canbus/vehicle/ge3/protocol/scu_bcs_1_306.cc`文件内,增加以下代码:
```
chassis->mutable_check_response()->set_is_esp_online(bcs_drvmode(bytes, length) == 3);
对黄色高亮部分的修改首先要确定是在哪三个文件中添加代码。经过我对ge3以及devkit代码的分析,发现应该加在转向/驱动/制动的反馈报文处,下面我贴出devkit在制动反馈报文中的代码:
文件名称为break_report_501.cc。
void Brakereport501::Parse(const std::uint8_t* bytes, int32_t length,
ChassisDetail* chassis) const {
chassis->mutable_devkit()->mutable_brake_report_501()->set_brake_pedal_actual(
brake_pedal_actual(bytes, length));
chassis->mutable_devkit()->mutable_brake_report_501()->set_brake_flt2(
brake_flt2(bytes, length));
chassis->mutable_devkit()->mutable_brake_report_501()->set_brake_flt1(
brake_flt1(bytes, length));
chassis->mutable_devkit()->mutable_brake_report_501()->set_brake_en_state(
brake_en_state(bytes, length));
chassis->mutable_check_response()->set_is_esp_online(
brake_en_state(bytes, length) == 1);
}
所以我们也要加在反馈报文处,按道理我们应该加在几个控制器的反馈信号报文内,即:转向在0x401,驱动在0x10/20/30/40,制动在0x142。我认为我应该修改tsy_message_menager.cc中的report报文,将这几个信号的注释给去掉,将他们加入chassis().tsy()这个结构下。
在0x10的电机反馈中添加的代码:
为什么ge3中是==3,而devkit是==1呢?因为那是他们自己定义的正常状态,我们没有一个使能的反馈,只好用错误码当做反馈使用了,错误码的正常状态就是0。
- void Mcufltorquefeedback10::Parse(const std::uint8_t* bytes, int32_t length,
- ChassisDetail* chassis) const {
- chassis->mutable_tsy()->mutable_mcufl_torque_feedback_10()->set_fl_errorcode(fl_errorcode(bytes, length));
- chassis->mutable_tsy()->mutable_mcufl_torque_feedback_10()->set_fl_motortemp(fl_motortemp(bytes, length));
- chassis->mutable_tsy()->mutable_mcufl_torque_feedback_10()->set_fl_current(fl_current(bytes, length));
- chassis->mutable_tsy()->mutable_mcufl_torque_feedback_10()->set_fl_torque(fl_torque(bytes, length));
- chassis->mutable_tsy()->mutable_mcufl_torque_feedback_10()->set_fl_speed(fl_speed(bytes, length));
- chassis->mutable_tsy()->mutable_mcufl_torque_feedback_10()->set_fl_shift(fl_shift(bytes, length));
- //tsy_controller.cc中CheckReponse中要求的代码
- chassis->mutable_check_response()->set_is_vcu_online(
- fl_errorcode(bytes, length) == 0);
- }
在制动0x142内添加的代码:
- void Dbsfstatus142::Parse(const std::uint8_t* bytes, int32_t length,
- ChassisDetail* chassis) const {
- chassis->mutable_tsy()->mutable_dbsf_status_142()->set_dbsf_reserved_2(dbsf_reserved_2(bytes, length));
- chassis->mutable_tsy()->mutable_dbsf_status_142()->set_dbsf_fault_code(dbsf_fault_code(bytes, length));
- chassis->mutable_tsy()->mutable_dbsf_status_142()->set_dbsf_hp_pressure(dbsf_hp_pressure(bytes, length));
- chassis->mutable_tsy()->mutable_dbsf_status_142()->set_dbsf_reserved_1(dbsf_reserved_1(bytes, length));
- chassis->mutable_tsy()->mutable_dbsf_status_142()->set_dbsf_system_status(dbsf_system_status(bytes, length));
- //tsy_controller.cc中CheckReponse中要求的代码
- chassis->mutable_check_response()->set_is_esp_online(
- dbsf_fault_code(bytes, length) == 0);
- }
在转向0x401内添加的代码:
但是这里需要注意,转向电机并没有错误码的反馈,或许抑或校验值可以判断,但是我选择了转向电机的工作模式来判断,当模式为0x20,也就是十进制下的32的时候,电机为角度控制模式,也就是说发送角度请求是可以获得响应的。
- void Epsfstatus401::Parse(const std::uint8_t* bytes, int32_t length,
- ChassisDetail* chassis) const {
- chassis->mutable_tsy()->mutable_epsf_status_401()->set_epsf_check_sum(epsf_check_sum(bytes, length));
- chassis->mutable_tsy()->mutable_epsf_status_401()->set_epsf_reserved2(epsf_reserved2(bytes, length));
- chassis->mutable_tsy()->mutable_epsf_status_401()->set_epsf_angle_in_middle_calib(epsf_angle_in_middle_calib(bytes, length));
- chassis->mutable_tsy()->mutable_epsf_status_401()->set_low_epsf_angle(low_epsf_angle(bytes, length));
- chassis->mutable_tsy()->mutable_epsf_status_401()->set_high_epsf_angle(high_epsf_angle(bytes, length));
- chassis->mutable_tsy()->mutable_epsf_status_401()->set_epsf_reserved1(epsf_reserved1(bytes, length));
- chassis->mutable_tsy()->mutable_epsf_status_401()->set_epsf_steering_wheel_torque_value(epsf_steering_wheel_torque_value(bytes, length));
- chassis->mutable_tsy()->mutable_epsf_status_401()->set_epsf_work_mode_status(epsf_work_mode_status(bytes, length));
- //tsy_controller.cc中CheckReponse中要求的代码
- chassis->mutable_check_response()->set_is_eps_online(
- epsf_work_mode_status(bytes, length) != 32);
- }
将反馈车速的单位调整为m/s
下面是技术文档中的参考内容:
### 4.修改底盘车速反馈协议,将车速反馈单位由km/h转化为m/s
Apollo系统内默认使用车速反馈量为`m/s`,底盘车速信息对Apollo非常重要,在车辆标定、控制、规划等都需要采集该数据,所以开发者要在开发适配代码时,重点检查车速反馈的单位。车速由`km/h`转化为`m/s`时,在反馈车速的信号除以`3.6`即可。
找到Ge3车辆反馈车速的报文在文件`apollo/modules/canbus/vehicle/ge3/protocol/scu_bcs_2_307.cc` 下,反馈车速消息为`Scubcs2307::bcs_vehspd{}`
我们这辆车的车速反馈报文整合在了0x304的信号里:
所以我们在modules/canbus/vehicle/tsy/protocol/vcu_vehicle_status_2_304.cc里面,找到反馈消息Vcuvehiclestatus2304::vehicle_speed{},进行下面的修改:
- // config detail: {'bit': 0, 'is_signed_var': False, 'len': 16, 'name': 'vehicle_speed', 'offset': -80.0, 'order': 'intel', 'physical_range': '[-80|80]', 'physical_unit': 'km/h', 'precision': 0.1, 'type': 'double'}
- double Vcuvehiclestatus2304::vehicle_speed(const std::uint8_t* bytes, int32_t length) const {
- Byte t0(bytes + 1);
- int32_t x = t0.get_byte(0, 8);
- Byte t1(bytes + 0);
- int32_t t = t1.get_byte(0, 8);
- x <<= 8;
- x |= t;
- double ret = (x * 0.100000 + -80.000000)/3.6;
- return ret;
- }
注册新车辆
参考技术文档内的内容进行注册车辆。
### 5.注册新车辆
在`modules/canbus/vehicle/vehicle_factory.cc`里注册新的车辆,在该文件内新建如下类:
![register_ge3](images/vehicle_adaption_tutorial/register_ge3.png)
添加头文件
![add_head_file](images/vehicle_adaption_tutorial/add_head_file.png)
添加BUILD依赖库
在`apollo/modules/canbus/vehicle/BUILD` 文件内添加`ge3_vehicle_factory`依赖库。
![add_build_depend](images/vehicle_adaption_tutorial/add_build_depend.png)
下面代码在文件modules/canbus/vehicle/vehicle_factory.cc里添加:
- //注册tsy的车辆工厂
- Register(apollo::common::TSY, []() -> AbstractVehicleFactory * {
- return new TsyVehicleFactory();
- });
- //添加tsy的车辆工厂头文件
- #include "modules/canbus/vehicle/tsy/tsy_vehicle_factory.h"
下面代码在文件apollo/modules/canbus/vehicle/BUILD里添加:
- cc_library(
- name = "vehicle_factory",
- srcs = ["vehicle_factory.cc"],
- hdrs = ["vehicle_factory.h"],
- copts = CANBUS_COPTS,
- deps = [
- ":abstract_vehicle_factory",
- "//modules/canbus/vehicle/ch:ch_vehicle_factory",
- "//modules/canbus/vehicle/devkit:devkit_vehicle_factory",
- "//modules/canbus/vehicle/ge3:ge3_vehicle_factory",
- "//modules/canbus/vehicle/gem:gem_vehicle_factory",
- "//modules/canbus/vehicle/lexus:lexus_vehicle_factory",
- "//modules/canbus/vehicle/lincoln:lincoln_vehicle_factory",
- "//modules/canbus/vehicle/neolix_edu:neolix_edu_vehicle_factory",
- "//modules/canbus/vehicle/transit:transit_vehicle_factory",
- "//modules/canbus/vehicle/wey:wey_vehicle_factory",
- "//modules/canbus/vehicle/zhongyun:zhongyun_vehicle_factory",
- "//modules/common/util:factory",
- #下面是tsy的车辆工厂依赖文件
- "//modules/canbus/vehicle/tsy:tsy_vehicle_factory",
- ],
- )
更新配置文件
参考技术文档的内容更新配置文件。
### 6.更新配置文件
在`modules/canbus/proto/vehicle_parameter.proto` 文件内添加GE3车辆分支。
![register1_ge3](images/vehicle_adaption_tutorial/register1_ge3.png)
在`modules/canbus/conf/canbus_conf.pb.txt` 更新配置,改为ge3的canbus通信程序。
![register2_ge3](images/vehicle_adaption_tutorial/register2_ge3.png)
先在proto文件里添加TSY车辆分支,但是发现没有emun的内容,所以参考一下袁珺博士的南阳理工学院的配适文件:
message VehicleParameter {
enum VehicleBrand {
LINCOLN_MKZ = 0;
GEM = 1;
CH = 2;
AGILEX = 4;
AGRIBOT = 5;
NYLG = 6;
}
optional VehicleBrand brand = 1;
optional double max_engine_pedal = 2;
optional int32 max_enable_fail_attempt = 3;
optional Chassis.DrivingMode driving_mode = 4;
}
下面是参考后我们的代码:
- message VehicleParameter {
- enum VehicleBrand {
- LINCOLN_MKZ = 0;
- GEM = 1;
- CH = 2;
- AGILEX = 4;
- AGRIBOT = 5;
- TSY = 6;
- }
- optional apollo.common.VehicleBrand brand = 1;
- optional double max_engine_pedal = 2;
- optional int32 max_enable_fail_attempt = 3;
- optional Chassis.DrivingMode driving_mode = 4;
- }
然后在conf文件中更改通信方式:
- vehicle_parameter {
- brand: TSY
- max_enable_fail_attempt: 5
- driving_mode: COMPLETE_AUTO_DRIVE
- }
- can_card_parameter {
- brand: SOCKET_CAN_RAW
- type: PCI_CARD
- channel_id: CHANNEL_ID_ZERO
- interface: NATIVE
- }
- enable_debug_mode: false
- enable_receiver_log: false
- enable_sender_log: false
vehicle的brand在上面调的那个文件里可以看到:modules/canbus/proto/vehicle_parameter.proto。can_card的brand可以在这个文件里看到:apollo\modules\drivers\canbus\proto\can_card_parameter.proto。
到这里收尾结束,底层CAN通讯和车辆配适的工作算是告一段落了。剩下的应该是对DBC配适的检测了,检测方法在技术文档中也提到了,使用teleop工具来检测。
本篇完
2020年12月23日 15:23
于宁波天尚元振狮路365号工厂二楼