Apollo 10.0
自动驾驶开放平台
gem_controller.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19#include <cmath>
20
21#include "modules/canbus_vehicle/gem/proto/gem.pb.h"
22#include "modules/common_msgs/basic_msgs/vehicle_signal.pb.h"
23#include "cyber/common/log.h"
24#include "cyber/time/time.h"
29
30namespace apollo {
31namespace canbus {
32namespace gem {
33
34// using ::apollo::canbus::gem;
35using ::apollo::common::ErrorCode;
36using ::apollo::common::VehicleSignal;
37using ::apollo::control::ControlCommand;
38using ::apollo::drivers::canbus::ProtocolData;
39
40namespace {
41
42const int32_t kMaxFailAttempt = 10;
43const int32_t CHECK_RESPONSE_STEER_UNIT_FLAG = 1;
44const int32_t CHECK_RESPONSE_SPEED_UNIT_FLAG = 2;
45
46} // namespace
47
49 const VehicleParameter& params,
50 CanSender<::apollo::canbus::Gem>* const can_sender,
51 MessageManager<::apollo::canbus::Gem>* const message_manager) {
52 if (is_initialized_) {
53 AINFO << "GemController has already been initialized.";
54 return ErrorCode::CANBUS_ERROR;
55 }
56 vehicle_params_.CopyFrom(
57 common::VehicleConfigHelper::Instance()->GetConfig().vehicle_param());
58 params_.CopyFrom(params);
59 if (!params_.has_driving_mode()) {
60 AERROR << "Vehicle conf pb not set driving_mode.";
61 return ErrorCode::CANBUS_ERROR;
62 }
63
64 if (can_sender == nullptr) {
65 AERROR << "Canbus sender is null.";
66 return ErrorCode::CANBUS_ERROR;
67 }
68 can_sender_ = can_sender;
69
70 if (message_manager == nullptr) {
71 AERROR << "Protocol manager is null.";
72 return ErrorCode::CANBUS_ERROR;
73 }
74 message_manager_ = message_manager;
75
76 // Sender part
77 brake_cmd_6b_ = dynamic_cast<Brakecmd6b*>(
78 message_manager_->GetMutableProtocolDataById(Brakecmd6b::ID));
79 if (brake_cmd_6b_ == nullptr) {
80 AERROR << "Brakecmd6b does not exist in the GemMessageManager!";
81 return ErrorCode::CANBUS_ERROR;
82 }
83
84 accel_cmd_67_ = dynamic_cast<Accelcmd67*>(
85 message_manager_->GetMutableProtocolDataById(Accelcmd67::ID));
86 if (accel_cmd_67_ == nullptr) {
87 AERROR << "Accelcmd67 does not exist in the GemMessageManager!";
88 return ErrorCode::CANBUS_ERROR;
89 }
90
91 steering_cmd_6d_ = dynamic_cast<Steeringcmd6d*>(
92 message_manager_->GetMutableProtocolDataById(Steeringcmd6d::ID));
93 if (steering_cmd_6d_ == nullptr) {
94 AERROR << "Steeringcmd6d does not exist in the GemMessageManager!";
95 return ErrorCode::CANBUS_ERROR;
96 }
97
98 shift_cmd_65_ = dynamic_cast<Shiftcmd65*>(
99 message_manager_->GetMutableProtocolDataById(Shiftcmd65::ID));
100 if (shift_cmd_65_ == nullptr) {
101 AERROR << "Shiftcmd65 does not exist in the GemMessageManager!";
102 return ErrorCode::CANBUS_ERROR;
103 }
104 turn_cmd_63_ = dynamic_cast<Turncmd63*>(
105 message_manager_->GetMutableProtocolDataById(Turncmd63::ID));
106 if (turn_cmd_63_ == nullptr) {
107 AERROR << "Turncmd63 does not exist in the GemMessageManager!";
108 return ErrorCode::CANBUS_ERROR;
109 }
110 global_cmd_69_ = dynamic_cast<Globalcmd69*>(
111 message_manager_->GetMutableProtocolDataById(Globalcmd69::ID));
112 if (global_cmd_69_ == nullptr) {
113 AERROR << "Turncmd63 does not exist in the GemMessageManager!";
114 return ErrorCode::CANBUS_ERROR;
115 }
116
117 can_sender_->AddMessage(Brakecmd6b::ID, brake_cmd_6b_, false);
118 can_sender_->AddMessage(Accelcmd67::ID, accel_cmd_67_, false);
119 can_sender_->AddMessage(Steeringcmd6d::ID, steering_cmd_6d_, false);
120 can_sender_->AddMessage(Shiftcmd65::ID, shift_cmd_65_, false);
121 can_sender_->AddMessage(Turncmd63::ID, turn_cmd_63_, false);
122 can_sender_->AddMessage(Globalcmd69::ID, global_cmd_69_, false);
123
124 // Need to sleep to ensure all messages received.
125 AINFO << "GemController is initialized.";
126
127 is_initialized_ = true;
128 return ErrorCode::OK;
129}
130
132
134 if (!is_initialized_) {
135 AERROR << "GemController has NOT been initiated.";
136 return false;
137 }
138 const auto& update_func = [this] { SecurityDogThreadFunc(); };
139 thread_.reset(new std::thread(update_func));
140
141 return true;
142}
143
145 if (!is_initialized_) {
146 AERROR << "GemController stops or starts improperly!";
147 return;
148 }
149
150 if (thread_ != nullptr && thread_->joinable()) {
151 thread_->join();
152 thread_.reset();
153 AINFO << "GemController stopped.";
154 }
155}
156
158 chassis_.Clear();
159
160 Gem chassis_detail;
161 message_manager_->GetSensorData(&chassis_detail);
162
163 // 21, 22, previously 1, 2
165 set_chassis_error_code(Chassis::NO_ERROR);
166 }
167
168 chassis_.set_driving_mode(driving_mode());
169 chassis_.set_error_code(chassis_error_code());
170
171 // 3
172 chassis_.set_engine_started(true);
173
174 // 5
175 if (chassis_detail.has_vehicle_speed_rpt_6f() &&
176 chassis_detail.vehicle_speed_rpt_6f().has_vehicle_speed()) {
177 chassis_.set_speed_mps(static_cast<float>(
178 chassis_detail.vehicle_speed_rpt_6f().vehicle_speed()));
179 } else {
180 chassis_.set_speed_mps(0);
181 }
182
183 // 7
184 chassis_.set_fuel_range_m(0);
185 // 8
186 if (chassis_detail.has_accel_rpt_68() &&
187 chassis_detail.accel_rpt_68().has_output_value()) {
188 chassis_.set_throttle_percentage(
189 static_cast<float>(chassis_detail.accel_rpt_68().output_value()));
190 } else {
191 chassis_.set_throttle_percentage(0);
192 }
193 // 9
194 if (chassis_detail.has_brake_rpt_6c() &&
195 chassis_detail.brake_rpt_6c().has_output_value()) {
196 chassis_.set_brake_percentage(
197 static_cast<float>(chassis_detail.brake_rpt_6c().output_value()));
198 } else {
199 chassis_.set_brake_percentage(0);
200 }
201
202 // 23, previously 10
203 if (chassis_detail.has_shift_rpt_66() &&
204 chassis_detail.shift_rpt_66().has_output_value()) {
206
207 if (chassis_detail.shift_rpt_66().output_value() ==
209 gear_pos = Chassis::GEAR_NEUTRAL;
210 }
211 if (chassis_detail.shift_rpt_66().output_value() ==
213 gear_pos = Chassis::GEAR_REVERSE;
214 }
215 if (chassis_detail.shift_rpt_66().output_value() ==
217 gear_pos = Chassis::GEAR_DRIVE;
218 }
219
220 chassis_.set_gear_location(gear_pos);
221 } else {
222 chassis_.set_gear_location(Chassis::GEAR_NONE);
223 }
224
225 // 11
226 // TODO(QiL) : verify the unit here.
227 if (chassis_detail.has_steering_rpt_1_6e() &&
228 chassis_detail.steering_rpt_1_6e().has_output_value()) {
229 chassis_.set_steering_percentage(
230 static_cast<float>(chassis_detail.steering_rpt_1_6e().output_value() *
232 } else {
233 chassis_.set_steering_percentage(0);
234 }
235
236 if (chassis_detail.has_global_rpt_6a() &&
237 chassis_detail.global_rpt_6a().has_pacmod_status()) {
238 if (chassis_detail.global_rpt_6a().pacmod_status() ==
240 chassis_.set_driving_mode(Chassis::COMPLETE_AUTO_DRIVE);
241 global_cmd_69_->set_clear_override(
243 } else {
244 chassis_.set_driving_mode(Chassis::COMPLETE_MANUAL);
245 }
246 } else {
247 chassis_.set_driving_mode(Chassis::COMPLETE_MANUAL);
248 }
249
250 // TODO(QiL) : implement the turn light signal here
251
252 // 16, 17
253 if (chassis_detail.has_light() &&
254 chassis_detail.light().has_turn_light_type() &&
255 chassis_detail.light().turn_light_type() != Light::TURN_LIGHT_OFF) {
256 if (chassis_detail.light().turn_light_type() == Light::TURN_LEFT_ON) {
257 chassis_.mutable_signal()->set_turn_signal(
259 } else if (chassis_detail.light().turn_light_type() ==
261 chassis_.mutable_signal()->set_turn_signal(
263 } else {
264 chassis_.mutable_signal()->set_turn_signal(
266 }
267 } else {
268 chassis_.mutable_signal()->set_turn_signal(
270 }
271
272 // TODO(all): implement the rest here/
273 // 26
274 if (chassis_error_mask_) {
275 chassis_.set_chassis_error_mask(chassis_error_mask_);
276 }
277
278 // Give engage_advice based on error_code and canbus feedback
279 if (!chassis_error_mask_ && !chassis_.parking_brake() &&
280 chassis_.throttle_percentage() == 0.0 &&
281 chassis_.brake_percentage() != 0.0) {
282 chassis_.mutable_engage_advice()->set_advice(
284 } else {
285 chassis_.mutable_engage_advice()->set_advice(
287 chassis_.mutable_engage_advice()->set_reason(
288 "CANBUS not ready, firmware error or emergency button pressed!");
289 }
290
291 return chassis_;
292}
293
294bool GemController::VerifyID() { return true; }
295
296void GemController::Emergency() {
298 ResetProtocol();
299 set_chassis_error_code(Chassis::CHASSIS_ERROR);
300}
301
302ErrorCode GemController::EnableAutoMode() {
304 AINFO << "Already in COMPLETE_AUTO_DRIVE mode";
305 return ErrorCode::OK;
306 }
307
308 global_cmd_69_->set_pacmod_enable(
310 global_cmd_69_->set_clear_override(
312
313 can_sender_->Update();
314 const int32_t flag =
315 CHECK_RESPONSE_STEER_UNIT_FLAG | CHECK_RESPONSE_SPEED_UNIT_FLAG;
316 if (!CheckResponse(flag, true)) {
317 AERROR << "Failed to switch to COMPLETE_AUTO_DRIVE mode.";
318 Emergency();
319 set_chassis_error_code(Chassis::CHASSIS_ERROR);
320 return ErrorCode::CANBUS_ERROR;
321 }
323 AINFO << "Switch to COMPLETE_AUTO_DRIVE mode ok.";
324 return ErrorCode::OK;
325}
326
327ErrorCode GemController::DisableAutoMode() {
328 ResetProtocol();
329 can_sender_->Update();
331 set_chassis_error_code(Chassis::NO_ERROR);
332 AINFO << "Switch to COMPLETE_MANUAL ok.";
333 return ErrorCode::OK;
334}
335
336ErrorCode GemController::EnableSteeringOnlyMode() {
337 AFATAL << "Not supported!";
338 return ErrorCode::OK;
339}
340
341ErrorCode GemController::EnableSpeedOnlyMode() {
342 AFATAL << "Not supported!";
343 return ErrorCode::OK;
344}
345
346// NEUTRAL, REVERSE, DRIVE
347void GemController::Gear(Chassis::GearPosition gear_position) {
350 AINFO << "This drive mode no need to set gear.";
351 return;
352 }
353
354 switch (gear_position) {
357 break;
358 }
361 break;
362 }
363 case Chassis::GEAR_DRIVE: {
365 break;
366 }
368 AERROR << "Gear command is invalid!";
370 break;
371 }
372 default: {
374 break;
375 }
376 }
377}
378
379// brake with new acceleration
380// acceleration:0.00~99.99, unit:
381// acceleration:0.0 ~ 7.0, unit:m/s^2
382// acceleration_spd:60 ~ 100, suggest: 90
383// -> pedal
384void GemController::Brake(double pedal) {
385 // double real_value = params_.max_acc() * acceleration / 100;
386 // TODO(QiL) Update brake value based on mode
389 AINFO << "The current drive mode does not need to set acceleration.";
390 return;
391 }
392
393 brake_cmd_6b_->set_brake_cmd(pedal / 100.0);
394}
395
396// drive with old acceleration
397// gas:0.00~99.99 unit:
398void GemController::Throttle(double pedal) {
401 AINFO << "The current drive mode does not need to set acceleration.";
402 return;
403 }
404
405 accel_cmd_67_->set_accel_cmd(pedal / 100.0);
406}
407
408// drive with acceleration/deceleration
409// acc:-7.0 ~ 5.0, unit:m/s^2
410void GemController::Acceleration(double acc) {
413 AINFO << "The current drive mode does not need to set acceleration.";
414 return;
415 }
416 // None
417}
418
419// gem default, -470 ~ 470, left:+, right:-
420// need to be compatible with control module, so reverse
421// steering with old angle speed
422// angle:-99.99~0.00~99.99, unit:, left:-, right:+
423void GemController::Steer(double angle) {
426 AINFO << "The current driving mode does not need to set steer.";
427 return;
428 }
429
430 const double real_angle = vehicle_params_.max_steer_angle() * angle / 100.0;
431
432 steering_cmd_6d_->set_position_value(real_angle)->set_speed_limit(9.0);
433}
434
435// steering with new angle speed
436// angle:-99.99~0.00~99.99, unit:, left:-, right:+
437// angle_spd:0.00~99.99, unit:deg/s
438void GemController::Steer(double angle, double angle_spd) {
441 AINFO << "The current driving mode does not need to set steer.";
442 return;
443 }
444 const double real_angle = vehicle_params_.max_steer_angle() * angle / 100.0;
445
446 const double real_angle_spd =
447 ProtocolData<::apollo::canbus::Gem>::BoundedValue(
450 vehicle_params_.max_steer_angle_rate() * angle_spd / 100.0);
451 steering_cmd_6d_->set_position_value(real_angle)
452 ->set_speed_limit(real_angle_spd);
453}
454
455void GemController::SetEpbBreak(const ControlCommand& command) {
456 if (command.parking_brake()) {
457 // None
458 } else {
459 // None
460 }
461}
462ErrorCode GemController::HandleCustomOperation(
463 const external_command::ChassisCommand& command) {
464 return ErrorCode::OK;
465}
466
467void GemController::SetBeam(const VehicleSignal& vehicle_signal) {
468 if (vehicle_signal.high_beam()) {
469 // None
470 } else if (vehicle_signal.low_beam()) {
471 // None
472 } else {
473 // None
474 }
475}
476
477void GemController::SetHorn(const VehicleSignal& vehicle_signal) {
478 if (vehicle_signal.horn()) {
479 // None
480 } else {
481 // None
482 }
483}
484
485void GemController::SetTurningSignal(const VehicleSignal& vehicle_signal) {
486 // Set Turn Signal
487 auto signal = vehicle_signal.turn_signal();
488 if (signal == common::VehicleSignal::TURN_LEFT) {
490 } else if (signal == common::VehicleSignal::TURN_RIGHT) {
492 } else {
494 }
495}
496
497void GemController::ResetProtocol() { message_manager_->ResetSendMessages(); }
498
499bool GemController::CheckChassisError() {
500 // TODO(QiL) : implement it here
501 return false;
502}
503
504void GemController::SecurityDogThreadFunc() {
505 int32_t vertical_ctrl_fail = 0;
506 int32_t horizontal_ctrl_fail = 0;
507
508 if (can_sender_ == nullptr) {
509 AERROR << "Failed to run SecurityDogThreadFunc() because can_sender_ is "
510 "nullptr.";
511 return;
512 }
513 while (!can_sender_->IsRunning()) {
514 std::this_thread::yield();
515 }
516
517 std::chrono::duration<double, std::micro> default_period{50000};
518 int64_t start = 0;
519 int64_t end = 0;
520 while (can_sender_->IsRunning()) {
522 const Chassis::DrivingMode mode = driving_mode();
523 bool emergency_mode = false;
524
525 // 1. horizontal control check
526 if ((mode == Chassis::COMPLETE_AUTO_DRIVE ||
527 mode == Chassis::AUTO_STEER_ONLY) &&
528 !CheckResponse(CHECK_RESPONSE_STEER_UNIT_FLAG, false)) {
529 ++horizontal_ctrl_fail;
530 if (horizontal_ctrl_fail >= kMaxFailAttempt) {
531 emergency_mode = true;
532 set_chassis_error_code(Chassis::MANUAL_INTERVENTION);
533 }
534 } else {
535 horizontal_ctrl_fail = 0;
536 }
537
538 // 2. vertical control check
539 if ((mode == Chassis::COMPLETE_AUTO_DRIVE ||
540 mode == Chassis::AUTO_SPEED_ONLY) &&
541 !CheckResponse(CHECK_RESPONSE_SPEED_UNIT_FLAG, false)) {
542 ++vertical_ctrl_fail;
543 if (vertical_ctrl_fail >= kMaxFailAttempt) {
544 emergency_mode = true;
545 set_chassis_error_code(Chassis::MANUAL_INTERVENTION);
546 }
547 } else {
548 vertical_ctrl_fail = 0;
549 }
550 if (CheckChassisError()) {
551 set_chassis_error_code(Chassis::CHASSIS_ERROR);
552 emergency_mode = true;
553 }
554
555 if (emergency_mode && mode != Chassis::EMERGENCY_MODE) {
557 message_manager_->ResetSendMessages();
558 }
560 std::chrono::duration<double, std::micro> elapsed{end - start};
561 if (elapsed < default_period) {
562 std::this_thread::sleep_for(default_period - elapsed);
563 } else {
564 AERROR << "Too much time consumption in GemController looping process:"
565 << elapsed.count();
566 }
567 }
568}
569
570bool GemController::CheckResponse(const int32_t flags, bool need_wait) {
571 /* ADD YOUR OWN CAR CHASSIS OPERATION
572 */
573 return true;
574}
575
576void GemController::set_chassis_error_mask(const int32_t mask) {
577 std::lock_guard<std::mutex> lock(chassis_mask_mutex_);
578 chassis_error_mask_ = mask;
579}
580
581int32_t GemController::chassis_error_mask() {
582 std::lock_guard<std::mutex> lock(chassis_mask_mutex_);
583 return chassis_error_mask_;
584}
585
586Chassis::ErrorCode GemController::chassis_error_code() {
587 std::lock_guard<std::mutex> lock(chassis_error_code_mutex_);
588 return chassis_error_code_;
589}
590
591void GemController::set_chassis_error_code(
592 const Chassis::ErrorCode& error_code) {
593 std::lock_guard<std::mutex> lock(chassis_error_code_mutex_);
594 chassis_error_code_ = error_code;
595}
596
597} // namespace gem
598} // namespace canbus
599} // namespace apollo
Defines SenderMessage class and CanSender class.
virtual void set_driving_mode(const Chassis::DrivingMode &driving_mode)
MessageManager< ::apollo::canbus::Gem > * message_manager_
Accelcmd67 * set_accel_cmd(double accel_cmd)
Brakecmd6b * set_brake_cmd(double brake_cmd)
void Stop() override
stop the vehicle controller.
bool Start() override
start the vehicle controller.
Chassis chassis() override
calculate and return the chassis.
::apollo::common::ErrorCode Init(const VehicleParameter &params, CanSender<::apollo::canbus::Gem > *const can_sender, MessageManager<::apollo::canbus::Gem > *const message_manager) override
Globalcmd69 * set_pacmod_enable(Global_cmd_69::Pacmod_enableType pacmod_enable)
Globalcmd69 * set_clear_override(Global_cmd_69::Clear_overrideType clear_override)
Shiftcmd65 * set_shift_cmd(Shift_cmd_65::Shift_cmdType shift_cmd)
Steeringcmd6d * set_position_value(double position_value)
Steeringcmd6d * set_speed_limit(double speed_limit)
Turncmd63 * set_turn_signal_cmd(Turn_cmd_63::Turn_signal_cmdType turn_signal_cmd)
static const int32_t ID
Definition turn_cmd_63.h:29
uint64_t ToMicrosecond() const
convert time to microsecond (us).
Definition time.cc:85
static Time Now()
get the current time.
Definition time.cc:57
#define AERROR
Definition log.h:44
#define AFATAL
Definition log.h:45
#define AINFO
Definition log.h:42
class register implement
Definition arena_queue.h:37
The class of ProtocolData
optional double output_value
Definition gem.proto:146
optional double output_value
Definition gem.proto:55
optional float brake_percentage
Definition chassis.proto:82
optional bool parking_brake
Definition chassis.proto:94
optional float throttle_percentage
Definition chassis.proto:79
optional Global_rpt_6a global_rpt_6a
Definition gem.proto:471
optional Light light
Definition gem.proto:501
optional Brake_rpt_6c brake_rpt_6c
Definition gem.proto:473
optional Vehicle_speed_rpt_6f vehicle_speed_rpt_6f
Definition gem.proto:494
optional Accel_rpt_68 accel_rpt_68
Definition gem.proto:480
optional Shift_rpt_66 shift_rpt_66
Definition gem.proto:485
optional Steering_rpt_1_6e steering_rpt_1_6e
Definition gem.proto:475
optional Pacmod_statusType pacmod_status
Definition gem.proto:23
optional TurnLightType turn_light_type
Definition gem.proto:464
optional Output_valueType output_value
Definition gem.proto:239
The class of VehicleController