Apollo 10.0
自动驾驶开放平台
channel_monitor.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19#include <memory>
20#include <string>
21#include <utility>
22#include <vector>
23
24#include "absl/strings/str_cat.h"
25#include "absl/strings/str_split.h"
26#include "google/protobuf/compiler/parser.h"
27#include "google/protobuf/descriptor.h"
28#include "google/protobuf/dynamic_message.h"
29
30#include "modules/common_msgs/chassis_msgs/chassis_detail.pb.h"
31#include "modules/common/latency_recorder/proto/latency_record.pb.h"
32#include "modules/common_msgs/control_msgs/control_cmd.pb.h"
33#include "modules/common_msgs/sensor_msgs/conti_radar.pb.h"
34#include "modules/common_msgs/sensor_msgs/pointcloud.pb.h"
35#include "modules/common_msgs/localization_msgs/pose.pb.h"
36#include "modules/common_msgs/planning_msgs/navigation.pb.h"
37#include "modules/common_msgs/perception_msgs/perception_obstacle.pb.h"
38#include "modules/common_msgs/planning_msgs/planning.pb.h"
39#include "modules/common_msgs/prediction_msgs/prediction_obstacle.pb.h"
40
41#include "cyber/common/log.h"
42#include "cyber/cyber.h"
47
48DEFINE_string(channel_monitor_name, "ChannelMonitor",
49 "Name of the channel monitor.");
50
51DEFINE_double(channel_monitor_interval, 5,
52 "Channel monitor checking interval in seconds.");
53
54namespace apollo {
55namespace monitor {
56namespace {
57
58using ReaderAndMessagePair =
59 std::pair<std::shared_ptr<cyber::ReaderBase>,
60 std::shared_ptr<google::protobuf::Message>>;
61
62template <typename T>
63ReaderAndMessagePair CreateReaderAndLatestsMessage(const std::string& channel) {
64 const auto reader = MonitorManager::Instance()->CreateReader<T>(channel);
65 reader->Observe();
66 const auto message = reader->GetLatestObserved();
67 return {reader, message};
68}
69
70// We have to specify exact type of each channel. This function is a wrapper for
71// those only need a ReaderBase.
72ReaderAndMessagePair GetReaderAndLatestMessage(const std::string& channel) {
73 static const auto channel_function_map =
74 std::unordered_map<std::string, std::function<ReaderAndMessagePair(
75 const std::string& channel)>>{
76 {FLAGS_control_command_topic,
77 &CreateReaderAndLatestsMessage<control::ControlCommand>},
78 {FLAGS_localization_topic,
79 &CreateReaderAndLatestsMessage<localization::LocalizationEstimate>},
80 {FLAGS_perception_obstacle_topic,
81 &CreateReaderAndLatestsMessage<perception::PerceptionObstacles>},
82 {FLAGS_prediction_topic,
83 &CreateReaderAndLatestsMessage<prediction::PredictionObstacles>},
84 {FLAGS_planning_trajectory_topic,
85 &CreateReaderAndLatestsMessage<planning::ADCTrajectory>},
86 {FLAGS_conti_radar_topic,
87 &CreateReaderAndLatestsMessage<drivers::ContiRadar>},
88 {FLAGS_relative_map_topic,
89 &CreateReaderAndLatestsMessage<relative_map::MapMsg>},
90 {FLAGS_pointcloud_topic,
91 &CreateReaderAndLatestsMessage<drivers::PointCloud>},
92 {FLAGS_pointcloud_16_topic,
93 &CreateReaderAndLatestsMessage<drivers::PointCloud>},
94 {FLAGS_pointcloud_16_raw_topic,
95 &CreateReaderAndLatestsMessage<drivers::PointCloud>},
96 {FLAGS_pointcloud_128_topic,
97 &CreateReaderAndLatestsMessage<drivers::PointCloud>},
98 {FLAGS_pointcloud_16_front_up_topic,
99 &CreateReaderAndLatestsMessage<drivers::PointCloud>},
100 {FLAGS_chassis_detail_topic,
101 &CreateReaderAndLatestsMessage<canbus::ChassisDetail>},
102 {FLAGS_pointcloud_hesai_40p_topic,
103 &CreateReaderAndLatestsMessage<drivers::PointCloud>}
104 // Add more channels here if you want to monitor.
105 };
106
107 auto entry = channel_function_map.find(channel);
108 if (entry != channel_function_map.end()) {
109 return (entry->second)(channel);
110 }
111
112 AERROR << "Channel is not handled by ChannelMonitor: " << channel;
113 return {nullptr, nullptr};
114}
115
116bool ValidateFields(const google::protobuf::Message& message,
117 const std::vector<std::string>& fields,
118 const size_t field_step) {
119 if (field_step >= fields.size()) {
120 return true;
121 }
122 const auto* desc = message.GetDescriptor();
123 const auto* refl = message.GetReflection();
124 const auto field_count = desc->field_count();
125 for (int field_idx = 0; field_idx < field_count; ++field_idx) {
126 const auto* field_desc = desc->field(field_idx);
127 if (field_desc->name() == fields[field_step]) {
128 if (field_desc->is_repeated()) {
129 // For repeated field, we do not expect it has deeper level validation
130 const auto size = refl->FieldSize(message, field_desc);
131 return size > 0 && field_step == fields.size() - 1;
132 }
133 if (field_desc->type() !=
134 google::protobuf::FieldDescriptor::TYPE_MESSAGE) {
135 return refl->HasField(message, field_desc) &&
136 field_step == fields.size() - 1;
137 }
138 return ValidateFields(refl->GetMessage(message, field_desc), fields,
139 field_step + 1);
140 }
141 }
142 return false;
143}
144
145} // namespace
146
148 const std::shared_ptr<LatencyMonitor>& latency_monitor)
149 : RecurrentRunner(FLAGS_channel_monitor_name,
150 FLAGS_channel_monitor_interval),
151 latency_monitor_(latency_monitor) {}
152
153void ChannelMonitor::RunOnce(const double current_time) {
154 auto manager = MonitorManager::Instance();
155 const auto& mode = manager->GetHMIMode();
156 auto* components = manager->GetStatus()->mutable_components();
157 for (const auto& iter : mode.monitored_components()) {
158 const std::string& name = iter.first;
159 const auto& config = iter.second;
160 if (config.has_channel()) {
161 double freq;
162 const auto update_freq =
163 latency_monitor_->GetFrequency(config.channel().name(), &freq);
164 UpdateStatus(config.channel(),
165 components->at(name).mutable_channel_status(), update_freq,
166 freq);
167 }
168 }
169}
170
171void ChannelMonitor::UpdateStatus(
173 ComponentStatus* status, const bool update_freq, const double freq) {
174 status->clear_status();
175
176 const auto reader_message_pair = GetReaderAndLatestMessage(config.name());
177 const auto reader = reader_message_pair.first;
178 const auto message = reader_message_pair.second;
179
180 if (reader == nullptr) {
182 ComponentStatus::UNKNOWN,
183 absl::StrCat(config.name(), " is not registered in ChannelMonitor."),
184 status);
185 return;
186 }
187
188 if (message == nullptr || message->ByteSize() == 0) {
190 ComponentStatus::FATAL,
191 absl::StrCat("the message ", config.name(), " reseived is empty."),
192 status);
193 return;
194 }
195
196 // Check channel delay
197 const double delay = reader->GetDelaySec();
198 if (delay < 0 || delay > config.delay_fatal()) {
200 ComponentStatus::FATAL,
201 absl::StrCat(config.name(), " delayed for ", delay, " seconds."),
202 status);
203 }
204
205 // Check channel fields
206 const std::string field_sepr = ".";
207 if (message != nullptr) {
208 for (const auto& field : config.mandatory_fields()) {
209 if (!ValidateFields(*message, absl::StrSplit(field, field_sepr), 0)) {
211 ComponentStatus::ERROR,
212 absl::StrCat(config.name(), " missing field ", field), status);
213 }
214 }
215 }
216
217 // Check channel frequency
218 if (update_freq) {
219 if (freq > config.max_frequency_allowed()) {
221 ComponentStatus::WARN,
222 absl::StrCat(config.name(), " has frequency ", freq,
223 " > max allowed ", config.max_frequency_allowed()),
224 status);
225 }
226 if (freq < config.min_frequency_allowed()) {
228 ComponentStatus::WARN,
229 absl::StrCat(config.name(), " has frequency ", freq,
230 " < min allowed ", config.max_frequency_allowed()),
231 status);
232 }
233 }
234
235 SummaryMonitor::EscalateStatus(ComponentStatus::OK, "", status);
236}
237
238} // namespace monitor
239} // namespace apollo
DEFINE_string(channel_monitor_name, "ChannelMonitor", "Name of the channel monitor.")
DEFINE_double(channel_monitor_interval, 5, "Channel monitor checking interval in seconds.")
void RunOnce(const double current_time) override
ChannelMonitor(const std::shared_ptr< LatencyMonitor > &latency_monitor)
static void EscalateStatus(const ComponentStatus::Status new_status, const std::string &message, ComponentStatus *current_status)
#define AERROR
Definition log.h:44
Some map util functions.
class register implement
Definition arena_queue.h:37