Apollo 10.0
自动驾驶开放平台
data_collection_monitor.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2019 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 "gflags/gflags.h"
20#include "google/protobuf/descriptor.h"
21#include "google/protobuf/message.h"
22
23#include "cyber/common/file.h"
29
30namespace apollo {
31namespace dreamview {
32
36using google::protobuf::FieldDescriptor;
37using Json = nlohmann::json;
38
39namespace {
40
41/*
42 * For simplicity, we are converting all supporting cpp types to float.
43 * It is okay to lost precision since this conversion is used
44 * for criteria comparison.
45 */
46bool GetProtobufFloatByFieldName(const google::protobuf::Message& message,
47 const google::protobuf::Descriptor* descriptor,
48 const google::protobuf::Reflection* reflection,
49 const std::string& field_name, float* value) {
50 if (!descriptor) {
51 AERROR << "Protobuf descriptor not found";
52 return false;
53 }
54
55 const auto* field_descriptor = descriptor->FindFieldByName(field_name);
56 const auto cpp_type = field_descriptor->cpp_type();
57 if (cpp_type == FieldDescriptor::CppType::CPPTYPE_FLOAT) {
58 *value = reflection->GetFloat(message, field_descriptor);
59 } else if (cpp_type == FieldDescriptor::CppType::CPPTYPE_DOUBLE) {
60 double value_in_double = reflection->GetDouble(message, field_descriptor);
61 *value = static_cast<float>(value_in_double);
62 } else if (cpp_type == FieldDescriptor::CppType::CPPTYPE_ENUM) {
63 int value_in_int = reflection->GetEnumValue(message, field_descriptor);
64 *value = static_cast<float>(value_in_int);
65 } else {
66 AERROR << field_name << " has unsupported conversion type: "
67 << field_descriptor->cpp_type();
68 return false;
69 }
70
71 return true;
72}
73
74bool IsCompliedWithCriterion(float actual_value,
75 const ComparisonOperator& comparison_operator,
76 float target_value) {
77 switch (comparison_operator) {
79 return std::fabs(actual_value - target_value) <
82 return (actual_value > target_value);
84 return (actual_value >= target_value);
86 return (actual_value < target_value);
88 return (actual_value <= target_value);
90 return (actual_value != target_value);
91 default:
92 AERROR << "Unsupported comparison operator found:" << comparison_operator;
93 return false;
94 }
95}
96
97} // namespace
98
100 : FuelMonitor(FLAGS_data_collection_monitor_name),
101 node_(cyber::CreateNode("data_collection_monitor")) {
102 InitReaders();
103 LoadConfiguration();
104}
105
107
108void DataCollectionMonitor::InitReaders() {
109 node_->CreateReader<Chassis>(FLAGS_chassis_topic,
110 [this](const std::shared_ptr<Chassis>& chassis) {
111 this->OnChassis(chassis);
112 });
113}
114
115void DataCollectionMonitor::LoadConfiguration() {
116 const std::string& vehicle_dir =
117 VehicleManager::Instance()->GetVehicleDataPath();
118 std::string data_collection_config_path =
119 vehicle_dir + "/data_collection_table.pb.txt";
120 if (!PathExists(data_collection_config_path)) {
121 AWARN << "No corresponding data collection table file found in "
122 << vehicle_dir << ". Using default one instead.";
123 data_collection_config_path = FLAGS_default_data_collection_config_path;
124 }
125
126 ACHECK(cyber::common::GetProtoFromFile(data_collection_config_path,
127 &data_collection_table_))
128 << "Unable to parse data collection configuration from file "
129 << data_collection_config_path;
130
131 ConstructCategories();
132
133 ADEBUG << "Configuration loaded.";
134}
135
136void DataCollectionMonitor::ConstructCategories() {
137 scenario_to_categories_.clear();
138
139 for (const auto& scenario_iter : data_collection_table_.scenario()) {
140 const std::string& scenario_name = scenario_iter.first;
141 const Scenario& scenario = scenario_iter.second;
142
143 Category category;
144 ConstructCategoriesHelper(scenario_name, scenario, 0, "", category);
145 }
146}
147
148void DataCollectionMonitor::ConstructCategoriesHelper(
149 const std::string& scenario_name, const Scenario& scenario, int feature_idx,
150 std::string current_category_name, const Category& current_category) {
151 if (feature_idx == scenario.feature_size()) {
152 scenario_to_categories_[scenario_name].insert(
153 {current_category_name, current_category});
154
155 category_consecutive_frame_count_[scenario_name][current_category_name] =
156 0.0;
157 category_frame_count_[scenario_name][current_category_name] = 0.0;
158 current_progress_json_[scenario_name][current_category_name] = 0.0;
159 return;
160 }
161
162 const Feature& feature = scenario.feature(feature_idx);
163 for (const auto& range : feature.range()) {
164 Category new_category(current_category);
165 new_category.push_back(range);
166
167 // set new category name by appending it with the current range name
168 std::string new_category_name(current_category_name);
169 const std::string& range_name = range.name();
170 if (feature.range().size() > 1 && !range_name.empty()) {
171 if (!new_category_name.empty()) {
172 new_category_name += ", ";
173 }
174 new_category_name += range_name;
175 }
176
177 ConstructCategoriesHelper(scenario_name, scenario, feature_idx + 1,
178 new_category_name, new_category);
179 }
180}
181
183 if (!enabled_) {
184 category_consecutive_frame_count_.clear();
185 category_frame_count_.clear();
186 current_progress_json_.clear();
187 LoadConfiguration();
188 }
189 enabled_ = true;
190}
191
193 enabled_ = false;
194 AINFO << "DataCollectionMonitor stopped";
195}
196
197void DataCollectionMonitor::OnChassis(const std::shared_ptr<Chassis>& chassis) {
198 if (!enabled_) {
199 return;
200 }
201
202 const size_t frame_threshold = data_collection_table_.frame_threshold();
203 const auto total_frames = data_collection_table_.total_frames();
204 for (const auto& scenario_iter : scenario_to_categories_) {
205 const std::string& scenario_name = scenario_iter.first;
206 const auto& categories = scenario_iter.second;
207
208 for (const auto& category_iter : categories) {
209 const std::string& category_name = category_iter.first;
210 const Category& category = category_iter.second;
211
212 // This category is done, skip
213 if (category_frame_count_[scenario_name][category_name] >= total_frames) {
214 continue;
215 }
216
217 if (!IsCompliedWithCriteria(chassis, category)) {
218 category_consecutive_frame_count_[scenario_name][category_name] = 0;
219 continue;
220 }
221
222 // Increment frame count only if consecutive count exceeds the threshold
223 const size_t consecutive_count =
224 ++category_consecutive_frame_count_[scenario_name][category_name];
225 if (consecutive_count == frame_threshold) {
226 category_frame_count_[scenario_name][category_name] +=
227 consecutive_count;
228 } else if (consecutive_count >= frame_threshold) {
229 category_frame_count_[scenario_name][category_name] += 1;
230 }
231
232 // Update category progress
233 const double progress_percentage =
234 100.0 *
235 static_cast<double>(
236 category_frame_count_[scenario_name][category_name]) /
237 static_cast<double>(total_frames);
238 {
239 boost::unique_lock<boost::shared_mutex> writer_lock(mutex_);
240 current_progress_json_[scenario_name][category_name] =
241 progress_percentage;
242 }
243 }
244 }
245}
246
247bool DataCollectionMonitor::IsCompliedWithCriteria(
248 const std::shared_ptr<Chassis>& chassis, const Category& category) {
249 const auto& vehicle_param = VehicleConfigHelper::GetConfig().vehicle_param();
250 const auto* vehicle_param_descriptor = vehicle_param.GetDescriptor();
251 const auto* vehicle_param_reflection = vehicle_param.GetReflection();
252
253 const auto* chassis_descriptor = chassis->GetDescriptor();
254 const auto* chassis_reflection = chassis->GetReflection();
255
256 for (const auto& range : category) {
257 for (const auto& criterion : range.criterion()) {
258 float target_value;
259 if (criterion.has_value()) {
260 target_value = criterion.value();
261 } else if (!GetProtobufFloatByFieldName(
262 vehicle_param, vehicle_param_descriptor,
263 vehicle_param_reflection, criterion.vehicle_config(),
264 &target_value)) {
265 return false;
266 }
267
268 float actual_value;
269 if (!GetProtobufFloatByFieldName(*chassis, chassis_descriptor,
270 chassis_reflection, criterion.field(),
271 &actual_value)) {
272 return false;
273 }
274
275 if (!IsCompliedWithCriterion(
276 actual_value, criterion.comparison_operator(), target_value)) {
277 return false;
278 }
279 }
280 }
281
282 return true;
283}
284
286 boost::unique_lock<boost::shared_mutex> reader_lock(mutex_);
287 return current_progress_json_;
288}
289
290} // namespace dreamview
291} // namespace apollo
@Brief This is a helper class that can load vehicle configurations.
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
DataCollectionMonitor()
Constructor of DataCollectionMonitor.
void Stop() override
stop monitoring collection progress
void Start() override
start monitoring collection progress
nlohmann::json GetProgressAsJson() override
return collection progress of categories and overall as json
A base class that monitor progress for Fuel client
#define ACHECK(cond)
Definition log.h:80
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
constexpr double kMathEpsilon
Definition vec2d.h:35
bool PathExists(const std::string &path)
Check if the path exists.
Definition file.cc:195
bool GetProtoFromFile(const std::string &file_name, google::protobuf::Message *message)
Parses the content of the file specified by the file_name as a representation of protobufs,...
Definition file.cc:132
std::vector< Range > Category
class register implement
Definition arena_queue.h:37
optional VehicleParam vehicle_param