Apollo 11.0
自动驾驶开放平台
semantic_decision.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 *****************************************************************************/
17
18#include <map>
19
20#include "boost/bind.hpp"
21
22#include "cyber/common/file.h"
24
25namespace apollo {
26namespace perception {
27namespace trafficlight {
28
29std::map<base::TLColor, std::string> s_color_strs = {
31 {base::TLColor::TL_RED, "red"},
32 {base::TLColor::TL_GREEN, "green"},
33 {base::TLColor::TL_YELLOW, "yellow"},
34 {base::TLColor::TL_BLACK, "black"}};
35
36bool compare(const SemanticTable &s1, const SemanticTable &s2) {
37 return s1.semantic == s2.semantic;
38}
39
41 : revise_time_s_(1.5f),
42 blink_threshold_s_(0.4f),
43 non_blink_threshold_s_(0.8f),
44 hysteretic_threshold_(1) {}
45
47 std::string config_file =
48 GetConfigFile(options.config_path, options.config_file);
49
50 if (!cyber::common::GetProtoFromFile(config_file, &semantic_param_)) {
51 AERROR << "load proto param failed, root dir: " << config_file;
52 return false;
53 }
54
55 int non_blink_coef = 2;
56 revise_time_s_ = semantic_param_.revise_time_second();
57 blink_threshold_s_ = semantic_param_.blink_threshold_second();
58 hysteretic_threshold_ = semantic_param_.hysteretic_threshold_count();
59 non_blink_threshold_s_ =
60 blink_threshold_s_ * static_cast<float>(non_blink_coef);
61
62 ADEBUG << "revise_time_s_: " << revise_time_s_;
63 ADEBUG << "blink_threshold_s_: " << blink_threshold_s_;
64 ADEBUG << "hysteretic_threshold_: " << hysteretic_threshold_;
65
66 return true;
67}
68
70 const SemanticTable &cur, std::vector<base::TrafficLightPtr> *lights,
71 std::vector<SemanticTable>::iterator *history) {
72 (*history)->time_stamp = cur.time_stamp;
73 if ((*history)->color == base::TLColor::TL_BLACK) {
74 if ((*history)->hystertic_window.hysteretic_color == cur.color) {
75 (*history)->hystertic_window.hysteretic_count++;
76 } else {
77 (*history)->hystertic_window.hysteretic_color = cur.color;
78 (*history)->hystertic_window.hysteretic_count = 1;
79 }
80 ADEBUG << "Black lights hysteretic change to " << s_color_strs[cur.color]
81 << " count " << (*history)->hystertic_window.hysteretic_count
82 << " threshold " << hysteretic_threshold_;
83
84 if ((*history)->hystertic_window.hysteretic_count > hysteretic_threshold_) {
85 (*history)->color = cur.color;
86 (*history)->hystertic_window.hysteretic_count = 0;
87 ADEBUG << "Black lights hysteretic change to " << s_color_strs[cur.color];
88 } else {
89 ReviseLights(lights, cur.light_ids, (*history)->color);
90 }
91 } else {
92 (*history)->color = cur.color;
93 }
94}
95
97 SemanticTable semantic_table, std::vector<base::TrafficLightPtr> *lights) {
98 std::vector<int> vote(static_cast<int>(base::TLColor::TL_TOTAL_COLOR_NUM), 0);
99 std::vector<base::TrafficLightPtr> &lights_ref = *lights;
101
102 for (size_t i = 0; i < semantic_table.light_ids.size(); ++i) {
103 int index = semantic_table.light_ids.at(i);
104 base::TrafficLightPtr light = lights_ref[index];
105 auto color = light->status.color;
106 vote.at(static_cast<int>(color))++;
107 }
108
109 if ((vote.at(static_cast<size_t>(base::TLColor::TL_RED)) == 0) &&
110 (vote.at(static_cast<size_t>(base::TLColor::TL_GREEN)) == 0) &&
111 (vote.at(static_cast<size_t>(base::TLColor::TL_YELLOW)) == 0)) {
112 if (vote.at(static_cast<size_t>(base::TLColor::TL_BLACK)) > 0) {
114 } else {
116 }
117 }
118
119 vote.at(static_cast<size_t>(base::TLColor::TL_BLACK)) = 0;
120 vote.at(static_cast<size_t>(base::TLColor::TL_UNKNOWN_COLOR)) = 0;
121
122 auto biggest = std::max_element(std::begin(vote), std::end(vote));
123
124 int max_color_num = *biggest;
125 max_color = base::TLColor(std::distance(std::begin(vote), biggest));
126
127 vote.erase(biggest);
128
129 auto second_biggest = std::max_element(std::begin(vote), std::end(vote));
130
131 ADEBUG << "color " << s_color_strs[max_color] << " is max " << max_color_num;
132
133 if (max_color_num == *second_biggest) {
135 } else {
136 return max_color;
137 }
138}
139
140void SemanticReviser::ReviseLights(std::vector<base::TrafficLightPtr> *lights,
141 const std::vector<int> &light_ids,
142 base::TLColor dst_color) {
143 for (auto index : light_ids) {
144 lights->at(index)->status.color = dst_color;
145 }
146
147 ADEBUG << "revise " << light_ids.size() << " lights to "
148 << s_color_strs[dst_color];
149}
150
152 double time_stamp, SemanticTable semantic_table,
153 std::vector<base::TrafficLightPtr> *lights) {
154 ADEBUG << "revise " << semantic_table.semantic
155 << ", lights number:" << semantic_table.light_ids.size();
156
157 std::vector<base::TrafficLightPtr> &lights_ref = *lights;
158 base::TLColor cur_color = ReviseBySemantic(semantic_table, lights);
160 semantic_table.color = cur_color;
161 semantic_table.time_stamp = time_stamp;
162 ADEBUG << "revise same semantic lights";
163 ReviseLights(lights, semantic_table.light_ids, cur_color);
164
165 std::vector<SemanticTable>::iterator iter =
166 std::find_if(std::begin(history_semantic_), std::end(history_semantic_),
167 boost::bind(compare, _1, semantic_table));
168
169 if (iter != history_semantic_.end()) {
170 pre_color = iter->color;
171 if (time_stamp - iter->time_stamp < revise_time_s_) {
172 ADEBUG << "revise by time series";
173 switch (cur_color) {
175 if (iter->color == base::TLColor::TL_RED) {
176 ReviseLights(lights, semantic_table.light_ids, iter->color);
177 iter->time_stamp = time_stamp;
178 iter->hystertic_window.hysteretic_count = 0;
179 } else {
180 UpdateHistoryAndLights(semantic_table, lights, &iter);
181 ADEBUG << "High confidence color " << s_color_strs[cur_color];
182 }
183 break;
186 UpdateHistoryAndLights(semantic_table, lights, &iter);
187 if (time_stamp - iter->last_bright_time_stamp > blink_threshold_s_ &&
188 iter->last_dark_time_stamp > iter->last_bright_time_stamp) {
189 iter->blink = true;
190 }
191 iter->last_bright_time_stamp = time_stamp;
192 ADEBUG << "High confidence color " << s_color_strs[cur_color];
193 break;
195 iter->last_dark_time_stamp = time_stamp;
196 iter->hystertic_window.hysteretic_count = 0;
197 if (iter->color == base::TLColor::TL_UNKNOWN_COLOR ||
198 iter->color == base::TLColor::TL_BLACK) {
199 iter->time_stamp = time_stamp;
200 UpdateHistoryAndLights(semantic_table, lights, &iter);
201 } else {
202 ReviseLights(lights, semantic_table.light_ids, iter->color);
203 }
204 break;
206 default:
207 ReviseLights(lights, semantic_table.light_ids, iter->color);
208 break;
209 }
210 } else {
211 iter->time_stamp = time_stamp;
212 iter->color = cur_color;
213 }
214
215 // set blink status
216 if (pre_color != iter->color ||
217 fabs(iter->last_dark_time_stamp - iter->last_bright_time_stamp) >
218 non_blink_threshold_s_) {
219 iter->blink = false;
220 }
221
222 for (auto index : semantic_table.light_ids) {
223 lights_ref[index]->status.blink =
224 (iter->blink && iter->color == base::TLColor::TL_GREEN);
225 }
226 ADEBUG << "semantic " << semantic_table.semantic << " color "
227 << s_color_strs[iter->color] << " blink " << iter->blink << " cur "
228 << s_color_strs[cur_color];
229 ADEBUG << "cur ts " << time_stamp;
230 ADEBUG << "bri ts " << iter->last_bright_time_stamp;
231 ADEBUG << "dar ts " << iter->last_dark_time_stamp;
232 } else {
233 semantic_table.last_dark_time_stamp = semantic_table.time_stamp;
234 semantic_table.last_bright_time_stamp = semantic_table.time_stamp;
235 history_semantic_.push_back(semantic_table);
236 }
237}
238
240 double time_stamp = frame->timestamp;
241 std::vector<base::TrafficLightPtr> &lights_ref = frame->traffic_lights;
242 std::vector<SemanticTable> semantic_table;
243 ADEBUG << "start revise ";
244
245 if (lights_ref.empty()) {
246 history_semantic_.clear();
247 ADEBUG << "no lights to revise, return";
248 return true;
249 }
250
251 ADEBUG << "lights_ref size is : " << lights_ref.size();
252 for (size_t i = 0; i < lights_ref.size(); i++) {
253 base::TrafficLightPtr light = lights_ref.at(i);
254 int cur_semantic = light->semantic;
255 ADEBUG << "light " << light->id << " semantic " << cur_semantic;
256
257 SemanticTable tmp;
258 std::stringstream ss;
259
260 if (cur_semantic > 0) {
261 ss << "Semantic_" << cur_semantic;
262 } else {
263 ss << "No_semantic_light_" << light->id;
264 }
265
266 tmp.semantic = ss.str();
267 tmp.light_ids.push_back(static_cast<int>(i));
268 tmp.color = light->status.color;
269 tmp.time_stamp = time_stamp;
270 tmp.blink = false;
271 auto iter =
272 std::find_if(std::begin(semantic_table), std::end(semantic_table),
273 boost::bind(compare, _1, tmp));
274
275 if (iter != semantic_table.end()) {
276 iter->light_ids.push_back(static_cast<int>(i));
277 } else {
278 semantic_table.push_back(tmp);
279 }
280 }
281
282 ADEBUG << "semantic_table size is : " << semantic_table.size();
283 for (size_t i = 0; i < semantic_table.size(); ++i) {
284 SemanticTable cur_semantic_table = semantic_table.at(i);
285 ReviseByTimeSeries(time_stamp, cur_semantic_table, &lights_ref);
286 }
287
288 return true;
289}
290
292
293} // namespace trafficlight
294} // namespace perception
295} // namespace apollo
#define REGISTER_TRAFFIC_LIGHT_TRACKER(name)
bool Init(const TrafficLightTrackerInitOptions &options=TrafficLightTrackerInitOptions()) override
Initialize semantic reviser parameters.
void ReviseLights(std::vector< base::TrafficLightPtr > *lights, const std::vector< int > &light_ids, base::TLColor dst_color)
Revise and tracking traffic light.
void ReviseByTimeSeries(double time_stamp, SemanticTable semantic_table, std::vector< base::TrafficLightPtr > *lights)
Correction based on timeseries information.
void UpdateHistoryAndLights(const SemanticTable &cur, std::vector< base::TrafficLightPtr > *lights, std::vector< SemanticTable >::iterator *history)
Update the traffic light history information.
bool Track(camera::TrafficLightFrame *frame) override
Track detected traffic_light.
SemanticReviser()
Construct a new semantic reviser object.
base::TLColor ReviseBySemantic(SemanticTable semantic_table, std::vector< base::TrafficLightPtr > *lights)
Correction based on semantic information.
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
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::shared_ptr< TrafficLight > TrafficLightPtr
bool compare(const SemanticTable &s1, const SemanticTable &s2)
std::map< base::TLColor, std::string > s_color_strs
std::string GetConfigFile(const std::string &config_path, const std::string &config_file)
Definition util.cc:80
class register implement
Definition arena_queue.h:37
std::vector< base::TrafficLightPtr > traffic_lights