Table of contents
Singleton pattern macro definition
Describe the current state of the system
Status information displayed on the HMI
Judging whether it is an automatic driving state
Reader management map for all monitors
monitor_manager analysis
structural analysis
// Centralized monitor config and status manager.
class MonitorManager {
public:
void Init(const std::shared_ptr<apollo::cyber::Node>& node);
// Start and end a monitoring frame.
bool StartFrame(const double current_time);
void EndFrame();
// Getters.
const apollo::dreamview::HMIMode& GetHMIMode() const { return mode_config_; }
bool IsInAutonomousMode() const { return in_autonomous_driving_; }
SystemStatus* GetStatus() { return &status_; }
apollo::common::monitor::MonitorLogBuffer& LogBuffer() { return log_buffer_; }
// Cyber reader / writer creator.
template <class T>
std::shared_ptr<cyber::Reader<T>> CreateReader(const std::string& channel) {
if (readers_.find(channel) == readers_.end()) {
readers_.emplace(channel, node_->CreateReader<T>(channel));
}
return std::dynamic_pointer_cast<cyber::Reader<T>>(readers_[channel]);
}
template <class T>
std::shared_ptr<cyber::Writer<T>> CreateWriter(const std::string& channel) {
return node_->CreateWriter<T>(channel);
}
private:
SystemStatus status_;
// Input statuses.
std::string current_mode_;
const apollo::dreamview::HMIConfig hmi_config_;
apollo::dreamview::HMIMode mode_config_;
bool in_autonomous_driving_ = false;
bool CheckAutonomousDriving(const double current_time);
apollo::common::monitor::MonitorLogBuffer log_buffer_;
std::shared_ptr<apollo::cyber::Node> node_;
std::unordered_map<std::string, std::shared_ptr<cyber::ReaderBase>> readers_;
DECLARE_SINGLETON(MonitorManager)
};
DECLARE_SINGLETON(MonitorManager)
Singleton pattern macro definition
#define DECLARE_SINGLETON(classname) \
public: \
static classname *Instance(bool create_if_needed = true) { \
static classname *instance = nullptr; \
if (!instance && create_if_needed) { \
static std::once_flag flag; \
std::call_once(flag, \
[&] { instance = new (std::nothrow) classname(); }); \
} \
return instance; \
} \
\
static void CleanUp() { \
auto instance = Instance(false); \
if (instance != nullptr) { \
CallShutdown(instance); \
} \
} \
\
private: \
classname(); \
DISALLOW_COPY_AND_ASSIGN(classname)
Describe the current state of the system
SystemStatus status_
Status information displayed on the HMI
std::string current_mode_
Simulation Judgment Status
const apollo::dreamview::HMIConfig hmi_config_; apollo::dreamview::HMIMode mode_config_;
Judging whether it is an automatic driving state
bool in_autonomous_driving_ = false; bool CheckAutonomousDriving(const double current_time);
log cache
apollo::common::monitor::MonitorLogBuffer log_buffer_;
current node
std::shared_ptr<apollo::cyber::Node> node_;
Reader management map for all monitors
std::unordered_map<std::string, std::shared_ptr<cyber::ReaderBase>> readers_;
Start a monitoring
bool StartFrame(const double current_time);
void EndFrame();
bool MonitorManager::StartFrame(const double current_time) {
// Get latest HMIStatus.
static auto hmi_status_reader =
CreateReader<apollo::dreamview::HMIStatus>(FLAGS_hmi_status_topic);
hmi_status_reader->Observe();
const auto hmi_status = hmi_status_reader->GetLatestObserved();
if (hmi_status == nullptr) {
AERROR << "No HMIStatus was received.";
return false;
}
if (current_mode_ != hmi_status->current_mode()) {
// Mode changed, update configs and monitored.
current_mode_ = hmi_status->current_mode();
mode_config_ = HMIWorker::LoadMode(hmi_config_.modes().at(current_mode_));
status_.clear_hmi_modules();
for (const auto& iter : mode_config_.modules()) {
status_.mutable_hmi_modules()->insert({iter.first, {}});
}
status_.clear_components();
for (const auto& iter : mode_config_.monitored_components()) {
status_.mutable_components()->insert({iter.first, {}});
}
status_.clear_other_components();
for (const auto& iter : mode_config_.other_components()) {
status_.mutable_other_components()->insert({iter.first, {}});
}
} else {
// Mode not changed, clear component summary from the last frame.
for (auto& iter : *status_.mutable_components()) {
iter.second.clear_summary();
}
}
in_autonomous_driving_ = CheckAutonomousDriving(current_time);
return true;
}
void MonitorManager::EndFrame() {
// Print and publish all monitor logs.
log_buffer_.Publish();
}
start frame analysis
1. Get the latest HMI status
1.1. Return false if not available
2. If the current state is different from the last state (HMI state), update
2.1. status_ update latest status
3. If the current state is the same as the last state (HMI state), clear the component summary
// Mode not changed, clear component summary from the last frame.
for (auto& iter : *status_.mutable_components()) {
iter.second.clear_summary();
}
end frame analysis
Print and publish the log information added by MonitorLogBuffrt::AddMonitorMsgItem in the current monitoring process
Publish topic: /apollo/monitor
// modules/common/monitor_log/monitor_log_buffer.cc
void MonitorLogBuffer::AddMonitorMsgItem(
const MonitorMessageItem::LogLevel log_level, const std::string &msg) {
level_ = log_level;
monitor_msg_items_.push_back(std::make_pair(log_level, msg));
}
//modules/common/monitor_log/monitor_logger.cc
MonitorLogger::MonitorLogger() {
const std::string node_name =
absl::StrCat("monitor_logger", Time::Now().ToNanosecond());
node_ = cyber::CreateNode(node_name);
if (node_ != nullptr) {
monitor_msg_writer_ =
node_->CreateWriter<MonitorMessage>("/apollo/monitor");
}
}
recurrent_runner analysis
structural analysis
class RecurrentRunner {
public:
RecurrentRunner(const std::string &name, const double interval);
virtual ~RecurrentRunner() = default;
// Tick once, which may or may not execute the RunOnce() function, based on
// the interval setting.
void Tick(const double current_time);
// Do the actual work.
virtual void RunOnce(const double current_time) = 0;
protected:
std::string name_;
unsigned int round_count_ = 0;
private:
double interval_;
double next_round_ = 0;
};
It can be seen from the naming of the class that this class is responsible for repeated work.
The meaning of Tick is the ticking of the clock, which can represent the periodic execution of tasks. It has also been written above. The Tick function may execute the RunOnce function, but it may not. The execution cycle is specified by the following interval_.
The round count refers to how many rounds were executed.
next round refers to the next execution time.
RunOnce is a pure virtual function, so this class is an interface and cannot be directly new.
Tick function analysis
void RecurrentRunner::Tick(const double current_time) {
if (next_round_ <= current_time) {
++round_count_;
AINFO_EVERY(100) << name_ << " is running round #" << round_count_;
next_round_ = current_time + interval_;
RunOnce(current_time);
}
}
Execute once to update the time to be executed next time, then execute the runOnce function and pass in the current time.