Apollo 10.0
自动驾驶开放平台
base_map_node.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 <cstdio>
20#include <memory>
21#include <string>
22#include <vector>
23
24#include "cyber/common/file.h"
27
28namespace apollo {
29namespace localization {
30namespace msf {
31namespace pyramid_map {
32
34 : map_config_(NULL),
35 map_matrix_(NULL),
36 map_matrix_handler_(NULL),
37 compression_strategy_(NULL) {
38 is_changed_ = false;
39 data_is_ready_ = false;
40 is_reserved_ = false;
43}
44
46 : map_config_(NULL),
47 map_matrix_(matrix),
48 map_matrix_handler_(NULL),
49 compression_strategy_(strategy) {
50 is_changed_ = false;
51 data_is_ready_ = false;
52 is_reserved_ = false;
54}
55
57
59 map_config_ = map_config;
60 map_matrix_->Init(*map_config);
61}
62
64 if (is_changed_) {
65 Save();
66 AINFO << "Save Map Node to disk: " << map_node_config_->node_index_ << ".";
67 }
68}
69
71 is_changed_ = false;
72 data_is_ready_ = false;
73 is_reserved_ = false;
76 map_matrix_->Reset();
77}
78
82
83 std::string path = map_config_->map_folder_path_;
84
85 char buf[1024];
86 std::vector<std::string> paths;
87
88 paths.push_back(path);
89
90 snprintf(buf, sizeof(buf), "/map");
91 paths.push_back(buf);
92 path = path + buf;
93
94 snprintf(buf, sizeof(buf), "/%03u",
95 map_node_config_->node_index_.resolution_id_);
96 paths.push_back(buf);
97 path = path + buf;
98
99 paths.push_back(map_node_config_->node_index_.zone_id_ > 0 ? "/north"
100 : "/south");
101 path = path + paths.back();
102
103 snprintf(buf, sizeof(buf), "/%02d",
104 abs(map_node_config_->node_index_.zone_id_));
105 paths.push_back(buf);
106 path = path + buf;
107
108 snprintf(buf, sizeof(buf), "/%08d", map_node_config_->node_index_.m_);
109 paths.push_back(buf);
110 path = path + buf;
111
112 if (!CreateMapDirectoryRecursively(paths)) {
113 return false;
114 }
115
116 snprintf(buf, sizeof(buf), "/%08d", map_node_config_->node_index_.n_);
117 path = path + buf;
118
119 FILE* file = fopen(path.c_str(), "wb");
120 if (file) {
121 bool success = CreateBinary(file);
122 fclose(file);
123 is_changed_ = false;
124 return success;
125 } else {
126 AERROR << "Can't write to file: " << path << ".";
127 return false;
128 }
129}
130
132 std::string path = map_config_->map_folder_path_;
133 char buf[1024];
134 std::vector<std::string> paths;
135 paths.push_back(path);
136 snprintf(buf, sizeof(buf), "/map");
137 paths.push_back(buf);
138 path = path + buf;
139 snprintf(buf, sizeof(buf), "/%03u",
140 map_node_config_->node_index_.resolution_id_);
141 paths.push_back(buf);
142 path = path + buf;
143 paths.push_back(map_node_config_->node_index_.zone_id_ > 0 ? "/north"
144 : "/south");
145 path = path + paths.back();
146 snprintf(buf, sizeof(buf), "/%02d",
147 abs(map_node_config_->node_index_.zone_id_));
148 paths.push_back(buf);
149 path = path + buf;
150 snprintf(buf, sizeof(buf), "/%08d", map_node_config_->node_index_.m_);
151 paths.push_back(buf);
152 path = path + buf;
153 if (!CheckMapDirectoryRecursively(paths)) {
154 return false;
155 }
156 snprintf(buf, sizeof(buf), "/%08d", map_node_config_->node_index_.n_);
157 path = path + buf;
158 return Load(path.c_str());
159}
160
161bool BaseMapNode::Load(const char* filename) {
162 data_is_ready_ = false;
163
164 FILE* file = fopen(filename, "rb");
165 if (file) {
166 bool success = LoadBinary(file);
167 fclose(file);
168 is_changed_ = false;
169 data_is_ready_ = success;
170 return success;
171 } else {
172 AERROR << "Can't find the file: " << filename;
173 return false;
174 }
175}
176
177bool BaseMapNode::LoadBinary(FILE* file) {
178 // Load the header
179 size_t header_size = GetHeaderBinarySize();
180 std::vector<unsigned char> buf(header_size);
181 size_t read_size = fread(&buf[0], 1, header_size, file);
182 if (read_size != header_size) {
183 return false;
184 }
185 size_t processed_size = LoadHeaderBinary(&buf[0]);
186 if (processed_size != header_size) {
187 return false;
188 }
189 // Load the body
190 buf.resize(file_body_binary_size_);
191 read_size = fread(&buf[0], 1, file_body_binary_size_, file);
192 if (read_size != file_body_binary_size_) {
193 return false;
194 }
195 processed_size = LoadBodyBinary(&buf);
196 if (processed_size != uncompressed_file_body_size_) {
197 return false;
198 }
199 return true;
200}
201
202bool BaseMapNode::CreateBinary(FILE* file) const {
203 size_t buf_size = GetBinarySize();
204 std::vector<unsigned char> buffer;
205 buffer.resize(buf_size);
206
207 size_t binary_size = 0;
208 std::vector<unsigned char> body_buffer;
209 size_t processed_size = CreateBodyBinary(&body_buffer);
210
211 if (map_node_config_->has_body_md5_) {
212 FileUtility::ComputeBinaryMd5(&body_buffer[0], body_buffer.size(),
213 map_node_config_->body_md5_);
214 }
215
216 if (processed_size == 0) {
217 return false;
218 }
219
220 // Create header
221 size_t header_size = GetHeaderBinarySize();
222 std::vector<unsigned char> header_buf(header_size);
223 processed_size = CreateHeaderBinary(&buffer[0], buf_size);
224
225 if (header_size != processed_size) {
226 return false;
227 }
228
229 size_t buffer_bias = processed_size;
230 buf_size -= processed_size;
231 binary_size += processed_size;
232 // Create body
233 memcpy(&buffer[buffer_bias], &body_buffer[0], body_buffer.size());
234 // write binary
235 binary_size += static_cast<unsigned int>(body_buffer.size());
236 fwrite(&buffer[0], 1, binary_size, file);
237
238 return true;
239}
240
242 // It is uncompressed binary size.
244}
245
246size_t BaseMapNode::LoadHeaderBinary(const unsigned char* buf) {
247 std::shared_ptr<BaseMapNodeConfig> node_config_tem =
248 map_node_config_->Clone();
249
250 size_t target_size = map_node_config_->LoadBinary(buf);
251
252 // check if header is valid
253 if (node_config_tem->map_version_ != map_node_config_->map_version_ ||
254 node_config_tem->node_index_ != map_node_config_->node_index_) {
255 return 0;
256 }
257
259
260 return target_size;
261}
262
263size_t BaseMapNode::CreateHeaderBinary(unsigned char* buf,
264 size_t buf_size) const {
266 return map_node_config_->CreateBinary(buf, buf_size);
267}
268
270 return map_node_config_->GetBinarySize();
271}
272
273size_t BaseMapNode::LoadBodyBinary(std::vector<unsigned char>* buf) {
274 if (compression_strategy_ == nullptr) {
275 return map_matrix_handler_->LoadBinary(&(*buf)[0], map_matrix_);
276 }
277 std::vector<unsigned char> buf_uncompressed;
278 int ret = compression_strategy_->Decode(buf, &buf_uncompressed);
279 if (ret < 0) {
280 AERROR << "compression Decode error: " << ret;
281 return 0;
282 }
283 uncompressed_file_body_size_ = buf_uncompressed.size();
284 AINFO << "map node compress ratio: "
285 << static_cast<float>(buf->size()) /
286 static_cast<float>(uncompressed_file_body_size_);
287
288 return map_matrix_handler_->LoadBinary(&buf_uncompressed[0], map_matrix_);
289}
290
291size_t BaseMapNode::CreateBodyBinary(std::vector<unsigned char>* buf) const {
292 if (compression_strategy_ == nullptr) {
293 size_t body_size = GetBodyBinarySize();
294 buf->resize(body_size);
296 map_matrix_handler_->CreateBinary(map_matrix_, &(*buf)[0], body_size);
298 }
299 std::vector<unsigned char> buf_uncompressed;
300 // Compute the uncompression binary body size
301 size_t body_size = GetBodyBinarySize();
302 buf_uncompressed.resize(body_size);
303 size_t binary_size = map_matrix_handler_->CreateBinary(
304 map_matrix_, &buf_uncompressed[0], body_size);
305 if (binary_size == 0) {
306 return 0;
307 }
308
309 compression_strategy_->Encode(&buf_uncompressed, buf);
310 file_body_binary_size_ = buf->size();
311
312 return buf->size();
313}
314
316 return map_matrix_handler_->GetBinarySize(map_matrix_);
317}
318
319bool BaseMapNode::GetCoordinate(const Eigen::Vector2d& coordinate,
320 unsigned int* x, unsigned int* y) const {
321 const Eigen::Vector2d& left_top_corner = GetLeftTopCorner();
322 unsigned int off_x = static_cast<unsigned int>(
323 (coordinate[0] - left_top_corner[0]) / GetMapResolution());
324 unsigned int off_y = static_cast<unsigned int>(
325 (coordinate[1] - left_top_corner[1]) / GetMapResolution());
326 if (off_x < this->map_config_->map_node_size_x_ &&
327 off_y < this->map_config_->map_node_size_y_) {
328 *x = off_x;
329 *y = off_y;
330 return true;
331 }
332 return false;
333}
334
335bool BaseMapNode::GetCoordinate(const Eigen::Vector3d& coordinate,
336 unsigned int* x, unsigned int* y) const {
337 Eigen::Vector2d coord2d(coordinate[0], coordinate[1]);
338 return GetCoordinate(coord2d, x, y);
339}
340
341Eigen::Vector2d BaseMapNode::GetCoordinate(unsigned int x,
342 unsigned int y) const {
343 const Eigen::Vector2d& left_top_corner = GetLeftTopCorner();
344 Eigen::Vector2d coord(
345 left_top_corner[0] + static_cast<float>(x) * GetMapResolution(),
346 left_top_corner[1] + static_cast<float>(y) * GetMapResolution());
347 return coord;
348}
349
351 map_node_config_->node_index_ = index;
354}
355
357 const MapNodeIndex& index) {
358 Eigen::Vector2d coord;
359 coord[0] = config.map_range_.GetMinX() +
360 static_cast<float>(config.map_node_size_x_) *
361 config.map_resolutions_[index.resolution_id_] *
362 static_cast<float>(index.n_);
363 coord[1] = config.map_range_.GetMinY() +
364 static_cast<float>(config.map_node_size_y_) *
365 config.map_resolutions_[index.resolution_id_] *
366 static_cast<float>(index.m_);
367 if (coord[0] >= config.map_range_.GetMaxX()) {
368 throw "[BaseMapNode::ComputeLeftTopCorner] coord[0]"
369 " >= config.map_range_.GetMaxX()";
370 }
371 if (coord[1] >= config.map_range_.GetMaxY()) {
372 throw "[BaseMapNode::compute_left_top_corner] coord[1]"
373 " >= config.map_range_.GetMaxY()";
374 }
375 return coord;
376}
377
378Eigen::Vector2d BaseMapNode::GetLeftTopCorner(const BaseMapConfig& config,
379 const MapNodeIndex& index) {
380 Eigen::Vector2d coord;
381 coord[0] = config.map_range_.GetMinX() +
382 static_cast<float>(config.map_node_size_x_) *
383 config.map_resolutions_[index.resolution_id_] *
384 static_cast<float>(index.n_);
385 coord[1] = config.map_range_.GetMinY() +
386 static_cast<float>(config.map_node_size_y_) *
387 config.map_resolutions_[index.resolution_id_] *
388 static_cast<float>(index.m_);
389 DCHECK_LT(coord[0], config.map_range_.GetMaxX());
390 DCHECK_LT(coord[1], config.map_range_.GetMaxY());
391 return coord;
392}
393
394bool BaseMapNode::CreateMapDirectory(const std::string& path) const {
397 }
398 return true;
399}
400
402 const std::vector<std::string>& paths) const {
403 std::string path = "";
404
405 for (unsigned int i = 0; i < paths.size(); ++i) {
406 path = path + paths[i];
407 if (!CreateMapDirectory(path)) {
408 return false;
409 }
410 }
411 return true;
412}
413
415 const std::vector<std::string>& paths) const {
416 std::string path = "";
417
418 for (unsigned int i = 0; i < paths.size(); ++i) {
419 path = path + paths[i];
420 if (!(cyber::common::DirectoryExists(path))) {
421 return false;
422 }
423 }
424
425 return true;
426}
427
429 std::string path = map_config_->map_folder_path_;
430
431 char buf[1024];
432 std::vector<std::string> paths;
433
434 paths.push_back(path);
435
436 snprintf(buf, sizeof(buf), "/image");
437 paths.push_back(buf);
438 path = path + buf;
439
440 snprintf(buf, sizeof(buf), "/%03u",
441 map_node_config_->node_index_.resolution_id_);
442 paths.push_back(buf);
443 path = path + buf;
444
445 paths.push_back(map_node_config_->node_index_.zone_id_ > 0 ? "/north"
446 : "/south");
447 path = path + paths.back();
448
449 snprintf(buf, sizeof(buf), "/%02d",
450 abs(map_node_config_->node_index_.zone_id_));
451 paths.push_back(buf);
452 path = path + buf;
453
454 snprintf(buf, sizeof(buf), "/%08d", map_node_config_->node_index_.m_);
455 paths.push_back(buf);
456 path = path + buf;
457
458 if (!CreateMapDirectoryRecursively(paths)) {
459 return false;
460 }
461
462 snprintf(buf, sizeof(buf), "/%08d.png", map_node_config_->node_index_.n_);
463 path = path + buf;
464
465 bool success = SaveIntensityImage(path);
466 return success;
467}
468
469bool BaseMapNode::SaveIntensityImage(const std::string& path) const {
470 cv::Mat image;
471 map_matrix_->GetIntensityImg(&image);
472 bool success = cv::imwrite(path, image);
473 return success;
474}
475
477 std::string path = map_config_->map_folder_path_;
478
479 char buf[1024];
480 std::vector<std::string> paths;
481
482 paths.push_back(path);
483
484 snprintf(buf, sizeof(buf), "/image_alt");
485 paths.push_back(buf);
486 path = path + buf;
487
488 snprintf(buf, sizeof(buf), "/%03u",
489 map_node_config_->node_index_.resolution_id_);
490 paths.push_back(buf);
491 path = path + buf;
492
493 paths.push_back(map_node_config_->node_index_.zone_id_ > 0 ? "/north"
494 : "/south");
495 path = path + paths.back();
496
497 snprintf(buf, sizeof(buf), "/%02d",
498 abs(map_node_config_->node_index_.zone_id_));
499 paths.push_back(buf);
500 path = path + buf;
501
502 snprintf(buf, sizeof(buf), "/%08d", map_node_config_->node_index_.m_);
503 paths.push_back(buf);
504 path = path + buf;
505
506 if (!CreateMapDirectoryRecursively(paths)) {
507 return false;
508 }
509
510 snprintf(buf, sizeof(buf), "/%08d.png", map_node_config_->node_index_.n_);
511 path = path + buf;
512
513 bool success = SaveAltitudeImage(path);
514 return success;
515}
516
517bool BaseMapNode::SaveAltitudeImage(const std::string& path) const {
518 cv::Mat image;
519 map_matrix_->GetAltitudeImg(&image);
520 if (image.empty()) {
521 return false;
522 }
523
524 bool success = cv::imwrite(path, image);
525 return success;
526}
527
528} // namespace pyramid_map
529} // namespace msf
530} // namespace localization
531} // namespace apollo
static void ComputeBinaryMd5(const unsigned char *binary, size_t size, unsigned char res[kUcharMd5Length])
Compute file md5 given a binary chunk.
T GetMaxY() const
Get the max y of the rectangle.
Definition rect2d.h:88
T GetMaxX() const
Get the max x of the rectangle.
Definition rect2d.h:83
T GetMinX() const
Get the min x of the rectangle.
Definition rect2d.h:73
T GetMinY() const
Get the min y of the rectangle.
Definition rect2d.h:78
unsigned int map_node_size_y_
The map node size in pixels.
std::vector< float > map_resolutions_
The pixel resolutions in the map in meters.
Rect2D< double > map_range_
The minimum and maximum UTM range in the map.
unsigned int map_node_size_x_
The map node size in pixels.
The data structure of the map cells in a map node.
virtual void Finalize()
call before deconstruction or reset.
std::shared_ptr< CompressionStrategy > compression_strategy_
@bried The compression strategy.
virtual bool LoadBinary(FILE *file)
Load the map cell from a binary chunk.
bool SaveIntensityImage() const
Save intensity image of node.
virtual bool GetCoordinate(const Eigen::Vector2d &coordinate, unsigned int *x, unsigned int *y) const
Given the global coordinate, get the local 2D coordinate of the map cell matrix.
const BaseMapConfig * map_config_
The map settings.
bool SaveAltitudeImage() const
Save altitude image of node.
bool is_changed_
Has the map node been changed.
virtual void ResetMapNode()
Reset map cells data.
bool is_reserved_
If the node is reserved in map.
bool Load()
Load the map node from the disk.
bool CreateMapDirectory(const std::string &path) const
Try to create the map directory.
virtual size_t LoadBodyBinary(std::vector< unsigned char > *buf)
Load the map node body from a binary chunk.
const Eigen::Vector2d & GetLeftTopCorner() const
virtual size_t GetBodyBinarySize() const
Get the size of the body in bytes.
virtual bool CreateBinary(FILE *file) const
Create the binary.
virtual size_t GetBinarySize() const
Get the binary size of the object.
static Eigen::Vector2d ComputeLeftTopCorner(const BaseMapConfig &config, const MapNodeIndex &index)
std::shared_ptr< BaseMapMatrixHandler > map_matrix_handler_
The class to load and create map matrix binary.
std::shared_ptr< BaseMapMatrix > map_matrix_
The data structure of the map datas, which is a matrix.
Eigen::Vector2d left_top_corner_
The left top corner of the map node in the global coordinate system.
bool CheckMapDirectoryRecursively(const std::vector< std::string > &paths) const
Try to check the map directory recursively.
bool Save()
Save the map node to the disk.
size_t file_body_binary_size_
The body binary size in file.
std::shared_ptr< BaseMapNodeConfig > map_node_config_
The map node config.
float GetMapResolution() const
Get the resolution of this map nodex.
virtual size_t GetHeaderBinarySize() const
Get the size of the header in bytes.
virtual size_t LoadHeaderBinary(const unsigned char *buf)
Load the map node header from a binary chunk.
virtual size_t CreateHeaderBinary(unsigned char *buf, size_t buf_size) const
Create the binary header.
void SetMapNodeIndex(const MapNodeIndex &index)
Set the map node index.
virtual void InitMapMatrix(const BaseMapConfig *map_config)
Initialize the map matrix.
virtual size_t CreateBodyBinary(std::vector< unsigned char > *buf) const
Create the binary body.
bool CreateMapDirectoryRecursively(const std::vector< std::string > &paths) const
Try to create the map directory recursively.
unsigned int m_
The map node ID at the northing direction.
unsigned int resolution_id_
The ID of the resolution.
unsigned int n_
The map node ID at the easting direction.
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
bool DirectoryExists(const std::string &directory_path)
Check if the directory specified by directory_path exists and is indeed a directory.
Definition file.cc:207
bool EnsureDirectory(const std::string &directory_path)
Check if a specified directory specified by directory_path exists.
Definition file.cc:299
class register implement
Definition arena_queue.h:37