32using ::apollo::common::ErrorCode;
33using ::apollo::common::VehicleSignal;
34using ::apollo::control::ControlCommand;
35using ::apollo::drivers::canbus::ProtocolData;
39const int32_t kMaxFailAttempt = 10;
40const int32_t CHECK_RESPONSE_STEER_UNIT_FLAG = 1;
41const int32_t CHECK_RESPONSE_SPEED_UNIT_FLAG = 2;
50 ads_light_horn_command_310_,
false);
55 CanSender<::apollo::canbus::Neolix_edu>*
const can_sender,
56 MessageManager<::apollo::canbus::Neolix_edu>*
const message_manager) {
58 AINFO <<
"Neolix_eduController has already been initiated.";
59 return ErrorCode::CANBUS_ERROR;
63 common::VehicleConfigHelper::Instance()->GetConfig().vehicle_param());
65 if (!
params_.has_driving_mode()) {
66 AERROR <<
"Vehicle conf pb not set driving_mode.";
67 return ErrorCode::CANBUS_ERROR;
70 if (can_sender ==
nullptr) {
71 return ErrorCode::CANBUS_ERROR;
75 if (message_manager ==
nullptr) {
76 AERROR <<
"protocol manager is null.";
77 return ErrorCode::CANBUS_ERROR;
84 if (ads_brake_command_46_ ==
nullptr) {
86 <<
"Adsbrakecommand46 does not exist in the Neolix_eduMessageManager!";
87 return ErrorCode::CANBUS_ERROR;
92 if (ads_diagnosis_628_ ==
nullptr) {
93 AERROR <<
"Adsdiagnosis628 does not exist in the Neolix_eduMessageManager!";
94 return ErrorCode::CANBUS_ERROR;
99 if (ads_drive_command_50_ ==
nullptr) {
101 <<
"Adsdrivecommand50 does not exist in the Neolix_eduMessageManager!";
102 return ErrorCode::CANBUS_ERROR;
107 if (ads_eps_command_56_ ==
nullptr) {
108 AERROR <<
"Adsepscommand56 does not exist in the Neolix_eduMessageManager!";
109 return ErrorCode::CANBUS_ERROR;
114 if (ads_light_horn_command_310_ ==
nullptr) {
115 AERROR <<
"Adslighthorncommand310 does not exist in the "
116 "Neolix_eduMessageManager!";
117 return ErrorCode::CANBUS_ERROR;
122 AINFO <<
"Neolix_eduController is initialized.";
125 return ErrorCode::OK;
132 AERROR <<
"Neolix_eduController has NOT been initiated.";
135 const auto& update_func = [
this] { SecurityDogThreadFunc(); };
136 thread_.reset(
new std::thread(update_func));
143 AERROR <<
"Neolix_eduController stops or starts improperly!";
147 if (thread_ !=
nullptr && thread_->joinable()) {
150 AINFO <<
"Neolix_eduController stopped.";
165 chassis_.set_error_code(chassis_error_code());
168 chassis_.set_engine_started(
true);
171 auto wheelspeed = chassis_.mutable_wheel_speed();
172 if (chassis_detail.has_aeb_frontwheelspeed_353() &&
173 chassis_detail.has_aeb_rearwheelspeed_354()) {
174 wheelspeed->set_wheel_spd_fl(
176 wheelspeed->set_wheel_spd_fr(
178 wheelspeed->set_wheel_spd_rl(
180 wheelspeed->set_wheel_spd_rr(
182 chassis_.set_speed_mps(
189 chassis_.set_speed_mps(0);
192 if (chassis_detail.has_vcu_vehicle_status_report_101() &&
194 .has_vcu_motor_direction()) {
220 wheelspeed->clear_wheel_direction_fl();
221 wheelspeed->clear_wheel_direction_fr();
222 wheelspeed->clear_wheel_direction_rl();
223 wheelspeed->clear_wheel_direction_rr();
227 if (chassis_detail.has_vcu_vehicle_status_report_101() &&
229 chassis_.set_battery_soc_percentage(
232 chassis_.set_battery_soc_percentage(0);
235 if (chassis_detail.has_vcu_eps_report_57() &&
237 chassis_.set_steering_percentage(
static_cast<float>(
241 chassis_.set_steering_percentage(0);
245 if (chassis_detail.has_vcu_drive_report_52() &&
247 chassis_.set_throttle_percentage(
250 chassis_.set_throttle_percentage(0);
254 if (chassis_detail.has_vcu_brake_report_47() &&
256 chassis_.set_brake_percentage(
259 chassis_.set_brake_percentage(0);
262 if (chassis_detail.has_vcu_drive_report_52() &&
264 chassis_.set_gear_location((apollo::canbus::Chassis_GearPosition)
269 if (chassis_detail.has_vcu_brake_report_47() &&
272 chassis_.set_parking_brake(
true);
274 chassis_.set_parking_brake(
false);
277 chassis_.set_parking_brake(
false);
280 if (chassis_error_mask_) {
281 chassis_.set_chassis_error_mask(chassis_error_mask_);
287 chassis_.mutable_engage_advice()->set_advice(
290 chassis_.mutable_engage_advice()->set_advice(
295 if (chassis_detail.has_vcu_brake_report_47() &&
311 if (chassis_detail.has_vcu_brake_report_47() &&
313 chassis_.mutable_check_response()->set_is_esp_online(
316 if (chassis_detail.has_vcu_drive_report_52() &&
318 chassis_.mutable_check_response()->set_is_vcu_online(
321 if (chassis_detail.has_vcu_eps_report_57() &&
323 chassis_.mutable_check_response()->set_is_eps_online(
327 if (CheckChassisError()) {
328 chassis_.mutable_engage_advice()->set_advice(
330 chassis_.mutable_engage_advice()->set_reason(
331 "Chassis has some fault, please check the chassis_detail.");
336 chassis_.mutable_engage_advice()->set_advice(
338 chassis_.mutable_engage_advice()->set_reason(
339 "neolix chassis detail is lost! Please check the communication error.");
347bool Neolix_eduController::VerifyID() {
return true; }
349void Neolix_eduController::Emergency() {
354ErrorCode Neolix_eduController::EnableAutoMode() {
356 AINFO <<
"already in COMPLETE_AUTO_DRIVE mode";
357 return ErrorCode::OK;
366 CHECK_RESPONSE_STEER_UNIT_FLAG | CHECK_RESPONSE_SPEED_UNIT_FLAG;
367 if (!CheckResponse(flag,
true)) {
368 AERROR <<
"Failed to switch to COMPLETE_AUTO_DRIVE mode. Please check the "
369 "emergency button or chassis.";
372 return ErrorCode::CANBUS_ERROR;
375 AINFO <<
"Switch to COMPLETE_AUTO_DRIVE mode ok.";
376 return ErrorCode::OK;
379ErrorCode Neolix_eduController::DisableAutoMode() {
384 AINFO <<
"Switch to COMPLETE_MANUAL ok.";
385 return ErrorCode::OK;
388ErrorCode Neolix_eduController::EnableSteeringOnlyMode() {
392 AINFO <<
"Already in AUTO_STEER_ONLY mode.";
393 return ErrorCode::OK;
395 AFATAL <<
"SpeedOnlyMode is not supported in Neolix_edu!";
396 return ErrorCode::OK;
399ErrorCode Neolix_eduController::EnableSpeedOnlyMode() {
403 AINFO <<
"Already in AUTO_SPEED_ONLY mode";
404 return ErrorCode::OK;
406 AFATAL <<
"SpeedOnlyMode is not supported in Neolix_edu!";
407 return ErrorCode::OK;
414 AINFO <<
"This drive mode no need to set gear.";
417 switch (gear_position) {
445void Neolix_eduController::Brake(
double pedal) {
449 AINFO <<
"The current drive mode does not need to set brake pedal.";
457void Neolix_eduController::Throttle(
double pedal) {
460 AINFO <<
"The current drive mode does not need to set throttle pedal.";
469void Neolix_eduController::Acceleration(
double acc) {
477void Neolix_eduController::Steer(
double angle) {
480 AINFO <<
"The current driving mode does not need to set steer.";
483 const double real_angle =
491void Neolix_eduController::Steer(
double angle,
double angle_spd) {
494 AINFO <<
"The current driving mode does not need to set steer.";
497 const double real_angle =
502void Neolix_eduController::SetEpbBreak(
const ControlCommand& command) {
503 if (command.parking_brake()) {
510ErrorCode Neolix_eduController::HandleCustomOperation(
511 const external_command::ChassisCommand& command) {
512 return ErrorCode::OK;
515void Neolix_eduController::SetBeam(
const VehicleSignal& vehicle_signal) {
516 if (vehicle_signal.high_beam()) {
518 }
else if (vehicle_signal.low_beam()) {
525void Neolix_eduController::SetHorn(
const VehicleSignal& vehicle_signal) {
526 if (vehicle_signal.horn()) {
533void Neolix_eduController::SetTurningSignal(
534 const VehicleSignal& vehicle_signal) {
538void Neolix_eduController::ResetProtocol() {
542bool Neolix_eduController::CheckChassisError() {
544 AERROR_EVERY(100) <<
"ChassisDetail has no neolix vehicle info.";
551void Neolix_eduController::SecurityDogThreadFunc() {
552 int32_t vertical_ctrl_fail = 0;
553 int32_t horizontal_ctrl_fail = 0;
556 AERROR <<
"Failed to run SecurityDogThreadFunc() because can_sender_ is "
561 std::this_thread::yield();
564 std::chrono::duration<double, std::micro> default_period{50000};
570 bool emergency_mode =
false;
575 CheckResponse(CHECK_RESPONSE_STEER_UNIT_FLAG,
false) ==
false) {
576 ++horizontal_ctrl_fail;
577 if (horizontal_ctrl_fail >= kMaxFailAttempt) {
578 emergency_mode =
true;
579 AERROR <<
"Driving_mode is into emergency by steer manual intervention";
583 horizontal_ctrl_fail = 0;
589 !CheckResponse(CHECK_RESPONSE_SPEED_UNIT_FLAG,
false)) {
590 ++vertical_ctrl_fail;
591 if (vertical_ctrl_fail >= kMaxFailAttempt) {
592 emergency_mode =
true;
593 AERROR <<
"Driving_mode is into emergency by speed manual intervention";
597 vertical_ctrl_fail = 0;
601 if (CheckChassisError()) {
603 emergency_mode =
true;
620 std::chrono::duration<double, std::micro> elapsed{end - start};
621 if (elapsed < default_period) {
622 std::this_thread::sleep_for(default_period - elapsed);
624 AERROR <<
"Too much time consumption in Neolix_eduController looping "
631bool Neolix_eduController::CheckResponse(
const int32_t flags,
bool need_wait) {
632 int32_t retry_num = 20;
633 Neolix_edu chassis_detail;
634 bool is_eps_online =
false;
635 bool is_vcu_online =
false;
636 bool is_esp_online =
false;
639 bool check_ok =
true;
640 if (flags & CHECK_RESPONSE_STEER_UNIT_FLAG) {
641 is_eps_online = chassis_.has_check_response() &&
644 check_ok = check_ok && is_eps_online;
647 if (flags & CHECK_RESPONSE_SPEED_UNIT_FLAG) {
648 is_vcu_online = chassis_.has_check_response() &&
651 is_esp_online = chassis_.has_check_response() &&
654 check_ok = check_ok && is_vcu_online && is_esp_online;
659 AINFO <<
"Need to check response again.";
663 std::this_thread::sleep_for(
664 std::chrono::duration<double, std::milli>(20));
666 }
while (need_wait && retry_num);
668 if (flags & CHECK_RESPONSE_STEER_UNIT_FLAG) {
669 AERROR <<
"steer check_response fail: is_eps_online:" << is_eps_online;
672 if (flags & CHECK_RESPONSE_SPEED_UNIT_FLAG) {
673 AERROR <<
"speed check_response fail: " <<
"is_vcu_online:" << is_vcu_online
674 <<
", is_esp_online:" << is_esp_online;
680void Neolix_eduController::set_chassis_error_mask(
const int32_t mask) {
681 std::lock_guard<std::mutex> lock(chassis_mask_mutex_);
682 chassis_error_mask_ = mask;
685int32_t Neolix_eduController::chassis_error_mask() {
686 std::lock_guard<std::mutex> lock(chassis_mask_mutex_);
687 return chassis_error_mask_;
691 std::lock_guard<std::mutex> lock(chassis_error_code_mutex_);
692 return chassis_error_code_;
695void Neolix_eduController::set_chassis_error_code(
697 std::lock_guard<std::mutex> lock(chassis_error_code_mutex_);
698 chassis_error_code_ = error_code;