Apollo 10.0
自动驾驶开放平台
transit_controller.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 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 "modules/common_msgs/basic_msgs/vehicle_signal.pb.h"
20#include "cyber/common/log.h"
21#include "cyber/time/time.h"
27
28namespace apollo {
29namespace canbus {
30namespace transit {
31
32using ::apollo::common::ErrorCode;
33using ::apollo::common::VehicleSignal;
34using ::apollo::control::ControlCommand;
35using ::apollo::drivers::canbus::ProtocolData;
36
37namespace {
38
39const int32_t kMaxFailAttempt = 10;
40const int32_t CHECK_RESPONSE_STEER_UNIT_FLAG = 1;
41const int32_t CHECK_RESPONSE_SPEED_UNIT_FLAG = 2;
42
43} // namespace
44
46 const VehicleParameter& params,
47 CanSender<::apollo::canbus::Transit>* const can_sender,
48 MessageManager<::apollo::canbus::Transit>* const message_manager) {
49 if (is_initialized_) {
50 AINFO << "TransitController has already been initialized.";
51 return ErrorCode::CANBUS_ERROR;
52 }
53
54 vehicle_params_.CopyFrom(
55 common::VehicleConfigHelper::Instance()->GetConfig().vehicle_param());
56
57 params_.CopyFrom(params);
58 if (!params_.has_driving_mode()) {
59 AERROR << "Vehicle conf pb not set driving_mode.";
60 return ErrorCode::CANBUS_ERROR;
61 }
62
63 if (can_sender == nullptr) {
64 AERROR << "Canbus sender is null.";
65 return ErrorCode::CANBUS_ERROR;
66 }
67 can_sender_ = can_sender;
68
69 if (message_manager == nullptr) {
70 AERROR << "protocol manager is null.";
71 return ErrorCode::CANBUS_ERROR;
72 }
73 message_manager_ = message_manager;
74
75 // sender part
76 adc_auxiliarycontrol_110_ = dynamic_cast<Adcauxiliarycontrol110*>(
77 message_manager_->GetMutableProtocolDataById(Adcauxiliarycontrol110::ID));
78 if (adc_auxiliarycontrol_110_ == nullptr) {
79 AERROR << "Adcauxiliarycontrol110 does not exist in the "
80 "TransitMessageManager!";
81 return ErrorCode::CANBUS_ERROR;
82 }
83
84 adc_motioncontrol1_10_ = dynamic_cast<Adcmotioncontrol110*>(
85 message_manager_->GetMutableProtocolDataById(Adcmotioncontrol110::ID));
86 if (adc_motioncontrol1_10_ == nullptr) {
87 AERROR
88 << "Adcmotioncontrol110 does not exist in the TransitMessageManager!";
89 return ErrorCode::CANBUS_ERROR;
90 }
91
92 adc_motioncontrollimits1_12_ = dynamic_cast<Adcmotioncontrollimits112*>(
93 message_manager_->GetMutableProtocolDataById(
95 if (adc_motioncontrollimits1_12_ == nullptr) {
96 AERROR << "Adcmotioncontrollimits112 does not exist in the "
97 "TransitMessageManager!";
98 return ErrorCode::CANBUS_ERROR;
99 }
100
101 llc_diag_brakecontrol_721_ = dynamic_cast<Llcdiagbrakecontrol721*>(
102 message_manager_->GetMutableProtocolDataById(Llcdiagbrakecontrol721::ID));
103 if (llc_diag_brakecontrol_721_ == nullptr) {
104 AERROR << "Llcdiagbrakecontrol721 does not exist in the "
105 "TransitMessageManager!";
106 return ErrorCode::CANBUS_ERROR;
107 }
108
109 llc_diag_steeringcontrol_722_ = dynamic_cast<Llcdiagsteeringcontrol722*>(
110 message_manager_->GetMutableProtocolDataById(
112 if (llc_diag_steeringcontrol_722_ == nullptr) {
113 AERROR << "Llcdiagsteeringcontrol722 does not exist in the "
114 "TransitMessageManager!";
115 return ErrorCode::CANBUS_ERROR;
116 }
117
118 can_sender_->AddMessage(Adcauxiliarycontrol110::ID, adc_auxiliarycontrol_110_,
119 false);
120 can_sender_->AddMessage(Adcmotioncontrol110::ID, adc_motioncontrol1_10_,
121 false);
123 adc_motioncontrollimits1_12_, false);
125 llc_diag_brakecontrol_721_, false);
127 llc_diag_steeringcontrol_722_, false);
128
129 // need sleep to ensure all messages received
130 AINFO << "TransitController is initialized.";
131
132 is_initialized_ = true;
133 return ErrorCode::OK;
134}
135
137
139 if (!is_initialized_) {
140 AERROR << "TransitController has NOT been initiated.";
141 return false;
142 }
143 const auto& update_func = [this] { SecurityDogThreadFunc(); };
144 thread_.reset(new std::thread(update_func));
145
146 return true;
147}
148
150 if (!is_initialized_) {
151 AERROR << "TransitController stops or starts improperly!";
152 return;
153 }
154
155 if (thread_ != nullptr && thread_->joinable()) {
156 thread_->join();
157 thread_.reset();
158 AINFO << "TransitController stopped.";
159 }
160}
161
163 chassis_.Clear();
164
165 Transit chassis_detail;
166 message_manager_->GetSensorData(&chassis_detail);
167
168 // 21, 22, previously 1, 2
170 set_chassis_error_code(Chassis::NO_ERROR);
171 }
172
173 chassis_.set_driving_mode(driving_mode());
174 chassis_.set_error_code(chassis_error_code());
175
176 // 3
177 chassis_.set_engine_started(true);
178
179 auto& motion20 = chassis_detail.llc_motionfeedback1_20();
180 if (motion20.has_llc_fbk_throttleposition()) {
181 chassis_.set_throttle_percentage(
182 static_cast<float>(motion20.llc_fbk_throttleposition()));
183 }
184
185 button_pressed_ = (chassis_detail.llc_motionfeedback1_20().llc_fbk_state() ==
187
188 if (motion20.has_llc_fbk_brakepercentrear()) {
189 // TODO(Udelv): fix scaling
190 chassis_.set_brake_percentage(
191 static_cast<float>(motion20.llc_fbk_brakepercentrear()));
192 }
193
194 if (motion20.has_llc_fbk_gear()) {
195 switch (motion20.llc_fbk_gear()) {
197 chassis_.set_gear_location(Chassis::GEAR_PARKING);
198 break;
200 chassis_.set_gear_location(Chassis::GEAR_DRIVE);
201 break;
203 chassis_.set_gear_location(Chassis::GEAR_NEUTRAL);
204 break;
206 chassis_.set_gear_location(Chassis::GEAR_REVERSE);
207 break;
208 default:
209 break;
210 }
211 }
212
213 auto& motion21 = chassis_detail.llc_motionfeedback2_21();
214 if (motion21.has_llc_fbk_vehiclespeed()) {
215 chassis_.set_speed_mps(static_cast<float>(motion21.llc_fbk_vehiclespeed()));
216 }
217
218 if (motion21.has_llc_fbk_steeringangle()) {
219 chassis_.set_steering_percentage(
220 static_cast<float>(-1.0 * motion21.llc_fbk_steeringangle() * M_PI /
221 180 / vehicle_params_.max_steer_angle() * 100));
222 }
223
224 auto& aux = chassis_detail.llc_auxiliaryfeedback_120();
225 if (aux.has_llc_fbk_turnsignal()) {
226 switch (aux.llc_fbk_turnsignal()) {
228 chassis_.mutable_signal()->set_turn_signal(
230 break;
232 chassis_.mutable_signal()->set_turn_signal(
234 break;
236 chassis_.mutable_signal()->set_turn_signal(
238 break;
239 default:
240 break;
241 }
242 }
243
244 return chassis_;
245}
246
247bool TransitController::VerifyID() { return true; }
248
249void TransitController::Emergency() {
251 ResetProtocol();
252}
253
254ErrorCode TransitController::EnableAutoMode() {
256 AINFO << "Already in COMPLETE_AUTO_DRIVE mode";
257 return ErrorCode::OK;
258 }
259
260 SetLimits();
261
262 adc_motioncontrol1_10_->set_adc_cmd_autonomyrequest(
264 adc_motioncontrol1_10_->set_adc_cmd_steeringcontrolmode(
266 adc_motioncontrol1_10_->set_adc_cmd_longitudinalcontrolmode(
267 Adc_motioncontrol1_10::
268 ADC_CMD_LONGITUDINALCONTROLMODE_DIRECT_THROTTLE_BRAKE);
269
270 can_sender_->Update();
271 if (!CheckResponse()) {
272 AERROR << "Failed to switch to COMPLETE_AUTO_DRIVE mode.";
273 Emergency();
274 return ErrorCode::CANBUS_ERROR;
275 }
276 if (button_pressed_) {
278 AINFO << "Switch to COMPLETE_AUTO_DRIVE mode ok.";
279 } else {
281 AINFO << "Physical button not pressed yet.";
282 }
283 return ErrorCode::OK;
284}
285
286ErrorCode TransitController::DisableAutoMode() {
287 ResetProtocol();
288 can_sender_->Update();
290 set_chassis_error_code(Chassis::NO_ERROR);
291 AINFO << "Switch to COMPLETE_MANUAL ok.";
292 return ErrorCode::OK;
293}
294
295ErrorCode TransitController::EnableSteeringOnlyMode() {
299 AINFO << "Already in AUTO_STEER_ONLY mode";
300 return ErrorCode::OK;
301 }
302
303 SetLimits();
304
305 adc_motioncontrol1_10_->set_adc_cmd_autonomyrequest(
307 adc_motioncontrol1_10_->set_adc_cmd_steeringcontrolmode(
309 adc_motioncontrol1_10_->set_adc_cmd_longitudinalcontrolmode(
311 can_sender_->Update();
313 return ErrorCode::OK;
314}
315
316ErrorCode TransitController::EnableSpeedOnlyMode() {
320 AINFO << "Already in AUTO_SPEED_ONLY mode";
321 return ErrorCode::OK;
322 }
323
324 SetLimits();
325
326 adc_motioncontrol1_10_->set_adc_cmd_autonomyrequest(
328 adc_motioncontrol1_10_->set_adc_cmd_steeringcontrolmode(
330 adc_motioncontrol1_10_->set_adc_cmd_longitudinalcontrolmode(
331 Adc_motioncontrol1_10::
332 ADC_CMD_LONGITUDINALCONTROLMODE_DIRECT_THROTTLE_BRAKE);
333 can_sender_->Update();
334 if (!CheckResponse()) {
335 AERROR << "Failed to switch to AUTO_STEER_ONLY mode.";
336 Emergency();
337 set_chassis_error_code(Chassis::CHASSIS_ERROR);
338 return ErrorCode::CANBUS_ERROR;
339 }
340 if (button_pressed_) {
342 AINFO << "Switch to COMPLETE_AUTO_DRIVE mode ok.";
343 } else {
345 AINFO << "Physical button not pressed yet.";
346 }
347 return ErrorCode::OK;
348}
349
350// NEUTRAL, REVERSE, DRIVE
351void TransitController::Gear(Chassis::GearPosition gear_position) {
354 AINFO << "This drive mode no need to set gear.";
355 return;
356 }
357 switch (gear_position) {
359 adc_motioncontrol1_10_->set_adc_cmd_gear(
361 break;
362 }
364 adc_motioncontrol1_10_->set_adc_cmd_gear(
366 break;
367 }
368 case Chassis::GEAR_DRIVE: {
369 adc_motioncontrol1_10_->set_adc_cmd_gear(
371 break;
372 }
374 adc_motioncontrol1_10_->set_adc_cmd_gear(
376 break;
377 }
378 case Chassis::GEAR_LOW: {
379 adc_motioncontrol1_10_->set_adc_cmd_gear(
381 break;
382 }
383 case Chassis::GEAR_NONE: {
384 adc_motioncontrol1_10_->set_adc_cmd_gear(
386 break;
387 }
389 AERROR << "Gear command is invalid!";
390 adc_motioncontrol1_10_->set_adc_cmd_gear(
392 break;
393 }
394 default: {
395 adc_motioncontrol1_10_->set_adc_cmd_gear(
397 break;
398 }
399 }
400}
401
402// brake with new acceleration
403// acceleration:0.00~99.99, unit:
404// acceleration:0.0 ~ 7.0, unit:m/s^2
405// acceleration_spd:60 ~ 100, suggest: 90
406// -> pedal
407void TransitController::Brake(double pedal) {
408 // double real_value = params_.max_acc() * acceleration / 100;
409 // TODO(QiL): Update brake value based on mode
412 AINFO << "The current drive mode does not need to set acceleration.";
413 return;
414 }
415 if (button_pressed_) {
416 adc_motioncontrol1_10_->set_adc_cmd_brakepercentage(pedal);
417 } else {
418 adc_motioncontrol1_10_->set_adc_cmd_brakepercentage(0.0);
419 }
420}
421
422// drive with old acceleration
423// gas:0.00~99.99 unit:
424void TransitController::Throttle(double pedal) {
427 AINFO << "The current drive mode does not need to set acceleration.";
428 return;
429 }
430 if (button_pressed_) {
431 adc_motioncontrol1_10_->set_adc_cmd_throttleposition(pedal);
432 } else {
433 adc_motioncontrol1_10_->set_adc_cmd_throttleposition(0.0);
434 }
435}
436
437// drive with acceleration/deceleration
438// acc:-7.0 ~ 5.0, unit:m/s^2
439void TransitController::Acceleration(double acc) {
442 AINFO << "The current drive mode does not need to set acceleration.";
443 return;
444 }
445 // None
446}
447
448// transit default, -470 ~ 470, left:+, right:-
449// need to be compatible with control module, so reverse
450// steering with old angle speed
451// angle:-99.99~0.00~99.99, unit:, left:-, right:+
452void TransitController::Steer(double angle) {
455 AINFO << "The current driving mode does not need to set steer.";
456 return;
457 }
458 // TODO(All): remove -1.0 once Udelv has a complete fix.
459 const double real_angle =
460 button_pressed_
461 ? vehicle_params_.max_steer_angle() * angle / 100.0 * 180 / M_PI
462 : 0;
463 adc_motioncontrol1_10_->set_adc_cmd_steerwheelangle(real_angle);
464}
465
466// steering with new angle speed
467// angle:-99.99~0.00~99.99, unit:, left:-, right:+
468// angle_spd:0.00~99.99, unit:deg/s
469void TransitController::Steer(double angle, double angle_spd) {
472 AINFO << "The current driving mode does not need to set steer.";
473 return;
474 }
475
476 // TODO(All): remove -1.0 once Udelv has a complete fix.
477 const double real_angle =
478 button_pressed_
479 ? vehicle_params_.max_steer_angle() * angle / 100.0 * 180 / M_PI
480 : 0;
481
482 adc_motioncontrol1_10_->set_adc_cmd_steerwheelangle(real_angle);
483 // TODO(QiL) : re-enable the angle_spd ajustment
484}
485
486void TransitController::SetEpbBreak(const ControlCommand& command) {
487 if (command.parking_brake()) {
488 adc_motioncontrol1_10_->set_adc_cmd_parkingbrake(true);
489 } else {
490 adc_motioncontrol1_10_->set_adc_cmd_parkingbrake(false);
491 }
492}
493
494ErrorCode TransitController::HandleCustomOperation(
495 const external_command::ChassisCommand& command) {
496 return ErrorCode::OK;
497}
498
499void TransitController::SetBeam(const VehicleSignal& vehicle_signal) {
500 if (vehicle_signal.has_high_beam() && vehicle_signal.high_beam()) {
501 adc_auxiliarycontrol_110_->set_adc_cmd_highbeam(true);
502 } else if (vehicle_signal.has_low_beam() && vehicle_signal.low_beam()) {
503 adc_auxiliarycontrol_110_->set_adc_cmd_lowbeam(true);
504 } else {
505 adc_auxiliarycontrol_110_->set_adc_cmd_highbeam(false);
506 adc_auxiliarycontrol_110_->set_adc_cmd_lowbeam(false);
507 }
508}
509
510void TransitController::SetHorn(const VehicleSignal& vehicle_signal) {
511 if (vehicle_signal.horn()) {
512 adc_auxiliarycontrol_110_->set_adc_cmd_horn(true);
513 } else {
514 adc_auxiliarycontrol_110_->set_adc_cmd_horn(false);
515 }
516}
517
518void TransitController::SetTurningSignal(const VehicleSignal& vehicle_signal) {
519 // Set Turn Signal
520 auto signal = vehicle_signal.turn_signal();
521 if (signal == common::VehicleSignal::TURN_LEFT) {
522 adc_auxiliarycontrol_110_->set_adc_cmd_turnsignal(
524 } else if (signal == common::VehicleSignal::TURN_RIGHT) {
525 adc_auxiliarycontrol_110_->set_adc_cmd_turnsignal(
527 } else {
528 adc_auxiliarycontrol_110_->set_adc_cmd_turnsignal(
530 }
531}
532
533void TransitController::ResetProtocol() {
534 message_manager_->ResetSendMessages();
535}
536
537bool TransitController::CheckChassisError() {
538 // TODO(QiL): re-design later
539 return true;
540}
541
542void TransitController::SecurityDogThreadFunc() {
543 int32_t vertical_ctrl_fail = 0;
544 int32_t horizontal_ctrl_fail = 0;
545
546 if (can_sender_ == nullptr) {
547 AERROR << "Failed to run SecurityDogThreadFunc() because can_sender_ is "
548 "nullptr.";
549 return;
550 }
551 while (!can_sender_->IsRunning()) {
552 std::this_thread::yield();
553 }
554
555 std::chrono::duration<double, std::micro> default_period{50000};
556 int64_t start = 0;
557 int64_t end = 0;
558 while (can_sender_->IsRunning()) {
560 const Chassis::DrivingMode mode = driving_mode();
561 bool emergency_mode = false;
562
563 // 1. horizontal control check
564 if ((mode == Chassis::COMPLETE_AUTO_DRIVE ||
565 mode == Chassis::AUTO_STEER_ONLY) &&
566 !CheckResponse()) {
567 ++horizontal_ctrl_fail;
568 if (horizontal_ctrl_fail >= kMaxFailAttempt) {
569 emergency_mode = true;
570 set_chassis_error_code(Chassis::MANUAL_INTERVENTION);
571 }
572 } else {
573 horizontal_ctrl_fail = 0;
574 }
575
576 // 2. vertical control check
577 if ((mode == Chassis::COMPLETE_AUTO_DRIVE ||
578 mode == Chassis::AUTO_SPEED_ONLY) &&
579 !CheckResponse()) {
580 ++vertical_ctrl_fail;
581 if (vertical_ctrl_fail >= kMaxFailAttempt) {
582 emergency_mode = true;
583 set_chassis_error_code(Chassis::MANUAL_INTERVENTION);
584 }
585 } else {
586 vertical_ctrl_fail = 0;
587 }
588
589 if (emergency_mode && mode != Chassis::EMERGENCY_MODE) {
591 message_manager_->ResetSendMessages();
592 }
594 std::chrono::duration<double, std::micro> elapsed{end - start};
595 if (elapsed < default_period) {
596 std::this_thread::sleep_for(default_period - elapsed);
597 } else {
598 AERROR
599 << "Too much time consumption in TransitController looping process:"
600 << elapsed.count();
601 }
602 }
603}
604
605bool TransitController::CheckResponse() {
606 // TODO(Udelv): Add separate indicators
607 Transit chassis_detail;
608 if (message_manager_->GetSensorData(&chassis_detail) != ErrorCode::OK) {
609 AERROR_EVERY(100) << "get chassis detail failed.";
610 return false;
611 }
612
613 auto& motion1_20 = chassis_detail.llc_motionfeedback1_20();
614
615 return (motion1_20.llc_fbk_state() ==
617 motion1_20.llc_fbk_state() ==
619 motion1_20.llc_fbk_state() ==
621 motion1_20.llc_fbk_state() ==
623}
624
625void TransitController::set_chassis_error_mask(const int32_t mask) {
626 std::lock_guard<std::mutex> lock(chassis_mask_mutex_);
627 chassis_error_mask_ = mask;
628}
629
630int32_t TransitController::chassis_error_mask() {
631 std::lock_guard<std::mutex> lock(chassis_mask_mutex_);
632 return chassis_error_mask_;
633}
634
635Chassis::ErrorCode TransitController::chassis_error_code() {
636 std::lock_guard<std::mutex> lock(chassis_error_code_mutex_);
637 return chassis_error_code_;
638}
639
640void TransitController::set_chassis_error_code(
641 const Chassis::ErrorCode& error_code) {
642 std::lock_guard<std::mutex> lock(chassis_error_code_mutex_);
643 chassis_error_code_ = error_code;
644}
645
646bool TransitController::CheckSafetyError(
647 const ::apollo::canbus::Transit& chassis_detail) {
648 return true;
649}
650
651void TransitController::SetLimits() {
652 adc_motioncontrollimits1_12_->set_adc_cmd_throttlecommandlimit(100);
653 adc_motioncontrollimits1_12_->set_adc_cmd_steerwheelanglelimit(1275);
654 adc_motioncontrollimits1_12_->set_adc_cmd_steeringrate(500);
655}
656
657} // namespace transit
658} // namespace canbus
659} // namespace apollo
Defines SenderMessage class and CanSender class.
virtual void set_driving_mode(const Chassis::DrivingMode &driving_mode)
MessageManager< ::apollo::canbus::Transit > * message_manager_
Adcauxiliarycontrol110 * set_adc_cmd_horn(bool adc_cmd_horn)
Adcauxiliarycontrol110 * set_adc_cmd_turnsignal(Adc_auxiliarycontrol_110::Adc_cmd_turnsignalType adc_cmd_turnsignal)
Adcauxiliarycontrol110 * set_adc_cmd_lowbeam(bool adc_cmd_lowbeam)
Adcauxiliarycontrol110 * set_adc_cmd_highbeam(bool adc_cmd_highbeam)
Adcmotioncontrol110 * set_adc_cmd_gear(Adc_motioncontrol1_10::Adc_cmd_gearType adc_cmd_gear)
Adcmotioncontrol110 * set_adc_cmd_brakepercentage(double adc_cmd_brakepercentage)
Adcmotioncontrol110 * set_adc_cmd_throttleposition(double adc_cmd_throttleposition)
Adcmotioncontrol110 * set_adc_cmd_parkingbrake(bool adc_cmd_parkingbrake)
Adcmotioncontrol110 * set_adc_cmd_longitudinalcontrolmode(Adc_motioncontrol1_10::Adc_cmd_longitudinalcontrolmodeType adc_cmd_longitudinalcontrolmode)
Adcmotioncontrol110 * set_adc_cmd_autonomyrequest(Adc_motioncontrol1_10::Adc_cmd_autonomyrequestType adc_cmd_autonomyrequest)
Adcmotioncontrol110 * set_adc_cmd_steerwheelangle(double adc_cmd_steerwheelangle)
Adcmotioncontrol110 * set_adc_cmd_steeringcontrolmode(Adc_motioncontrol1_10::Adc_cmd_steeringcontrolmodeType adc_cmd_steeringcontrolmode)
Adcmotioncontrollimits112 * set_adc_cmd_steeringrate(double adc_cmd_steeringrate)
Adcmotioncontrollimits112 * set_adc_cmd_throttlecommandlimit(double adc_cmd_throttlecommandlimit)
Adcmotioncontrollimits112 * set_adc_cmd_steerwheelanglelimit(double adc_cmd_steerwheelanglelimit)
Chassis chassis() override
calculate and return the chassis.
bool Start() override
start the vehicle controller.
::apollo::common::ErrorCode Init(const VehicleParameter &params, CanSender<::apollo::canbus::Transit > *const can_sender, MessageManager<::apollo::canbus::Transit > *const message_manager) override
void Stop() override
stop the vehicle controller.
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 AERROR_EVERY(freq)
Definition log.h:86
#define AINFO
Definition log.h:42
class register implement
Definition arena_queue.h:37
The class of ProtocolData
optional Llc_fbk_stateType llc_fbk_state
optional Llc_motionfeedback1_20 llc_motionfeedback1_20
optional Llc_motionfeedback2_21 llc_motionfeedback2_21
optional Llc_auxiliaryfeedback_120 llc_auxiliaryfeedback_120
The class of VehicleController