Apollo 11.0
自动驾驶开放平台
tl_preprocessor.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 "cyber/common/file.h"
19#include "cyber/common/log.h"
21
22namespace apollo {
23namespace perception {
24namespace trafficlight {
25
27 trafficlight::MultiCamerasInitOption projection_init_option;
28 projection_init_option.camera_names = options.camera_names;
29 if (!projection_.Init(projection_init_option)) {
30 AERROR << "init multi_camera_projection failed.";
31 return false;
32 }
33
34 num_cameras_ = projection_.getCameraNamesByDescendingFocalLen().size();
35 lights_on_image_array_.resize(num_cameras_);
36 lights_outside_image_array_.resize(num_cameras_);
37 sync_interval_seconds_ = options.sync_interval_seconds;
38
39 AINFO << "preprocessor init succeed";
40
41 return true;
42}
43
45 const camera::CarPose &pose, const TLPreprocessorOption &option,
46 std::vector<base::TrafficLightPtr> *lights) {
47 const double &timestamp = pose.getTimestamp();
48 selected_camera_name_.first = timestamp;
49 selected_camera_name_.second = GetMaxFocalLenWorkingCameraName();
50
51 AINFO << "TLPreprocessor Got signal number: " << lights->size()
52 << ", ts: " << timestamp;
53 if (lights->empty()) {
54 AINFO << "No signals, select camera with max focal length: "
55 << selected_camera_name_.second;
56 return true;
57 }
58
59 if (!ProjectLightsAndSelectCamera(pose, option,
60 &(selected_camera_name_.second), lights)) {
61 AERROR << "project_lights_and_select_camera failed, ts: " << timestamp;
62 }
63
64 AINFO << "selected_camera_id: " << selected_camera_name_.second;
65
66 return true;
67}
68
69bool TLPreprocessor::SyncInformation(const double image_timestamp,
70 const std::string &cam_name) {
71 const double &proj_ts = selected_camera_name_.first;
72 const std::string &proj_camera_name = selected_camera_name_.second;
73 AINFO << "ready to sync information";
74
75 if (!projection_.HasCamera(cam_name)) {
76 AERROR << "sync_image failed, "
77 << "get invalid camera_name: " << cam_name;
78 return false;
79 }
80
81 AINFO << "Enter TLPreprocessor::sync_image. proj_ts: " << proj_ts
82 << " proj_camera_name: " << proj_camera_name
83 << " image_ts: " << image_timestamp
84 << " image_camera_name: " << cam_name;
85 if (image_timestamp < last_pub_img_ts_) {
86 AWARN << "TLPreprocessor reject the image pub ts:" << image_timestamp
87 << " which is earlier than last output ts:" << last_pub_img_ts_
88 << ", image_camera_name: " << cam_name;
89 return false;
90 }
91
92 if (proj_camera_name != cam_name) {
93 AWARN << "sync_image failed - find close enough projection,"
94 << "but camera_name not match.";
95 return false;
96 }
97 AINFO << "sync_image succeeded.";
98 last_pub_img_ts_ = image_timestamp;
99 return true;
100}
101
103 const camera::CarPose &pose, const TLPreprocessorOption &option,
104 const std::string &camera_name,
105 std::vector<base::TrafficLightPtr> *lights) {
106 lights_on_image_.clear();
107 lights_outside_image_.clear();
108
109 AINFO << "clear lights_outside_image_ " << lights_outside_image_.size();
110
111 if (lights->empty()) {
112 AINFO << "No lights to be projected";
113 return true;
114 }
115
116 if (!ProjectLights(pose, camera_name, lights, &lights_on_image_,
117 &lights_outside_image_)) {
118 AERROR << "update_lights_projection project lights on " << camera_name
119 << " image failed";
120 return false;
121 }
122
123 if (lights_outside_image_.size() > 0) {
124 AERROR << "update_lights_projection failed,"
125 << "lights_outside_image->size() " << lights_outside_image_.size()
126 << " ts: " << pose.getTimestamp();
127 return false;
128 }
129
130 auto min_focal_len_working_camera = GetMinFocalLenWorkingCameraName();
131 if (camera_name == min_focal_len_working_camera) {
132 return lights_on_image_.size() > 0;
133 }
134 for (const base::TrafficLightPtr &light : lights_on_image_) {
135 if (camera::OutOfValidRegion(light->region.projection_roi,
136 projection_.getImageWidth(camera_name),
137 projection_.getImageHeight(camera_name),
138 option.image_borders_size->at(camera_name))) {
139 AINFO << "update_lights_projection light project out of image region. "
140 << "camera_name: " << camera_name;
141 return false;
142 }
143 }
144
145 AINFO << "UpdateLightsProjection success";
146 return true;
147}
148
149bool TLPreprocessor::SetCameraWorkingFlag(const std::string &camera_name,
150 bool is_working) {
151 if (!projection_.HasCamera(camera_name)) {
152 AERROR << "SetCameraWorkingFlag failed, "
153 << "get invalid camera_name: " << camera_name;
154 return false;
155 }
156 camera_is_working_flags_[camera_name] = is_working;
157 AINFO << "SetCameraWorkingFlag succeeded, camera_name: " << camera_name
158 << ", flag: " << camera_is_working_flags_[camera_name];
159 return true;
160}
161
162bool TLPreprocessor::GetCameraWorkingFlag(const std::string &camera_name,
163 bool *is_working) const {
164 if (!projection_.HasCamera(camera_name)) {
165 AERROR << "GetCameraWorkingFlag failed, "
166 << "get invalid camera_name: " << camera_name;
167 return false;
168 }
169
170 if (camera_is_working_flags_.find(camera_name) ==
171 camera_is_working_flags_.end() ||
172 !camera_is_working_flags_.at(camera_name)) {
173 *is_working = false;
174 } else {
175 *is_working = true;
176 }
177 return true;
178}
179
180void TLPreprocessor::SelectCamera(
181 std::vector<base::TrafficLightPtrs> *lights_on_image_array,
182 std::vector<base::TrafficLightPtrs> *lights_outside_image_array,
183 const TLPreprocessorOption &option, std::string *selected_camera_name) {
184 // do not check boundary if this is min focal camera
185 auto min_focal_len_working_camera = GetMinFocalLenWorkingCameraName();
186 AINFO << "working camera with minimum focal length: "
187 << min_focal_len_working_camera;
188
189 const auto &camera_names = projection_.getCameraNamesByDescendingFocalLen();
190 for (size_t cam_id = 0; cam_id < lights_on_image_array->size(); ++cam_id) {
191 const auto &camera_name = camera_names[cam_id];
192 bool is_working = false;
193 // camera is not working ,skip
194 if (!GetCameraWorkingFlag(camera_name, &is_working) || !is_working) {
195 AINFO << "camera " << camera_name << "is not working";
196 continue;
197 }
198
199 bool ok = true;
200 if (camera_name != min_focal_len_working_camera) {
201 // lights must project on the image if this is not min focal camera
202 if (lights_outside_image_array->at(cam_id).size() > 0) {
203 AINFO << "light project out of image, "
204 << "camera_name: " << camera_name
205 << " lights_outside_image_array->at(cam_id).size(): "
206 << lights_outside_image_array->at(cam_id).size();
207 continue;
208 }
209 auto lights = lights_on_image_array->at(cam_id);
210 for (const auto light : lights) {
211 // check boundary
212 if (camera::OutOfValidRegion(light->region.projection_roi,
213 projection_.getImageWidth(camera_name),
214 projection_.getImageHeight(camera_name),
215 option.image_borders_size->at(camera_name))) {
216 ok = false;
217 AINFO << "light project out of image region, "
218 << "camera_name: " << camera_name << " border_size: "
219 << option.image_borders_size->at(camera_name);
220 break;
221 }
222 }
223 } else {
224 // do not checkout the boundary if this is min focal camera
225 ok = (lights_on_image_array->at(cam_id).size() > 0);
226 }
227
228 if (ok) {
229 *selected_camera_name = camera_name;
230 break;
231 }
232 }
233 AINFO << "select_camera selection: " << *selected_camera_name;
234}
235
236bool TLPreprocessor::ProjectLights(
237 const camera::CarPose &pose, const std::string &camera_name,
238 std::vector<base::TrafficLightPtr> *lights,
239 base::TrafficLightPtrs *lights_on_image,
240 base::TrafficLightPtrs *lights_outside_image) {
241 if (lights->empty()) {
242 AINFO << "project_lights get empty signals.";
243 return true;
244 }
245 if (!projection_.HasCamera(camera_name)) {
246 AERROR << "project_lights get invalid camera_name: " << camera_name;
247 return false;
248 }
249
250 // camera is not working
251 bool is_working = false;
252 if (!GetCameraWorkingFlag(camera_name, &is_working) || !is_working) {
253 AWARN << "TLPreprocessor::project_lights not project lights, "
254 << "camera is not working, camera_name: " << camera_name;
255 return true;
256 }
257
258 for (size_t i = 0; i < lights->size(); ++i) {
259 base::TrafficLightPtr light_proj(new base::TrafficLight);
260 auto light = lights->at(i);
261 if (!projection_.Project(pose, ProjectOption(camera_name), light.get())) {
262 light->region.outside_image = true;
263 *light_proj = *light;
264 lights_outside_image->push_back(light_proj);
265 } else {
266 light->region.outside_image = false;
267 *light_proj = *light;
268 lights_on_image->push_back(light_proj);
269 }
270 }
271 return true;
272}
273
274bool TLPreprocessor::ProjectLightsAndSelectCamera(
275 const camera::CarPose &pose, const TLPreprocessorOption &option,
276 std::string *selected_camera_name,
277 std::vector<base::TrafficLightPtr> *lights) {
278 if (selected_camera_name == nullptr) {
279 AERROR << "selected_camera_name is not available";
280 return false;
281 }
282 if (lights == nullptr) {
283 AERROR << "lights is not available";
284 return false;
285 }
286
287 for (auto &light_ptrs : lights_on_image_array_) {
288 light_ptrs.clear();
289 }
290 for (auto &light_ptrs : lights_outside_image_array_) {
291 light_ptrs.clear();
292 }
293
294 // project light region on each camera's image plane
295 const auto &camera_names = projection_.getCameraNamesByDescendingFocalLen();
296 for (size_t cam_id = 0; cam_id < num_cameras_; ++cam_id) {
297 const std::string &camera_name = camera_names[cam_id];
298 if (!ProjectLights(pose, camera_name, lights,
299 &(lights_on_image_array_[cam_id]),
300 &(lights_outside_image_array_[cam_id]))) {
301 AERROR << "select_camera_by_lights_projection project lights on "
302 << camera_name << " image failed";
303 return false;
304 }
305 }
306 // todo : can be optimized
307 projections_outside_all_images_ = !lights->empty();
308 for (size_t cam_id = 0; cam_id < num_cameras_; ++cam_id) {
309 projections_outside_all_images_ =
310 projections_outside_all_images_ &&
311 (lights_on_image_array_[cam_id].size() < lights->size());
312 }
313 if (projections_outside_all_images_) {
314 AWARN << "lights projections outside all images";
315 }
316
317 // select which camera to be used
318 SelectCamera(&lights_on_image_array_, &lights_outside_image_array_, option,
319 selected_camera_name);
320
321 return true;
322}
323
325 return projections_outside_all_images_;
326}
327
328std::string TLPreprocessor::Name() const { return "TLPreprocessor"; }
329
330std::string TLPreprocessor::GetMinFocalLenWorkingCameraName() const {
331 const auto &camera_names = projection_.getCameraNamesByDescendingFocalLen();
332 for (auto itr = camera_names.crbegin(); itr != camera_names.crend(); ++itr) {
333 bool is_working = false;
334 if (GetCameraWorkingFlag(*itr, &is_working) && is_working) {
335 return *itr;
336 }
337 }
338 AWARN << "No working camera, return empty camera_name";
339 return "";
340}
341
342std::string TLPreprocessor::GetMaxFocalLenWorkingCameraName() const {
343 const auto &camera_names = projection_.getCameraNamesByDescendingFocalLen();
344 for (const auto &camera_name : camera_names) {
345 bool is_working = false;
346 if (GetCameraWorkingFlag(camera_name, &is_working) && is_working) {
347 return camera_name;
348 }
349 }
350 AWARN << "No working camera, return empty camera_name";
351 return "";
352}
353
355
356} // namespace trafficlight
357} // namespace perception
358} // namespace apollo
#define PERCEPTION_REGISTER_TLPREPROCESSOR(name)
bool Project(const camera::CarPose &pose, const ProjectOption &option, base::TrafficLight *light) const
Boundary projection based on vehicle position and traffic lights.
bool Init(const MultiCamerasInitOption &options)
multicamera project initialization parameters.
bool HasCamera(const std::string &camera_name) const
Determine whether the camera exists.
int getImageWidth(const std::string &camera_name) const
Get the image width object.
int getImageHeight(const std::string &camera_name) const
Get the image height object.
const std::vector< std::string > & getCameraNamesByDescendingFocalLen() const
Get the camera names by descending focal len object.
bool GetAlllightsOutsideFlag() const
Get all projections outside the image.
bool Init(const TrafficLightPreprocessorInitOptions &options) override
Traffic light preprocessing initialization parameters.
bool SyncInformation(const double ts, const std::string &camera_name)
Determine whether the selected camera is available and synchronize timestamp information.
bool SetCameraWorkingFlag(const std::string &camera_name, bool is_working) override
Set the camera working flag object.
bool GetCameraWorkingFlag(const std::string &camera_name, bool *is_working) const override
Get the camera working flag object.
std::string Name() const override
returns the name of the preprocessing plugin.
bool UpdateCameraSelection(const camera::CarPose &pose, const TLPreprocessorOption &option, std::vector< base::TrafficLightPtr > *lights) override
Select the appropriate camera for preprocessing according to the position of the vehicle and the posi...
bool UpdateLightsProjection(const camera::CarPose &pose, const TLPreprocessorOption &option, const std::string &camera_name, std::vector< base::TrafficLightPtr > *lights) override
Update the traffic light projection status and determine whether the projection exceeds the boundary ...
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
std::shared_ptr< TrafficLight > TrafficLightPtr
std::vector< TrafficLightPtr > TrafficLightPtrs
bool OutOfValidRegion(const base::BBox2D< T > box, const T width, const T height, const T border_size=0)
Definition util.h:74
class register implement
Definition arena_queue.h:37