18#include "modules/common_msgs/basic_msgs/vehicle_signal.pb.h"
30using ::apollo::common::ErrorCode;
31using ::apollo::common::VehicleSignal;
32using ::apollo::control::ControlCommand;
33using ::apollo::drivers::canbus::ProtocolData;
37const int32_t kMaxFailAttempt = 10;
38const int32_t CHECK_RESPONSE_STEER_UNIT_FLAG = 1;
39const int32_t CHECK_RESPONSE_SPEED_UNIT_FLAG = 2;
44 CanSender<::apollo::canbus::Zhongyun>*
const can_sender,
45 MessageManager<::apollo::canbus::Zhongyun>*
const message_manager) {
47 AINFO <<
"ZhongyunController has already been initialized.";
48 return ErrorCode::CANBUS_ERROR;
51 common::VehicleConfigHelper::Instance()->GetConfig().vehicle_param());
53 if (!
params_.has_driving_mode()) {
54 AERROR <<
"Vehicle conf pb not set driving_mode.";
55 return ErrorCode::CANBUS_ERROR;
58 if (can_sender ==
nullptr) {
59 AERROR <<
"Canbus sender is null.";
60 return ErrorCode::CANBUS_ERROR;
64 if (message_manager ==
nullptr) {
65 AERROR <<
"Protocol manager is null.";
66 return ErrorCode::CANBUS_ERROR;
73 if (brake_control_a4_ ==
nullptr) {
74 AERROR <<
"Brakecontrola4 does not exist in the ZhongyunMessageManager!";
75 return ErrorCode::CANBUS_ERROR;
80 if (gear_control_a1_ ==
nullptr) {
81 AERROR <<
"Gearcontrola1 does not exist in the ZhongyunMessageManager!";
82 return ErrorCode::CANBUS_ERROR;
87 if (parking_control_a5_ ==
nullptr) {
88 AERROR <<
"Parkingcontrola5 does not exist in the ZhongyunMessageManager!";
89 return ErrorCode::CANBUS_ERROR;
94 if (steering_control_a2_ ==
nullptr) {
95 AERROR <<
"Steeringcontrola2 does not exist in the ZhongyunMessageManager!";
96 return ErrorCode::CANBUS_ERROR;
101 if (torque_control_a3_ ==
nullptr) {
102 AERROR <<
"Torquecontrola3 does not exist in the ZhongyunMessageManager!";
103 return ErrorCode::CANBUS_ERROR;
113 AINFO <<
"ZhongyunController is initialized.";
116 return ErrorCode::OK;
123 AERROR <<
"ZhongyunController has not been initialized.";
126 const auto& update_func = [
this] { SecurityDogThreadFunc(); };
127 thread_.reset(
new std::thread(update_func));
134 AERROR <<
"ZhongyunController stops or starts improperly!";
138 if (thread_ !=
nullptr && thread_->joinable()) {
141 AINFO <<
"ZhongyunController stopped.";
157 chassis_.set_error_code(chassis_error_code());
160 chassis_.set_engine_started(
true);
163 if (chassis_detail.has_vehicle_state_feedback_2_c4() &&
165 chassis_.set_engine_rpm(
static_cast<float>(
168 chassis_.set_engine_rpm(0);
171 if (chassis_detail.has_vehicle_state_feedback_c1() &&
173 chassis_.set_speed_mps(
176 chassis_.set_speed_mps(0);
179 chassis_.set_fuel_range_m(0);
182 if (chassis_detail.has_vehicle_state_feedback_2_c4() &&
184 .has_driven_torque_feedback()) {
185 chassis_.set_throttle_percentage(
static_cast<float>(
188 chassis_.set_throttle_percentage(0);
191 if (chassis_detail.has_vehicle_state_feedback_c1() &&
193 chassis_.set_brake_percentage(
static_cast<float>(
196 chassis_.set_brake_percentage(0);
199 if (chassis_detail.has_vehicle_state_feedback_c1() &&
222 if (chassis_detail.has_vehicle_state_feedback_c1() &&
224 chassis_.set_steering_percentage(
static_cast<float>(
228 chassis_.set_steering_percentage(0);
231 if (chassis_detail.has_vehicle_state_feedback_c1() &&
233 chassis_.set_parking_brake(
237 chassis_.set_parking_brake(
false);
240 if (chassis_error_mask_) {
241 chassis_.set_chassis_error_mask(chassis_error_mask_);
245 chassis_.mutable_engage_advice()->set_advice(
248 chassis_.mutable_engage_advice()->set_advice(
250 chassis_.mutable_engage_advice()->set_reason(
251 "CANBUS not ready, epb is not released or firmware error!");
255 if (chassis_detail.has_enable_state_feedback_c3()) {
257 chassis_.mutable_check_response()->set_is_esp_online(
262 chassis_.mutable_check_response()->set_is_vcu_online(
269 chassis_.mutable_check_response()->set_is_eps_online(
278bool ZhongyunController::VerifyID() {
return true; }
280void ZhongyunController::Emergency() {
285ErrorCode ZhongyunController::EnableAutoMode() {
287 AINFO <<
"Already in COMPLETE_AUTO_DRIVE mode.";
288 return ErrorCode::OK;
303 CHECK_RESPONSE_STEER_UNIT_FLAG | CHECK_RESPONSE_SPEED_UNIT_FLAG;
304 if (!CheckResponse(flag,
true)) {
305 AERROR <<
"Failed to switch to COMPLETE_AUTO_DRIVE mode.";
308 return ErrorCode::CANBUS_ERROR;
311 AINFO <<
"Switch to COMPLETE_AUTO_DRIVE mode ok.";
312 return ErrorCode::OK;
315ErrorCode ZhongyunController::DisableAutoMode() {
320 AINFO <<
"Switch to COMPLETE_MANUAL mode ok.";
321 return ErrorCode::OK;
324ErrorCode ZhongyunController::EnableSteeringOnlyMode() {
328 AINFO <<
"Already in AUTO_STEER_ONLY mode";
329 return ErrorCode::OK;
344 CHECK_RESPONSE_STEER_UNIT_FLAG | CHECK_RESPONSE_SPEED_UNIT_FLAG;
345 if (!CheckResponse(flag,
true)) {
346 AERROR <<
"Failed to switch to COMPLETE_AUTO_DRIVE mode. Please check the "
347 "emergency button or chassis.";
350 return ErrorCode::CANBUS_ERROR;
353 AINFO <<
"Switch to COMPLETE_AUTO_DRIVE mode ok.";
354 return ErrorCode::OK;
357ErrorCode ZhongyunController::EnableSpeedOnlyMode() {
361 AINFO <<
"Already in AUTO_SPEED_ONLY mode";
362 return ErrorCode::OK;
376 if (CheckResponse(CHECK_RESPONSE_SPEED_UNIT_FLAG,
true) ==
false) {
377 AERROR <<
"Failed to switch to AUTO_SPEED_ONLY mode.";
380 return ErrorCode::CANBUS_ERROR;
383 AINFO <<
"Switch to AUTO_SPEED_ONLY mode ok.";
384 return ErrorCode::OK;
391 AINFO <<
"This drive mode no need to set gear.";
395 switch (gear_position) {
418 AERROR <<
"Gear command is invalid!";
433void ZhongyunController::Brake(
double pedal) {
436 AINFO <<
"The current drive mode does not need to set brake pedal.";
444void ZhongyunController::Throttle(
double pedal) {
447 AINFO <<
"The current drive mode does not need to set throttle pedal.";
456void ZhongyunController::Acceleration(
double acc) {
459 AINFO <<
"The current drive mode does not need to set acceleration.";
469void ZhongyunController::Steer(
double angle) {
472 AINFO <<
"The current driving mode does not need to set steer.";
475 const double real_angle =
483void ZhongyunController::Steer(
double angle,
double angle_spd) {
486 AINFO <<
"The current driving mode does not need to set steer.";
489 const double real_angle =
494void ZhongyunController::SetEpbBreak(
const ControlCommand& command) {
495 if (command.parking_brake()) {
504ErrorCode ZhongyunController::HandleCustomOperation(
505 const external_command::ChassisCommand& command) {
506 return ErrorCode::OK;
509void ZhongyunController::SetBeam(
const VehicleSignal& vehicle_signal) {
510 if (vehicle_signal.high_beam()) {
512 }
else if (vehicle_signal.low_beam()) {
519void ZhongyunController::SetHorn(
const VehicleSignal& vehicle_signal) {
520 if (vehicle_signal.horn()) {
527void ZhongyunController::SetTurningSignal(
const VehicleSignal& vehicle_signal) {
532void ZhongyunController::ResetProtocol() {
536bool ZhongyunController::CheckChassisError() {
537 Zhongyun chassis_detail;
539 if (!chassis_.has_check_response()) {
540 AERROR_EVERY(100) <<
"ChassisDetail has NO zhongyun vehicle info.";
545 if (chassis_detail.has_error_state_e1() &&
546 chassis_detail.error_state_e1().has_steering_error_code()) {
547 if (chassis_detail.error_state_e1().steering_error_code() ==
553 if (chassis_detail.has_error_state_e1() &&
554 chassis_detail.error_state_e1().has_driven_error_code()) {
555 if (chassis_detail.error_state_e1().driven_error_code() ==
561 if (chassis_detail.has_error_state_e1() &&
562 chassis_detail.error_state_e1().has_brake_error_code()) {
563 if (chassis_detail.error_state_e1().brake_error_code() ==
569 if (chassis_detail.has_error_state_e1() &&
570 chassis_detail.error_state_e1().has_gear_error_msg()) {
571 if (chassis_detail.error_state_e1().gear_error_msg() ==
577 if (chassis_detail.has_error_state_e1() &&
578 chassis_detail.error_state_e1().has_parking_error_code()) {
579 if (chassis_detail.error_state_e1().parking_error_code() ==
587void ZhongyunController::SecurityDogThreadFunc() {
588 int32_t vertical_ctrl_fail = 0;
589 int32_t horizontal_ctrl_fail = 0;
592 AERROR <<
"Failed to run SecurityDogThreadFunc() because can_sender_ is "
597 std::this_thread::yield();
600 std::chrono::duration<double, std::micro> default_period{50000};
606 bool emergency_mode =
false;
611 !CheckResponse(CHECK_RESPONSE_STEER_UNIT_FLAG,
false)) {
612 ++horizontal_ctrl_fail;
613 if (horizontal_ctrl_fail >= kMaxFailAttempt) {
614 emergency_mode =
true;
615 AINFO <<
"Driving_mode is into emergency by steer manual intervention";
619 horizontal_ctrl_fail = 0;
625 !CheckResponse(CHECK_RESPONSE_SPEED_UNIT_FLAG,
false)) {
626 ++vertical_ctrl_fail;
627 if (vertical_ctrl_fail >= kMaxFailAttempt) {
628 emergency_mode =
true;
629 AINFO <<
"Driving_mode is into emergency by speed manual intervention";
633 vertical_ctrl_fail = 0;
635 if (CheckChassisError()) {
637 emergency_mode =
true;
646 std::chrono::duration<double, std::micro> elapsed{end - start};
647 if (elapsed < default_period) {
648 std::this_thread::sleep_for(default_period - elapsed);
651 <<
"Too much time consumption in ZhongyunController looping process:"
657bool ZhongyunController::CheckResponse(
const int32_t flags,
bool need_wait) {
660 int32_t retry_num = 20;
661 Zhongyun chassis_detail;
662 bool is_eps_online =
false;
663 bool is_vcu_online =
false;
664 bool is_esp_online =
false;
671 bool check_ok =
true;
672 if (flags & CHECK_RESPONSE_STEER_UNIT_FLAG) {
673 is_eps_online = chassis_.has_check_response() &&
676 check_ok = check_ok && is_eps_online;
679 if (flags & CHECK_RESPONSE_SPEED_UNIT_FLAG) {
680 is_vcu_online = chassis_.has_check_response() &&
683 is_esp_online = chassis_.has_check_response() &&
686 check_ok = check_ok && is_vcu_online && is_esp_online;
690 std::this_thread::sleep_for(
691 std::chrono::duration<double, std::milli>(20));
696 AINFO <<
"Need to check response again.";
698 }
while (need_wait && retry_num);
700 AINFO <<
"check_response fail: is_eps_online:" << is_eps_online
701 <<
", is_vcu_online:" << is_vcu_online
702 <<
", is_esp_online:" << is_esp_online;
706void ZhongyunController::set_chassis_error_mask(
const int32_t mask) {
707 std::lock_guard<std::mutex> lock(chassis_mask_mutex_);
708 chassis_error_mask_ = mask;
711int32_t ZhongyunController::chassis_error_mask() {
712 std::lock_guard<std::mutex> lock(chassis_mask_mutex_);
713 return chassis_error_mask_;
717 std::lock_guard<std::mutex> lock(chassis_error_code_mutex_);
718 return chassis_error_code_;
721void ZhongyunController::set_chassis_error_code(
723 std::lock_guard<std::mutex> lock(chassis_error_code_mutex_);
724 chassis_error_code_ = error_code;
Defines SenderMessage class and CanSender class.
common::VehicleParam vehicle_params_
canbus::VehicleParameter params_
CanSender< ::apollo::canbus::Zhongyun > * can_sender_
virtual void set_driving_mode(const Chassis::DrivingMode &driving_mode)
MessageManager< ::apollo::canbus::Zhongyun > * message_manager_
virtual Chassis::DrivingMode driving_mode()
Brakecontrola4 * set_brake_enable_control(Brake_control_a4::Brake_enable_controlType brake_enable_control)
Brakecontrola4 * set_brake_torque(double brake_torque)
Gearcontrola1 * set_gear_enable_control(Gear_control_a1::Gear_enable_controlType gear_enable_control)
Gearcontrola1 * set_gear_state_target(Gear_control_a1::Gear_state_targetType gear_state_target)
Parkingcontrola5 * set_parking_target(Parking_control_a5::Parking_targetType parking_target)
Parkingcontrola5 * set_parking_enable_control(Parking_control_a5::Parking_enable_controlType parking_enable_control)
Steeringcontrola2 * set_steering_target(double steering_target)
Steeringcontrola2 * set_steering_enable_control(Steering_control_a2::Steering_enable_controlType steering_enable_control)
Torquecontrola3 * set_driven_torque(double driven_torque)
Torquecontrola3 * set_driven_enable_control(Torque_control_a3::Driven_enable_controlType driven_enable_control)
virtual ~ZhongyunController()
bool Start() override
start the vehicle controller.
void Stop() override
stop the vehicle controller.
::apollo::common::ErrorCode Init(const VehicleParameter ¶ms, CanSender<::apollo::canbus::Zhongyun > *const can_sender, MessageManager<::apollo::canbus::Zhongyun > *const message_manager) override
Chassis chassis() override
calculate and return the chassis.
uint64_t ToMicrosecond() const
convert time to microsecond (us).
static Time Now()
get the current time.
#define AERROR_EVERY(freq)
The class of ProtocolData
@ BRAKE_ENABLE_CONTROL_BRAKE_MANUAL
@ BRAKE_ENABLE_CONTROL_BRAKE_AUTO
optional CheckResponse check_response
optional bool parking_brake
optional bool is_esp_online
optional bool is_vcu_online
optional bool is_eps_online
optional Brake_enable_stateType brake_enable_state
optional Gear_enable_actualType gear_enable_actual
optional Steering_enable_stateType steering_enable_state
optional Driven_enable_stateType driven_enable_state
@ PARKING_ERROR_CODE_ERROR
@ STEERING_ERROR_CODE_ERROR
@ DRIVEN_ERROR_CODE_ERROR
@ GEAR_STATE_TARGET_INVALID
@ GEAR_ENABLE_CONTROL_GEAR_MANUALCONTROL
@ GEAR_ENABLE_CONTROL_GEAR_AUTOCONTROL
@ PARKING_ENABLE_CONTROL_PARKING_MANUALCONTROL
@ PARKING_ENABLE_CONTROL_PARKING_AUTOCONTROL
@ PARKING_TARGET_PARKING_TRIGGER
@ STEERING_ENABLE_CONTROL_STEERING_AUTOCONTROL
@ STEERING_ENABLE_CONTROL_STEERING_MANUALCONTROL
@ DRIVEN_ENABLE_CONTROL_DRIVE_MANUAL
@ DRIVEN_ENABLE_CONTROL_DRIVE_AUTO
optional int32 motor_speed
optional double driven_torque_feedback
optional Parking_actualType parking_actual
@ PARKING_ACTUAL_PARKING_TRIGGER
optional Gear_state_actualType gear_state_actual
optional double steering_actual
optional double brake_torque_feedback
optional Enable_state_feedback_c3 enable_state_feedback_c3
optional Vehicle_state_feedback_2_c4 vehicle_state_feedback_2_c4
optional Vehicle_state_feedback_c1 vehicle_state_feedback_c1
optional double max_steer_angle
The class of VehicleController