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"
46DEFINE_string(cyber_recorder_play_command,
"cyber_recorder play -p 1 -f ",
47 "Cyber recorder play command");
67using apollo::monitor::ComponentStatus;
68using apollo::monitor::SystemStatus;
69using RLock = boost::shared_lock<boost::shared_mutex>;
70using WLock = boost::unique_lock<boost::shared_mutex>;
71using Json = nlohmann::json;
73constexpr char kNavigationModeName[] =
"Navigation";
76const std::vector<HMIModeOperation> OperationBasedOnSimControl = {
77 HMIModeOperation::Scenario_Sim,
78 HMIModeOperation::Sim_Control,
81template <
class FlagType,
class ValueType>
82void SetGlobalFlag(std::string_view flag_name,
const ValueType &value,
84 constexpr char kGlobalFlagfile[] =
85 "/apollo/modules/common/data/global_flagfile.txt";
89 std::ofstream fout(kGlobalFlagfile, std::ios_base::app);
90 ACHECK(fout) <<
"Fail to open global flagfile " << kGlobalFlagfile;
91 fout <<
"\n--" << flag_name <<
"=" << value << std::endl;
95void System(std::string_view cmd) {
96 const int ret = std::system(cmd.data());
98 AINFO <<
"SUCCESS: " << cmd;
100 AERROR <<
"FAILED(" << ret <<
"): " << cmd;
107 const std::shared_ptr<Node> &node,
109 : config_(util::HMIUtil::
LoadConfig(FLAGS_dv_plus_hmi_modes_config_path)),
111 monitor_log_buffer_(monitor_log_buffer) {
113 time_interval_ms_ = 3000;
115 monitor_timer_.reset(
new cyber::Timer(
116 time_interval_ms_, [
this]() { this->OnTimer(overtime_time_); },
false));
117 monitor_timer_->Start();
120void HMIWorker::Start(DvCallback callback_api) {
121 callback_api_ = callback_api;
122 InitReadersAndWriters();
123 RegisterStatusUpdateHandler(
124 [
this](
const bool status_changed, HMIStatus *status) {
125 apollo::common::util::FillHeader(
"HMI", status);
126 status_writer_->Write(*status);
127 status->clear_header();
129 ResetComponentStatusTimer();
130 thread_future_ = cyber::Async(&HMIWorker::StatusUpdateThreadLoop,
this);
133void HMIWorker::Stop() {
135 std::system(FLAGS_terminal_stop_cmd.data());
136 if (thread_future_.valid()) {
137 thread_future_.get();
141bool HMIWorker::LoadVehicleDefinedMode(
const std::string &mode_config_path,
142 const std::string ¤t_vehicle_path,
143 HMIMode *self_defined_mode) {
144 const std::string mode_file_name =
145 cyber::common::GetFileName(mode_config_path);
146 const std::string vehicle_mode_config_path =
147 current_vehicle_path +
"/dreamview_conf/hmi_modes/" + mode_file_name;
148 if (!cyber::common::PathExists(vehicle_mode_config_path)) {
151 ACHECK(cyber::common::GetProtoFromFile(vehicle_mode_config_path,
153 <<
"Unable to parse vehicle self defined HMIMode from file "
154 << vehicle_mode_config_path;
155 util::HMIUtil::TranslateCyberModules(self_defined_mode);
159void HMIWorker::InitStatus() {
160 static constexpr char kDockerImageEnv[] =
"DOCKER_IMG";
161 status_.set_docker_image(cyber::common::GetEnv(kDockerImageEnv));
162 status_.set_utm_zone_id(FLAGS_local_utm_zone_id);
165 const auto &modes = config_.modes();
166 for (
const auto &iter : modes) {
167 const std::string &mode = iter.first;
168 status_.add_modes(mode);
169 if (mode == FLAGS_vehicle_calibration_mode) {
170 FuelMonitorManager::Instance()->RegisterFuelMonitor(
171 mode, std::make_unique<DataCollectionMonitor>());
172 FuelMonitorManager::Instance()->RegisterFuelMonitor(
173 mode, std::make_unique<PreprocessMonitor>());
174 }
else if (mode == FLAGS_lidar_calibration_mode) {
175 FuelMonitorManager::Instance()->RegisterFuelMonitor(
176 mode, std::make_unique<PreprocessMonitor>(
"lidar_to_gnss"));
177 }
else if (mode == FLAGS_camera_calibration_mode) {
178 FuelMonitorManager::Instance()->RegisterFuelMonitor(
179 mode, std::make_unique<PreprocessMonitor>(
"camera_to_lidar"));
184 for (
const auto &map_entry : config_.maps()) {
185 status_.add_maps(map_entry.first);
188 if (map_entry.second == FLAGS_map_dir) {
189 status_.set_current_map(map_entry.first);
194 for (
const auto &vehicle : config_.vehicles()) {
195 status_.add_vehicles(vehicle.first);
203 const std::string cached_mode =
204 KVDB::Get(FLAGS_current_mode_db_key).value_or(
"");
205 if (FLAGS_use_navigation_mode && ContainsKey(modes, kNavigationModeName)) {
206 ChangeMode(kNavigationModeName);
207 }
else if (ContainsKey(modes, cached_mode)) {
208 ChangeMode(cached_mode);
209 }
else if (ContainsKey(modes, FLAGS_default_hmi_mode)) {
210 ChangeMode(FLAGS_default_hmi_mode);
212 ChangeMode(modes.begin()->first);
216void HMIWorker::InitReadersAndWriters() {
217 status_writer_ = node_->CreateWriter<HMIStatus>(FLAGS_hmi_status_topic);
218 action_command_client_ = node_->CreateClient<ActionCommand, CommandStatus>(
219 FLAGS_action_command_topic);
220 audio_event_writer_ =
221 node_->CreateWriter<AudioEvent>(FLAGS_audio_event_topic);
222 drive_event_writer_ =
223 node_->CreateWriter<DriveEvent>(FLAGS_drive_event_topic);
225 monitor_reader_ = node_->CreateReader<SystemStatus>(
226 FLAGS_system_status_topic,
227 [
this](
const std::shared_ptr<SystemStatus> &system_status) {
228 this->ResetComponentStatusTimer();
230 WLock wlock(status_mutex_);
232 const bool is_realtime_msg =
234 ? system_status->is_realtime_in_simulation()
236 system_status->header().timestamp_sec() <
237 FLAGS_system_status_lifetime_seconds;
239 if (is_realtime_msg) {
240 for (
auto &iter : *status_.mutable_modules()) {
241 bool previous_second = iter.second;
242 auto *status = FindOrNull(system_status->hmi_modules(), iter.first);
244 status !=
nullptr && status->status() == ComponentStatus::OK;
245 if (previous_second != iter.second) {
246 LockModule(iter.first,
false);
251 if (system_status->detect_immediately()) {
252 status_.set_expected_modules(status_.expected_modules() - 1);
256 for (
auto &iter : *status_.mutable_monitored_components()) {
257 auto *status = FindOrNull(system_status->components(), iter.first);
258 if (status !=
nullptr) {
259 iter.second = status->summary();
261 iter.second.set_status(ComponentStatus::UNKNOWN);
262 iter.second.set_message(
"Status not reported by Monitor.");
267 for (
auto &iter : *status_.mutable_other_components()) {
269 FindOrNull(system_status->other_components(), iter.first);
270 if (status !=
nullptr) {
271 iter.second.CopyFrom(*status);
273 iter.second.set_status(ComponentStatus::UNKNOWN);
274 iter.second.set_message(
"Status not reported by Monitor.");
278 for (
auto &iter : *system_status->mutable_global_components()) {
279 (*status_.mutable_global_components())[iter.first] = iter.second;
283 const size_t new_fingerprint =
285 if (last_status_fingerprint_ != new_fingerprint) {
286 status_changed_ =
true;
287 last_status_fingerprint_ = new_fingerprint;
291 node_->CreateReader<RecordInfo>(
292 FLAGS_record_info_topic,
293 [
this](
const std::shared_ptr<RecordInfo> &record_info) {
294 WLock wlock(status_mutex_);
295 if (record_info->record_name() ==
296 status_.current_record_status().current_record_id()) {
297 status_.mutable_current_record_status()->set_curr_time_s(
298 record_info.get()->curr_time_s());
299 status_changed_ =
true;
303 localization_reader_ =
304 node_->CreateReader<LocalizationEstimate>(FLAGS_localization_topic);
306 chassis_reader_ = node_->CreateReader<Chassis>(
307 FLAGS_chassis_topic, [
this](
const std::shared_ptr<Chassis> &chassis) {
309 FLAGS_system_status_lifetime_seconds) {
310 if (chassis->signal().high_beam()) {
312 const bool ret = Trigger(HMIAction::NONE);
313 AERROR_IF(!ret) <<
"Failed to execute high_beam action.";
319bool HMIWorker::Trigger(
const HMIAction action) {
320 AERROR <<
"HMIAction " << HMIAction_Name(action) <<
" was triggered!";
322 case HMIAction::NONE:
324 case HMIAction::SETUP_MODE:
326 AddExpectedModules(action);
328 case HMIAction::ENTER_AUTO_MODE:
329 return ChangeDrivingMode(Chassis::COMPLETE_AUTO_DRIVE);
330 case HMIAction::DISENGAGE:
331 return ChangeDrivingMode(Chassis::COMPLETE_MANUAL);
332 case HMIAction::RESET_MODE:
335 case HMIAction::LOAD_DYNAMIC_MODELS:
338 case HMIAction::LOAD_RECORDS:
341 case HMIAction::LOAD_RTK_RECORDS:
344 case HMIAction::STOP_RECORD:
347 case HMIAction::LOAD_MAPS:
351 AERROR <<
"HMIAction not implemented, yet!";
357bool HMIWorker::Trigger(
const HMIAction action,
const std::string &value) {
358 AINFO <<
"HMIAction " << HMIAction_Name(action) <<
"(" << value
359 <<
") was triggered!";
362 case HMIAction::CHANGE_MODE:
365 case HMIAction::CHANGE_MAP:
366 ret = ChangeMap(value);
369 SimControlManager::Instance()->Restart();
371 case HMIAction::CHANGE_VEHICLE:
372 ChangeVehicle(value);
374 case HMIAction::START_MODULE:
376 AddExpectedModules(action);
378 case HMIAction::STOP_MODULE:
381 case HMIAction::DELETE_SCENARIO_SET:
382 DeleteScenarioSet(value);
384 case HMIAction::CHANGE_DYNAMIC_MODEL:
385 ChangeDynamicModel(value);
387 case HMIAction::DELETE_DYNAMIC_MODEL:
388 DeleteDynamicModel(value);
390 case HMIAction::DELETE_RECORD:
393 case HMIAction::CHANGE_RECORD:
396 case HMIAction::CHANGE_RTK_RECORD:
397 ChangeRtkRecord(value);
399 case HMIAction::CHANGE_OPERATION:
400 ChangeOperation(value);
402 case HMIAction::DELETE_VEHICLE_CONF:
403 DeleteVehicleConfig(value);
404 case HMIAction::DELETE_V2X_CONF:
405 DeleteV2xConfig(value);
407 case HMIAction::DELETE_MAP:
410 case HMIAction::LOAD_RECORD:
411 LoadRecordAndChangeStatus(value);
414 AERROR <<
"HMIAction not implemented, yet!";
420void HMIWorker::SubmitAudioEvent(
const uint64_t event_time_ms,
421 const int obstacle_id,
const int audio_type,
422 const int moving_result,
423 const int audio_direction,
424 const bool is_siren_on) {
425 std::shared_ptr<AudioEvent> audio_event = std::make_shared<AudioEvent>();
426 apollo::common::util::FillHeader(
"HMI", audio_event.get());
430 audio_event->mutable_header()->set_timestamp_sec(
431 static_cast<double>(event_time_ms) / 1000.0);
432 audio_event->set_id(obstacle_id);
433 audio_event->set_audio_type(
435 audio_event->set_moving_result(
437 audio_event->set_audio_direction(
439 audio_event->set_siren_is_on(is_siren_on);
442 localization_reader_->Observe();
443 if (localization_reader_->Empty()) {
444 AERROR <<
"Failed to get localization associated with the audio event: "
445 << audio_event->DebugString() <<
"\n Localization reader is empty!";
449 const std::shared_ptr<LocalizationEstimate> localization =
450 localization_reader_->GetLatestObserved();
451 audio_event->mutable_pose()->CopyFrom(localization->pose());
452 AINFO <<
"AudioEvent: " << audio_event->DebugString();
454 audio_event_writer_->Write(audio_event);
457void HMIWorker::SubmitDriveEvent(
const uint64_t event_time_ms,
458 const std::string &event_msg,
459 const std::vector<std::string> &event_types,
460 const bool is_reportable) {
461 std::shared_ptr<DriveEvent> drive_event = std::make_shared<DriveEvent>();
462 apollo::common::util::FillHeader(
"HMI", drive_event.get());
466 drive_event->mutable_header()->set_timestamp_sec(
467 static_cast<double>(event_time_ms) / 1000.0);
468 drive_event->set_event(event_msg);
469 drive_event->set_is_reportable(is_reportable);
470 for (
const auto &type_name : event_types) {
471 DriveEvent::Type type;
472 if (DriveEvent::Type_Parse(type_name, &type)) {
473 drive_event->add_type(type);
475 AERROR <<
"Failed to parse drive event type:" << type_name;
478 drive_event_writer_->Write(drive_event);
481void HMIWorker::SensorCalibrationPreprocess(
const std::string &task_type) {
482 std::string start_command = absl::StrCat(
483 "nohup bash /apollo/modules/tools/sensor_calibration/extract_data.sh -t ",
485 System(start_command);
488void HMIWorker::VehicleCalibrationPreprocess() {
489 std::string start_command = absl::StrCat(
490 "nohup bash /apollo/modules/tools/vehicle_calibration/preprocess.sh "
492 status_.current_vehicle(),
"\" --record_num=", record_count_,
" &");
493 System(start_command);
496bool HMIWorker::ChangeDrivingMode(
const Chassis::DrivingMode mode) {
498 const std::string mode_name = Chassis::DrivingMode_Name(mode);
499 if (mode != Chassis::COMPLETE_MANUAL) {
500 if (!ChangeDrivingMode(Chassis::COMPLETE_MANUAL)) {
501 AERROR <<
"Failed to reset to MANUAL before changing to " << mode_name;
506 auto command = std::make_shared<ActionCommand>();
509 case Chassis::COMPLETE_MANUAL:
510 command->set_command(
513 case Chassis::COMPLETE_AUTO_DRIVE:
514 command->set_command(
518 AFATAL <<
"Change driving mode to " << mode_name <<
" not implemented!";
522 static constexpr int kMaxTries = 3;
523 static constexpr auto kTryInterval = std::chrono::milliseconds(500);
524 for (
int i = 0; i < kMaxTries; ++i) {
526 common::util::FillHeader(
"HMI", command.get());
527 action_command_client_->SendRequest(command);
529 std::this_thread::sleep_for(kTryInterval);
531 chassis_reader_->Observe();
532 if (chassis_reader_->Empty()) {
533 AERROR <<
"No Chassis message received!";
534 }
else if (chassis_reader_->GetLatestObserved()->driving_mode() == mode) {
538 AERROR <<
"Failed to change driving mode to " << mode_name;
542bool HMIWorker::ChangeMap(
const std::string &map_name) {
543 if (status_.current_map() == map_name) {
547 return SelectAndReloadMap(map_name);
550bool HMIWorker::SelectAndReloadMap(
const std::string &map_name) {
551 const std::string *map_dir = FindOrNull(config_.maps(), map_name);
552 if (map_dir ==
nullptr) {
553 AERROR <<
"Unknown map " << map_name;
559 SetGlobalFlag(
"map_dir", *map_dir, &FLAGS_map_dir);
561 Json callback_res = callback_api_(
"MapServiceReloadMap", {});
564 WLock wlock(status_mutex_);
565 status_.set_current_map(map_name);
566 status_changed_ =
true;
568 return callback_res[
"result"];
571void HMIWorker::UpdateModeModulesAndMonitoredComponents() {
572 status_.clear_modules();
573 status_.clear_modules_lock();
574 previous_modules_lock_.clear();
575 for (
const auto &iter : current_mode_.
modules()) {
576 status_.mutable_modules()->insert({iter.first,
false});
577 status_.mutable_modules_lock()->insert({iter.first,
false});
578 previous_modules_lock_.insert({iter.first,
false});
582 status_.clear_monitored_components();
583 for (
const auto &iter : current_mode_.monitored_components()) {
584 status_.mutable_monitored_components()->insert({iter.first, {}});
588void HMIWorker::ChangeVehicle(
const std::string &vehicle_name) {
589 const std::string *vehicle_dir = FindOrNull(config_.vehicles(), vehicle_name);
590 if (vehicle_dir ==
nullptr) {
591 AERROR <<
"Unknown vehicle " << vehicle_name;
594 std::string current_mode;
597 WLock wlock(status_mutex_);
598 current_mode = status_.current_mode();
599 if (status_.current_vehicle() == vehicle_name) {
605 const std::string vehicle_type_file_path = *vehicle_dir +
"/vehicle_type";
606 std::string vehicle_type_str;
607 cyber::common::GetContent(vehicle_type_file_path, &vehicle_type_str);
608 int vehicle_type = std::stoi(vehicle_type_str);
609 status_.set_current_vehicle_type(vehicle_type);
610 }
catch (
const std::exception &e) {
611 AWARN <<
"get vehicle type config failed: " << e.what();
612 status_.clear_current_vehicle_type();
614 status_.set_current_vehicle(vehicle_name);
615 status_changed_ =
true;
619 HMIMode vehicle_defined_mode;
620 const std::string mode_config_path = config_.modes().at(current_mode);
621 if (LoadVehicleDefinedMode(mode_config_path, *vehicle_dir,
622 &vehicle_defined_mode)) {
623 MergeToCurrentMode(&vehicle_defined_mode);
627 current_mode_ = util::HMIUtil::LoadMode(mode_config_path);
630 WLock wlock(status_mutex_);
631 UpdateModeModulesAndMonitoredComponents();
633 ACHECK(VehicleManager::Instance()->UseVehicle(*vehicle_dir));
635 auto *monitors = FuelMonitorManager::Instance()->GetCurrentMonitors();
636 if (monitors !=
nullptr) {
637 for (
const auto &monitor : *monitors) {
638 if (monitor.second->IsEnabled()) {
639 monitor.second->Restart();
645void HMIWorker::MergeToCurrentMode(HMIMode *mode) {
646 current_mode_.clear_modules();
647 current_mode_.clear_cyber_modules();
648 current_mode_.clear_monitored_components();
649 current_mode_.mutable_modules()->swap(*(mode->mutable_modules()));
650 current_mode_.mutable_monitored_components()->swap(
651 *(mode->mutable_monitored_components()));
654void HMIWorker::ChangeMode(
const std::string &mode_name) {
655 if (!ContainsKey(config_.modes(), mode_name)) {
656 AERROR <<
"Cannot change to unknown mode " << mode_name;
661 RLock rlock(status_mutex_);
663 if (status_.current_mode() == mode_name) {
668 std::string default_operation_str =
"";
670 WLock wlock(status_mutex_);
671 status_.set_current_mode(mode_name);
672 current_mode_ = util::HMIUtil::LoadMode(config_.modes().at(mode_name));
674 HMIMode vehicle_defined_mode;
675 const std::string *vehicle_dir =
676 FindOrNull(config_.vehicles(), status_.current_vehicle());
677 if (vehicle_dir !=
nullptr &&
678 LoadVehicleDefinedMode(config_.modes().at(mode_name), *vehicle_dir,
679 &vehicle_defined_mode)) {
680 MergeToCurrentMode(&vehicle_defined_mode);
682 UpdateModeModulesAndMonitoredComponents();
684 status_.clear_other_components();
685 for (
const auto &iter : current_mode_.other_components()) {
686 status_.mutable_other_components()->insert({iter.first, {}});
690 status_.clear_operations();
691 status_.mutable_operations()->CopyFrom(current_mode_.operations());
695 if ((mode_name ==
"Pnc" || mode_name ==
"Default") &&
696 PackageExist(
"simulator-plugin")) {
697 status_.add_operations(HMIModeOperation::Scenario_Sim);
700 if (current_mode_.has_default_operation()) {
701 default_operation_str =
702 HMIModeOperation_Name(current_mode_.default_operation());
704 status_changed_ =
true;
710 if (!default_operation_str.empty()) {
711 ChangeOperation(default_operation_str);
713 FuelMonitorManager::Instance()->SetCurrentMode(mode_name);
714 KVDB::Put(FLAGS_current_mode_db_key, mode_name);
717void HMIWorker::StartModule(
const std::string &module) {
718 const Module *module_conf = FindOrNull(current_mode_.modules(), module);
719 if (module_conf !=
nullptr) {
721 WLock wlock(status_mutex_);
722 LockModule(module,
true);
724 System(module_conf->start_command());
726 AERROR <<
"Cannot find module " <<
module;
730void HMIWorker::StopModule(
const std::string &module) {
731 const Module *module_conf = FindOrNull(current_mode_.modules(), module);
732 if (module_conf !=
nullptr) {
734 WLock wlock(status_mutex_);
735 LockModule(module,
true);
737 System(module_conf->stop_command());
739 AERROR <<
"Cannot find module " <<
module;
743HMIStatus HMIWorker::GetStatus()
const {
744 RLock rlock(status_mutex_);
748void HMIWorker::SetupMode() {
750 WLock wlock(status_mutex_);
751 status_.set_backend_shutdown(
false);
753 for (
const auto &iter : current_mode_.
modules()) {
755 WLock wlock(status_mutex_);
756 auto modules = status_.modules();
758 LockModule(iter.first,
true);
761 System(iter.second.start_command());
765void HMIWorker::ResetMode() {
769 WLock wlock(status_mutex_);
770 status_.set_backend_shutdown(
true);
772 for (
const auto &iter : current_mode_.
modules()) {
774 WLock wlock(status_mutex_);
775 auto modules = status_.modules();
777 LockModule(iter.first,
true);
780 System(iter.second.stop_command());
785void HMIWorker::StatusUpdateThreadLoop() {
786 constexpr int kLoopIntervalMs = 200;
788 std::this_thread::sleep_for(std::chrono::milliseconds(kLoopIntervalMs));
789 UpdateComponentStatus();
790 bool status_changed =
false;
792 WLock wlock(status_mutex_);
793 status_changed = status_changed_;
794 status_changed_ =
false;
797 if (!status_changed) {
798 static double next_update_time = 0;
800 if (now < next_update_time) {
803 next_update_time = now + FLAGS_status_publish_interval;
807 HMIStatus status = GetStatus();
808 for (
const auto handler : status_update_handlers_) {
809 handler(status_changed, &status);
814void HMIWorker::ResetComponentStatusTimer() {
816 last_status_fingerprint_ = 0;
819void HMIWorker::UpdateComponentStatus() {
821 if (now - last_status_received_s_.load() > FLAGS_monitor_timeout_threshold) {
822 if (!monitor_timed_out_) {
823 WLock wlock(status_mutex_);
825 const uint64_t now_ms =
static_cast<uint64_t
>(now * 2e3);
826 static constexpr bool kIsReportable =
true;
827 SubmitDriveEvent(now_ms,
"Monitor timed out", {
"PROBLEM"}, kIsReportable);
828 AWARN <<
"System fault. Auto disengage.";
829 Trigger(HMIAction::DISENGAGE);
831 for (
auto &monitored_component :
832 *status_.mutable_monitored_components()) {
833 monitored_component.second.set_status(ComponentStatus::UNKNOWN);
834 monitored_component.second.set_message(
835 "Status not reported by Monitor.");
837 status_changed_ =
true;
839 monitor_timed_out_ =
true;
841 monitor_timed_out_ =
false;
845void HMIWorker::GetScenarioResourcePath(std::string *scenario_resource_path) {
846 CHECK_NOTNULL(scenario_resource_path);
847 const std::string home = cyber::common::GetEnv(
"HOME");
848 *scenario_resource_path = home + FLAGS_resource_scenario_path;
851void HMIWorker::ChangeDynamicModel(
const std::string &dynamic_model_name) {
860 if (dynamic_model_name.empty()) {
861 AERROR <<
"Failed to change empty dynamic model!";
864 auto sim_control_manager = SimControlManager::Instance();
865 if (!sim_control_manager->IsEnabled()) {
866 AERROR <<
"Sim control is not enabled!";
870 if (!sim_control_manager->ChangeDynamicModel(dynamic_model_name)) {
874 AERROR <<
"Failed to change dynamic model! Please check if the param is "
878 std::string current_dynamic_model_name = dynamic_model_name;
880 WLock wlock(status_mutex_);
881 status_.set_current_dynamic_model(dynamic_model_name);
882 status_changed_ =
true;
887bool HMIWorker::UpdateDynamicModelToStatus(
888 const std::string &dynamic_model_name) {
889 auto sim_control_manager = SimControlManager::Instance();
890 if (!sim_control_manager->IsEnabled()) {
891 AERROR <<
"Sim control is not enabled or missing dynamic model name "
896 if (!sim_control_manager->AddDynamicModel(dynamic_model_name)) {
897 AERROR <<
"Failed to add dynamic model to local dynamic model list for "
902 WLock wlock(status_mutex_);
903 for (
const auto &iter : status_.dynamic_models()) {
904 if (iter == dynamic_model_name) {
905 AERROR <<
"Do not need to add new dynamic model for is duplicate!";
909 status_.add_dynamic_models(dynamic_model_name);
910 status_changed_ =
true;
915bool HMIWorker::LoadDynamicModels() {
916 auto sim_control_manager = SimControlManager::Instance();
917 nlohmann::json load_res;
918 if (sim_control_manager->IsEnabled()) {
919 load_res = sim_control_manager->LoadDynamicModels();
921 AERROR <<
"Sim control is not enabled!";
924 if (!load_res.contains(
"result") || !load_res[
"result"]) {
929 WLock wlock(status_mutex_);
930 auto dynamic_models = status_.mutable_dynamic_models();
932 for (
auto iter = dynamic_models->begin(); iter != dynamic_models->end();) {
933 iter = dynamic_models->erase(iter);
935 for (
const auto &dynamic_model : load_res[
"loaded_dynamic_models"]) {
936 status_.add_dynamic_models(dynamic_model);
938 status_changed_ =
true;
943void HMIWorker::DeleteScenarioSet(
const std::string &scenario_set_id) {
944 if (scenario_set_id.empty()) {
947 std::string directory_path;
948 GetScenarioResourcePath(&directory_path);
949 directory_path = directory_path + scenario_set_id;
950 if (!cyber::common::PathExists(directory_path)) {
951 AERROR <<
"Failed to find scenario_set!";
954 std::string command =
"rm -fr " + directory_path;
957 if (std::system(command.data()) != 0) {
958 AERROR <<
"Failed to delete scenario set directory for: "
959 << std::strerror(errno);
965void HMIWorker::DeleteDynamicModel(
const std::string &dynamic_model_name) {
966 if (dynamic_model_name.empty()) {
967 AERROR <<
"Invalid param:empty dynamic model name!";
971 RLock rlock(status_mutex_);
973 if (dynamic_model_name == status_.current_dynamic_model()) {
974 AERROR <<
"Cannot delete current dynamic model!";
977 if (dynamic_model_name == FLAGS_sim_perfect_control) {
978 AERROR <<
"Cannot delete default sim control:SimPerfectControl!";
982 auto sim_control_manager = SimControlManager::Instance();
983 if (!sim_control_manager->IsEnabled()) {
984 AERROR <<
"Sim control is not enabled!";
987 if (!sim_control_manager->DeleteDynamicModel(dynamic_model_name)) {
990 AERROR <<
"Failed to delete dynamic model!";
994 WLock wlock(status_mutex_);
995 auto iter = status_.dynamic_models().begin();
996 while (iter != status_.dynamic_models().end()) {
997 if (*iter == dynamic_model_name) {
1002 if (iter != status_.dynamic_models().end()) {
1003 status_.mutable_dynamic_models()->erase(iter);
1004 status_changed_ =
true;
1006 AWARN <<
"Can not find dynamic model to delete!";
1012void HMIWorker::GetRecordPath(std::string *record_path) {
1013 CHECK_NOTNULL(record_path);
1014 const std::string home = cyber::common::GetEnv(
"HOME");
1015 *record_path = home + FLAGS_resource_record_path;
1018bool HMIWorker::handlePlayRecordProcess(
const std::string &action_type) {
1019 std::string record_id;
1020 PlayRecordStatus current_play_record_status;
1021 PlayRecordStatus expected_play_record_status;
1022 PlayRecordStatus reasonable_play_record_status;
1024 RLock rlock(status_mutex_);
1025 auto record_status = status_.current_record_status();
1026 record_id = record_status.current_record_id();
1027 current_play_record_status = record_status.play_record_status();
1028 if (record_id.empty()) {
1029 AERROR <<
"Failed to pause record for record has not been selected"
1030 "or process is not exists!";
1033 if (!RecordIsLoaded(record_id)) {
1034 AERROR <<
"Failed to pause record for record has not been loaded!";
1038 if (action_type.compare(
"continue") == 0) {
1039 expected_play_record_status = PlayRecordStatus::RUNNING;
1040 reasonable_play_record_status = PlayRecordStatus::PAUSED;
1041 }
else if (action_type.compare(
"pause") == 0) {
1042 expected_play_record_status = PlayRecordStatus::PAUSED;
1043 reasonable_play_record_status = PlayRecordStatus::RUNNING;
1045 AERROR <<
"Invalid action type for play record.";
1048 if (reasonable_play_record_status != current_play_record_status) {
1051 auto *record_player_factory = RecordPlayerFactory::Instance();
1052 auto player_ptr = record_player_factory->GetRecordPlayer(record_id);
1054 AERROR <<
"Failed to get record player.";
1057 player_ptr->HandleNohupThreadStatus();
1060 WLock wlock(status_mutex_);
1061 status_.mutable_current_record_status()->set_play_record_status(
1062 expected_play_record_status);
1063 status_changed_ =
true;
1065 record_player_factory->IncreaseRecordPriority(record_id);
1069bool HMIWorker::RePlayRecord() {
1070 std::string record_id;
1072 RLock rlock(status_mutex_);
1073 auto record_status = status_.current_record_status();
1074 record_id = record_status.current_record_id();
1075 if (record_status.current_record_id().empty()) {
1076 AERROR <<
"Failed to play record for record has not been selected!";
1079 if (!RecordIsLoaded(record_id)) {
1080 AERROR <<
"Failed to play record for record has not been loaded!";
1083 if (record_status.play_record_status() == PlayRecordStatus::RUNNING) {
1084 AERROR <<
"Record has been played,ignore dumplicate request.";
1088 std::string record_path;
1089 GetRecordPath(&record_path);
1090 record_path = record_path + record_id +
".record";
1092 if (!cyber::common::PathExists(record_path)) {
1093 AERROR <<
"Failed to find record!";
1097 auto *record_player_factory = RecordPlayerFactory::Instance();
1098 auto player_ptr = record_player_factory->GetRecordPlayer(record_id);
1099 bool play_record_res = (player_ptr !=
nullptr);
1100 PlayRecordStatus play_record_status;
1101 if (!play_record_res) {
1102 AERROR <<
"Failed to get record related player";
1103 play_record_status = PlayRecordStatus::CLOSED;
1105 player_ptr->PreloadPlayRecord();
1106 player_ptr->NohupPlayRecord();
1108 callback_api_(
"GetDataHandlerConf", {});
1109 play_record_status = PlayRecordStatus::RUNNING;
1112 WLock wlock(status_mutex_);
1113 auto record_status = status_.mutable_current_record_status();
1114 record_status->set_play_record_status(play_record_status);
1115 status_changed_ =
true;
1117 record_player_factory->IncreaseRecordPriority(record_id);
1118 return play_record_res;
1121bool HMIWorker::ResetRecordProgress(
const double &progress) {
1122 std::string record_id;
1123 double total_time_s;
1124 PlayRecordStatus last_record_status;
1126 RLock rlock(status_mutex_);
1127 auto record_status = status_.current_record_status();
1128 record_id = record_status.current_record_id();
1129 last_record_status = record_status.play_record_status();
1130 if (record_status.current_record_id().empty()) {
1131 AERROR <<
"Failed to reset record progress for record has not been "
1135 if (!RecordIsLoaded(record_id)) {
1136 AERROR <<
"Failed to reset record progress for record has not been "
1140 total_time_s = status_.records().at(record_id).total_time_s();
1142 AERROR <<
"total : " << total_time_s;
1143 if (progress > total_time_s) {
1144 AERROR <<
"Failed to reset record progress for progress exceeds the "
1145 "record's total time.";
1148 auto *record_player_factory = RecordPlayerFactory::Instance();
1149 auto player_ptr = record_player_factory->GetRecordPlayer(record_id);
1151 AERROR <<
"Failed to get record player.";
1154 player_ptr->Reset();
1155 player_ptr->PreloadPlayRecord(
1156 progress, (last_record_status != PlayRecordStatus::RUNNING));
1157 player_ptr->NohupPlayRecord();
1161 if (last_record_status == PlayRecordStatus::CLOSED) {
1162 last_record_status = PlayRecordStatus::PAUSED;
1165 callback_api_(
"GetDataHandlerConf", {});
1167 WLock wlock(status_mutex_);
1168 auto record_status = status_.mutable_current_record_status();
1169 record_status->set_play_record_status(last_record_status);
1170 record_status->set_curr_time_s(progress);
1171 status_changed_ =
true;
1173 record_player_factory->IncreaseRecordPriority(record_id);
1177void HMIWorker::StopRecordPlay(
const std::string &record_id) {
1178 std::string curr_record_id =
"";
1180 RLock rlock(status_mutex_);
1181 curr_record_id = status_.current_record_status().current_record_id();
1183 if (!record_id.empty()) {
1184 curr_record_id = record_id;
1186 if (!RecordIsLoaded(curr_record_id)) {
1187 AERROR <<
"Failed to stop record player under unloaded status!";
1190 auto *record_player_factory = RecordPlayerFactory::Instance();
1191 auto player_ptr = record_player_factory->GetRecordPlayer(curr_record_id);
1193 AERROR <<
"Failed to get record player to reset.";
1196 player_ptr->Reset();
1198 WLock wlock(status_mutex_);
1199 auto record_status = status_.mutable_current_record_status();
1200 record_status->set_play_record_status(PlayRecordStatus::CLOSED);
1201 record_status->clear_curr_time_s();
1203 status_changed_ =
true;
1206bool HMIWorker::RecordIsLoaded(
const std::string &record_id) {
1208 RLock rlock(status_mutex_);
1209 auto iter = status_.records().find(record_id);
1210 return iter != status_.records().end() &&
1211 (iter->second.load_record_status() == LoadRecordStatus::LOADED);
1215void HMIWorker::ChangeRecord(
const std::string &record_id) {
1216 std::string last_record_id;
1218 RLock rlock(status_mutex_);
1219 auto status_records = status_.mutable_records();
1220 auto iter = status_records->find(record_id);
1221 if (iter == status_records->end()) {
1222 AERROR <<
"Cannot change to unknown record!";
1225 if (!RecordIsLoaded(record_id)) {
1226 AERROR <<
"Cannot change to unloaded record, load this record before!";
1229 last_record_id = status_.current_record_status().current_record_id();
1231 if (!last_record_id.empty()) {
1232 StopRecordPlay(last_record_id);
1235 callback_api_(
"ClearDataHandlerConfChannelMsgs", {});
1236 WLock wlock(status_mutex_);
1237 status_.mutable_current_record_status()->set_current_record_id(record_id);
1238 auto *record_player_factory = RecordPlayerFactory::Instance();
1239 record_player_factory->SetCurrentRecord(record_id);
1240 record_player_factory->IncreaseRecordPriority(record_id);
1241 status_changed_ =
true;
1245void HMIWorker::ClearInvalidResourceUnderChangeOperation(
1246 const HMIModeOperation operation) {
1247 ClearInvalidRecordStatus(operation);
1248 HMIModeOperation old_operation;
1250 RLock rlock(status_mutex_);
1251 old_operation = status_.current_operation();
1255 auto sim_control_manager = SimControlManager::Instance();
1256 auto iter = std::find(OperationBasedOnSimControl.begin(),
1257 OperationBasedOnSimControl.end(), operation);
1258 if (iter != OperationBasedOnSimControl.end()) {
1259 sim_control_manager->Start();
1261 sim_control_manager->Stop();
1264 WLock wlock(status_mutex_);
1265 status_.set_current_dynamic_model(
"");
1266 status_.clear_dynamic_models();
1267 status_changed_ =
true;
1270 if (old_operation == HMIModeOperation::Record) {
1274 if (old_operation == HMIModeOperation::Waypoint_Follow) {
1276 ClearRtkRecordInfo();
1280void HMIWorker::ChangeOperation(
const std::string &operation_str) {
1281 HMIModeOperation operation;
1282 if (!HMIModeOperation_Parse(operation_str, &operation)) {
1283 AERROR <<
"Invalid HMI operation string: " << operation_str;
1287 RLock rlock(status_mutex_);
1288 if (status_.current_mode().empty()) {
1289 AERROR <<
"Please select mode!";
1292 auto status_operations = status_.operations();
1293 auto iter = status_operations.begin();
1294 for (; iter != status_operations.end(); iter++) {
1295 if (*iter == operation) {
1299 if (iter == status_operations.end()) {
1300 AERROR <<
"Cannot change to unknown operation!";
1304 ClearInvalidResourceUnderChangeOperation(operation);
1306 WLock wlock(status_mutex_);
1307 status_.set_current_operation(operation);
1308 status_changed_ =
true;
1313bool HMIWorker::ReadRecordInfo(
const std::string &file,
1314 double *total_time_s)
const {
1315 cyber::record::RecordFileReader file_reader;
1316 if (!file_reader.Open(file)) {
1317 AERROR <<
"open record file error. file: " << file;
1320 cyber::proto::Header hdr = file_reader.GetHeader();
1321 if (!hdr.is_complete()) {
1322 AERROR <<
"record is not complete, can not be used. file: " << file;
1325 auto begin_time_s =
static_cast<double>(hdr.begin_time()) / 1e9;
1326 auto end_time_s =
static_cast<double>(hdr.end_time()) / 1e9;
1327 double loop_time_s = end_time_s - begin_time_s;
1328 *total_time_s = std::round(loop_time_s * 1e2) / 1e2;
1332bool HMIWorker::UpdateMapToStatus(
const std::string &map_tar_name) {
1333 if (map_tar_name.empty()) {
1337 std::string map_dir = FLAGS_maps_data_path +
"/";
1338 std::string map_name_prefix;
1339 int index = map_tar_name.rfind(
".tar.xz");
1340 if (index != -1 && map_tar_name[0] !=
'.') {
1341 map_name_prefix = map_tar_name.substr(0, index);
1342 map_dir = map_dir + map_name_prefix;
1344 AERROR <<
"The map name does not meet the standard!" << map_tar_name;
1347 if (!cyber::common::PathExists(map_dir)) {
1348 AERROR <<
"Failed to find maps!";
1351 map_name_prefix = util::HMIUtil::TitleCase(map_name_prefix);
1353 WLock wlock(status_mutex_);
1354 auto iter = status_.maps().begin();
1355 for (; iter != status_.maps().end(); iter++) {
1356 if (*iter == map_name_prefix) {
1360 if (iter != status_.maps().end()) {
1363 status_.add_maps(map_name_prefix);
1364 status_changed_ =
true;
1369bool HMIWorker::LoadRecordAndChangeStatus(
const std::string &record_name) {
1370 std::string record_file_path;
1372 RLock rlock(status_mutex_);
1373 auto &status_records = status_.records();
1374 auto iter = status_records.find(record_name);
1375 if (iter == status_records.end()) {
1376 AERROR <<
"Cannot load unknown record!";
1379 if (RecordIsLoaded(record_name)) {
1380 AERROR <<
"Cannot load already loaded record.";
1383 if (iter->second.record_file_path().empty()) {
1384 AERROR <<
"Cannot load record without record file path!";
1387 record_file_path = iter->second.record_file_path();
1390 WLock wlock(status_mutex_);
1391 auto status_records = status_.mutable_records();
1392 (*status_records)[record_name].set_load_record_status(
1393 LoadRecordStatus::LOADING);
1395 double total_time_s;
1396 if (LoadRecord(record_name, record_file_path, &total_time_s)) {
1398 WLock wlock(status_mutex_);
1399 auto status_records = status_.mutable_records();
1400 (*status_records)[record_name].set_load_record_status(
1401 LoadRecordStatus::LOADED);
1402 (*status_records)[record_name].set_total_time_s(total_time_s);
1404 RecordPlayerFactory::Instance()->IncreaseRecordPriority(record_name);
1407 WLock wlock(status_mutex_);
1408 auto status_records = status_.mutable_records();
1409 (*status_records)[record_name].set_load_record_status(
1410 LoadRecordStatus::NOT_LOAD);
1416bool HMIWorker::LoadRecord(
const std::string &record_name,
1417 const std::string &record_file_path,
1418 double *total_time_s) {
1419 if (RecordIsLoaded(record_name)) {
1420 AERROR <<
"Record is loaded,no need to load";
1424 auto record_player_factory = RecordPlayerFactory::Instance();
1425 if (!record_player_factory->EnableContinueLoad()) {
1427 std::string remove_record_id;
1428 if (record_player_factory->RemoveLRURecord(&remove_record_id)) {
1431 WLock wlock(status_mutex_);
1432 auto status_records = status_.mutable_records();
1433 (*status_records)[remove_record_id].set_load_record_status(
1434 LoadRecordStatus::NOT_LOAD);
1435 (*status_records)[remove_record_id].clear_total_time_s();
1439 if (!ReadRecordInfo(record_file_path, total_time_s)) {
1442 if (!record_player_factory->RegisterRecordPlayer(record_name,
1443 record_file_path)) {
1449bool HMIWorker::LoadRecords() {
1450 std::string directory_path;
1451 auto *record_player_factory = RecordPlayerFactory::Instance();
1452 GetRecordPath(&directory_path);
1453 if (!cyber::common::PathExists(directory_path)) {
1454 AERROR <<
"Failed to find records!";
1457 DIR *directory = opendir(directory_path.c_str());
1458 if (directory ==
nullptr) {
1459 AERROR <<
"Cannot open record directory" << directory_path;
1462 struct dirent *file;
1463 google::protobuf::Map<std::string, LoadRecordInfo> new_records;
1464 while ((file = readdir(directory)) !=
nullptr) {
1465 if (!strcmp(file->d_name,
".") || !strcmp(file->d_name,
"..")) {
1468 if (file->d_type == DT_DIR) {
1471 const std::string record_id = file->d_name;
1472 const int index = record_id.rfind(
".record");
1474 size_t record_suffix_length = 7;
1475 if (record_id.length() - index != record_suffix_length) {
1478 if (index != -1 && record_id[0] !=
'.') {
1479 const std::string local_record_resource = record_id.substr(0, index);
1480 const std::string record_file_path = directory_path +
"/" + record_id;
1481 double total_time_s;
1483 if (RecordIsLoaded(local_record_resource)) {
1487 if (!record_player_factory->EnableContinuePreload()) {
1488 new_records[local_record_resource].set_load_record_status(
1489 LoadRecordStatus::NOT_LOAD);
1490 new_records[local_record_resource].set_record_file_path(
1495 if (!LoadRecord(local_record_resource, record_file_path, &total_time_s)) {
1499 new_records[local_record_resource].set_total_time_s(total_time_s);
1500 new_records[local_record_resource].set_load_record_status(
1501 LoadRecordStatus::LOADED);
1502 new_records[local_record_resource].set_record_file_path(record_file_path);
1505 closedir(directory);
1507 WLock wlock(status_mutex_);
1508 auto status_records = status_.mutable_records();
1509 for (
auto iter = new_records.begin(); iter != new_records.end(); iter++) {
1510 (*status_records)[iter->first] = iter->second;
1512 status_changed_ =
true;
1517void HMIWorker::DeleteMap(
const std::string &map_name) {
1518 std::string title_map_name = util::HMIUtil::TitleCase(map_name);
1519 if (map_name.empty()) {
1522 std::string map_dir = FLAGS_maps_data_path +
"/";
1523 std::string map_abs_path = map_dir + map_name;
1524 if (!cyber::common::PathExists(map_abs_path)) {
1525 AERROR <<
"Failed to get map path: " << map_abs_path;
1529 WLock wlock(status_mutex_);
1530 auto iter = status_.maps().begin();
1531 for (; iter != status_.maps().end(); iter++) {
1532 if (*iter == title_map_name) {
1536 if (iter == status_.maps().end()) {
1537 AERROR <<
"Faile to find map name";
1540 if (status_.current_map() == title_map_name) {
1541 AERROR <<
"Cann't delete current selected map";
1544 status_.mutable_maps()->erase(iter);
1545 status_changed_ =
true;
1548 std::string cmd =
"rm -rf " + map_abs_path;
1549 if (std::system(cmd.data()) != 0) {
1550 AERROR <<
"Failed to delete map for: " << std::strerror(errno);
1553 std::string tar_abs_path = map_dir + map_name +
".tar.xz";
1555 if (cyber::common::PathExists(tar_abs_path)) {
1556 cmd =
"rm -rf " + tar_abs_path;
1557 if (std::system(cmd.data()) != 0) {
1558 AERROR <<
"Failed to delete map tar file for: " << std::strerror(errno);
1564void HMIWorker::DeleteRecord(
const std::string &record_id) {
1565 if (record_id.empty()) {
1568 std::string record_path;
1569 GetRecordPath(&record_path);
1570 const std::string record_abs_path = record_path + record_id +
".record";
1571 if (!cyber::common::PathExists(record_abs_path)) {
1572 AERROR <<
"Failed to get record path: " << record_abs_path;
1577 RLock rlock(status_mutex_);
1578 auto &status_records = status_.records();
1579 if (status_records.find(record_id) == status_records.end()) {
1580 AERROR <<
"Failed to find record id: " << record_id;
1583 if (record_id == status_.current_record_status().current_record_id()) {
1584 AERROR <<
"Cann't delete current selected record";
1589 auto *record_player_factory = RecordPlayerFactory::Instance();
1590 record_player_factory->UnregisterRecordPlayer(record_id);
1592 WLock wlock(status_mutex_);
1593 status_.mutable_records()->erase(record_id);
1594 status_changed_ =
true;
1598 std::string command =
"rm -rf " + record_abs_path;
1599 if (std::system(command.data()) != 0) {
1600 AERROR <<
"Failed to delete record for: " << std::strerror(errno);
1605 const std::string tar_abs_path = record_path + record_id +
".tar.xz";
1606 if (cyber::common::PathExists(tar_abs_path)) {
1607 command =
"rm -rf " + tar_abs_path;
1608 if (std::system(command.data()) != 0) {
1609 AERROR <<
"Failed to delete record tar file for: "
1610 << std::strerror(errno);
1617void HMIWorker::ReloadMaps() {
1618 WLock wlock(status_mutex_);
1619 config_.mutable_maps()->clear();
1620 *(config_.mutable_maps()) =
1621 util::HMIUtil::ListDirAsDict(FLAGS_maps_data_path);
1622 status_.clear_maps();
1623 for (
const auto &map : config_.maps()) {
1624 status_.add_maps(map.first);
1626 if (status_.current_map() !=
"") {
1628 if (config_.maps().find(status_.current_map()) == config_.maps().end()) {
1630 AINFO <<
"Current map is not in status. Reset it.";
1631 status_.set_current_map(
"");
1634 status_changed_ =
true;
1638bool HMIWorker::ReloadVehicles() {
1640 util::HMIUtil::LoadConfig(FLAGS_dv_plus_hmi_modes_config_path);
1642 config.SerializeToString(&msg);
1644 WLock wlock(status_mutex_);
1645 config_.ParseFromString(msg);
1648 status_.clear_vehicles();
1651 for (
const auto &vehicle : config_.vehicles()) {
1652 status_.add_vehicles(vehicle.first);
1654 status_changed_ =
true;
1658void HMIWorker::UpdateCameraSensorChannelToStatus(
1659 const std::string &channel_name) {
1661 WLock wlock(status_mutex_);
1662 if (status_.current_camera_sensor_channel() == channel_name) {
1663 AINFO <<
"Input channel name is current camera sensor channel";
1666 status_.set_current_camera_sensor_channel(channel_name);
1667 status_changed_ =
true;
1671void HMIWorker::UpdatePointCloudChannelToStatus(
1672 const std::string &channel_name) {
1674 WLock wlock(status_mutex_);
1675 if (status_.current_point_cloud_channel() == channel_name) {
1676 AINFO <<
"Input channel name is current camera sensor channel";
1679 status_.set_current_point_cloud_channel(channel_name);
1680 status_changed_ =
true;
1684void HMIWorker::DeleteVehicleConfig(
const std::string &vehicle_name) {
1685 if (vehicle_name.empty()) {
1688 const std::string *vehicle_dir =
1689 FindOrNull(config_.vehicles(), vehicle_name);
1690 if (vehicle_dir ==
nullptr) {
1691 AERROR <<
"Unknow vehicle name" << vehicle_name;
1695 RLock rlock(status_mutex_);
1696 if (status_.current_vehicle() == vehicle_name) {
1697 AERROR <<
"The deleted vehicle profile is the one in use.";
1701 if (!cyber::common::DeleteFile(*vehicle_dir)) {
1702 AERROR <<
"Delete vehicle profile [" << vehicle_name <<
"] failed!";
1705 if (!ReloadVehicles()) {
1706 AERROR <<
"Update vehicle profile [" << vehicle_name <<
"] failed!";
1711void HMIWorker::DeleteV2xConfig(
const std::string &vehicle_name) {
1712 if (vehicle_name.empty()) {
1715 const std::string *vehicle_dir =
1716 FindOrNull(config_.vehicles(), util::HMIUtil::TitleCase(vehicle_name));
1717 if (vehicle_dir ==
nullptr) {
1718 AERROR <<
"Unknow vehicle name " << vehicle_name;
1721 const std::string v2x_dir = *vehicle_dir +
"/v2x_conf";
1722 if (!cyber::common::PathExists(v2x_dir)) {
1723 AINFO <<
"The directory does not exist or the directory has been deleted";
1725 if (!cyber::common::DeleteFile(v2x_dir)) {
1726 AERROR <<
"Delete v2x config [" << vehicle_name <<
"/v2x_conf] failed!";
1731bool HMIWorker::StartDataRecorder() {
1733 "/apollo/scripts/record_bag.py --start --all --dreamview "
1735 FLAGS_data_record_default_name;
1736 int ret = std::system(
start_cmd.data());
1738 auto *monitors = FuelMonitorManager::Instance()->GetCurrentMonitors();
1739 if (monitors !=
nullptr) {
1740 auto iter = monitors->find(FLAGS_data_collection_monitor_name);
1741 if (iter != monitors->end()) {
1742 auto *data_collection_monitor = iter->second.get();
1743 if (data_collection_monitor->IsEnabled() && record_count_ == 0) {
1744 data_collection_monitor->Restart();
1751 AERROR <<
"Failed to start the cyber_recorder process";
1756bool HMIWorker::StopDataRecorder() {
1757 std::string
stop_cmd =
"/apollo/scripts/record_bag.py --stop";
1758 int ret = std::system(
stop_cmd.data());
1762 AERROR <<
"Failed to stop the cyber_recorder process";
1767int HMIWorker::SaveDataRecorder(
const std::string &new_name) {
1768 std::string data_record_default_path =
1769 std::string(cyber::common::GetEnv(
"HOME",
"/home/apollo")) +
1770 "/.apollo/resources/records/" + FLAGS_data_record_default_name;
1771 if (!cyber::common::PathExists(data_record_default_path)) {
1772 AERROR <<
"Failed to save the record, the dreamview recording record does "
1773 "not exist, please record through dreamview.";
1776 std::string save_cmd =
"/apollo/scripts/record_bag.py --default_name " +
1777 FLAGS_data_record_default_name +
" --rename " +
1779 int ret = std::system(save_cmd.data());
1784 AERROR <<
"Failed to save the record, a file with the same name exists";
1789bool HMIWorker::DeleteDataRecorder() {
1790 std::string delete_cmd =
1791 "/apollo/scripts/record_bag.py --delete --default_name " +
1792 FLAGS_data_record_default_name;
1793 int ret = std::system(delete_cmd.data());
1797 AERROR <<
"Failed to delete the record";
1802void HMIWorker::ClearRecordInfo() {
1803 std::string last_record_id;
1805 RLock rlock(status_mutex_);
1806 if (status_.current_operation() != HMIModeOperation::Record) {
1809 last_record_id = status_.current_record_status().current_record_id();
1811 if (!last_record_id.empty()) {
1812 StopRecordPlay(last_record_id);
1815 callback_api_(
"ClearDataHandlerConfChannelMsgs", {});
1816 WLock wlock(status_mutex_);
1817 status_.mutable_current_record_status()->clear_current_record_id();
1818 status_changed_ =
true;
1822void HMIWorker::ClearRtkRecordInfo() {
1823 std::string last_rtk_record_id;
1825 RLock rlock(status_mutex_);
1826 if (status_.current_operation() != HMIModeOperation::Waypoint_Follow) {
1829 last_rtk_record_id = status_.current_rtk_record_id();
1831 if (!last_rtk_record_id.empty()) {
1832 StopPlayRtkRecorder();
1835 WLock wlock(status_mutex_);
1836 status_.set_current_rtk_record_id(
"");
1837 status_changed_ =
true;
1842void HMIWorker::AddExpectedModules(
const HMIAction& action) {
1843 WLock wlock(status_mutex_);
1844 int expected_modules = 1;
1845 if (action == HMIAction::SETUP_MODE) {
1846 expected_modules = status_.modules_size();
1848 status_.set_expected_modules(status_.expected_modules() + expected_modules);
1849 status_changed_ =
true;
1852void HMIWorker::OnTimer(
const double& overtime_time) {
1853 if (monitor_reader_ !=
nullptr) {
1854 auto delay_sec = monitor_reader_->GetDelaySec();
1855 if (delay_sec < 0 || delay_sec > overtime_time) {
1856 AERROR <<
"Running time error: monitor is not turned on!";
1858 WLock wlock(status_mutex_);
1859 for (
auto& iter : *status_.mutable_modules_lock()) {
1860 iter.second =
false;
1868 WLock wlock(status_mutex_);
1869 auto modules = status_.mutable_modules();
1870 auto modules_lock = status_.mutable_modules_lock();
1871 for (
const auto &iter : current_mode_.
modules()) {
1872 if (previous_modules_lock_[iter.first] && (*modules_lock)[iter.first] &&
1873 !isProcessRunning(iter.second.start_command())) {
1874 (*modules)[iter.first] =
false;
1875 LockModule(iter.first,
false);
1877 previous_modules_lock_[iter.first] = (*modules_lock)[iter.first];
1882void HMIWorker::LockModule(
const std::string& module,
const bool& lock_flag) {
1883 auto modules_lock = status_.mutable_modules_lock();
1884 (*modules_lock)[module] = lock_flag;
1887bool HMIWorker::AddOrModifyObjectToDB(
const std::string& key,
1888 const std::string& value) {
1889 return KVDB::Put(key, value);
1892bool HMIWorker::DeleteObjectToDB(
const std::string& key) {
1893 return KVDB::Delete(key);
1896std::string HMIWorker::GetObjectFromDB(
const std::string& key) {
1897 return KVDB::Get(key).value_or(
"");
1900std::vector<std::pair<std::string, std::string>>
1901HMIWorker::GetTuplesWithTypeFromDB(
const std::string& type) {
1902 return KVDB::GetWithStart(type);
1905bool HMIWorker::StartTerminal() {
1906 return std::system(FLAGS_terminal_start_cmd.data()) == 0;
1909void HMIWorker::GetRtkRecordPath(std::string *record_path) {
1910 CHECK_NOTNULL(record_path);
1911 *record_path = FLAGS_resource_rtk_record_path;
1914bool HMIWorker::LoadRtkRecords() {
1916 WLock wLock(status_mutex_);
1917 status_.clear_rtk_records();
1919 std::string directory_path;
1920 GetRtkRecordPath(&directory_path);
1921 if (!cyber::common::PathExists(directory_path)) {
1922 AERROR <<
"Failed to find rtk records!";
1925 DIR *directory = opendir(directory_path.c_str());
1926 if (directory ==
nullptr) {
1927 AERROR <<
"Cannot open rtk record directory" << directory_path;
1930 struct dirent *file;
1931 std::map<std::string, double> new_records;
1932 while ((file = readdir(directory)) !=
nullptr) {
1933 if (!strcmp(file->d_name,
".") || !strcmp(file->d_name,
"..")) {
1936 if (file->d_type == DT_DIR) {
1939 const std::string record_id = file->d_name;
1940 const int index = record_id.rfind(
".csv");
1941 if (index != -1 && record_id[0] !=
'.') {
1942 const std::string local_record_resource = record_id.substr(0, index);
1944 WLock wLock(status_mutex_);
1945 status_.add_rtk_records(local_record_resource);
1949 closedir(directory);
1951 WLock wlock(status_mutex_);
1952 status_changed_ =
true;
1957bool HMIWorker::StartRtkDataRecorder() {
1958 std::string
start_cmd =
"nohup /apollo/scripts/rtk_recorder.sh start &";
1959 int ret = std::system(
start_cmd.data());
1963 AERROR <<
"Failed to start the rtk_recorder process";
1968bool HMIWorker::StopRtkDataRecorder() {
1969 std::string
stop_cmd =
"/apollo/scripts/rtk_recorder.sh stop";
1970 int ret = std::system(
stop_cmd.data());
1974 AERROR <<
"Failed to stop the rtk_recorder process";
1979Json HMIWorker::StartPlayRtkRecorder() {
1981 if (!ChangeDrivingMode(Chassis::COMPLETE_AUTO_DRIVE)) {
1982 AERROR <<
"Failed to play rtk: Failed to enter auto drive.";
1983 result[
"error"] =
"Failed to enter auto drive";
1984 result[
"isOk"] =
false;
1987 std::string record_id;
1989 RLock rlock(status_mutex_);
1990 record_id = status_.current_rtk_record_id();
1993 "nohup /apollo/scripts/rtk_player.sh start " + record_id +
" &";
1994 int ret = std::system(
start_cmd.data());
1996 AINFO <<
"Start the rtk_recorder process Successful.";
1997 result[
"isOk"] =
true;
1999 AERROR <<
"Failed to play rtk: Failed to start the rtk_recorder process.";
2000 result[
"error"] =
"Failed to start the rtk_recorder process";
2001 result[
"isOk"] =
false;
2006bool HMIWorker::StopPlayRtkRecorder() {
2007 std::string
stop_cmd =
"/apollo/scripts/rtk_player.sh stop";
2008 int ret = std::system(
stop_cmd.data());
2012 AERROR <<
"Failed to stop the rtk_recorder process";
2017int HMIWorker::SaveRtkDataRecorder(
const std::string &new_name) {
2018 std::string new_rtk_record_file =
2019 FLAGS_default_rtk_record_path + new_name +
".csv";
2020 if (cyber::common::PathExists(new_rtk_record_file)) {
2021 AERROR <<
"Failed to save the ret record, a file with the same name exists";
2024 if (std::rename(FLAGS_default_rtk_record_file.data(),
2025 new_rtk_record_file.data()) == 0) {
2026 UpdateRtkRecordToStatus(new_name);
2029 AERROR <<
"Failed to save the ret record, save command execution failed";
2034bool HMIWorker::DeleteRtkDataRecorder() {
2035 if (!cyber::common::PathExists(FLAGS_default_rtk_record_file)) {
2036 AERROR <<
"Failed to delete the ret record, file not exist";
2039 if (std::remove(FLAGS_default_rtk_record_file.data()) == 0) {
2042 AERROR <<
"Failed to delete the record, delete command execution failed";
2047void HMIWorker::ChangeRtkRecord(
const std::string &record_id) {
2048 if (!StopPlayRtkRecorder()) {
2049 AWARN <<
"Warning to change rtk record: Failed to stop the rtk_recorder "
2052 std::string last_record_id;
2054 RLock rlock(status_mutex_);
2055 last_record_id = status_.current_rtk_record_id();
2057 if (last_record_id == record_id) {
2058 AERROR <<
"Failed to change rtk record: rtk record is same!";
2061 WLock wlock(status_mutex_);
2062 status_.set_current_rtk_record_id(record_id);
2063 status_changed_ =
true;
2067void HMIWorker::UpdateRtkRecordToStatus(
const std::string &new_name) {
2068 WLock wlock(status_mutex_);
2069 status_.add_rtk_records(new_name);
2070 status_changed_ =
true;
2073void HMIWorker::ClearInvalidRecordStatus(
const HMIModeOperation &operation) {
2074 HMIModeOperation last_operation;
2076 RLock rlock(status_mutex_);
2077 last_operation = status_.current_operation();
2079 if (operation == last_operation) {
2081 }
else if (last_operation == HMIModeOperation::Waypoint_Follow) {
2082 StopRtkDataRecorder();
2083 DeleteRtkDataRecorder();
2084 }
else if (operation == HMIModeOperation::Waypoint_Follow) {
2086 DeleteDataRecorder();
2090bool HMIWorker::isProcessRunning(
const std::string &process_name) {
2091 std::stringstream commandStream;
2092 commandStream <<
"pgrep -f " << process_name;
2093 std::string command = commandStream.str();
2095 FILE *fp = popen(command.c_str(),
"r");
2098 if (fgets(result,
sizeof(result), fp) !=
nullptr) {
2099 AINFO << process_name <<
" is running";
2103 AINFO << process_name <<
" is not running";
2110bool HMIWorker::PackageExist(
const std::string& package_name) {
2111 std::string package_meta_info_path =
2112 FLAGS_apollo_package_meta_info_path_prefix + package_name +
2114 AINFO <<
"package_meta_info_path: " << package_meta_info_path;
2115 return (cyber::common::PathExists(package_meta_info_path));
Lightweight key-value database to store system-wide parameters.
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")