Apollo 애플리케이션 및 소스 코드 분석: 모니터링 모니터링-소프트웨어 모니터링-포지셔닝, 카메라, 기능 안전, 데이터 기록 모니터링

목차

위치 모니터링

코드

분석하다

주목

카메라 모니터링

코드

분석하다

기능 안전 모니터링

코드

분석하다

CheckSafety 기능 분석

RunOnce 함수 분석

기록 기능 모니터링

코드

분석하다

SmartRecorderStatus 프로토타입

상태 보고 위치 분석

모니터링 정보 요약 서비스

코드

분석하다


위치 모니터링

코드

class LocalizationMonitor : public RecurrentRunner {
 public:
  LocalizationMonitor();
  void RunOnce(const double current_time) override;
};

void LocalizationMonitor::RunOnce(const double current_time) {
  auto manager = MonitorManager::Instance();
  auto* component = apollo::common::util::FindOrNull(
      *manager->GetStatus()->mutable_components(),
      FLAGS_localization_component_name);
  if (component == nullptr) {
    // localization is not monitored in current mode, skip.
    return;
  }

  static auto reader =
      manager->CreateReader<LocalizationStatus>(FLAGS_localization_msf_status);
  reader->Observe();
  const auto status = reader->GetLatestObserved();

  ComponentStatus* component_status = component->mutable_other_status();
  component_status->clear_status();
  if (status == nullptr) {
    SummaryMonitor::EscalateStatus(ComponentStatus::ERROR,
                                   "No LocalizationStatus received",
                                   component_status);
    return;
  }

  // Translate LocalizationStatus to ComponentStatus. Note that ERROR and FATAL
  // will trigger safety mode in current settings.
  switch (status->fusion_status()) {
    case MeasureState::OK:
      SummaryMonitor::EscalateStatus(ComponentStatus::OK, "", component_status);
      break;
    case MeasureState::WARNNING:
      SummaryMonitor::EscalateStatus(
          ComponentStatus::WARN,
          absl::StrCat("WARNNING: ", status->state_message()),
          component_status);
      break;
    case MeasureState::ERROR:
      SummaryMonitor::EscalateStatus(
          ComponentStatus::WARN,
          absl::StrCat("ERROR: ", status->state_message()), component_status);
      break;
    case MeasureState::CRITICAL_ERROR:
      SummaryMonitor::EscalateStatus(
          ComponentStatus::ERROR,
          absl::StrCat("CRITICAL_ERROR: ", status->state_message()),
          component_status);
      break;
    case MeasureState::FATAL_ERROR:
      SummaryMonitor::EscalateStatus(
          ComponentStatus::FATAL,
          absl::StrCat("FATAL_ERROR: ", status->state_message()),
          component_status);
      break;
    default:
      AFATAL << "Unknown fusion_status: " << status->fusion_status();
      break;
  }
}

분석하다

  1. 포지셔닝 모듈이 모니터링되는 모듈에 속하는지 확인
  2. localization_msf_status 구독, 읽을 수 없으면 ERROR 수준 오류 보고
  3. 주제의 상태 정보를 직접 판단하고 상태에 따라 해당 오류를 보고합니다.

주목

## MSF 현지화 상태 확인 LiDAR 현지화, GNSS 현지화 및 융합 현지화 상태를 확인하는 간단한 방법을 제공합니다. 현지화 상태에는 {NOT_VALID, NOT_STABLE, OK, VALID} 네 가지 상태가 있습니다. 단순히 `rostopic echo /apollo/localization/msf_status`를 사용하여 현지화 상태를 확인할 수 있습니다. fusion_status가 VALID 또는 OK이면 msf 지역화 출력이 신뢰할 수 있습니다.

위는 apollo MSF 포지셔닝 상태의 판단 논리이며 위의 결함은 모두 비즈니스 모듈의 포지셔닝 부분에서 설정 및 발행됩니다.

다음은 module/localization/rtk/rtk_localization.cc의 상태 감지 부분입니다.

void RTKLocalization::FillLocalizationStatusMsg(
    const drivers::gnss::InsStat &status,
    LocalizationStatus *localization_status) {
  apollo::common::Header *header = localization_status->mutable_header();
  double timestamp = apollo::cyber::Clock::NowInSeconds();
  header->set_timestamp_sec(timestamp);
  localization_status->set_measurement_time(status.header().timestamp_sec());

  if (!status.has_pos_type()) {
    localization_status->set_fusion_status(MeasureState::ERROR);
    localization_status->set_state_message(
        "Error: Current Localization Status Is Missing.");
    return;
  }

카메라 모니터링

코드

class CameraMonitor : public RecurrentRunner {
 public:
  CameraMonitor();
  void RunOnce(const double current_time) override;

 private:
  static void UpdateStatus(ComponentStatus* status);
};
void CameraMonitor::RunOnce(const double current_time) {
  auto* manager = MonitorManager::Instance();
  auto* component = apollo::common::util::FindOrNull(
      *manager->GetStatus()->mutable_components(), FLAGS_camera_component_name);
  if (component == nullptr) {
    // camera is not monitored in current mode, skip.
    return;
  }
  auto* status = component->mutable_other_status();
  UpdateStatus(status);
}

분석하다

카메라가 모니터링 구성으로 구성되었는지 여부를 판단하는 것 외에도 핵심 기능은 UpdateStatus에 있습니다.

void CameraMonitor::UpdateStatus(ComponentStatus* status) {
  status->clear_status();
  std::string frame_id = "";
  for (const auto& topic : camera_topic_set) {
    const auto& reader_message_pair = CreateReaderAndLatestsMessage(topic);
    const auto& reader = reader_message_pair.first;
    const auto& message = reader_message_pair.second;
    if (reader != nullptr && message != nullptr) {
      if (frame_id.empty()) {
        const auto& header = message->header();
        if (header.has_frame_id()) {
          frame_id = header.frame_id();
        }
      } else {
        SummaryMonitor::EscalateStatus(
            ComponentStatus::ERROR,
            absl::StrCat("Only one camera is permitted"), status);
      }
    }
  }
  if (frame_id.empty()) {
    SummaryMonitor::EscalateStatus(
        ComponentStatus::ERROR, absl::StrCat("No camera is detected"), status);
  } else {
    SummaryMonitor::EscalateStatus(
        ComponentStatus::OK, absl::StrCat("Detected one camera: ", frame_id),
        status);
  }
}
static const auto camera_topic_set = std::set<std::string>{
    FLAGS_image_long_topic,         FLAGS_camera_image_long_topic,
    FLAGS_camera_image_short_topic, FLAGS_camera_front_6mm_topic,
    FLAGS_camera_front_6mm_2_topic, FLAGS_camera_front_12mm_topic,
    // Add more cameras here if you want to monitor.
};
  1. 최신 뉴스를 얻다
  2. 메시지 헤더 가져오기, 프레임 ID 가져오기, 두 세트의 프레임 ID가 있는 경우 ERROR 보고
absl::StrCat("하나의 카메라만 허용됩니다."), status);

  프레임 ID가 비어 있으면 ERROR를 보고합니다.

ComponentStatus::ERROR, absl::StrCat("감지된 카메라가 없습니다."), status);

기능 안전 모니터링

코드

// Check if we need to switch to safe mode, and then
// 1. Notify driver to take action.
// 2. Trigger Guardian if no proper action was taken.
class FunctionalSafetyMonitor : public RecurrentRunner {
 public:
  FunctionalSafetyMonitor();
  void RunOnce(const double current_time);

 private:
  bool CheckSafety();
};
void FunctionalSafetyMonitor::RunOnce(const double current_time) {
  auto* system_status = MonitorManager::Instance()->GetStatus();
  // Everything looks good or has been handled properly.
  if (CheckSafety()) {
    system_status->clear_passenger_msg();
    system_status->clear_safety_mode_trigger_time();
    system_status->clear_require_emergency_stop();
    return;
  }
  if (system_status->require_emergency_stop()) {
    // EStop has already been triggered.
    return;
  }

  // Newly entered safety mode.
  system_status->set_passenger_msg("Error! Please disengage.");
  if (!system_status->has_safety_mode_trigger_time()) {
    system_status->set_safety_mode_trigger_time(current_time);
    return;
  }

  // Trigger EStop if no action was taken in time.
  if (system_status->safety_mode_trigger_time() +
          FLAGS_safety_mode_seconds_before_estop <
      current_time) {
    system_status->set_require_emergency_stop(true);
  }
}

분석하다

CheckSafety 기능 분석

bool FunctionalSafetyMonitor::CheckSafety() {
  // We only check safety in self driving mode.
  auto manager = MonitorManager::Instance();
  if (!manager->IsInAutonomousMode()) {
    return true;
  }

  // Check HMI modules status.
  const auto& mode = manager->GetHMIMode();
  const auto& hmi_modules = manager->GetStatus()->hmi_modules();
  for (const auto& iter : mode.modules()) {
    const std::string& module_name = iter.first;
    const auto& module = iter.second;
    if (module.required_for_safety() &&
        !IsSafe(module_name, hmi_modules.at(module_name))) {
      return false;
    }
  }

  // Check monitored components status.
  const auto& components = manager->GetStatus()->components();
  for (const auto& iter : mode.monitored_components()) {
    const std::string& component_name = iter.first;
    const auto& component = iter.second;
    if (component.required_for_safety() &&
        !IsSafe(component_name, components.at(component_name).summary())) {
      return false;
    }
  }

  // Everything looks good.
  return true;
}
  1. 자동 조종 모드인지 판단하고 그렇지 않으면 직접 뛰어 내립니다.
  2. 모니터링되는 모든 구성 요소의 상태가 ERROR 또는 FATAL인지 확인하십시오.
  3. 있으면 안전하지 않고 안전하지 않으면 안전합니다.

RunOnce 함수 분석

  1. 현재 보안 상태 확인
  2. 안전하다면 이전 상태 정보를 지우고 돌아갑니다.
  3. 안전하지 않은 경우 보안 조치가 호출되었는지 판단: Estop, Estop이 이미 작동 중인 경우 반환
  4. ESTOP이 동작하지 않는 것으로 판단되면 트리거가 ESTOP을 안전하게 처리할 수 있는 시간을 확인하고 타임아웃이 없으면 대기한다.

기록 기능 모니터링

녹음기 모니터는 녹음기 상태를 얻기 위해 주제 /apollo/data/recorder/status를 구독하여 apollo가 녹음 서비스를 모니터링하기 위한 것입니다.

코드

class RecorderMonitor : public RecurrentRunner {
 public:
  RecorderMonitor();
  void RunOnce(const double current_time) override;
};

void RecorderMonitor::RunOnce(const double current_time) {
  auto manager = MonitorManager::Instance();
  auto* component = apollo::common::util::FindOrNull(
      *manager->GetStatus()->mutable_components(),
      FLAGS_smart_recorder_component_name);
  if (component == nullptr) {
    // SmartRecorder is not monitored in current mode, skip.
    return;
  }

  static auto reader =
      manager->CreateReader<SmartRecorderStatus>(FLAGS_recorder_status_topic);
  reader->Observe();
  const auto status = reader->GetLatestObserved();

  ComponentStatus* component_status = component->mutable_other_status();
  component_status->clear_status();
  if (status == nullptr) {
    SummaryMonitor::EscalateStatus(ComponentStatus::ERROR,
                                   "No SmartRecorderStatus received",
                                   component_status);
    return;
  }

  // Translate SmartRecorderStatus to ComponentStatus. Note that ERROR and FATAL
  // will trigger safety mode in current settings.
  switch (status->recording_state()) {
    case RecordingState::RECORDING:
      SummaryMonitor::EscalateStatus(ComponentStatus::OK, "", component_status);
      break;
    case RecordingState::TERMINATING:
      SummaryMonitor::EscalateStatus(
          ComponentStatus::WARN,
          absl::StrCat("WARNNING: ", status->state_message()),
          component_status);
      break;
    case RecordingState::STOPPED:
      SummaryMonitor::EscalateStatus(
          ComponentStatus::OK,
          absl::StrCat("STOPPED: ", status->state_message()), component_status);
      break;
    default:
      AFATAL << "Unknown recording status: " << status->recording_state();
      break;
  }
}

분석하다

첫 번째 단계는 여전히 레코더가 구성된 모니터링 모듈인지 여부를 판단하는 것입니다. 그렇지 않은 경우 직접 반환합니다.

그런 다음 status->recording_state()를 직접 판단하여 RecordingState::TERMINATING(종료) 상태이면 WARNING 오류를 보고합니다.

SmartRecorderStatus 프로토타입

enum RecordingState {
  STOPPED = 0;
  RECORDING = 1;
  TERMINATING = 2;
}

message SmartRecorderStatus {
  optional apollo.common.Header header = 1;
  optional RecordingState recording_state = 2;
  optional string state_message = 3;
}

상태 보고 위치 분석

모듈/데이터/도구/smart_recorder/realtime_record_processor.cc

위의 파일에서 레코더 상태 할당을 찾을 수 있지만 안타깝게도 현재 아폴로에는 RecordingState::TERMINATING(종료) 상태를 적극적으로 채울 모듈이 없습니다.

모니터링 정보 요약 서비스

코드

// A monitor which summarize other monitors' result and publish the whole status
// if it has changed.
class SummaryMonitor : public RecurrentRunner {
 public:
  SummaryMonitor();
  void RunOnce(const double current_time) override;

  // Escalate the status to a higher priority new status:
  //    FATAL > ERROR > WARN > OK > UNKNOWN.
  static void EscalateStatus(const ComponentStatus::Status new_status,
                             const std::string& message,
                             ComponentStatus* current_status);

 private:
  size_t system_status_fp_ = 0;
  double last_broadcast_ = 0;
};


void SummaryMonitor::RunOnce(const double current_time) {
  auto manager = MonitorManager::Instance();
  auto* status = manager->GetStatus();
  // Escalate the summary status to the most severe one.
  for (auto& component : *status->mutable_components()) {
    auto* summary = component.second.mutable_summary();
    const auto& process_status = component.second.process_status();
    EscalateStatus(process_status.status(), process_status.message(), summary);
    const auto& module_status = component.second.module_status();
    EscalateStatus(module_status.status(), module_status.message(), summary);
    const auto& channel_status = component.second.channel_status();
    EscalateStatus(channel_status.status(), channel_status.message(), summary);
    const auto& resource_status = component.second.resource_status();
    EscalateStatus(resource_status.status(), resource_status.message(),
                   summary);
    const auto& other_status = component.second.other_status();
    EscalateStatus(other_status.status(), other_status.message(), summary);
  }

  // Get fingerprint of current status.
  // Don't use DebugString() which has known bug on Map field. The string
  // doesn't change though the value has changed.
  static std::hash<std::string> hash_fn;
  std::string proto_bytes;
  status->SerializeToString(&proto_bytes);
  const size_t new_fp = hash_fn(proto_bytes);

  if (system_status_fp_ != new_fp ||
      current_time - last_broadcast_ > FLAGS_system_status_publish_interval) {
    static auto writer =
        manager->CreateWriter<SystemStatus>(FLAGS_system_status_topic);

    apollo::common::util::FillHeader("SystemMonitor", status);
    writer->Write(*status);
    status->clear_header();
    system_status_fp_ = new_fp;
    last_broadcast_ = current_time;
  }
}

분석하다

모든 이전 모니터에서 보고된 오류 정보를 통합하고 /apollo/monitor/system_status 항목으로 보냅니다.

Guess you like

Origin blog.csdn.net/qq_32378713/article/details/128112717