Apollo 10.0
自动驾驶开放平台
visualization_manager.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 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 <algorithm>
20#include <thread>
21
22#include <boost/date_time/posix_time/posix_time.hpp>
23#include <boost/filesystem.hpp>
24
25#include "cyber/common/log.h"
26
27namespace apollo {
28namespace localization {
29namespace msf {
30
31// ===================MessageBuffer=======================
32template <class MessageType>
33MessageBuffer<MessageType>::MessageBuffer(int capacity) : capacity_(capacity) {
34 pthread_mutex_init(&buffer_mutex_, nullptr);
35}
36
37template <class MessageType>
39 pthread_mutex_destroy(&buffer_mutex_);
40}
41
42template <class MessageType>
44 const MessageType &msg) {
45 if (capacity_ == 0) {
46 AERROR << "The buffer capacity is 0.";
47 return false;
48 }
49
50 pthread_mutex_lock(&buffer_mutex_);
51 auto found_iter = msg_map_.find(timestamp);
52 if (found_iter != msg_map_.end()) {
53 AERROR << "The msg has existed in buffer.";
54 pthread_mutex_unlock(&buffer_mutex_);
55 return false;
56 }
57 pthread_mutex_unlock(&buffer_mutex_);
58
59 std::pair<double, MessageType> msg_pair = std::make_pair(timestamp, msg);
60 pthread_mutex_lock(&buffer_mutex_);
61 if (msg_list_.size() < capacity_) {
62 msg_list_.push_back(msg_pair);
63 } else {
64 msg_map_.erase(msg_list_.begin()->first);
65 msg_list_.pop_front();
66 msg_list_.push_back(msg_pair);
67 }
68 ListIterator iter = msg_list_.end();
69 msg_map_[timestamp] = (--iter);
70 pthread_mutex_unlock(&buffer_mutex_);
71
72 return true;
73}
74
75template <class MessageType>
77 if (IsEmpty()) {
78 AERROR << "The buffer is empty.";
79 return false;
80 }
81
82 pthread_mutex_lock(&buffer_mutex_);
83 *msg = msg_list_.begin()->second;
84 msg_map_.erase(msg_list_.begin()->first);
85 msg_list_.pop_front();
86 pthread_mutex_unlock(&buffer_mutex_);
87
88 return true;
89}
90
91template <class MessageType>
93 MessageType *msg) {
94 if (IsEmpty()) {
95 AERROR << "The buffer is empty.";
96 return false;
97 }
99 std::list<std::pair<double, MessageType>> msg_list;
100 pthread_mutex_lock(&buffer_mutex_);
101 std::copy(this->msg_list_.begin(), this->msg_list_.end(),
102 std::back_inserter(msg_list));
103 pthread_mutex_unlock(&buffer_mutex_);
104
105 for (ListIterator iter = msg_list.end(); iter != msg_list.begin();) {
106 --iter;
107 if (iter->first <= timestamp) {
108 *msg = iter->second;
109 return true;
110 }
111 }
112
113 return false;
114}
115
116template <class MessageType>
117bool MessageBuffer<MessageType>::GetMessage(const double timestamp,
118 MessageType *msg) {
119 pthread_mutex_lock(&buffer_mutex_);
120 auto found_iter = msg_map_.find(timestamp);
121 if (found_iter != msg_map_.end()) {
122 *msg = found_iter->second->second;
123 pthread_mutex_unlock(&buffer_mutex_);
124 return true;
126 pthread_mutex_unlock(&buffer_mutex_);
127 return false;
128}
129
130template <class MessageType>
132 pthread_mutex_lock(&buffer_mutex_);
133 msg_list_.clear();
134 msg_map_.clear();
135 pthread_mutex_unlock(&buffer_mutex_);
136}
137
138template <class MessageType>
139void MessageBuffer<MessageType>::SetCapacity(const unsigned int capacity) {
140 capacity_ = capacity;
141}
142
143template <class MessageType>
145 std::list<std::pair<double, MessageType>> *msg_list) {
146 pthread_mutex_lock(&buffer_mutex_);
147 msg_list->clear();
148 std::copy(msg_list_.begin(), msg_list_.end(), std::back_inserter(*msg_list));
149 pthread_mutex_unlock(&buffer_mutex_);
150}
151
152template <class MessageType>
154 bool flag = true;
155 pthread_mutex_lock(&buffer_mutex_);
156 flag = msg_list_.empty();
157 pthread_mutex_unlock(&buffer_mutex_);
158 return flag;
159}
160
161template <class MessageType>
163 unsigned int size = 0;
164 pthread_mutex_lock(&buffer_mutex_);
165 size = static_cast<unsigned int>(msg_list_.size());
166 pthread_mutex_unlock(&buffer_mutex_);
167
168 return size;
169}
170
171// ==============IntepolationMessageBuffer==================
172template <class MessageType>
175
176template <class MessageType>
178
179template <class MessageType>
181 const double timestamp, MessageType *msg, double timeout_s) {
182 std::map<double, ListIterator> msg_map_tem;
183 std::list<std::pair<double, MessageType>> msg_list_tem;
184
185 if (!WaitMessageBufferOk(timestamp, &msg_map_tem, &msg_list_tem,
186 timeout_s * 100)) {
187 return false;
188 }
189
190 auto found_iter = msg_map_tem.find(timestamp);
191 if (found_iter != msg_map_tem.end()) {
192 *msg = found_iter->second->second;
193 return true;
194 }
195
196 ListIterator begin_iter = msg_list_tem.begin();
197 if (begin_iter->first > timestamp) {
198 return false;
199 }
200
201 ListIterator after_iter;
202 ListIterator before_iter;
203 for (ListIterator iter = msg_list_tem.end(); iter != msg_list_tem.begin();) {
204 --iter;
205 if (iter->first > timestamp) {
206 after_iter = iter;
207 } else {
208 before_iter = iter;
209
210 double delta_time = after_iter->first - before_iter->first;
211 // if (delete_time > 0.1) {
212 // return false;
213 // }
214 if (std::abs(delta_time) < 1e-9) {
215 AERROR << "Delta_time is too small.";
216 return false;
217 }
218 double scale = (timestamp - before_iter->first) / delta_time;
219 *msg = before_iter->second.interpolate(scale, after_iter->second);
220 msg->timestamp = timestamp;
221 break;
222 }
223 }
224 return true;
225}
226
227template <class MessageType>
229 const double timestamp, std::map<double, ListIterator> *msg_map,
230 std::list<std::pair<double, MessageType>> *msg_list, double timeout_ms) {
231 boost::posix_time::ptime start_time =
232 boost::posix_time::microsec_clock::local_time();
233 pthread_mutex_lock(&(this->buffer_mutex_));
234 msg_list->clear();
235 std::copy(this->msg_list_.begin(), this->msg_list_.end(),
236 std::back_inserter(*msg_list));
237 *msg_map = this->msg_map_;
238 pthread_mutex_unlock(&(this->buffer_mutex_));
239
240 if (msg_list->empty()) {
241 AERROR << "The queried buffer is empty.";
242 return false;
243 }
244
245 ListIterator last_iter = msg_list->end();
246 --last_iter;
247
248 if (last_iter->first < timestamp && timeout_ms < 5000) {
249 return false;
250 }
251
252 while (last_iter->first < timestamp) {
253 AINFO << "Waiting new message!";
254 std::this_thread::sleep_for(std::chrono::milliseconds(5));
255 pthread_mutex_lock(&(this->buffer_mutex_));
256 msg_list->clear();
257 std::copy(this->msg_list_.begin(), this->msg_list_.end(),
258 std::back_inserter(*msg_list));
259 *msg_map = this->msg_map_;
260 pthread_mutex_unlock(&(this->buffer_mutex_));
261 last_iter = msg_list->end();
262 --last_iter;
263
264 boost::posix_time::ptime end_time =
265 boost::posix_time::microsec_clock::local_time();
266 boost::posix_time::time_duration during_time = end_time - start_time;
267
268 if (during_time.total_milliseconds() >= timeout_ms) {
269 AERROR << "Waiting time is out";
270 return false;
271 }
272 }
273
274 return true;
275}
276
277// ==================VisualizationManager=================
279 : visual_engine_(),
280 stop_visualization_(false),
281 lidar_frame_buffer_(10),
282 gnss_loc_info_buffer_(20),
283 lidar_loc_info_buffer_(40),
284 fusion_loc_info_buffer_(400) {}
285
287 if (!(stop_visualization_.load())) {
288 stop_visualization_ = true;
289 visual_thread_.join();
290 }
291}
292
293bool VisualizationManager::Init(const std::string &map_folder,
294 const std::string &map_visual_folder,
295 const Eigen::Affine3d &velodyne_extrinsic,
296 const VisualMapParam &map_param) {
297 AINFO << "Get zone id.";
298 unsigned int resolution_id = 0;
299 int zone_id = 0;
300
301 bool success = GetZoneIdFromMapFolder(map_folder, resolution_id, &zone_id);
302 if (!success) {
303 AERROR << "Get zone id failed.";
304 return false;
305 }
306 AINFO << "Get zone id succeed.";
307
308 AINFO << "Init visualization engine.";
309 success = visual_engine_.Init(map_folder, map_visual_folder, map_param,
310 resolution_id, zone_id, velodyne_extrinsic,
312 if (!success) {
313 AERROR << "Visualization engine init failed.";
314 return false;
315 }
316 AINFO << "Visualization engine init succeed.";
317
318 visual_engine_.SetAutoPlay(true);
319
320 return true;
321}
322
324 lidar_frame_buffer_.SetCapacity(params.lidar_frame_buffer_capacity);
325 gnss_loc_info_buffer_.SetCapacity(params.gnss_loc_info_buffer_capacity);
326 lidar_loc_info_buffer_.SetCapacity(params.lidar_loc_info_buffer_capacity);
327 fusion_loc_info_buffer_.SetCapacity(params.fusion_loc_info_buffer_capacity);
328
329 return Init(params.map_folder, params.map_visual_folder,
330 params.velodyne_extrinsic, params.map_param);
331}
332
334 AINFO << "AddLidarFrame.";
335 static int id = 0;
336 AINFO << "id." << id;
337 lidar_frame_buffer_.PushNewMessage(lidar_frame.timestamp, lidar_frame);
338 id++;
339}
340
342 const LocalizationMsg &gnss_loc_msg) {
343 AINFO << "AddGNSSLocMessage.";
344 gnss_loc_info_buffer_.PushNewMessage(gnss_loc_msg.timestamp, gnss_loc_msg);
345}
346
348 const LocalizationMsg &lidar_loc_msg) {
349 AINFO << "AddLidarLocMessage.";
350 lidar_loc_info_buffer_.PushNewMessage(lidar_loc_msg.timestamp, lidar_loc_msg);
351}
352
354 const LocalizationMsg &fusion_loc_msg) {
355 AINFO << "AddFusionLocMessage.";
356 fusion_loc_info_buffer_.PushNewMessage(fusion_loc_msg.timestamp,
357 fusion_loc_msg);
358}
359
361 visual_thread_ = std::thread(&VisualizationManager::DoVisualize, this);
362}
363
365 stop_visualization_ = true;
366 visual_thread_.join();
367}
368
369void VisualizationManager::DoVisualize() {
370 while (!(stop_visualization_.load())) {
371 std::this_thread::sleep_for(std::chrono::milliseconds(10));
372 // if (!lidar_frame_buffer_.IsEmpty()) {
373 if (lidar_frame_buffer_.BufferSize() > 5) {
374 LidarVisFrame lidar_frame;
375 bool pop_success = lidar_frame_buffer_.PopOldestMessage(&lidar_frame);
376 if (!pop_success) {
377 continue;
378 }
379
380 LocalizationMsg lidar_loc;
381 LocalizationMsg fusion_loc;
382 bool lidar_query_success = lidar_loc_info_buffer_.QueryMessage(
383 lidar_frame.timestamp, &lidar_loc, 0);
384 // bool lidar_query_success = lidar_loc_info_buffer_.GetMessage(
385 // lidar_frame.timestamp, lidar_loc);
386
387 bool fusion_query_success = fusion_loc_info_buffer_.QueryMessage(
388 lidar_frame.timestamp, &fusion_loc, 0);
389
390 if (!lidar_query_success && !fusion_query_success) {
391 continue;
392 }
393
394 LocalizatonInfo lidar_loc_info;
395 LocalizatonInfo fusion_loc_info;
396 LocalizatonInfo gnss_loc_info;
397
398 if (lidar_query_success) {
399 Eigen::Translation3d trans(
400 Eigen::Vector3d(lidar_loc.x, lidar_loc.y, lidar_loc.z));
401 Eigen::Quaterniond quat(lidar_loc.qw, lidar_loc.qx, lidar_loc.qy,
402 lidar_loc.qz);
403
404 const Eigen::Vector3d lidar_std(lidar_loc.std_x, lidar_loc.std_y,
405 lidar_loc.std_z);
406
407 lidar_loc_info.set(trans, quat, lidar_std, "Lidar.",
408 lidar_frame.timestamp, lidar_frame.frame_id);
409 }
410
411 if (fusion_query_success) {
412 Eigen::Translation3d trans(
413 Eigen::Vector3d(fusion_loc.x, fusion_loc.y, fusion_loc.z));
414 Eigen::Quaterniond quat(fusion_loc.qw, fusion_loc.qx, fusion_loc.qy,
415 fusion_loc.qz);
416
417 const Eigen::Vector3d fusion_std(fusion_loc.std_x, fusion_loc.std_y,
418 fusion_loc.std_z);
419
420 fusion_loc_info.set(trans, quat, fusion_std, "Fusion.",
421 lidar_frame.timestamp, lidar_frame.frame_id);
422 }
423
424 LocalizationMsg gnss_loc;
425 bool success = gnss_loc_info_buffer_.GetMessageBefore(
426 lidar_frame.timestamp, &gnss_loc);
427 if (success) {
428 Eigen::Translation3d trans(
429 Eigen::Vector3d(gnss_loc.x, gnss_loc.y, gnss_loc.z));
430
431 const Eigen::Vector3d gnss_std(gnss_loc.std_x, gnss_loc.std_y,
432 gnss_loc.std_z);
433
434 gnss_loc_info.set(trans, gnss_std, "GNSS.", lidar_frame.timestamp,
435 lidar_frame.frame_id);
436 }
437
439 lidar_loc_info, fusion_loc_info, gnss_loc_info};
440 visual_engine_.Visualize(std::move(loc_infos), lidar_frame.pt3ds);
441 }
442 }
443}
444
445bool VisualizationManager::GetZoneIdFromMapFolder(
446 const std::string &map_folder, const unsigned int resolution_id,
447 int *zone_id) {
448 char buf[256];
449 snprintf(buf, sizeof(buf), "/%03u", resolution_id);
450 std::string folder_north = map_folder + "/map" + buf + "/north";
451 std::string folder_south = map_folder + "/map" + buf + "/south";
452 boost::filesystem::directory_iterator directory_end;
453 boost::filesystem::directory_iterator iter_north(folder_north);
454 if (iter_north == directory_end) {
455 boost::filesystem::directory_iterator iter_south(folder_south);
456 if (iter_south == directory_end) {
457 return false;
458 } else {
459 std::string zone_id_full_path = (*iter_south).path().string();
460 std::size_t pos = zone_id_full_path.find_last_of("/");
461 std::string zone_id_str =
462 zone_id_full_path.substr(pos + 1, zone_id_full_path.length());
463
464 *zone_id = -(std::stoi(zone_id_str));
465 AINFO << "Find zone id: " << *zone_id;
466 return true;
467 }
468 }
469 std::string zone_id_full_path = (*iter_north).path().string();
470 std::size_t pos = zone_id_full_path.find_last_of("/");
471 std::string zone_id_str =
472 zone_id_full_path.substr(pos + 1, zone_id_full_path.length());
473
474 *zone_id = (std::stoi(zone_id_str));
475 AINFO << "Find zone id: " << *zone_id;
476 return true;
477}
478
479} // namespace msf
480} // namespace localization
481} // namespace apollo
bool QueryMessage(const double timestamp, MessageType *msg, double timeout_s=0.01)
std::list< std::pair< double, MessageType > >::iterator ListIterator
bool GetMessageBefore(const double timestamp, MessageType *msg)
std::list< std::pair< double, MessageType > >::iterator ListIterator
bool GetMessage(const double timestamp, MessageType *msg)
void SetCapacity(const unsigned int capacity)
void GetAllMessages(std::list< std::pair< double, MessageType > > *msg_list)
bool PushNewMessage(const double timestamp, const MessageType &msg)
bool Init(const std::string &map_folder, const std::string &map_visual_folder, const VisualMapParam &map_param, const unsigned int resolution_id, const int zone_id, const Eigen::Affine3d &extrinsic, const unsigned int loc_info_num=1)
void Visualize(::apollo::common::EigenVector< LocalizatonInfo > &&loc_infos, const ::apollo::common::EigenVector3dVec &cloud)
void AddLidarLocMessage(const LocalizationMsg &lidar_loc_msg)
void AddFusionLocMessage(const LocalizationMsg &fusion_loc_msg)
void AddLidarFrame(const LidarVisFrame &lidar_frame)
bool Init(const std::string &map_folder, const std::string &map_visual_folder, const Eigen::Affine3d &velodyne_extrinsic, const VisualMapParam &map_param)
void AddGNSSLocMessage(const LocalizationMsg &gnss_loc_msg)
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
std::vector< EigenType, Eigen::aligned_allocator< EigenType > > EigenVector
Definition eigen_defs.h:33
class register implement
Definition arena_queue.h:37
::apollo::common::EigenVector3dVec pt3ds
The 3D point cloud in this frame.
The data structure to store parameters of a map
EIGEN_MAKE_ALIGNED_OPERATOR_NEW std::string map_folder
#define LOC_INFO_NUM