Table of contents
the code
class ChannelMonitor : public RecurrentRunner {
public:
explicit ChannelMonitor(
const std::shared_ptr<LatencyMonitor>& latency_monitor);
void RunOnce(const double current_time) override;
private:
static void UpdateStatus(
const apollo::dreamview::ChannelMonitorConfig& config,
ComponentStatus* status, const bool update_freq, const double freq);
std::shared_ptr<LatencyMonitor> latency_monitor_;
};
void ChannelMonitor::RunOnce(const double current_time) {
auto manager = MonitorManager::Instance();
const auto& mode = manager->GetHMIMode();
auto* components = manager->GetStatus()->mutable_components();
for (const auto& iter : mode.monitored_components()) {
const std::string& name = iter.first;
const auto& config = iter.second;
if (config.has_channel()) {
double freq;
const auto update_freq =
latency_monitor_->GetFrequency(config.channel().name(), &freq);
UpdateStatus(config.channel(),
components->at(name).mutable_channel_status(), update_freq,
freq);
}
}
}
analyze
The main structure
The same routine in runOnce:
- First obtain all configured monitoring items from the HMI mode;
- Traversing the monitoring items, use latency_monitor_->GetFrequency to get the frequency of the channel;
- Use UpdateStatus to update status, generate alarm
judgment logic
void ChannelMonitor::UpdateStatus(
const apollo::dreamview::ChannelMonitorConfig& config,
ComponentStatus* status, const bool update_freq, const double freq) {
status->clear_status();
const auto reader_message_pair = GetReaderAndLatestMessage(config.name());
const auto reader = reader_message_pair.first;
const auto message = reader_message_pair.second;
if (reader == nullptr) {
SummaryMonitor::EscalateStatus(
ComponentStatus::UNKNOWN,
absl::StrCat(config.name(), " is not registered in ChannelMonitor."),
status);
return;
}
if (message == nullptr || message->ByteSize() == 0) {
SummaryMonitor::EscalateStatus(
ComponentStatus::FATAL,
absl::StrCat("the message ", config.name(), " reseived is empty."),
status);
return;
}
// Check channel delay
const double delay = reader->GetDelaySec();
if (delay < 0 || delay > config.delay_fatal()) {
SummaryMonitor::EscalateStatus(
ComponentStatus::FATAL,
absl::StrCat(config.name(), " delayed for ", delay, " seconds."),
status);
}
// Check channel fields
const std::string field_sepr = ".";
if (message != nullptr) {
for (const auto& field : config.mandatory_fields()) {
if (!ValidateFields(*message, absl::StrSplit(field, field_sepr), 0)) {
SummaryMonitor::EscalateStatus(
ComponentStatus::ERROR,
absl::StrCat(config.name(), " missing field ", field), status);
}
}
}
// Check channel frequency
if (update_freq) {
if (freq > config.max_frequency_allowed()) {
SummaryMonitor::EscalateStatus(
ComponentStatus::WARN,
absl::StrCat(config.name(), " has frequency ", freq,
" > max allowed ", config.max_frequency_allowed()),
status);
}
if (freq < config.min_frequency_allowed()) {
SummaryMonitor::EscalateStatus(
ComponentStatus::WARN,
absl::StrCat(config.name(), " has frequency ", freq,
" < min allowed ", config.max_frequency_allowed()),
status);
}
}
SummaryMonitor::EscalateStatus(ComponentStatus::OK, "", status);
}
- Create a reader through the channel to get the last msg;
- If the reader fails to be created, set the state to unknown;
- If the last frame message is empty, set the status to FATAL;
- double delay = reader->GetDelaySec(); Get the delay; if the delay is <0 or greater than the threshold, FATAL alarms;
- Check whether the required fields are missing, and ERROR if missing;
- Check whether the sending frequency is normal, and report WARN if it is not within the threshold range;
Remark
template <typename MessageT>
double Reader<MessageT>::GetDelaySec() const {
if (latest_recv_time_sec_ < 0) {
return -1.0;
}
if (second_to_lastest_recv_time_sec_ < 0) {
return Time::Now().ToSecond() - latest_recv_time_sec_;
}
return std::max((Time::Now().ToSecond() - latest_recv_time_sec_),
(latest_recv_time_sec_ - second_to_lastest_recv_time_sec_));
}
The way for the Reader to obtain the time delay is to subscribe to the received data and then make the difference of the previous frame time