22#include "absl/strings/str_cat.h"
23#include "absl/strings/str_join.h"
24#include "absl/strings/str_split.h"
26#include "cyber/proto/dag_conf.pb.h"
27#include "cyber/proto/record.pb.h"
28#include "modules/dreamview/proto/scenario.pb.h"
47DEFINE_string(cyber_recorder_play_command,
"cyber_recorder play -p 1 -f ",
48 "Cyber recorder play command");
68using apollo::monitor::ComponentStatus;
69using apollo::monitor::SystemStatus;
70using RLock = boost::shared_lock<boost::shared_mutex>;
71using WLock = boost::unique_lock<boost::shared_mutex>;
72using Json = nlohmann::json;
74constexpr char kNavigationModeName[] =
"Navigation";
77const std::vector<HMIModeOperation> OperationBasedOnSimControl = {
78 HMIModeOperation::Scenario_Sim,
79 HMIModeOperation::Sim_Control,
82template <
class FlagType,
class ValueType>
83void SetGlobalFlag(std::string_view flag_name,
const ValueType &value,
85 constexpr char kGlobalFlagfile[] =
86 "/apollo/modules/common/data/global_flagfile.txt";
90 std::ofstream fout(kGlobalFlagfile, std::ios_base::app);
91 ACHECK(fout) <<
"Fail to open global flagfile " << kGlobalFlagfile;
92 fout <<
"\n--" << flag_name <<
"=" << value << std::endl;
96void System(std::string_view cmd) {
97 const int ret = std::system(cmd.data());
99 AINFO <<
"SUCCESS: " << cmd;
101 AERROR <<
"FAILED(" << ret <<
"): " << cmd;
108 const std::shared_ptr<Node> &node,
110 : config_(util::HMIUtil::
LoadConfig(FLAGS_dv_plus_hmi_modes_config_path)),
112 monitor_log_buffer_(monitor_log_buffer) {
114 LoadDvPluginPanelsJson();
115 time_interval_ms_ = 3000;
117 monitor_timer_.reset(
new cyber::Timer(
118 time_interval_ms_, [
this]() { this->OnTimer(overtime_time_); },
false));
119 monitor_timer_->Start();
122void HMIWorker::Start(DvCallback callback_api) {
123 callback_api_ = callback_api;
124 InitReadersAndWriters();
125 RegisterStatusUpdateHandler(
126 [
this](
const bool status_changed, HMIStatus *status) {
127 apollo::common::util::FillHeader(
"HMI", status);
128 status_writer_->Write(*status);
129 status->clear_header();
131 ResetComponentStatusTimer();
132 thread_future_ = cyber::Async(&HMIWorker::StatusUpdateThreadLoop,
this);
135void HMIWorker::Stop() {
137 std::system(FLAGS_terminal_stop_cmd.data());
138 if (thread_future_.valid()) {
139 thread_future_.get();
143bool HMIWorker::LoadVehicleDefinedMode(
const std::string &mode_config_path,
144 const std::string ¤t_vehicle_path,
145 HMIMode *self_defined_mode) {
146 const std::string mode_file_name =
147 cyber::common::GetFileName(mode_config_path);
148 const std::string vehicle_mode_config_path =
149 current_vehicle_path +
"/dreamview_conf/hmi_modes/" + mode_file_name;
150 if (!cyber::common::PathExists(vehicle_mode_config_path)) {
153 ACHECK(cyber::common::GetProtoFromFile(vehicle_mode_config_path,
155 <<
"Unable to parse vehicle self defined HMIMode from file "
156 << vehicle_mode_config_path;
157 util::HMIUtil::TranslateCyberModules(self_defined_mode);
161void HMIWorker::InitStatus() {
162 static constexpr char kDockerImageEnv[] =
"DOCKER_IMG";
163 status_.set_docker_image(cyber::common::GetEnv(kDockerImageEnv));
164 status_.set_utm_zone_id(FLAGS_local_utm_zone_id);
167 const auto &modes = config_.modes();
168 for (
const auto &iter : modes) {
169 const std::string &mode = iter.first;
170 status_.add_modes(mode);
171 if (mode == FLAGS_vehicle_calibration_mode) {
172 FuelMonitorManager::Instance()->RegisterFuelMonitor(
173 mode, std::make_unique<DataCollectionMonitor>());
174 FuelMonitorManager::Instance()->RegisterFuelMonitor(
175 mode, std::make_unique<PreprocessMonitor>());
176 }
else if (mode == FLAGS_lidar_calibration_mode) {
177 FuelMonitorManager::Instance()->RegisterFuelMonitor(
178 mode, std::make_unique<PreprocessMonitor>(
"lidar_to_gnss"));
179 }
else if (mode == FLAGS_camera_calibration_mode) {
180 FuelMonitorManager::Instance()->RegisterFuelMonitor(
181 mode, std::make_unique<PreprocessMonitor>(
"camera_to_lidar"));
186 for (
const auto &map_entry : config_.maps()) {
187 status_.add_maps(map_entry.first);
190 if (map_entry.second == FLAGS_map_dir) {
191 status_.set_current_map(map_entry.first);
196 for (
const auto &vehicle : config_.vehicles()) {
197 status_.add_vehicles(vehicle.first);
205 const std::string cached_mode =
206 KVDB::Get(FLAGS_current_mode_db_key).value_or(
"");
207 if (FLAGS_use_navigation_mode && ContainsKey(modes, kNavigationModeName)) {
208 ChangeMode(kNavigationModeName);
209 }
else if (ContainsKey(modes, cached_mode)) {
210 ChangeMode(cached_mode);
211 }
else if (ContainsKey(modes, FLAGS_default_hmi_mode)) {
212 ChangeMode(FLAGS_default_hmi_mode);
214 ChangeMode(modes.begin()->first);
218void HMIWorker::InitReadersAndWriters() {
219 status_writer_ = node_->CreateWriter<HMIStatus>(FLAGS_hmi_status_topic);
220 action_command_client_ = node_->CreateClient<ActionCommand, CommandStatus>(
221 FLAGS_action_command_topic);
222 audio_event_writer_ =
223 node_->CreateWriter<AudioEvent>(FLAGS_audio_event_topic);
224 drive_event_writer_ =
225 node_->CreateWriter<DriveEvent>(FLAGS_drive_event_topic);
227 monitor_reader_ = node_->CreateReader<SystemStatus>(
228 FLAGS_system_status_topic,
229 [
this](
const std::shared_ptr<SystemStatus> &system_status) {
230 this->ResetComponentStatusTimer();
232 WLock wlock(status_mutex_);
234 const bool is_realtime_msg =
236 ? system_status->is_realtime_in_simulation()
238 system_status->header().timestamp_sec() <
239 FLAGS_system_status_lifetime_seconds;
241 if (is_realtime_msg) {
242 for (
auto &iter : *status_.mutable_modules()) {
243 bool previous_second = iter.second;
244 auto *status = FindOrNull(system_status->hmi_modules(), iter.first);
246 status !=
nullptr && status->status() == ComponentStatus::OK;
247 if (previous_second != iter.second) {
248 LockModule(iter.first,
false);
253 if (system_status->detect_immediately()) {
254 status_.set_expected_modules(status_.expected_modules() - 1);
258 for (
auto &iter : *status_.mutable_monitored_components()) {
259 auto *status = FindOrNull(system_status->components(), iter.first);
260 if (status !=
nullptr) {
261 iter.second = status->summary();
263 iter.second.set_status(ComponentStatus::UNKNOWN);
264 iter.second.set_message(
"Status not reported by Monitor.");
269 for (
auto &iter : *status_.mutable_other_components()) {
271 FindOrNull(system_status->other_components(), iter.first);
272 if (status !=
nullptr) {
273 iter.second.CopyFrom(*status);
275 iter.second.set_status(ComponentStatus::UNKNOWN);
276 iter.second.set_message(
"Status not reported by Monitor.");
280 for (
auto &iter : *system_status->mutable_global_components()) {
281 (*status_.mutable_global_components())[iter.first] = iter.second;
285 const size_t new_fingerprint =
287 if (last_status_fingerprint_ != new_fingerprint) {
288 status_changed_ =
true;
289 last_status_fingerprint_ = new_fingerprint;
293 node_->CreateReader<RecordInfo>(
294 FLAGS_record_info_topic,
295 [
this](
const std::shared_ptr<RecordInfo> &record_info) {
296 WLock wlock(status_mutex_);
297 if (record_info->record_name() ==
298 status_.current_record_status().current_record_id()) {
299 status_.mutable_current_record_status()->set_curr_time_s(
300 record_info.get()->curr_time_s());
301 status_changed_ =
true;
305 localization_reader_ =
306 node_->CreateReader<LocalizationEstimate>(FLAGS_localization_topic);
308 chassis_reader_ = node_->CreateReader<Chassis>(
309 FLAGS_chassis_topic, [
this](
const std::shared_ptr<Chassis> &chassis) {
311 FLAGS_system_status_lifetime_seconds) {
312 if (chassis->signal().high_beam()) {
314 const bool ret = Trigger(HMIAction::NONE);
315 AERROR_IF(!ret) <<
"Failed to execute high_beam action.";
321bool HMIWorker::Trigger(
const HMIAction action) {
322 AERROR <<
"HMIAction " << HMIAction_Name(action) <<
" was triggered!";
324 case HMIAction::NONE:
326 case HMIAction::SETUP_MODE:
328 AddExpectedModules(action);
330 case HMIAction::ENTER_AUTO_MODE:
331 return ChangeDrivingMode(Chassis::COMPLETE_AUTO_DRIVE);
332 case HMIAction::DISENGAGE:
333 return ChangeDrivingMode(Chassis::COMPLETE_MANUAL);
334 case HMIAction::RESET_MODE:
337 case HMIAction::LOAD_DYNAMIC_MODELS:
340 case HMIAction::LOAD_RECORDS:
343 case HMIAction::LOAD_RTK_RECORDS:
346 case HMIAction::STOP_RECORD:
349 case HMIAction::LOAD_MAPS:
353 AERROR <<
"HMIAction not implemented, yet!";
359bool HMIWorker::Trigger(
const HMIAction action,
const std::string &value) {
360 AINFO <<
"HMIAction " << HMIAction_Name(action) <<
"(" << value
361 <<
") was triggered!";
364 case HMIAction::CHANGE_MODE:
367 case HMIAction::CHANGE_MAP:
368 ret = ChangeMap(value);
371 SimControlManager::Instance()->Restart();
373 case HMIAction::CHANGE_VEHICLE:
374 ChangeVehicle(value);
376 case HMIAction::START_MODULE:
378 AddExpectedModules(action);
380 case HMIAction::STOP_MODULE:
383 case HMIAction::DELETE_SCENARIO_SET:
384 DeleteScenarioSet(value);
386 case HMIAction::CHANGE_DYNAMIC_MODEL:
387 ChangeDynamicModel(value);
389 case HMIAction::DELETE_DYNAMIC_MODEL:
390 DeleteDynamicModel(value);
392 case HMIAction::DELETE_RECORD:
395 case HMIAction::CHANGE_RECORD:
398 case HMIAction::CHANGE_RTK_RECORD:
399 ChangeRtkRecord(value);
401 case HMIAction::CHANGE_OPERATION:
402 ChangeOperation(value);
404 case HMIAction::DELETE_VEHICLE_CONF:
405 DeleteVehicleConfig(value);
406 case HMIAction::DELETE_V2X_CONF:
407 DeleteV2xConfig(value);
409 case HMIAction::DELETE_MAP:
412 case HMIAction::LOAD_RECORD:
413 LoadRecordAndChangeStatus(value);
416 AERROR <<
"HMIAction not implemented, yet!";
422void HMIWorker::SubmitAudioEvent(
const uint64_t event_time_ms,
423 const int obstacle_id,
const int audio_type,
424 const int moving_result,
425 const int audio_direction,
426 const bool is_siren_on) {
427 std::shared_ptr<AudioEvent> audio_event = std::make_shared<AudioEvent>();
428 apollo::common::util::FillHeader(
"HMI", audio_event.get());
432 audio_event->mutable_header()->set_timestamp_sec(
433 static_cast<double>(event_time_ms) / 1000.0);
434 audio_event->set_id(obstacle_id);
435 audio_event->set_audio_type(
437 audio_event->set_moving_result(
439 audio_event->set_audio_direction(
441 audio_event->set_siren_is_on(is_siren_on);
444 localization_reader_->Observe();
445 if (localization_reader_->Empty()) {
446 AERROR <<
"Failed to get localization associated with the audio event: "
447 << audio_event->DebugString() <<
"\n Localization reader is empty!";
451 const std::shared_ptr<LocalizationEstimate> localization =
452 localization_reader_->GetLatestObserved();
453 audio_event->mutable_pose()->CopyFrom(localization->pose());
454 AINFO <<
"AudioEvent: " << audio_event->DebugString();
456 audio_event_writer_->Write(audio_event);
459void HMIWorker::SubmitDriveEvent(
const uint64_t event_time_ms,
460 const std::string &event_msg,
461 const std::vector<std::string> &event_types,
462 const bool is_reportable) {
463 std::shared_ptr<DriveEvent> drive_event = std::make_shared<DriveEvent>();
464 apollo::common::util::FillHeader(
"HMI", drive_event.get());
468 drive_event->mutable_header()->set_timestamp_sec(
469 static_cast<double>(event_time_ms) / 1000.0);
470 drive_event->set_event(event_msg);
471 drive_event->set_is_reportable(is_reportable);
472 for (
const auto &type_name : event_types) {
473 DriveEvent::Type type;
474 if (DriveEvent::Type_Parse(type_name, &type)) {
475 drive_event->add_type(type);
477 AERROR <<
"Failed to parse drive event type:" << type_name;
480 drive_event_writer_->Write(drive_event);
483void HMIWorker::SensorCalibrationPreprocess(
const std::string &task_type) {
484 std::string start_command = absl::StrCat(
485 "nohup bash /apollo/modules/tools/sensor_calibration/extract_data.sh -t ",
487 System(start_command);
490void HMIWorker::VehicleCalibrationPreprocess() {
491 std::string start_command = absl::StrCat(
492 "nohup bash /apollo/modules/tools/vehicle_calibration/preprocess.sh "
494 status_.current_vehicle(),
"\" --record_num=", record_count_,
" &");
495 System(start_command);
498bool HMIWorker::ChangeDrivingMode(
const Chassis::DrivingMode mode) {
500 const std::string mode_name = Chassis::DrivingMode_Name(mode);
501 if (mode != Chassis::COMPLETE_MANUAL) {
502 if (!ChangeDrivingMode(Chassis::COMPLETE_MANUAL)) {
503 AERROR <<
"Failed to reset to MANUAL before changing to " << mode_name;
508 auto command = std::make_shared<ActionCommand>();
511 case Chassis::COMPLETE_MANUAL:
512 command->set_command(
515 case Chassis::COMPLETE_AUTO_DRIVE:
516 command->set_command(
520 AFATAL <<
"Change driving mode to " << mode_name <<
" not implemented!";
524 static constexpr int kMaxTries = 3;
525 static constexpr auto kTryInterval = std::chrono::milliseconds(500);
526 for (
int i = 0; i < kMaxTries; ++i) {
528 common::util::FillHeader(
"HMI", command.get());
529 action_command_client_->SendRequest(command);
531 std::this_thread::sleep_for(kTryInterval);
533 chassis_reader_->Observe();
534 if (chassis_reader_->Empty()) {
535 AERROR <<
"No Chassis message received!";
536 }
else if (chassis_reader_->GetLatestObserved()->driving_mode() == mode) {
540 AERROR <<
"Failed to change driving mode to " << mode_name;
544bool HMIWorker::ChangeMap(
const std::string &map_name) {
545 if (status_.current_map() == map_name) {
549 return SelectAndReloadMap(map_name);
552bool HMIWorker::SelectAndReloadMap(
const std::string &map_name) {
553 const std::string *map_dir = FindOrNull(config_.maps(), map_name);
554 if (map_dir ==
nullptr) {
555 AERROR <<
"Unknown map " << map_name;
561 SetGlobalFlag(
"map_dir", *map_dir, &FLAGS_map_dir);
563 Json callback_res = callback_api_(
"MapServiceReloadMap", {});
566 WLock wlock(status_mutex_);
567 status_.set_current_map(map_name);
568 status_changed_ =
true;
570 return callback_res[
"result"];
573void HMIWorker::UpdateModeModulesAndMonitoredComponents() {
574 status_.clear_modules();
575 status_.clear_modules_lock();
576 previous_modules_lock_.clear();
577 for (
const auto &iter : current_mode_.
modules()) {
578 status_.mutable_modules()->insert({iter.first,
false});
579 status_.mutable_modules_lock()->insert({iter.first,
false});
580 previous_modules_lock_.insert({iter.first,
false});
584 status_.clear_monitored_components();
585 for (
const auto &iter : current_mode_.monitored_components()) {
586 status_.mutable_monitored_components()->insert({iter.first, {}});
590void HMIWorker::ChangeVehicle(
const std::string &vehicle_name) {
591 const std::string *vehicle_dir = FindOrNull(config_.vehicles(), vehicle_name);
592 if (vehicle_dir ==
nullptr) {
593 AERROR <<
"Unknown vehicle " << vehicle_name;
596 std::string current_mode;
599 WLock wlock(status_mutex_);
600 current_mode = status_.current_mode();
601 if (status_.current_vehicle() == vehicle_name) {
607 const std::string vehicle_type_file_path = *vehicle_dir +
"/vehicle_type";
608 std::string vehicle_type_str;
609 cyber::common::GetContent(vehicle_type_file_path, &vehicle_type_str);
610 int vehicle_type = std::stoi(vehicle_type_str);
611 status_.set_current_vehicle_type(vehicle_type);
612 }
catch (
const std::exception &e) {
613 AWARN <<
"get vehicle type config failed: " << e.what();
614 status_.clear_current_vehicle_type();
616 status_.set_current_vehicle(vehicle_name);
617 status_changed_ =
true;
621 HMIMode vehicle_defined_mode;
622 const std::string mode_config_path = config_.modes().at(current_mode);
623 if (LoadVehicleDefinedMode(mode_config_path, *vehicle_dir,
624 &vehicle_defined_mode)) {
625 MergeToCurrentMode(&vehicle_defined_mode);
629 current_mode_ = util::HMIUtil::LoadMode(mode_config_path);
632 WLock wlock(status_mutex_);
633 UpdateModeModulesAndMonitoredComponents();
635 ACHECK(VehicleManager::Instance()->UseVehicle(*vehicle_dir));
637 auto *monitors = FuelMonitorManager::Instance()->GetCurrentMonitors();
638 if (monitors !=
nullptr) {
639 for (
const auto &monitor : *monitors) {
640 if (monitor.second->IsEnabled()) {
641 monitor.second->Restart();
647void HMIWorker::MergeToCurrentMode(HMIMode *mode) {
648 current_mode_.clear_modules();
649 current_mode_.clear_cyber_modules();
650 current_mode_.clear_monitored_components();
651 current_mode_.mutable_modules()->swap(*(mode->mutable_modules()));
652 current_mode_.mutable_monitored_components()->swap(
653 *(mode->mutable_monitored_components()));
656void HMIWorker::ChangeMode(
const std::string &mode_name) {
657 if (!ContainsKey(config_.modes(), mode_name)) {
658 AERROR <<
"Cannot change to unknown mode " << mode_name;
663 RLock rlock(status_mutex_);
665 if (status_.current_mode() == mode_name) {
670 std::string default_operation_str =
"";
672 WLock wlock(status_mutex_);
673 status_.set_current_mode(mode_name);
674 current_mode_ = util::HMIUtil::LoadMode(config_.modes().at(mode_name));
676 HMIMode vehicle_defined_mode;
677 const std::string *vehicle_dir =
678 FindOrNull(config_.vehicles(), status_.current_vehicle());
679 if (vehicle_dir !=
nullptr &&
680 LoadVehicleDefinedMode(config_.modes().at(mode_name), *vehicle_dir,
681 &vehicle_defined_mode)) {
682 MergeToCurrentMode(&vehicle_defined_mode);
684 UpdateModeModulesAndMonitoredComponents();
686 status_.clear_other_components();
687 for (
const auto &iter : current_mode_.other_components()) {
688 status_.mutable_other_components()->insert({iter.first, {}});
692 status_.clear_operations();
693 status_.mutable_operations()->CopyFrom(current_mode_.operations());
697 if ((mode_name ==
"Pnc" || mode_name ==
"Default") &&
698 PackageExist(
"simulator-plugin")) {
699 status_.add_operations(HMIModeOperation::Scenario_Sim);
702 if (current_mode_.has_default_operation()) {
703 default_operation_str =
704 HMIModeOperation_Name(current_mode_.default_operation());
706 status_changed_ =
true;
712 if (!default_operation_str.empty()) {
713 ChangeOperation(default_operation_str);
715 FuelMonitorManager::Instance()->SetCurrentMode(mode_name);
716 KVDB::Put(FLAGS_current_mode_db_key, mode_name);
719void HMIWorker::StartModule(
const std::string &module) {
720 const Module *module_conf = FindOrNull(current_mode_.modules(), module);
721 if (module_conf !=
nullptr) {
723 WLock wlock(status_mutex_);
724 LockModule(module,
true);
726 System(module_conf->start_command());
728 AERROR <<
"Cannot find module " <<
module;
732void HMIWorker::StopModule(
const std::string &module) {
733 const Module *module_conf = FindOrNull(current_mode_.modules(), module);
734 if (module_conf !=
nullptr) {
736 WLock wlock(status_mutex_);
737 LockModule(module,
true);
739 System(module_conf->stop_command());
741 AERROR <<
"Cannot find module " <<
module;
745HMIStatus HMIWorker::GetStatus()
const {
746 RLock rlock(status_mutex_);
750void HMIWorker::SetupMode() {
752 WLock wlock(status_mutex_);
753 status_.set_backend_shutdown(
false);
755 for (
const auto &iter : current_mode_.
modules()) {
757 WLock wlock(status_mutex_);
758 auto modules = status_.modules();
760 LockModule(iter.first,
true);
763 System(iter.second.start_command());
767void HMIWorker::ResetMode() {
771 WLock wlock(status_mutex_);
772 status_.set_backend_shutdown(
true);
774 for (
const auto &iter : current_mode_.
modules()) {
776 WLock wlock(status_mutex_);
777 auto modules = status_.modules();
779 LockModule(iter.first,
true);
782 System(iter.second.stop_command());
787void HMIWorker::StatusUpdateThreadLoop() {
788 constexpr int kLoopIntervalMs = 200;
790 std::this_thread::sleep_for(std::chrono::milliseconds(kLoopIntervalMs));
791 UpdateComponentStatus();
792 bool status_changed =
false;
794 WLock wlock(status_mutex_);
795 status_changed = status_changed_;
796 status_changed_ =
false;
799 if (!status_changed) {
800 static double next_update_time = 0;
802 if (now < next_update_time) {
805 next_update_time = now + FLAGS_status_publish_interval;
809 HMIStatus status = GetStatus();
810 for (
const auto handler : status_update_handlers_) {
811 handler(status_changed, &status);
816void HMIWorker::ResetComponentStatusTimer() {
818 last_status_fingerprint_ = 0;
821void HMIWorker::UpdateComponentStatus() {
823 if (now - last_status_received_s_.load() > FLAGS_monitor_timeout_threshold) {
824 if (!monitor_timed_out_) {
825 WLock wlock(status_mutex_);
827 const uint64_t now_ms =
static_cast<uint64_t
>(now * 2e3);
828 static constexpr bool kIsReportable =
true;
829 SubmitDriveEvent(now_ms,
"Monitor timed out", {
"PROBLEM"}, kIsReportable);
830 AWARN <<
"System fault. Auto disengage.";
831 Trigger(HMIAction::DISENGAGE);
833 for (
auto &monitored_component :
834 *status_.mutable_monitored_components()) {
835 monitored_component.second.set_status(ComponentStatus::UNKNOWN);
836 monitored_component.second.set_message(
837 "Status not reported by Monitor.");
839 status_changed_ =
true;
841 monitor_timed_out_ =
true;
843 monitor_timed_out_ =
false;
847void HMIWorker::GetScenarioResourcePath(std::string *scenario_resource_path) {
848 CHECK_NOTNULL(scenario_resource_path);
849 const std::string home = cyber::common::GetEnv(
"HOME");
850 *scenario_resource_path = home + FLAGS_resource_scenario_path;
853void HMIWorker::ChangeDynamicModel(
const std::string &dynamic_model_name) {
862 if (dynamic_model_name.empty()) {
863 AERROR <<
"Failed to change empty dynamic model!";
866 auto sim_control_manager = SimControlManager::Instance();
867 if (!sim_control_manager->IsEnabled()) {
868 AERROR <<
"Sim control is not enabled!";
872 if (!sim_control_manager->ChangeDynamicModel(dynamic_model_name)) {
876 AERROR <<
"Failed to change dynamic model! Please check if the param is "
880 std::string current_dynamic_model_name = dynamic_model_name;
882 WLock wlock(status_mutex_);
883 status_.set_current_dynamic_model(dynamic_model_name);
884 status_changed_ =
true;
889bool HMIWorker::UpdateDynamicModelToStatus(
890 const std::string &dynamic_model_name) {
891 auto sim_control_manager = SimControlManager::Instance();
892 if (!sim_control_manager->IsEnabled()) {
893 AERROR <<
"Sim control is not enabled or missing dynamic model name "
898 if (!sim_control_manager->AddDynamicModel(dynamic_model_name)) {
899 AERROR <<
"Failed to add dynamic model to local dynamic model list for "
904 WLock wlock(status_mutex_);
905 for (
const auto &iter : status_.dynamic_models()) {
906 if (iter == dynamic_model_name) {
907 AERROR <<
"Do not need to add new dynamic model for is duplicate!";
911 status_.add_dynamic_models(dynamic_model_name);
912 status_changed_ =
true;
917bool HMIWorker::LoadDynamicModels() {
918 auto sim_control_manager = SimControlManager::Instance();
919 nlohmann::json load_res;
920 if (sim_control_manager->IsEnabled()) {
921 load_res = sim_control_manager->LoadDynamicModels();
923 AERROR <<
"Sim control is not enabled!";
926 if (!load_res.contains(
"result") || !load_res[
"result"]) {
931 WLock wlock(status_mutex_);
932 auto dynamic_models = status_.mutable_dynamic_models();
934 for (
auto iter = dynamic_models->begin(); iter != dynamic_models->end();) {
935 iter = dynamic_models->erase(iter);
937 for (
const auto &dynamic_model : load_res[
"loaded_dynamic_models"]) {
938 status_.add_dynamic_models(dynamic_model);
940 status_changed_ =
true;
945void HMIWorker::DeleteScenarioSet(
const std::string &scenario_set_id) {
946 if (scenario_set_id.empty()) {
949 std::string directory_path;
950 GetScenarioResourcePath(&directory_path);
951 directory_path = directory_path + scenario_set_id;
952 if (!cyber::common::PathExists(directory_path)) {
953 AERROR <<
"Failed to find scenario_set!";
956 std::string command =
"rm -fr " + directory_path;
959 if (std::system(command.data()) != 0) {
960 AERROR <<
"Failed to delete scenario set directory for: "
961 << std::strerror(errno);
967void HMIWorker::DeleteDynamicModel(
const std::string &dynamic_model_name) {
968 if (dynamic_model_name.empty()) {
969 AERROR <<
"Invalid param:empty dynamic model name!";
973 RLock rlock(status_mutex_);
975 if (dynamic_model_name == status_.current_dynamic_model()) {
976 AERROR <<
"Cannot delete current dynamic model!";
979 if (dynamic_model_name == FLAGS_sim_perfect_control) {
980 AERROR <<
"Cannot delete default sim control:SimPerfectControl!";
984 auto sim_control_manager = SimControlManager::Instance();
985 if (!sim_control_manager->IsEnabled()) {
986 AERROR <<
"Sim control is not enabled!";
989 if (!sim_control_manager->DeleteDynamicModel(dynamic_model_name)) {
992 AERROR <<
"Failed to delete dynamic model!";
996 WLock wlock(status_mutex_);
997 auto iter = status_.dynamic_models().begin();
998 while (iter != status_.dynamic_models().end()) {
999 if (*iter == dynamic_model_name) {
1004 if (iter != status_.dynamic_models().end()) {
1005 status_.mutable_dynamic_models()->erase(iter);
1006 status_changed_ =
true;
1008 AWARN <<
"Can not find dynamic model to delete!";
1014void HMIWorker::GetRecordPath(std::string *record_path) {
1015 CHECK_NOTNULL(record_path);
1016 const std::string home = cyber::common::GetEnv(
"HOME");
1017 *record_path = home + FLAGS_resource_record_path;
1020bool HMIWorker::handlePlayRecordProcess(
const std::string &action_type) {
1021 std::string record_id;
1022 PlayRecordStatus current_play_record_status;
1023 PlayRecordStatus expected_play_record_status;
1024 PlayRecordStatus reasonable_play_record_status;
1026 RLock rlock(status_mutex_);
1027 auto record_status = status_.current_record_status();
1028 record_id = record_status.current_record_id();
1029 current_play_record_status = record_status.play_record_status();
1030 if (record_id.empty()) {
1031 AERROR <<
"Failed to pause record for record has not been selected"
1032 "or process is not exists!";
1035 if (!RecordIsLoaded(record_id)) {
1036 AERROR <<
"Failed to pause record for record has not been loaded!";
1040 if (action_type.compare(
"continue") == 0) {
1041 expected_play_record_status = PlayRecordStatus::RUNNING;
1042 reasonable_play_record_status = PlayRecordStatus::PAUSED;
1043 }
else if (action_type.compare(
"pause") == 0) {
1044 expected_play_record_status = PlayRecordStatus::PAUSED;
1045 reasonable_play_record_status = PlayRecordStatus::RUNNING;
1047 AERROR <<
"Invalid action type for play record.";
1050 if (reasonable_play_record_status != current_play_record_status) {
1053 auto *record_player_factory = RecordPlayerFactory::Instance();
1054 auto player_ptr = record_player_factory->GetRecordPlayer(record_id);
1056 AERROR <<
"Failed to get record player.";
1059 player_ptr->HandleNohupThreadStatus();
1062 WLock wlock(status_mutex_);
1063 status_.mutable_current_record_status()->set_play_record_status(
1064 expected_play_record_status);
1065 status_changed_ =
true;
1067 record_player_factory->IncreaseRecordPriority(record_id);
1071bool HMIWorker::RePlayRecord() {
1072 std::string record_id;
1074 RLock rlock(status_mutex_);
1075 auto record_status = status_.current_record_status();
1076 record_id = record_status.current_record_id();
1077 if (record_status.current_record_id().empty()) {
1078 AERROR <<
"Failed to play record for record has not been selected!";
1081 if (!RecordIsLoaded(record_id)) {
1082 AERROR <<
"Failed to play record for record has not been loaded!";
1085 if (record_status.play_record_status() == PlayRecordStatus::RUNNING) {
1086 AERROR <<
"Record has been played,ignore dumplicate request.";
1090 std::string record_path;
1091 GetRecordPath(&record_path);
1092 record_path = record_path + record_id +
".record";
1094 if (!cyber::common::PathExists(record_path)) {
1095 AERROR <<
"Failed to find record!";
1099 auto *record_player_factory = RecordPlayerFactory::Instance();
1100 auto player_ptr = record_player_factory->GetRecordPlayer(record_id);
1101 bool play_record_res = (player_ptr !=
nullptr);
1102 PlayRecordStatus play_record_status;
1103 if (!play_record_res) {
1104 AERROR <<
"Failed to get record related player";
1105 play_record_status = PlayRecordStatus::CLOSED;
1107 player_ptr->PreloadPlayRecord();
1108 player_ptr->NohupPlayRecord();
1110 callback_api_(
"GetDataHandlerConf", {});
1111 play_record_status = PlayRecordStatus::RUNNING;
1114 WLock wlock(status_mutex_);
1115 auto record_status = status_.mutable_current_record_status();
1116 record_status->set_play_record_status(play_record_status);
1117 status_changed_ =
true;
1119 record_player_factory->IncreaseRecordPriority(record_id);
1120 return play_record_res;
1123bool HMIWorker::ResetRecordProgress(
const double &progress) {
1124 std::string record_id;
1125 double total_time_s;
1126 PlayRecordStatus last_record_status;
1128 RLock rlock(status_mutex_);
1129 auto record_status = status_.current_record_status();
1130 record_id = record_status.current_record_id();
1131 last_record_status = record_status.play_record_status();
1132 if (record_status.current_record_id().empty()) {
1133 AERROR <<
"Failed to reset record progress for record has not been "
1137 if (!RecordIsLoaded(record_id)) {
1138 AERROR <<
"Failed to reset record progress for record has not been "
1142 total_time_s = status_.records().at(record_id).total_time_s();
1144 AERROR <<
"total : " << total_time_s;
1145 if (progress > total_time_s) {
1146 AERROR <<
"Failed to reset record progress for progress exceeds the "
1147 "record's total time.";
1150 auto *record_player_factory = RecordPlayerFactory::Instance();
1151 auto player_ptr = record_player_factory->GetRecordPlayer(record_id);
1153 AERROR <<
"Failed to get record player.";
1156 player_ptr->Reset();
1157 player_ptr->PreloadPlayRecord(
1158 progress, (last_record_status != PlayRecordStatus::RUNNING));
1159 player_ptr->NohupPlayRecord();
1163 if (last_record_status == PlayRecordStatus::CLOSED) {
1164 last_record_status = PlayRecordStatus::PAUSED;
1167 callback_api_(
"GetDataHandlerConf", {});
1169 WLock wlock(status_mutex_);
1170 auto record_status = status_.mutable_current_record_status();
1171 record_status->set_play_record_status(last_record_status);
1172 record_status->set_curr_time_s(progress);
1173 status_changed_ =
true;
1175 record_player_factory->IncreaseRecordPriority(record_id);
1179void HMIWorker::StopRecordPlay(
const std::string &record_id) {
1180 std::string curr_record_id =
"";
1182 RLock rlock(status_mutex_);
1183 curr_record_id = status_.current_record_status().current_record_id();
1185 if (!record_id.empty()) {
1186 curr_record_id = record_id;
1188 if (!RecordIsLoaded(curr_record_id)) {
1189 AERROR <<
"Failed to stop record player under unloaded status!";
1192 auto *record_player_factory = RecordPlayerFactory::Instance();
1193 auto player_ptr = record_player_factory->GetRecordPlayer(curr_record_id);
1195 AERROR <<
"Failed to get record player to reset.";
1198 player_ptr->Reset();
1200 WLock wlock(status_mutex_);
1201 auto record_status = status_.mutable_current_record_status();
1202 record_status->set_play_record_status(PlayRecordStatus::CLOSED);
1203 record_status->clear_curr_time_s();
1205 status_changed_ =
true;
1208bool HMIWorker::RecordIsLoaded(
const std::string &record_id) {
1210 RLock rlock(status_mutex_);
1211 auto iter = status_.records().find(record_id);
1212 return iter != status_.records().end() &&
1213 (iter->second.load_record_status() == LoadRecordStatus::LOADED);
1217void HMIWorker::ChangeRecord(
const std::string &record_id) {
1218 std::string last_record_id;
1220 RLock rlock(status_mutex_);
1221 auto status_records = status_.mutable_records();
1222 auto iter = status_records->find(record_id);
1223 if (iter == status_records->end()) {
1224 AERROR <<
"Cannot change to unknown record!";
1227 if (!RecordIsLoaded(record_id)) {
1228 AERROR <<
"Cannot change to unloaded record, load this record before!";
1231 last_record_id = status_.current_record_status().current_record_id();
1233 if (!last_record_id.empty()) {
1234 StopRecordPlay(last_record_id);
1237 callback_api_(
"ClearDataHandlerConfChannelMsgs", {});
1238 WLock wlock(status_mutex_);
1239 status_.mutable_current_record_status()->set_current_record_id(record_id);
1240 auto *record_player_factory = RecordPlayerFactory::Instance();
1241 record_player_factory->SetCurrentRecord(record_id);
1242 record_player_factory->IncreaseRecordPriority(record_id);
1243 status_changed_ =
true;
1247void HMIWorker::ClearInvalidResourceUnderChangeOperation(
1248 const HMIModeOperation operation) {
1249 ClearInvalidRecordStatus(operation);
1250 HMIModeOperation old_operation;
1252 RLock rlock(status_mutex_);
1253 old_operation = status_.current_operation();
1257 auto sim_control_manager = SimControlManager::Instance();
1258 auto iter = std::find(OperationBasedOnSimControl.begin(),
1259 OperationBasedOnSimControl.end(), operation);
1260 if (iter != OperationBasedOnSimControl.end()) {
1261 sim_control_manager->Start();
1263 sim_control_manager->Stop();
1266 WLock wlock(status_mutex_);
1267 status_.set_current_dynamic_model(
"");
1268 status_.clear_dynamic_models();
1269 status_changed_ =
true;
1272 if (old_operation == HMIModeOperation::Record) {
1276 if (old_operation == HMIModeOperation::Waypoint_Follow) {
1278 ClearRtkRecordInfo();
1282void HMIWorker::ChangeOperation(
const std::string &operation_str) {
1283 HMIModeOperation operation;
1284 if (!HMIModeOperation_Parse(operation_str, &operation)) {
1285 AERROR <<
"Invalid HMI operation string: " << operation_str;
1289 RLock rlock(status_mutex_);
1290 if (status_.current_mode().empty()) {
1291 AERROR <<
"Please select mode!";
1294 auto status_operations = status_.operations();
1295 auto iter = status_operations.begin();
1296 for (; iter != status_operations.end(); iter++) {
1297 if (*iter == operation) {
1301 if (iter == status_operations.end()) {
1302 AERROR <<
"Cannot change to unknown operation!";
1306 ClearInvalidResourceUnderChangeOperation(operation);
1308 WLock wlock(status_mutex_);
1309 status_.set_current_operation(operation);
1310 status_changed_ =
true;
1315bool HMIWorker::ReadRecordInfo(
const std::string &file,
1316 double *total_time_s)
const {
1317 cyber::record::RecordFileReader file_reader;
1318 if (!file_reader.Open(file)) {
1319 AERROR <<
"open record file error. file: " << file;
1322 cyber::proto::Header hdr = file_reader.GetHeader();
1323 if (!hdr.is_complete()) {
1324 AERROR <<
"record is not complete, can not be used. file: " << file;
1327 auto begin_time_s =
static_cast<double>(hdr.begin_time()) / 1e9;
1328 auto end_time_s =
static_cast<double>(hdr.end_time()) / 1e9;
1329 double loop_time_s = end_time_s - begin_time_s;
1330 *total_time_s = std::round(loop_time_s * 1e2) / 1e2;
1334bool HMIWorker::UpdateMapToStatus(
const std::string &map_tar_name) {
1335 if (map_tar_name.empty()) {
1339 std::string map_dir = FLAGS_maps_data_path +
"/";
1340 std::string map_name_prefix;
1341 int index = map_tar_name.rfind(
".tar.xz");
1342 if (index != -1 && map_tar_name[0] !=
'.') {
1343 map_name_prefix = map_tar_name.substr(0, index);
1344 map_dir = map_dir + map_name_prefix;
1346 AERROR <<
"The map name does not meet the standard!" << map_tar_name;
1349 if (!cyber::common::PathExists(map_dir)) {
1350 AERROR <<
"Failed to find maps!";
1353 map_name_prefix = util::HMIUtil::TitleCase(map_name_prefix);
1355 WLock wlock(status_mutex_);
1356 auto iter = status_.maps().begin();
1357 for (; iter != status_.maps().end(); iter++) {
1358 if (*iter == map_name_prefix) {
1362 if (iter != status_.maps().end()) {
1365 status_.add_maps(map_name_prefix);
1366 status_changed_ =
true;
1371bool HMIWorker::LoadRecordAndChangeStatus(
const std::string &record_name) {
1372 std::string record_file_path;
1374 RLock rlock(status_mutex_);
1375 auto &status_records = status_.records();
1376 auto iter = status_records.find(record_name);
1377 if (iter == status_records.end()) {
1378 AERROR <<
"Cannot load unknown record!";
1381 if (RecordIsLoaded(record_name)) {
1382 AERROR <<
"Cannot load already loaded record.";
1385 if (iter->second.record_file_path().empty()) {
1386 AERROR <<
"Cannot load record without record file path!";
1389 record_file_path = iter->second.record_file_path();
1392 WLock wlock(status_mutex_);
1393 auto status_records = status_.mutable_records();
1394 (*status_records)[record_name].set_load_record_status(
1395 LoadRecordStatus::LOADING);
1397 double total_time_s;
1398 if (LoadRecord(record_name, record_file_path, &total_time_s)) {
1400 WLock wlock(status_mutex_);
1401 auto status_records = status_.mutable_records();
1402 (*status_records)[record_name].set_load_record_status(
1403 LoadRecordStatus::LOADED);
1404 (*status_records)[record_name].set_total_time_s(total_time_s);
1406 RecordPlayerFactory::Instance()->IncreaseRecordPriority(record_name);
1409 WLock wlock(status_mutex_);
1410 auto status_records = status_.mutable_records();
1411 (*status_records)[record_name].set_load_record_status(
1412 LoadRecordStatus::NOT_LOAD);
1418bool HMIWorker::LoadRecord(
const std::string &record_name,
1419 const std::string &record_file_path,
1420 double *total_time_s) {
1421 if (RecordIsLoaded(record_name)) {
1422 AERROR <<
"Record is loaded,no need to load";
1426 auto record_player_factory = RecordPlayerFactory::Instance();
1427 if (!record_player_factory->EnableContinueLoad()) {
1429 std::string remove_record_id;
1430 if (record_player_factory->RemoveLRURecord(&remove_record_id)) {
1433 WLock wlock(status_mutex_);
1434 auto status_records = status_.mutable_records();
1435 (*status_records)[remove_record_id].set_load_record_status(
1436 LoadRecordStatus::NOT_LOAD);
1437 (*status_records)[remove_record_id].clear_total_time_s();
1441 if (!ReadRecordInfo(record_file_path, total_time_s)) {
1444 if (!record_player_factory->RegisterRecordPlayer(record_name,
1445 record_file_path)) {
1451bool HMIWorker::LoadRecords() {
1452 std::string directory_path;
1453 auto *record_player_factory = RecordPlayerFactory::Instance();
1454 GetRecordPath(&directory_path);
1455 if (!cyber::common::PathExists(directory_path)) {
1456 AERROR <<
"Failed to find records!";
1459 DIR *directory = opendir(directory_path.c_str());
1460 if (directory ==
nullptr) {
1461 AERROR <<
"Cannot open record directory" << directory_path;
1464 struct dirent *file;
1465 google::protobuf::Map<std::string, LoadRecordInfo> new_records;
1466 while ((file = readdir(directory)) !=
nullptr) {
1467 if (!strcmp(file->d_name,
".") || !strcmp(file->d_name,
"..")) {
1470 if (file->d_type == DT_DIR) {
1473 const std::string record_id = file->d_name;
1474 const int index = record_id.rfind(
".record");
1476 size_t record_suffix_length = 7;
1477 if (record_id.length() - index != record_suffix_length) {
1480 if (index != -1 && record_id[0] !=
'.') {
1481 const std::string local_record_resource = record_id.substr(0, index);
1482 const std::string record_file_path = directory_path +
"/" + record_id;
1483 double total_time_s;
1485 if (RecordIsLoaded(local_record_resource)) {
1489 if (!record_player_factory->EnableContinuePreload()) {
1490 new_records[local_record_resource].set_load_record_status(
1491 LoadRecordStatus::NOT_LOAD);
1492 new_records[local_record_resource].set_record_file_path(
1497 if (!LoadRecord(local_record_resource, record_file_path, &total_time_s)) {
1501 new_records[local_record_resource].set_total_time_s(total_time_s);
1502 new_records[local_record_resource].set_load_record_status(
1503 LoadRecordStatus::LOADED);
1504 new_records[local_record_resource].set_record_file_path(record_file_path);
1507 closedir(directory);
1509 WLock wlock(status_mutex_);
1510 auto status_records = status_.mutable_records();
1511 for (
auto iter = new_records.begin(); iter != new_records.end(); iter++) {
1512 (*status_records)[iter->first] = iter->second;
1514 status_changed_ =
true;
1519void HMIWorker::DeleteMap(
const std::string &map_name) {
1520 std::string title_map_name = util::HMIUtil::TitleCase(map_name);
1521 if (map_name.empty()) {
1524 std::string map_dir = FLAGS_maps_data_path +
"/";
1525 std::string map_abs_path = map_dir + map_name;
1526 if (!cyber::common::PathExists(map_abs_path)) {
1527 AERROR <<
"Failed to get map path: " << map_abs_path;
1531 WLock wlock(status_mutex_);
1532 auto iter = status_.maps().begin();
1533 for (; iter != status_.maps().end(); iter++) {
1534 if (*iter == title_map_name) {
1538 if (iter == status_.maps().end()) {
1539 AERROR <<
"Faile to find map name";
1542 if (status_.current_map() == title_map_name) {
1543 AERROR <<
"Cann't delete current selected map";
1546 status_.mutable_maps()->erase(iter);
1547 status_changed_ =
true;
1550 std::string cmd =
"rm -rf " + map_abs_path;
1551 if (std::system(cmd.data()) != 0) {
1552 AERROR <<
"Failed to delete map for: " << std::strerror(errno);
1555 std::string tar_abs_path = map_dir + map_name +
".tar.xz";
1557 if (cyber::common::PathExists(tar_abs_path)) {
1558 cmd =
"rm -rf " + tar_abs_path;
1559 if (std::system(cmd.data()) != 0) {
1560 AERROR <<
"Failed to delete map tar file for: " << std::strerror(errno);
1566void HMIWorker::DeleteRecord(
const std::string &record_id) {
1567 if (record_id.empty()) {
1570 std::string record_path;
1571 GetRecordPath(&record_path);
1572 const std::string record_abs_path = record_path + record_id +
".record";
1573 if (!cyber::common::PathExists(record_abs_path)) {
1574 AERROR <<
"Failed to get record path: " << record_abs_path;
1579 RLock rlock(status_mutex_);
1580 auto &status_records = status_.records();
1581 if (status_records.find(record_id) == status_records.end()) {
1582 AERROR <<
"Failed to find record id: " << record_id;
1585 if (record_id == status_.current_record_status().current_record_id()) {
1586 AERROR <<
"Cann't delete current selected record";
1591 auto *record_player_factory = RecordPlayerFactory::Instance();
1592 record_player_factory->UnregisterRecordPlayer(record_id);
1594 WLock wlock(status_mutex_);
1595 status_.mutable_records()->erase(record_id);
1596 status_changed_ =
true;
1600 std::string command =
"rm -rf " + record_abs_path;
1601 if (std::system(command.data()) != 0) {
1602 AERROR <<
"Failed to delete record for: " << std::strerror(errno);
1607 const std::string tar_abs_path = record_path + record_id +
".tar.xz";
1608 if (cyber::common::PathExists(tar_abs_path)) {
1609 command =
"rm -rf " + tar_abs_path;
1610 if (std::system(command.data()) != 0) {
1611 AERROR <<
"Failed to delete record tar file for: "
1612 << std::strerror(errno);
1619void HMIWorker::ReloadMaps() {
1620 WLock wlock(status_mutex_);
1621 config_.mutable_maps()->clear();
1622 *(config_.mutable_maps()) =
1623 util::HMIUtil::ListDirAsDict(FLAGS_maps_data_path);
1624 status_.clear_maps();
1625 for (
const auto &map : config_.maps()) {
1626 status_.add_maps(map.first);
1628 if (status_.current_map() !=
"") {
1630 if (config_.maps().find(status_.current_map()) == config_.maps().end()) {
1632 AINFO <<
"Current map is not in status. Reset it.";
1633 status_.set_current_map(
"");
1636 status_changed_ =
true;
1640bool HMIWorker::ReloadVehicles() {
1642 util::HMIUtil::LoadConfig(FLAGS_dv_plus_hmi_modes_config_path);
1644 config.SerializeToString(&msg);
1646 WLock wlock(status_mutex_);
1647 config_.ParseFromString(msg);
1650 status_.clear_vehicles();
1653 for (
const auto &vehicle : config_.vehicles()) {
1654 status_.add_vehicles(vehicle.first);
1656 status_changed_ =
true;
1660void HMIWorker::UpdateCameraSensorChannelToStatus(
1661 const std::string &channel_name) {
1663 WLock wlock(status_mutex_);
1664 if (status_.current_camera_sensor_channel() == channel_name) {
1665 AINFO <<
"Input channel name is current camera sensor channel";
1668 status_.set_current_camera_sensor_channel(channel_name);
1669 status_changed_ =
true;
1673void HMIWorker::UpdatePointCloudChannelToStatus(
1674 const std::string &channel_name) {
1676 WLock wlock(status_mutex_);
1677 if (status_.current_point_cloud_channel() == channel_name) {
1678 AINFO <<
"Input channel name is current camera sensor channel";
1681 status_.set_current_point_cloud_channel(channel_name);
1682 status_changed_ =
true;
1686void HMIWorker::DeleteVehicleConfig(
const std::string &vehicle_name) {
1687 if (vehicle_name.empty()) {
1690 const std::string *vehicle_dir =
1691 FindOrNull(config_.vehicles(), vehicle_name);
1692 if (vehicle_dir ==
nullptr) {
1693 AERROR <<
"Unknow vehicle name" << vehicle_name;
1697 RLock rlock(status_mutex_);
1698 if (status_.current_vehicle() == vehicle_name) {
1699 AERROR <<
"The deleted vehicle profile is the one in use.";
1703 if (!cyber::common::DeleteFile(*vehicle_dir)) {
1704 AERROR <<
"Delete vehicle profile [" << vehicle_name <<
"] failed!";
1707 if (!ReloadVehicles()) {
1708 AERROR <<
"Update vehicle profile [" << vehicle_name <<
"] failed!";
1713void HMIWorker::DeleteV2xConfig(
const std::string &vehicle_name) {
1714 if (vehicle_name.empty()) {
1717 const std::string *vehicle_dir =
1718 FindOrNull(config_.vehicles(), util::HMIUtil::TitleCase(vehicle_name));
1719 if (vehicle_dir ==
nullptr) {
1720 AERROR <<
"Unknow vehicle name " << vehicle_name;
1723 const std::string v2x_dir = *vehicle_dir +
"/v2x_conf";
1724 if (!cyber::common::PathExists(v2x_dir)) {
1725 AINFO <<
"The directory does not exist or the directory has been deleted";
1727 if (!cyber::common::DeleteFile(v2x_dir)) {
1728 AERROR <<
"Delete v2x config [" << vehicle_name <<
"/v2x_conf] failed!";
1733bool HMIWorker::StartDataRecorder() {
1735 "/apollo/scripts/record_bag.py --start --all --dreamview "
1737 FLAGS_data_record_default_name;
1738 int ret = std::system(
start_cmd.data());
1740 auto *monitors = FuelMonitorManager::Instance()->GetCurrentMonitors();
1741 if (monitors !=
nullptr) {
1742 auto iter = monitors->find(FLAGS_data_collection_monitor_name);
1743 if (iter != monitors->end()) {
1744 auto *data_collection_monitor = iter->second.get();
1745 if (data_collection_monitor->IsEnabled() && record_count_ == 0) {
1746 data_collection_monitor->Restart();
1753 AERROR <<
"Failed to start the cyber_recorder process";
1758bool HMIWorker::StopDataRecorder() {
1759 std::string
stop_cmd =
"/apollo/scripts/record_bag.py --stop";
1760 int ret = std::system(
stop_cmd.data());
1764 AERROR <<
"Failed to stop the cyber_recorder process";
1769int HMIWorker::SaveDataRecorder(
const std::string &new_name) {
1770 std::string data_record_default_path =
1771 std::string(cyber::common::GetEnv(
"HOME",
"/home/apollo")) +
1772 "/.apollo/resources/records/" + FLAGS_data_record_default_name;
1773 if (!cyber::common::PathExists(data_record_default_path)) {
1774 AERROR <<
"Failed to save the record, the dreamview recording record does "
1775 "not exist, please record through dreamview.";
1778 std::string save_cmd =
"/apollo/scripts/record_bag.py --default_name " +
1779 FLAGS_data_record_default_name +
" --rename " +
1781 int ret = std::system(save_cmd.data());
1786 AERROR <<
"Failed to save the record, a file with the same name exists";
1791bool HMIWorker::DeleteDataRecorder() {
1792 std::string delete_cmd =
1793 "/apollo/scripts/record_bag.py --delete --default_name " +
1794 FLAGS_data_record_default_name;
1795 int ret = std::system(delete_cmd.data());
1799 AERROR <<
"Failed to delete the record";
1804void HMIWorker::ClearRecordInfo() {
1805 std::string last_record_id;
1807 RLock rlock(status_mutex_);
1808 if (status_.current_operation() != HMIModeOperation::Record) {
1811 last_record_id = status_.current_record_status().current_record_id();
1813 if (!last_record_id.empty()) {
1814 StopRecordPlay(last_record_id);
1817 callback_api_(
"ClearDataHandlerConfChannelMsgs", {});
1818 WLock wlock(status_mutex_);
1819 status_.mutable_current_record_status()->clear_current_record_id();
1820 status_changed_ =
true;
1824void HMIWorker::ClearRtkRecordInfo() {
1825 std::string last_rtk_record_id;
1827 RLock rlock(status_mutex_);
1828 if (status_.current_operation() != HMIModeOperation::Waypoint_Follow) {
1831 last_rtk_record_id = status_.current_rtk_record_id();
1833 if (!last_rtk_record_id.empty()) {
1834 StopPlayRtkRecorder();
1837 WLock wlock(status_mutex_);
1838 status_.set_current_rtk_record_id(
"");
1839 status_changed_ =
true;
1844void HMIWorker::AddExpectedModules(
const HMIAction& action) {
1845 WLock wlock(status_mutex_);
1846 int expected_modules = 1;
1847 if (action == HMIAction::SETUP_MODE) {
1848 expected_modules = status_.modules_size();
1850 status_.set_expected_modules(status_.expected_modules() + expected_modules);
1851 status_changed_ =
true;
1854void HMIWorker::OnTimer(
const double& overtime_time) {
1855 if (monitor_reader_ !=
nullptr) {
1856 auto delay_sec = monitor_reader_->GetDelaySec();
1857 if (delay_sec < 0 || delay_sec > overtime_time) {
1858 AERROR <<
"Running time error: monitor is not turned on!";
1860 WLock wlock(status_mutex_);
1861 for (
auto& iter : *status_.mutable_modules_lock()) {
1862 iter.second =
false;
1870 WLock wlock(status_mutex_);
1871 auto modules = status_.mutable_modules();
1872 auto modules_lock = status_.mutable_modules_lock();
1873 for (
const auto &iter : current_mode_.
modules()) {
1874 if (previous_modules_lock_[iter.first] && (*modules_lock)[iter.first] &&
1875 !isProcessRunning(iter.second.start_command())) {
1876 (*modules)[iter.first] =
false;
1877 LockModule(iter.first,
false);
1879 previous_modules_lock_[iter.first] = (*modules_lock)[iter.first];
1884void HMIWorker::LockModule(
const std::string& module,
const bool& lock_flag) {
1885 auto modules_lock = status_.mutable_modules_lock();
1886 (*modules_lock)[module] = lock_flag;
1889bool HMIWorker::AddOrModifyObjectToDB(
const std::string& key,
1890 const std::string& value) {
1891 return KVDB::Put(key, value);
1894bool HMIWorker::DeleteObjectToDB(
const std::string& key) {
1895 return KVDB::Delete(key);
1898std::string HMIWorker::GetObjectFromDB(
const std::string& key) {
1899 return KVDB::Get(key).value_or(
"");
1902std::vector<std::pair<std::string, std::string>>
1903HMIWorker::GetTuplesWithTypeFromDB(
const std::string& type) {
1904 return KVDB::GetWithStart(type);
1907bool HMIWorker::StartTerminal() {
1908 return std::system(FLAGS_terminal_start_cmd.data()) == 0;
1911void HMIWorker::GetRtkRecordPath(std::string *record_path) {
1912 CHECK_NOTNULL(record_path);
1913 *record_path = FLAGS_resource_rtk_record_path;
1916bool HMIWorker::LoadRtkRecords() {
1918 WLock wLock(status_mutex_);
1919 status_.clear_rtk_records();
1921 std::string directory_path;
1922 GetRtkRecordPath(&directory_path);
1923 if (!cyber::common::PathExists(directory_path)) {
1924 AERROR <<
"Failed to find rtk records!";
1927 DIR *directory = opendir(directory_path.c_str());
1928 if (directory ==
nullptr) {
1929 AERROR <<
"Cannot open rtk record directory" << directory_path;
1932 struct dirent *file;
1933 std::map<std::string, double> new_records;
1934 while ((file = readdir(directory)) !=
nullptr) {
1935 if (!strcmp(file->d_name,
".") || !strcmp(file->d_name,
"..")) {
1938 if (file->d_type == DT_DIR) {
1941 const std::string record_id = file->d_name;
1942 const int index = record_id.rfind(
".csv");
1943 if (index != -1 && record_id[0] !=
'.') {
1944 const std::string local_record_resource = record_id.substr(0, index);
1946 WLock wLock(status_mutex_);
1947 status_.add_rtk_records(local_record_resource);
1951 closedir(directory);
1953 WLock wlock(status_mutex_);
1954 status_changed_ =
true;
1959bool HMIWorker::StartRtkDataRecorder() {
1960 std::string
start_cmd =
"nohup /apollo/scripts/rtk_recorder.sh start &";
1961 int ret = std::system(
start_cmd.data());
1965 AERROR <<
"Failed to start the rtk_recorder process";
1970bool HMIWorker::StopRtkDataRecorder() {
1971 std::string
stop_cmd =
"/apollo/scripts/rtk_recorder.sh stop";
1972 int ret = std::system(
stop_cmd.data());
1976 AERROR <<
"Failed to stop the rtk_recorder process";
1981Json HMIWorker::StartPlayRtkRecorder() {
1983 if (!ChangeDrivingMode(Chassis::COMPLETE_AUTO_DRIVE)) {
1984 AERROR <<
"Failed to play rtk: Failed to enter auto drive.";
1985 result[
"error"] =
"Failed to enter auto drive";
1986 result[
"isOk"] =
false;
1989 std::string record_id;
1991 RLock rlock(status_mutex_);
1992 record_id = status_.current_rtk_record_id();
1995 "nohup /apollo/scripts/rtk_player.sh start " + record_id +
" &";
1996 int ret = std::system(
start_cmd.data());
1998 AINFO <<
"Start the rtk_recorder process Successful.";
1999 result[
"isOk"] =
true;
2001 AERROR <<
"Failed to play rtk: Failed to start the rtk_recorder process.";
2002 result[
"error"] =
"Failed to start the rtk_recorder process";
2003 result[
"isOk"] =
false;
2008bool HMIWorker::StopPlayRtkRecorder() {
2009 std::string
stop_cmd =
"/apollo/scripts/rtk_player.sh stop";
2010 int ret = std::system(
stop_cmd.data());
2014 AERROR <<
"Failed to stop the rtk_recorder process";
2019int HMIWorker::SaveRtkDataRecorder(
const std::string &new_name) {
2020 std::string new_rtk_record_file =
2021 FLAGS_default_rtk_record_path + new_name +
".csv";
2022 if (cyber::common::PathExists(new_rtk_record_file)) {
2023 AERROR <<
"Failed to save the ret record, a file with the same name exists";
2026 if (std::rename(FLAGS_default_rtk_record_file.data(),
2027 new_rtk_record_file.data()) == 0) {
2028 UpdateRtkRecordToStatus(new_name);
2031 AERROR <<
"Failed to save the ret record, save command execution failed";
2036bool HMIWorker::DeleteRtkDataRecorder() {
2037 if (!cyber::common::PathExists(FLAGS_default_rtk_record_file)) {
2038 AERROR <<
"Failed to delete the ret record, file not exist";
2041 if (std::remove(FLAGS_default_rtk_record_file.data()) == 0) {
2044 AERROR <<
"Failed to delete the record, delete command execution failed";
2049void HMIWorker::ChangeRtkRecord(
const std::string &record_id) {
2050 if (!StopPlayRtkRecorder()) {
2051 AWARN <<
"Warning to change rtk record: Failed to stop the rtk_recorder "
2054 std::string last_record_id;
2056 RLock rlock(status_mutex_);
2057 last_record_id = status_.current_rtk_record_id();
2059 if (last_record_id == record_id) {
2060 AERROR <<
"Failed to change rtk record: rtk record is same!";
2063 WLock wlock(status_mutex_);
2064 status_.set_current_rtk_record_id(record_id);
2065 status_changed_ =
true;
2069void HMIWorker::UpdateRtkRecordToStatus(
const std::string &new_name) {
2070 WLock wlock(status_mutex_);
2071 status_.add_rtk_records(new_name);
2072 status_changed_ =
true;
2075void HMIWorker::ClearInvalidRecordStatus(
const HMIModeOperation &operation) {
2076 HMIModeOperation last_operation;
2078 RLock rlock(status_mutex_);
2079 last_operation = status_.current_operation();
2081 if (operation == last_operation) {
2083 }
else if (last_operation == HMIModeOperation::Waypoint_Follow) {
2084 StopRtkDataRecorder();
2085 DeleteRtkDataRecorder();
2086 }
else if (operation == HMIModeOperation::Waypoint_Follow) {
2088 DeleteDataRecorder();
2092bool HMIWorker::isProcessRunning(
const std::string &process_name) {
2093 std::stringstream commandStream;
2094 commandStream <<
"pgrep -f " << process_name;
2095 std::string command = commandStream.str();
2097 FILE *fp = popen(command.c_str(),
"r");
2100 if (fgets(result,
sizeof(result), fp) !=
nullptr) {
2101 AINFO << process_name <<
" is running";
2105 AINFO << process_name <<
" is not running";
2112bool HMIWorker::PackageExist(
const std::string& package_name) {
2113 std::string package_meta_info_path =
2114 FLAGS_apollo_package_meta_info_path_prefix + package_name +
2116 AINFO <<
"package_meta_info_path: " << package_meta_info_path;
2117 return (cyber::common::PathExists(package_meta_info_path));
2120std::string HMIWorker::GetCurrentModeDefaultLayout() {
2121 if (current_mode_.has_layout()) {
2122 const auto default_layout_json =
2124 "default_layout", current_mode_.layout());
2125 return default_layout_json[
"data"].dump();
2127 AWARN <<
"There is no default layout for the current mode.";
2131void HMIWorker::LoadDvPluginPanelsJson() {
2132 plugin_panels_json_ = Json::array();
2134 DIR *directory = opendir(FLAGS_dv_plugin_panels_path.c_str());
2136 AERROR <<
"can not open: " << FLAGS_dv_plugin_panels_path;
2140 struct dirent *file;
2141 while ((file = readdir(directory)) !=
nullptr) {
2142 if (!strcmp(file->d_name,
".") || !strcmp(file->d_name,
"..")) {
2145 std::string subdir_path = FLAGS_dv_plugin_panels_path +
"/" + file->d_name;
2146 if (file->d_type == DT_DIR) {
2147 std::string file_path = subdir_path +
"/conf.json";
2149 std::ifstream ifs(file_path);
2150 if (!ifs.is_open()) {
2151 AERROR <<
"can not open: " << file_path;
2158 plugin_panels_json_.push_back(conf_json);
2161 closedir(directory);
2164std::string HMIWorker::GetDvPluginPanelsJsonStr() {
2165 return plugin_panels_json_.empty() ?
"" : plugin_panels_json_.dump();
Lightweight key-value database to store system-wide parameters.
static nlohmann::json ProtoToTypedJson(const std::string &json_type, const google::protobuf::Message &proto)
Convert proto to a json string.
a singleton clock that can be used to get the current timestamp.
static double NowInSeconds()
gets the current time in second.
Node is the fundamental building block of Cyber RT.
Some string util functions.
size_t MessageFingerprint(const google::protobuf::Message &message)
bool LoadConfig(const std::string &relative_path, T *config)
boost::shared_lock< boost::shared_mutex > RLock
boost::unique_lock< boost::shared_mutex > WLock
const std::string start_cmd
const std::string stop_cmd
DEFINE_string(cyber_recorder_play_command, "cyber_recorder play -p 1 -f ", "Cyber recorder play command")