17#include "absl/strings/str_cat.h"
41 : monitor_logger_buffer_(common::monitor::MonitorMessageItem::CONTROL) {}
44 injector_ = std::make_shared<DependencyInjector>();
47 AINFO <<
"Control init, starting ...";
51 <<
"Unable to load control pipeline file: " + FLAGS_pipeline_file;
53 AINFO <<
"ControlTask pipeline config file: " << FLAGS_pipeline_file
57 ADEBUG <<
"FLAGS_use_control_submodules: " << FLAGS_use_control_submodules;
58 if (!FLAGS_is_control_ut_test_mode) {
59 if (!FLAGS_use_control_submodules &&
60 !control_task_agent_.
Init(injector_, control_pipeline_).
ok()) {
62 ADEBUG <<
"original control";
63 monitor_logger_buffer_.ERROR(
64 "Control init controller failed! Stopping...");
70 chassis_reader_config.
channel_name = FLAGS_chassis_topic;
74 node_->CreateReader<
Chassis>(chassis_reader_config,
nullptr);
75 ACHECK(chassis_reader_ !=
nullptr);
78 planning_reader_config.
channel_name = FLAGS_planning_trajectory_topic;
83 ACHECK(trajectory_reader_ !=
nullptr);
87 FLAGS_planning_command_status;
89 FLAGS_planning_status_msg_pending_queue_size;
90 planning_command_status_reader_ =
92 planning_command_status_reader_config,
nullptr);
93 ACHECK(planning_command_status_reader_ !=
nullptr);
96 localization_reader_config.
channel_name = FLAGS_localization_topic;
98 FLAGS_localization_pending_queue_size;
101 localization_reader_config,
nullptr);
102 ACHECK(localization_reader_ !=
nullptr);
110 ACHECK(pad_msg_reader_ !=
nullptr);
112 if (!FLAGS_use_control_submodules) {
113 control_cmd_writer_ =
115 ACHECK(control_cmd_writer_ !=
nullptr);
119 ACHECK(local_view_writer_ !=
nullptr);
122 FLAGS_control_interative_topic);
123 ACHECK(control_interactive_writer_ !=
nullptr);
128 AINFO <<
"Control resetting vehicle state, sleeping for 1000 ms ...";
129 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
134 AINFO <<
"Control default driving action is "
141void ControlComponent::OnPad(
const std::shared_ptr<PadMessage> &pad) {
142 std::lock_guard<std::mutex> lock(mutex_);
143 pad_msg_.CopyFrom(*pad);
144 ADEBUG <<
"Received Pad Msg:" << pad_msg_.DebugString();
145 AERROR_IF(!pad_msg_.has_action()) <<
"pad message check failed!";
148void ControlComponent::OnChassis(
const std::shared_ptr<Chassis> &chassis) {
149 ADEBUG <<
"Received chassis data: run chassis callback.";
150 std::lock_guard<std::mutex> lock(mutex_);
151 latest_chassis_.CopyFrom(*chassis);
154void ControlComponent::OnPlanning(
155 const std::shared_ptr<ADCTrajectory> &trajectory) {
156 ADEBUG <<
"Received chassis data: run trajectory callback.";
157 std::lock_guard<std::mutex> lock(mutex_);
158 latest_trajectory_.CopyFrom(*trajectory);
161void ControlComponent::OnPlanningCommandStatus(
162 const std::shared_ptr<external_command::CommandStatus>
163 &planning_command_status) {
164 ADEBUG <<
"Received plannning command status data: run planning command "
166 std::lock_guard<std::mutex> lock(mutex_);
167 planning_command_status_.CopyFrom(*planning_command_status);
170void ControlComponent::OnLocalization(
171 const std::shared_ptr<LocalizationEstimate> &localization) {
172 ADEBUG <<
"Received control data: run localization message callback.";
173 std::lock_guard<std::mutex> lock(mutex_);
174 latest_localization_.CopyFrom(*localization);
177void ControlComponent::OnMonitor(
178 const common::monitor::MonitorMessage &monitor_message) {
179 for (
const auto &item : monitor_message.item()) {
187Status ControlComponent::ProduceControlCommand(
188 ControlCommand *control_command) {
189 Status status = CheckInput(&local_view_);
193 << status.error_message();
194 control_command->mutable_engage_advice()->set_advice(
196 control_command->mutable_engage_advice()->set_reason(
197 status.error_message());
199 estop_reason_ = status.error_message();
202 Status status_ts = CheckTimestamp(local_view_);
203 if (!status_ts.ok()) {
204 AERROR <<
"Input messages timeout";
213 control_command->mutable_engage_advice()->set_advice(
215 control_command->mutable_engage_advice()->set_reason(
216 status.error_message());
219 control_command->mutable_engage_advice()->set_advice(
226 estop_ = FLAGS_enable_persistent_estop
232 estop_reason_ =
"estop from planning : ";
237 AWARN_EVERY(100) <<
"planning has no trajectory point. ";
239 estop_reason_ =
"estop for empty planning trajectory, planning headers: " +
243 if (FLAGS_enable_gear_drive_negative_speed_protection) {
244 const double kEpsilon = 0.001;
247 first_trajectory_point.v() < -1 * kEpsilon) {
249 estop_reason_ =
"estop for negative speed when gear_drive";
255 control_task_agent_.
Reset();
256 AINFO_EVERY(100) <<
"No estop. Reset Controllers in Manual Mode";
259 auto debug = control_command->mutable_debug()->mutable_input_debug();
260 debug->mutable_localization_header()->CopyFrom(
262 debug->mutable_canbus_header()->CopyFrom(local_view_.
chassis().
header());
263 debug->mutable_trajectory_header()->CopyFrom(
270 if (latest_replan_trajectory_header_.has_sequence_num()) {
271 debug->mutable_latest_replan_trajectory_header()->CopyFrom(
272 latest_replan_trajectory_header_);
282 ADEBUG <<
"status_compute is " << status_compute;
284 if (!status_compute.ok()) {
285 AERROR <<
"Control main function failed" <<
" with localization: "
287 <<
" with chassis: " << local_view_.
chassis().ShortDebugString()
288 <<
" with trajectory: "
289 << local_view_.
trajectory().ShortDebugString()
290 <<
" with cmd: " << control_command->ShortDebugString()
291 <<
" status:" << status_compute.error_message();
293 estop_reason_ = status_compute.error_message();
294 status = status_compute;
298 control_task_agent_.
Reset();
299 AINFO_EVERY(10) <<
"Estop trigger, Reset Controllers in Auto Mode";
304 AWARN_EVERY(100) <<
"Estop triggered! No control core method executed!";
306 control_command->set_speed(0.0);
307 control_command->set_throttle(0.0);
308 control_command->set_brake(FLAGS_soft_estop_brake);
309 control_command->set_acceleration(FLAGS_soft_estop_acceleration);
310 control_command->set_gear_location(latest_chassis_.
gear_location());
311 control_command->set_parking_brake(latest_chassis_.
parking_brake());
312 previous_steering_command_ =
313 injector_->previous_control_command_mutable()->steering_target();
314 control_command->set_steering_target(previous_steering_command_);
318 control_command->mutable_signal()->CopyFrom(
325 AINFO <<
"control proc start.";
328 injector_->control_debug_info_clear();
330 chassis_reader_->Observe();
331 const auto &chassis_msg = chassis_reader_->GetLatestObserved();
332 if (chassis_msg ==
nullptr) {
333 AERROR <<
"Chassis msg is not ready!";
334 injector_->set_control_process(
false);
337 OnChassis(chassis_msg);
339 trajectory_reader_->Observe();
340 const auto &trajectory_msg = trajectory_reader_->GetLatestObserved();
341 if (trajectory_msg ==
nullptr) {
342 AERROR <<
"planning msg is not ready!";
346 trajectory_msg->header().sequence_num()) {
347 OnPlanning(trajectory_msg);
351 planning_command_status_reader_->Observe();
352 const auto &planning_status_msg =
353 planning_command_status_reader_->GetLatestObserved();
354 if (planning_status_msg !=
nullptr) {
355 OnPlanningCommandStatus(planning_status_msg);
356 ADEBUG <<
"Planning command status msg is \n"
357 << planning_command_status_.ShortDebugString();
359 injector_->set_planning_command_status(planning_command_status_);
361 localization_reader_->Observe();
362 const auto &localization_msg = localization_reader_->GetLatestObserved();
363 if (localization_msg ==
nullptr) {
364 AERROR <<
"localization msg is not ready!";
365 injector_->set_control_process(
false);
368 OnLocalization(localization_msg);
370 pad_msg_reader_->Observe();
371 const auto &pad_msg = pad_msg_reader_->GetLatestObserved();
372 if (pad_msg !=
nullptr) {
378 std::lock_guard<std::mutex> lock(mutex_);
379 local_view_.mutable_chassis()->CopyFrom(latest_chassis_);
380 local_view_.mutable_trajectory()->CopyFrom(latest_trajectory_);
381 local_view_.mutable_localization()->CopyFrom(latest_localization_);
382 if (pad_msg !=
nullptr) {
383 local_view_.mutable_pad_msg()->CopyFrom(pad_msg_);
388 if (FLAGS_use_control_submodules) {
389 local_view_.mutable_header()->set_lidar_timestamp(
391 local_view_.mutable_header()->set_camera_timestamp(
393 local_view_.mutable_header()->set_radar_timestamp(
395 common::util::FillHeader(FLAGS_control_local_view_topic, &local_view_);
401 FLAGS_control_local_view_topic);
406 local_view_writer_->Write(local_view_);
410 if (pad_msg !=
nullptr) {
411 ADEBUG <<
"pad_msg: " << pad_msg_.ShortDebugString();
412 ADEBUG <<
"pad_msg is not nullptr";
414 AINFO <<
"Control received RESET action!";
416 estop_reason_.clear();
418 pad_received_ =
true;
421 if (FLAGS_is_control_test_mode && FLAGS_control_test_duration > 0 &&
422 (start_time - init_time_).ToSecond() > FLAGS_control_test_duration) {
423 AERROR <<
"Control finished testing. exit";
424 injector_->set_control_process(
false);
428 injector_->set_control_process(
true);
430 injector_->mutable_control_debug_info()
431 ->mutable_control_component_debug()
433 CheckAutoMode(&local_view_.
chassis());
440 status = ProduceControlCommand(&control_command);
441 ADEBUG <<
"Produce control command normal.";
443 ADEBUG <<
"Into reset control command.";
444 ResetAndProduceZeroControlCommand(&latest_chassis_, &control_command);
447 AERROR_IF(!status.
ok()) <<
"Failed to produce control command:"
451 control_command.mutable_pad_msg()->CopyFrom(pad_msg_);
452 pad_received_ =
false;
457 control_command.mutable_header()->mutable_status()->set_msg(estop_reason_);
461 control_command.mutable_header()->set_lidar_timestamp(
463 control_command.mutable_header()->set_camera_timestamp(
465 control_command.mutable_header()->set_radar_timestamp(
468 if (FLAGS_is_control_test_mode) {
469 ADEBUG <<
"Skip publish control command in test mode";
475 injector_->vehicle_state()->Update(local_view_.
localization(),
477 GetVehiclePitchAngle(&control_command);
481 const double time_diff_ms = (end_time - start_time).ToSecond() * 1e3;
482 ADEBUG <<
"total control time spend: " << time_diff_ms <<
" ms.";
484 control_command.mutable_latency_stats()->set_total_time_ms(time_diff_ms);
485 control_command.mutable_latency_stats()->set_total_time_exceeded(
486 time_diff_ms > FLAGS_control_period * 1e3);
487 if (control_command.mutable_latency_stats()->total_time_exceeded()) {
488 AINFO <<
"total control cycle time is exceeded: " << time_diff_ms <<
" ms.";
490 status.
Save(control_command.mutable_header()->mutable_status());
495 FLAGS_control_command_topic);
501 common::util::FillHeader(
node_->Name(), &control_command);
502 if (FLAGS_sim_by_record) {
503 control_command.mutable_header()->set_timestamp_sec(
506 ADEBUG << control_command.ShortDebugString();
508 control_cmd_writer_->Write(control_command);
511 injector_->Set_pervious_control_command(&control_command);
512 injector_->previous_control_command_mutable()->CopyFrom(control_command);
514 injector_->previous_control_debug_mutable()->CopyFrom(
515 injector_->control_debug_info());
517 PublishControlInteractiveMsg();
518 const auto end_process_control_time =
Clock::Now();
519 const double process_control_time_diff =
520 (end_process_control_time - start_time).ToSecond() * 1e3;
521 if (control_command.mutable_latency_stats()->total_time_exceeded()) {
522 AINFO <<
"control all spend time is exceeded.";
524 AINFO <<
"control proc finished, total time spend: "
525 << process_control_time_diff <<
" ms.";
530 ADEBUG <<
"Received localization:"
531 <<
local_view->localization().ShortDebugString();
534 if (!
local_view->trajectory().estop().is_estop() &&
535 local_view->trajectory().trajectory_point().empty()) {
536 AWARN_EVERY(100) <<
"planning has no trajectory point. ";
537 const std::string msg =
538 absl::StrCat(
"planning has no trajectory point. planning_seq_num:",
539 local_view->trajectory().header().sequence_num());
540 return Status(ErrorCode::CONTROL_COMPUTE_ERROR, msg);
543 for (
auto &trajectory_point :
544 *
local_view->mutable_trajectory()->mutable_trajectory_point()) {
545 if (std::abs(trajectory_point.v()) < FLAGS_minimum_speed_resolution &&
546 std::abs(trajectory_point.a()) < FLAGS_max_acceleration_when_stopped) {
547 trajectory_point.set_v(0.0);
548 trajectory_point.set_a(0.0);
552 injector_->vehicle_state()->Update(
local_view->localization(),
559 if (!FLAGS_enable_input_timestamp_check || FLAGS_is_control_test_mode) {
560 ADEBUG <<
"Skip input timestamp check by gflags.";
563 std::string err_msg =
"";
564 double current_timestamp = FLAGS_sim_by_record
567 double localization_diff =
568 current_timestamp -
local_view.localization().header().timestamp_sec();
569 bool localization_consist_timeout =
false;
570 if (localization_diff >
571 (FLAGS_max_localization_miss_num * FLAGS_localization_period)) {
572 localization_consist_timeout =
true;
573 localization_timeout_count_++;
574 AERROR <<
"Localization msg lost for " << std::to_string(localization_diff)
576 AERROR <<
"current_timestamp: " << std::to_string(current_timestamp)
577 <<
", localization_timestamp: "
579 local_view.localization().header().timestamp_sec());
580 err_msg = err_msg +
" Localization msg timeout. ";
582 localization_consist_timeout =
false;
583 localization_timeout_count_ = 0;
585 if (localization_consist_timeout &&
586 (localization_timeout_count_ >= FLAGS_max_localization_miss_num)) {
587 localization_timeout_count_ = FLAGS_max_localization_miss_num;
588 AERROR <<
"write the monitor logger, localization msg lost "
589 << localization_timeout_count_ <<
" times.";
590 monitor_logger_buffer_.ERROR(
"Localization msg lost");
593 double chassis_diff =
594 current_timestamp -
local_view.chassis().header().timestamp_sec();
595 bool chassis_consist_timeout =
false;
596 if (chassis_diff > (FLAGS_max_chassis_miss_num * FLAGS_chassis_period)) {
597 chassis_consist_timeout =
true;
598 chassis_timeout_count_++;
599 AERROR <<
"Chassis msg lost for " << std::to_string(chassis_diff) <<
"s";
600 AERROR <<
"current_timestamp: " << std::to_string(current_timestamp)
601 <<
", chassis_timestamp: "
602 << std::to_string(
local_view.chassis().header().timestamp_sec());
603 err_msg = err_msg +
" Chassis msg timeout. ";
605 chassis_consist_timeout =
false;
606 chassis_timeout_count_ = 0;
608 if (chassis_consist_timeout &&
609 (chassis_timeout_count_ >= FLAGS_max_chassis_miss_num)) {
610 chassis_timeout_count_ = FLAGS_max_chassis_miss_num;
611 AERROR <<
"write the monitor logger, chassis msg lost "
612 << chassis_timeout_count_ <<
" times.";
613 monitor_logger_buffer_.ERROR(
"Chassis msg lost");
616 double trajectory_diff =
617 current_timestamp -
local_view.trajectory().header().timestamp_sec();
618 bool trajectory_consist_timeout =
false;
619 if (trajectory_diff >
620 (FLAGS_max_planning_miss_num * FLAGS_trajectory_period)) {
621 trajectory_consist_timeout =
true;
622 trajectory_timeout_count_++;
623 AERROR <<
"Trajectory msg lost for " << std::to_string(trajectory_diff)
625 AERROR <<
"current_timestamp: " << std::to_string(current_timestamp)
626 <<
", trajectory_timestamp: "
627 << std::to_string(
local_view.trajectory().header().timestamp_sec());
628 err_msg = err_msg +
" Trajectory msg lost. ";
630 trajectory_consist_timeout =
false;
631 trajectory_timeout_count_ = 0;
633 if (trajectory_consist_timeout &&
634 (trajectory_timeout_count_ >= FLAGS_max_localization_miss_num)) {
635 trajectory_timeout_count_ = FLAGS_max_localization_miss_num;
636 AERROR <<
"write the monitor logger, trajectory msg lost "
637 << trajectory_timeout_count_ <<
" times.";
638 monitor_logger_buffer_.ERROR(
"Trajectory msg lost");
641 if (!err_msg.empty()) {
642 return Status(ErrorCode::CONTROL_COMPUTE_ERROR, err_msg);
648void ControlComponent::ResetAndProduceZeroControlCommand(
649 const canbus::Chassis *chassis, ControlCommand *control_command) {
650 control_command->set_throttle(0.0);
651 control_command->set_steering_target(0.0);
652 control_command->set_steering_rate(0.0);
653 control_command->set_speed(0.0);
654 control_command->set_brake(0.0);
655 control_command->set_gear_location(chassis->gear_location());
656 control_command->set_parking_brake(chassis->parking_brake());
657 control_task_agent_.
Reset();
658 latest_trajectory_.mutable_trajectory_point()->Clear();
659 latest_trajectory_.mutable_path_point()->Clear();
660 trajectory_reader_->ClearData();
663void ControlComponent::GetVehiclePitchAngle(ControlCommand *control_command) {
664 double vehicle_pitch = injector_->vehicle_state()->pitch() * 180 / M_PI;
665 control_command->mutable_debug()
666 ->mutable_simple_lon_debug()
667 ->set_vehicle_pitch(vehicle_pitch + FLAGS_pitch_offset_deg);
670void ControlComponent::CheckAutoMode(
const canbus::Chassis *chassis) {
671 if (!injector_->previous_control_debug_mutable()
672 ->mutable_control_component_debug()
675 from_else_to_auto_ =
true;
676 AINFO <<
"From else to auto!!!";
678 from_else_to_auto_ =
false;
680 ADEBUG <<
"from_else_to_auto_: " << from_else_to_auto_;
681 injector_->mutable_control_debug_info()
682 ->mutable_control_component_debug()
683 ->set_from_else_to_auto(from_else_to_auto_);
690 injector_->mutable_control_debug_info()
691 ->mutable_control_component_debug()
692 ->set_is_auto(is_auto_);
695void ControlComponent::PublishControlInteractiveMsg() {
696 auto control_interactive_msg = injector_->control_interactive_info();
697 common::util::FillHeader(
node_->Name(), &control_interactive_msg);
698 ADEBUG <<
"control interactive msg is: "
699 << control_interactive_msg.ShortDebugString();
700 control_interactive_writer_->Write(control_interactive_msg);
void AppendLatencyRecord(const uint64_t message_id, const apollo::cyber::Time &begin_time, const apollo::cyber::Time &end_time)
A general class to denote the return status of an API call.
bool ok() const
check whether the return status is OK.
const std::string & error_message() const
returns the error message of the status, empty if the status is OK.
void Save(StatusPb *status_pb)
save the error_code and error message to protobuf
static Status OK()
generate a success status.
The class of vehicle state.
bool Proc() override
The Proc logic of the component, which called by the CyberRT frame.
common::Status Reset()
reset ControlTaskAgent
common::Status Init(std::shared_ptr< DependencyInjector > injector, const ControlPipeline &control_pipeline)
initialize ControlTaskAgent
common::Status ComputeControlCommand(const localization::LocalizationEstimate *localization, const canbus::Chassis *chassis, const planning::ADCTrajectory *trajectory, control::ControlCommand *cmd)
compute control command based on current vehicle status and target trajectory
a singleton clock that can be used to get the current timestamp.
static double NowInSeconds()
gets the current time in second.
static Time Now()
PRECISION >= 1000000 means the precision is at least 1us.
std::shared_ptr< Node > node_
#define AINFO_EVERY(freq)
#define AERROR_EVERY(freq)
#define AWARN_EVERY(freq)
const double kDoubleEpsilon
bool GetProtoFromFile(const std::string &file_name, google::protobuf::Message *message)
Parses the content of the file specified by the file_name as a representation of protobufs,...
optional GearPosition gear_location
optional apollo::common::Header header
optional DrivingMode driving_mode
optional bool parking_brake
optional SimpleLongitudinalDebug simple_lon_debug
optional apollo::planning::ADCTrajectory trajectory
optional apollo::canbus::Chassis chassis
optional apollo::localization::LocalizationEstimate localization
optional DrivingAction action
optional double vehicle_pitch
uint32_t pending_queue_size
configuration for responding ChannelBuffer.
optional apollo::common::Header header
repeated apollo::common::TrajectoryPoint trajectory_point
optional apollo::common::Header header
optional apollo::planning::DecisionResult decision
LocalView contains all necessary data as planning input