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 if (chassis_detail.has_aeb_frontwheelspeed_353() &&
172 chassis_detail.has_aeb_rearwheelspeed_354()) {
173 auto wheelspeed = chassis_.mutable_wheel_speed();
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 chassis_.set_battery_soc_percentage(
197 chassis_.set_battery_soc_percentage(0);
200 if (chassis_detail.has_vcu_eps_report_57() &&
202 chassis_.set_steering_percentage(
static_cast<float>(
206 chassis_.set_steering_percentage(0);
210 if (chassis_detail.has_vcu_drive_report_52() &&
212 chassis_.set_throttle_percentage(
215 chassis_.set_throttle_percentage(0);
219 if (chassis_detail.has_vcu_brake_report_47() &&
221 chassis_.set_brake_percentage(
224 chassis_.set_brake_percentage(0);
227 if (chassis_detail.has_vcu_drive_report_52() &&
229 chassis_.set_gear_location((apollo::canbus::Chassis_GearPosition)
234 if (chassis_detail.has_vcu_brake_report_47() &&
237 chassis_.set_parking_brake(
true);
239 chassis_.set_parking_brake(
false);
242 chassis_.set_parking_brake(
false);
245 if (chassis_error_mask_) {
246 chassis_.set_chassis_error_mask(chassis_error_mask_);
252 chassis_.mutable_engage_advice()->set_advice(
255 chassis_.mutable_engage_advice()->set_advice(
260 if (chassis_detail.has_vcu_brake_report_47() &&
276 if (chassis_detail.has_vcu_brake_report_47() &&
278 chassis_.mutable_check_response()->set_is_esp_online(
281 if (chassis_detail.has_vcu_drive_report_52() &&
283 chassis_.mutable_check_response()->set_is_vcu_online(
286 if (chassis_detail.has_vcu_eps_report_57() &&
288 chassis_.mutable_check_response()->set_is_eps_online(
292 if (CheckChassisError()) {
293 chassis_.mutable_engage_advice()->set_advice(
295 chassis_.mutable_engage_advice()->set_reason(
296 "Chassis has some fault, please check the chassis_detail.");
301 chassis_.mutable_engage_advice()->set_advice(
303 chassis_.mutable_engage_advice()->set_reason(
304 "neolix chassis detail is lost! Please check the communication error.");
312bool Neolix_eduController::VerifyID() {
return true; }
314void Neolix_eduController::Emergency() {
319ErrorCode Neolix_eduController::EnableAutoMode() {
321 AINFO <<
"already in COMPLETE_AUTO_DRIVE mode";
322 return ErrorCode::OK;
331 CHECK_RESPONSE_STEER_UNIT_FLAG | CHECK_RESPONSE_SPEED_UNIT_FLAG;
332 if (!CheckResponse(flag,
true)) {
333 AERROR <<
"Failed to switch to COMPLETE_AUTO_DRIVE mode. Please check the "
334 "emergency button or chassis.";
337 return ErrorCode::CANBUS_ERROR;
340 AINFO <<
"Switch to COMPLETE_AUTO_DRIVE mode ok.";
341 return ErrorCode::OK;
344ErrorCode Neolix_eduController::DisableAutoMode() {
349 AINFO <<
"Switch to COMPLETE_MANUAL ok.";
350 return ErrorCode::OK;
353ErrorCode Neolix_eduController::EnableSteeringOnlyMode() {
357 AINFO <<
"Already in AUTO_STEER_ONLY mode.";
358 return ErrorCode::OK;
360 AFATAL <<
"SpeedOnlyMode is not supported in Neolix_edu!";
361 return ErrorCode::OK;
364ErrorCode Neolix_eduController::EnableSpeedOnlyMode() {
368 AINFO <<
"Already in AUTO_SPEED_ONLY mode";
369 return ErrorCode::OK;
371 AFATAL <<
"SpeedOnlyMode is not supported in Neolix_edu!";
372 return ErrorCode::OK;
379 AINFO <<
"This drive mode no need to set gear.";
382 switch (gear_position) {
410void Neolix_eduController::Brake(
double pedal) {
414 AINFO <<
"The current drive mode does not need to set brake pedal.";
422void Neolix_eduController::Throttle(
double pedal) {
425 AINFO <<
"The current drive mode does not need to set throttle pedal.";
434void Neolix_eduController::Acceleration(
double acc) {
442void Neolix_eduController::Steer(
double angle) {
445 AINFO <<
"The current driving mode does not need to set steer.";
448 const double real_angle =
456void Neolix_eduController::Steer(
double angle,
double angle_spd) {
459 AINFO <<
"The current driving mode does not need to set steer.";
462 const double real_angle =
467void Neolix_eduController::SetEpbBreak(
const ControlCommand& command) {
468 if (command.parking_brake()) {
475ErrorCode Neolix_eduController::HandleCustomOperation(
476 const external_command::ChassisCommand& command) {
477 return ErrorCode::OK;
480void Neolix_eduController::SetBeam(
const VehicleSignal& vehicle_signal) {
481 if (vehicle_signal.high_beam()) {
483 }
else if (vehicle_signal.low_beam()) {
490void Neolix_eduController::SetHorn(
const VehicleSignal& vehicle_signal) {
491 if (vehicle_signal.horn()) {
498void Neolix_eduController::SetTurningSignal(
499 const VehicleSignal& vehicle_signal) {
503void Neolix_eduController::ResetProtocol() {
507bool Neolix_eduController::CheckChassisError() {
509 AERROR_EVERY(100) <<
"ChassisDetail has no neolix vehicle info.";
516void Neolix_eduController::SecurityDogThreadFunc() {
517 int32_t vertical_ctrl_fail = 0;
518 int32_t horizontal_ctrl_fail = 0;
521 AERROR <<
"Failed to run SecurityDogThreadFunc() because can_sender_ is "
526 std::this_thread::yield();
529 std::chrono::duration<double, std::micro> default_period{50000};
535 bool emergency_mode =
false;
540 CheckResponse(CHECK_RESPONSE_STEER_UNIT_FLAG,
false) ==
false) {
541 ++horizontal_ctrl_fail;
542 if (horizontal_ctrl_fail >= kMaxFailAttempt) {
543 emergency_mode =
true;
544 AERROR <<
"Driving_mode is into emergency by steer manual intervention";
548 horizontal_ctrl_fail = 0;
554 !CheckResponse(CHECK_RESPONSE_SPEED_UNIT_FLAG,
false)) {
555 ++vertical_ctrl_fail;
556 if (vertical_ctrl_fail >= kMaxFailAttempt) {
557 emergency_mode =
true;
558 AERROR <<
"Driving_mode is into emergency by speed manual intervention";
562 vertical_ctrl_fail = 0;
566 if (CheckChassisError()) {
568 emergency_mode =
true;
585 std::chrono::duration<double, std::micro> elapsed{end - start};
586 if (elapsed < default_period) {
587 std::this_thread::sleep_for(default_period - elapsed);
589 AERROR <<
"Too much time consumption in Neolix_eduController looping "
596bool Neolix_eduController::CheckResponse(
const int32_t flags,
bool need_wait) {
597 int32_t retry_num = 20;
598 Neolix_edu chassis_detail;
599 bool is_eps_online =
false;
600 bool is_vcu_online =
false;
601 bool is_esp_online =
false;
604 bool check_ok =
true;
605 if (flags & CHECK_RESPONSE_STEER_UNIT_FLAG) {
606 is_eps_online = chassis_.has_check_response() &&
609 check_ok = check_ok && is_eps_online;
612 if (flags & CHECK_RESPONSE_SPEED_UNIT_FLAG) {
613 is_vcu_online = chassis_.has_check_response() &&
616 is_esp_online = chassis_.has_check_response() &&
619 check_ok = check_ok && is_vcu_online && is_esp_online;
624 AINFO <<
"Need to check response again.";
628 std::this_thread::sleep_for(
629 std::chrono::duration<double, std::milli>(20));
631 }
while (need_wait && retry_num);
633 if (flags & CHECK_RESPONSE_STEER_UNIT_FLAG) {
634 AERROR <<
"steer check_response fail: is_eps_online:" << is_eps_online;
637 if (flags & CHECK_RESPONSE_SPEED_UNIT_FLAG) {
638 AERROR <<
"speed check_response fail: " <<
"is_vcu_online:" << is_vcu_online
639 <<
", is_esp_online:" << is_esp_online;
645void Neolix_eduController::set_chassis_error_mask(
const int32_t mask) {
646 std::lock_guard<std::mutex> lock(chassis_mask_mutex_);
647 chassis_error_mask_ = mask;
650int32_t Neolix_eduController::chassis_error_mask() {
651 std::lock_guard<std::mutex> lock(chassis_mask_mutex_);
652 return chassis_error_mask_;
656 std::lock_guard<std::mutex> lock(chassis_error_code_mutex_);
657 return chassis_error_code_;
660void Neolix_eduController::set_chassis_error_code(
662 std::lock_guard<std::mutex> lock(chassis_error_code_mutex_);
663 chassis_error_code_ = error_code;