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) <<
"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_);
281 ADEBUG <<
"status_compute is " << status_compute;
283 if (!status_compute.ok()) {
284 AERROR <<
"Control main function failed" <<
" with localization: "
286 <<
" with chassis: " << local_view_.
chassis().ShortDebugString()
287 <<
" with trajectory: "
288 << local_view_.
trajectory().ShortDebugString()
289 <<
" with cmd: " << control_command->ShortDebugString()
290 <<
" status:" << status_compute.error_message();
292 estop_reason_ = status_compute.error_message();
293 status = status_compute;
299 AWARN_EVERY(100) <<
"Estop triggered! No control core method executed!";
301 control_command->set_speed(0);
302 control_command->set_throttle(0);
303 control_command->set_brake(FLAGS_soft_estop_brake);
305 previous_steering_command_ =
306 injector_->previous_control_command_mutable()->steering_target();
307 control_command->set_steering_target(previous_steering_command_);
311 control_command->mutable_signal()->CopyFrom(
320 injector_->control_debug_info_clear();
322 chassis_reader_->Observe();
323 const auto &chassis_msg = chassis_reader_->GetLatestObserved();
324 if (chassis_msg ==
nullptr) {
325 AERROR <<
"Chassis msg is not ready!";
326 injector_->set_control_process(
false);
329 OnChassis(chassis_msg);
331 trajectory_reader_->Observe();
332 const auto &trajectory_msg = trajectory_reader_->GetLatestObserved();
333 if (trajectory_msg ==
nullptr) {
334 AERROR <<
"planning msg is not ready!";
338 trajectory_msg->header().sequence_num()) {
339 OnPlanning(trajectory_msg);
343 planning_command_status_reader_->Observe();
344 const auto &planning_status_msg =
345 planning_command_status_reader_->GetLatestObserved();
346 if (planning_status_msg !=
nullptr) {
347 OnPlanningCommandStatus(planning_status_msg);
348 ADEBUG <<
"Planning command status msg is \n"
349 << planning_command_status_.ShortDebugString();
351 injector_->set_planning_command_status(planning_command_status_);
353 localization_reader_->Observe();
354 const auto &localization_msg = localization_reader_->GetLatestObserved();
355 if (localization_msg ==
nullptr) {
356 AERROR <<
"localization msg is not ready!";
357 injector_->set_control_process(
false);
360 OnLocalization(localization_msg);
362 pad_msg_reader_->Observe();
363 const auto &pad_msg = pad_msg_reader_->GetLatestObserved();
364 if (pad_msg !=
nullptr) {
370 std::lock_guard<std::mutex> lock(mutex_);
371 local_view_.mutable_chassis()->CopyFrom(latest_chassis_);
372 local_view_.mutable_trajectory()->CopyFrom(latest_trajectory_);
373 local_view_.mutable_localization()->CopyFrom(latest_localization_);
374 if (pad_msg !=
nullptr) {
375 local_view_.mutable_pad_msg()->CopyFrom(pad_msg_);
380 if (FLAGS_use_control_submodules) {
381 local_view_.mutable_header()->set_lidar_timestamp(
383 local_view_.mutable_header()->set_camera_timestamp(
385 local_view_.mutable_header()->set_radar_timestamp(
387 common::util::FillHeader(FLAGS_control_local_view_topic, &local_view_);
393 FLAGS_control_local_view_topic);
398 local_view_writer_->Write(local_view_);
402 if (pad_msg !=
nullptr) {
403 ADEBUG <<
"pad_msg: " << pad_msg_.ShortDebugString();
404 ADEBUG <<
"pad_msg is not nullptr";
406 AINFO <<
"Control received RESET action!";
408 estop_reason_.clear();
410 pad_received_ =
true;
413 if (FLAGS_is_control_test_mode && FLAGS_control_test_duration > 0 &&
414 (start_time - init_time_).ToSecond() > FLAGS_control_test_duration) {
415 AERROR <<
"Control finished testing. exit";
416 injector_->set_control_process(
false);
420 injector_->set_control_process(
true);
422 injector_->mutable_control_debug_info()
423 ->mutable_control_component_debug()
425 CheckAutoMode(&local_view_.
chassis());
432 status = ProduceControlCommand(&control_command);
433 ADEBUG <<
"Produce control command normal.";
435 ADEBUG <<
"Into reset control command.";
436 ResetAndProduceZeroControlCommand(&control_command);
439 AERROR_IF(!status.
ok()) <<
"Failed to produce control command:"
443 control_command.mutable_pad_msg()->CopyFrom(pad_msg_);
444 pad_received_ =
false;
449 control_command.mutable_header()->mutable_status()->set_msg(estop_reason_);
453 control_command.mutable_header()->set_lidar_timestamp(
455 control_command.mutable_header()->set_camera_timestamp(
457 control_command.mutable_header()->set_radar_timestamp(
460 if (FLAGS_is_control_test_mode) {
461 ADEBUG <<
"Skip publish control command in test mode";
467 injector_->vehicle_state()->Update(local_view_.
localization(),
469 GetVehiclePitchAngle(&control_command);
473 const double time_diff_ms = (end_time - start_time).ToSecond() * 1e3;
474 ADEBUG <<
"total control time spend: " << time_diff_ms <<
" ms.";
476 control_command.mutable_latency_stats()->set_total_time_ms(time_diff_ms);
477 control_command.mutable_latency_stats()->set_total_time_exceeded(
478 time_diff_ms > FLAGS_control_period * 1e3);
479 if (control_command.mutable_latency_stats()->total_time_exceeded()) {
480 AINFO <<
"total control cycle time is exceeded: " << time_diff_ms <<
" ms.";
482 status.
Save(control_command.mutable_header()->mutable_status());
487 FLAGS_control_command_topic);
493 common::util::FillHeader(
node_->Name(), &control_command);
494 ADEBUG << control_command.ShortDebugString();
495 control_cmd_writer_->Write(control_command);
498 injector_->Set_pervious_control_command(&control_command);
499 injector_->previous_control_command_mutable()->CopyFrom(control_command);
501 injector_->previous_control_debug_mutable()->CopyFrom(
502 injector_->control_debug_info());
504 PublishControlInteractiveMsg();
505 const auto end_process_control_time =
Clock::Now();
506 const double process_control_time_diff =
507 (end_process_control_time - start_time).ToSecond() * 1e3;
508 if (control_command.mutable_latency_stats()->total_time_exceeded()) {
509 AINFO <<
"control all spend time is: " << process_control_time_diff
517 ADEBUG <<
"Received localization:"
518 <<
local_view->localization().ShortDebugString();
521 if (!
local_view->trajectory().estop().is_estop() &&
522 local_view->trajectory().trajectory_point().empty()) {
523 AWARN_EVERY(100) <<
"planning has no trajectory point. ";
524 const std::string msg =
525 absl::StrCat(
"planning has no trajectory point. planning_seq_num:",
526 local_view->trajectory().header().sequence_num());
527 return Status(ErrorCode::CONTROL_COMPUTE_ERROR, msg);
530 for (
auto &trajectory_point :
531 *
local_view->mutable_trajectory()->mutable_trajectory_point()) {
532 if (std::abs(trajectory_point.v()) < FLAGS_minimum_speed_resolution &&
533 std::abs(trajectory_point.a()) < FLAGS_max_acceleration_when_stopped) {
534 trajectory_point.set_v(0.0);
535 trajectory_point.set_a(0.0);
539 injector_->vehicle_state()->Update(
local_view->localization(),
546 if (!FLAGS_enable_input_timestamp_check || FLAGS_is_control_test_mode) {
547 ADEBUG <<
"Skip input timestamp check by gflags.";
551 double localization_diff =
552 current_timestamp -
local_view.localization().header().timestamp_sec();
553 if (localization_diff >
554 (FLAGS_max_localization_miss_num * FLAGS_localization_period)) {
555 AERROR <<
"Localization msg lost for " << std::setprecision(6)
556 << localization_diff <<
"s";
557 monitor_logger_buffer_.ERROR(
"Localization msg lost");
558 return Status(ErrorCode::CONTROL_COMPUTE_ERROR,
"Localization msg timeout");
561 double chassis_diff =
562 current_timestamp -
local_view.chassis().header().timestamp_sec();
563 if (chassis_diff > (FLAGS_max_chassis_miss_num * FLAGS_chassis_period)) {
564 AERROR <<
"Chassis msg lost for " << std::setprecision(6) << chassis_diff
566 monitor_logger_buffer_.ERROR(
"Chassis msg lost");
567 return Status(ErrorCode::CONTROL_COMPUTE_ERROR,
"Chassis msg timeout");
570 double trajectory_diff =
571 current_timestamp -
local_view.trajectory().header().timestamp_sec();
572 if (trajectory_diff >
573 (FLAGS_max_planning_miss_num * FLAGS_trajectory_period)) {
574 AERROR <<
"Trajectory msg lost for " << std::setprecision(6)
575 << trajectory_diff <<
"s";
576 monitor_logger_buffer_.ERROR(
"Trajectory msg lost");
577 return Status(ErrorCode::CONTROL_COMPUTE_ERROR,
"Trajectory msg timeout");
582void ControlComponent::ResetAndProduceZeroControlCommand(
583 ControlCommand *control_command) {
584 control_command->set_throttle(0.0);
585 control_command->set_steering_target(0.0);
586 control_command->set_steering_rate(0.0);
587 control_command->set_speed(0.0);
588 control_command->set_brake(0.0);
590 control_task_agent_.
Reset();
591 latest_trajectory_.mutable_trajectory_point()->Clear();
592 latest_trajectory_.mutable_path_point()->Clear();
593 trajectory_reader_->ClearData();
596void ControlComponent::GetVehiclePitchAngle(ControlCommand *control_command) {
597 double vehicle_pitch = injector_->vehicle_state()->pitch() * 180 / M_PI;
598 control_command->mutable_debug()
599 ->mutable_simple_lon_debug()
600 ->set_vehicle_pitch(vehicle_pitch + FLAGS_pitch_offset_deg);
603void ControlComponent::CheckAutoMode(
const canbus::Chassis *chassis) {
604 if (!injector_->previous_control_debug_mutable()
605 ->mutable_control_component_debug()
608 from_else_to_auto_ =
true;
609 AINFO <<
"From else to auto!!!";
611 from_else_to_auto_ =
false;
613 ADEBUG <<
"from_else_to_auto_: " << from_else_to_auto_;
614 injector_->mutable_control_debug_info()
615 ->mutable_control_component_debug()
616 ->set_from_else_to_auto(from_else_to_auto_);
623 injector_->mutable_control_debug_info()
624 ->mutable_control_component_debug()
625 ->set_is_auto(is_auto_);
628void ControlComponent::PublishControlInteractiveMsg() {
629 auto control_interactive_msg = injector_->control_interactive_info();
630 common::util::FillHeader(
node_->Name(), &control_interactive_msg);
631 ADEBUG <<
"control interactive msg is: "
632 << control_interactive_msg.ShortDebugString();
633 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 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