Apollo 10.0
自动驾驶开放平台
ndt_map_matrix.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
20
21namespace apollo {
22namespace localization {
23namespace msf {
24namespace pyramid_map {
25
27 intensity_ = 0.0;
28 intensity_var_ = 0.0;
30 count_ = 0;
31 centroid_ = Eigen::Vector3f::Zero();
32 centroid_average_cov_ = Eigen::Matrix3f::Zero();
33 centroid_icov_ = Eigen::Matrix3f::Identity();
35}
36
38 intensity_ = 0.0;
39 intensity_var_ = 0.0;
41 count_ = 0;
42 centroid_ = Eigen::Vector3f::Zero();
43 centroid_average_cov_ = Eigen::Matrix3f::Zero();
44 centroid_icov_ = Eigen::Matrix3f::Identity();
45 is_icov_available_ = false;
46}
47
48size_t NdtMapSingleCell::LoadBinary(const unsigned char* buf) {
49 const float* f_buf = reinterpret_cast<const float*>(buf);
50 intensity_ = *f_buf;
51 ++f_buf;
52 intensity_var_ = *f_buf;
53 ++f_buf;
54 const unsigned int* ui_buf = reinterpret_cast<const unsigned int*>(
55 reinterpret_cast<const void*>(f_buf));
56 road_pt_count_ = *ui_buf;
57 ++ui_buf;
58 count_ = *ui_buf;
59 ++ui_buf;
60 f_buf = reinterpret_cast<const float*>(reinterpret_cast<const void*>(ui_buf));
61 centroid_[0] = *f_buf;
62 ++f_buf;
63 centroid_[1] = *f_buf;
64 ++f_buf;
65 centroid_[2] = *f_buf;
66
67 for (unsigned int i = 0; i < 3; ++i) {
68 for (unsigned int j = 0; j < 3; ++j) {
69 ++f_buf;
70 centroid_average_cov_(i, j) = *f_buf;
71 }
72 }
74 for (unsigned int i = 0; i < 3; ++i) {
75 for (unsigned int j = 0; j < 3; ++j) {
76 ++f_buf;
77 centroid_icov_(i, j) = *f_buf;
78 }
79 }
80 ++f_buf;
81 const unsigned char* uc_buf = reinterpret_cast<const unsigned char*>(f_buf);
82 is_icov_available_ = *uc_buf;
83 } else {
84 centroid_icov_ = Eigen::Matrix3f::Identity();
86 }
87 return GetBinarySize();
88}
89
90size_t NdtMapSingleCell::CreateBinary(unsigned char* buf,
91 size_t buf_size) const {
92 size_t target_size = GetBinarySize();
93 if (buf_size >= target_size) {
94 float* p = reinterpret_cast<float*>(buf);
95 *p = intensity_;
96 ++p;
97 *p = intensity_var_;
98 ++p;
99 unsigned int* pp =
100 reinterpret_cast<unsigned int*>(reinterpret_cast<void*>(p));
101 *pp = road_pt_count_;
102 ++pp;
103 *pp = count_;
104 ++pp;
105 float* ppp = reinterpret_cast<float*>(reinterpret_cast<void*>(pp));
106 *ppp = centroid_[0];
107 ++ppp;
108 *ppp = centroid_[1];
109 ++ppp;
110 *ppp = centroid_[2];
111
112 for (unsigned int i = 0; i < 3; ++i) {
113 for (unsigned int j = 0; j < 3; ++j) {
114 ++ppp;
115 *ppp = centroid_average_cov_(i, j);
116 }
117 }
119 for (unsigned int i = 0; i < 3; ++i) {
120 for (unsigned int j = 0; j < 3; ++j) {
121 ++ppp;
122 *ppp = centroid_icov_(i, j);
123 }
124 }
125 ++ppp;
126 unsigned char* pppp = reinterpret_cast<unsigned char*>(ppp);
127 *pppp = is_icov_available_;
128 }
129 }
130 return target_size;
131}
132
134 size_t sz = sizeof(float) * 2 + sizeof(unsigned int) * 2 + sizeof(float) * 3 +
135 sizeof(float) * 9;
137 sz += sizeof(float) * 9 + sizeof(unsigned char) * 1;
138 }
139 return sz;
140}
141
153
155 const NdtMapSingleCell& cell_new) {
156 cell->MergeCell(cell_new);
157}
158
159void NdtMapSingleCell::AddSample(const float intensity, const float altitude,
160 const Eigen::Vector3f& centroid,
161 bool is_road) {
162 ++count_;
163 float v1 = intensity - intensity_;
164 intensity_ += v1 / static_cast<float>(count_);
165 float v2 = intensity - intensity_;
166 intensity_var_ = (static_cast<float>(count_ - 1) * intensity_var_ + v1 * v2) /
167 static_cast<float>(count_);
168
169 if (is_road) {
171 }
172
173 Eigen::Vector3f v3 = centroid - centroid_;
174 centroid_ += v3 / static_cast<float>(count_);
175 Eigen::Matrix3f v4 = centroid * centroid.transpose() - centroid_average_cov_;
176 centroid_average_cov_ += v4 / static_cast<float>(count_);
178}
179
180void NdtMapSingleCell::MergeCell(const float intensity,
181 const float intensity_var,
182 const unsigned int road_pt_count,
183 const unsigned int count,
184 const Eigen::Vector3f& centroid,
185 const Eigen::Matrix3f& centroid_cov) {
186 unsigned int new_count = count_ + count;
187 float p0 = static_cast<float>(count_) / static_cast<float>(new_count);
188 float p1 = static_cast<float>(count) / static_cast<float>(new_count);
189 float intensity_diff = intensity_ - intensity;
190
191 intensity_ = intensity_ * p0 + intensity * p1;
192 intensity_var_ = intensity_var_ * p0 + intensity_var * p1 +
193 intensity_diff * intensity_diff * p0 * p1;
194
195 centroid_[0] = centroid_[0] * p0 + centroid[0] * p1;
196 centroid_[1] = centroid_[1] * p0 + centroid[1] * p1;
197 centroid_[2] = centroid_[2] * p0 + centroid[2] * p1;
198
199 count_ = new_count;
200 road_pt_count_ += road_pt_count;
201}
202
204 MergeCell(cell_new.intensity_, cell_new.intensity_var_,
205 cell_new.road_pt_count_, cell_new.count_, cell_new.centroid_,
206 cell_new.centroid_average_cov_);
207}
208
210 const Eigen::Matrix3f& centroid_cov) {
211 // Contain more than five points, we calculate the eigen vector/value of cov.
212 // [Magnusson 2009]
214 Eigen::Matrix3f cov = centroid_cov - centroid_ * centroid_.transpose();
215 cov *= static_cast<float>((count_ - 1.0) / count_);
216 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigen_solver;
217 eigen_solver.compute(cov);
218 Eigen::Matrix3f eigen_val = eigen_solver.eigenvalues().asDiagonal();
219 Eigen::Matrix3f centroid_evecs = eigen_solver.eigenvectors();
220 if (eigen_val(0, 0) < 0 || eigen_val(1, 1) < 0 || eigen_val(2, 2) <= 0) {
222 return;
223 }
224 // Avoid matrices near singularities (eq 6.11) [Magnusson 2009].
225 float min_covar_eigvalue = 0.01f * eigen_val(2, 2);
226 if (eigen_val(0, 0) < min_covar_eigvalue) {
227 eigen_val(0, 0) = min_covar_eigvalue;
228 if (eigen_val(1, 1) < min_covar_eigvalue) {
229 eigen_val(1, 1) = min_covar_eigvalue;
230 }
231 }
232 // Calculate inverse covariance
234 (centroid_evecs * eigen_val * centroid_evecs.inverse()).inverse();
235 if (centroid_icov_.maxCoeff() == std::numeric_limits<float>::infinity() ||
236 centroid_icov_.minCoeff() == -std::numeric_limits<float>::infinity()) {
238 return;
239 }
240 // Set icov available
242 }
243}
244
246 max_altitude_index_ = static_cast<int>(-1e10);
247 min_altitude_index_ = static_cast<int>(1e10);
248}
249
251 max_altitude_index_ = static_cast<int>(-1e10);
252 min_altitude_index_ = static_cast<int>(1e10);
253 cells_.clear();
254 road_cell_indices_.clear();
255}
256
257int NdtMapCells::AddSample(const float intensity, const float altitude,
258 const float resolution,
259 const Eigen::Vector3f& centroid, bool is_road) {
260 int altitude_index = CalAltitudeIndex(resolution, altitude);
261 NdtMapSingleCell& cell = cells_[altitude_index];
262 cell.AddSample(intensity, altitude, centroid, is_road);
263 if (altitude_index > max_altitude_index_) {
264 max_altitude_index_ = altitude_index;
265 }
266 if (altitude_index < min_altitude_index_) {
267 min_altitude_index_ = altitude_index;
268 }
269 if (is_road) {
270 auto got = std::find(road_cell_indices_.begin(), road_cell_indices_.end(),
271 altitude_index);
272 if (got == road_cell_indices_.end()) {
273 road_cell_indices_.push_back(altitude_index);
274 }
275 }
276
277 return altitude_index;
278}
279
280size_t NdtMapCells::LoadBinary(const unsigned char* buf) {
281 const unsigned int* p = reinterpret_cast<const unsigned int*>(buf);
282 unsigned int size = *p;
283 ++p;
284
285 const unsigned char* pp = reinterpret_cast<const unsigned char*>(p);
286 for (unsigned int i = 0; i < size; ++i) {
287 const int* ppp = reinterpret_cast<const int*>(pp);
288 int altitude_index = *ppp;
289 ++ppp;
290 pp = reinterpret_cast<const unsigned char*>(ppp);
291 NdtMapSingleCell cell;
292 size_t processed_size = cell.LoadBinary(pp);
293 cells_[altitude_index] = cell;
294 pp += processed_size;
295 }
296
297 const int* ppp = reinterpret_cast<const int*>(pp);
298 max_altitude_index_ = *ppp;
299 ++ppp;
300 min_altitude_index_ = *ppp;
301 ++ppp;
302
303 p = reinterpret_cast<const unsigned int*>(ppp);
304 size = *p;
305 ++p;
306 ppp = reinterpret_cast<const int*>(p);
307 for (unsigned int i = 0; i < size; ++i) {
308 int index = *ppp;
309 ++ppp;
310 road_cell_indices_.push_back(index);
311 }
312
313 return GetBinarySize();
314}
315
316size_t NdtMapCells::CreateBinary(unsigned char* buf, size_t buf_size) const {
317 size_t target_size = GetBinarySize();
318 if (buf_size >= target_size) {
319 unsigned int* p = reinterpret_cast<unsigned int*>(buf);
320 *p = static_cast<unsigned int>(cells_.size());
321 ++p;
322 buf_size -= static_cast<unsigned int>(sizeof(unsigned int));
323 unsigned char* pp = reinterpret_cast<unsigned char*>(p);
324 for (auto it = cells_.begin(); it != cells_.end(); ++it) {
325 int altitude_index = it->first;
326 const NdtMapSingleCell& cell = it->second;
327 int* ppp = reinterpret_cast<int*>(pp);
328 *ppp = altitude_index;
329 ++ppp;
330 pp = reinterpret_cast<unsigned char*>(ppp);
331 size_t processed_size = cell.CreateBinary(pp, buf_size);
332 assert(buf_size >= processed_size);
333 buf_size -= processed_size;
334 pp += processed_size;
335 }
336
337 int* ppp = reinterpret_cast<int*>(pp);
338 *ppp = max_altitude_index_;
339 ++ppp;
340 *ppp = min_altitude_index_;
341 ++ppp;
342
343 size_t size = road_cell_indices_.size();
344 p = reinterpret_cast<unsigned int*>(ppp);
345 *p = static_cast<unsigned int>(size);
346 ++p;
347 ppp = reinterpret_cast<int*>(p);
348 for (unsigned int i = 0; i < size; ++i) {
349 *ppp = road_cell_indices_[i];
350 ++ppp;
351 }
352 }
353 return target_size;
354}
355
357 size_t target_size = sizeof(unsigned int);
358 for (auto it = cells_.begin(); it != cells_.end(); ++it) {
359 target_size += sizeof(int);
360 const NdtMapSingleCell& cell = it->second;
361 target_size += cell.GetBinarySize();
362 }
363 target_size += sizeof(int) * 2;
364 target_size += sizeof(unsigned int);
365 target_size += sizeof(int) * road_cell_indices_.size();
366 return target_size;
367}
368
369int NdtMapCells::CalAltitudeIndex(const float resolution,
370 const float altitude) {
371 return static_cast<int>(altitude / resolution);
372}
373
374float NdtMapCells::CalAltitude(const float resolution,
375 const int altitude_index) {
376 return static_cast<float>(resolution *
377 (static_cast<float>(altitude_index) + 0.5));
378}
379
380void NdtMapCells::Reduce(NdtMapCells* cell, const NdtMapCells& cell_new) {
381 // Reduce cells
382 for (auto it = cell_new.cells_.begin(); it != cell_new.cells_.end(); ++it) {
383 int altitude_index = it->first;
384 auto got = cell->cells_.find(altitude_index);
385 if (got != cell->cells_.end()) {
386 cell->cells_[altitude_index].MergeCell(it->second);
387 } else {
388 cell->cells_[altitude_index] = NdtMapSingleCell(it->second);
389 }
390 }
391
392 if (cell_new.max_altitude_index_ > cell->max_altitude_index_) {
394 }
395
396 if (cell_new.min_altitude_index_ < cell->min_altitude_index_) {
398 }
399
400 for (auto it_new = cell_new.road_cell_indices_.begin();
401 it_new != cell_new.road_cell_indices_.end(); ++it_new) {
402 auto got_it = std::find(cell->road_cell_indices_.begin(),
403 cell->road_cell_indices_.end(), *it_new);
404 if (got_it != cell->road_cell_indices_.end()) {
405 *got_it += *it_new;
406 } else {
407 cell->road_cell_indices_.push_back(*it_new);
408 }
409 }
410}
411
413 rows_ = 0;
414 cols_ = 0;
415 map3d_cells_ = nullptr;
416}
417
419
421 Init(cells.rows_, cells.cols_);
422 for (unsigned int y = 0; y < rows_; ++y) {
423 for (unsigned int x = 0; x < cols_; ++x) {
424 NdtMapCells& cell = GetMapCell(y, x);
425 const NdtMapCells& src_cell = cells.GetMapCell(y, x);
426 cell = NdtMapCells(src_cell);
427 }
428 }
429}
430
432 Init(config.map_node_size_y_, config.map_node_size_x_);
433}
434
435void NdtMapMatrix::Reset() { Reset(rows_, cols_); }
436
437void NdtMapMatrix::Init(unsigned int rows, unsigned int cols) {
438 map3d_cells_.reset(new NdtMapCells[rows * cols]);
439 rows_ = rows;
440 cols_ = cols;
441}
442
443void NdtMapMatrix::Reset(unsigned int rows, unsigned int cols) {
444 unsigned int length = rows * cols;
445 for (unsigned int i = 0; i < length; ++i) {
446 map3d_cells_[i].Reset();
447 }
448}
449
450size_t NdtMapMatrix::LoadBinary(const unsigned char* buf) {
451 const unsigned int* p = reinterpret_cast<const unsigned int*>(buf);
452 rows_ = *p;
453 ++p;
454 cols_ = *p;
455 ++p;
456 Init(rows_, cols_);
457 const unsigned char* pp = reinterpret_cast<const unsigned char*>(p);
458 for (unsigned int y = 0; y < rows_; ++y) {
459 for (unsigned int x = 0; x < cols_; ++x) {
460 NdtMapCells& cell = GetMapCell(y, x);
461 size_t processed_size = cell.LoadBinary(pp);
462 pp += processed_size;
463 }
464 }
465 return GetBinarySize();
466}
467
468size_t NdtMapMatrix::CreateBinary(unsigned char* buf, size_t buf_size) const {
469 size_t target_size = GetBinarySize();
470 if (buf_size >= target_size) {
471 unsigned int* p = reinterpret_cast<unsigned int*>(buf);
472 *p = rows_;
473 ++p;
474 *p = cols_;
475 ++p;
476 buf_size -= static_cast<unsigned int>(sizeof(unsigned int) * 2);
477 unsigned char* pp = reinterpret_cast<unsigned char*>(p);
478 for (unsigned int y = 0; y < rows_; ++y) {
479 for (unsigned int x = 0; x < cols_; ++x) {
480 const NdtMapCells& cell = GetMapCell(y, x);
481 size_t processed_size = cell.CreateBinary(pp, buf_size);
482 assert(buf_size >= processed_size);
483 buf_size -= processed_size;
484 pp += processed_size;
485 }
486 }
487 }
488 return target_size;
489}
490
492 size_t target_size = sizeof(unsigned int) * 2;
493 for (unsigned int y = 0; y < rows_; ++y) {
494 for (unsigned int x = 0; x < cols_; ++x) {
495 const NdtMapCells& cell = GetMapCell(y, x);
496 target_size += cell.GetBinarySize();
497 }
498 }
499 return target_size;
500}
501
502void NdtMapMatrix::Reduce(NdtMapMatrix* cells, const NdtMapMatrix& cells_new) {
503 for (unsigned int y = 0; y < cells->GetRows(); ++y) {
504 for (unsigned int x = 0; x < cells->GetCols(); ++x) {
505 NdtMapCells& cell = cells->GetMapCell(y, x);
506 const NdtMapCells& cell_new = cells_new.GetMapCell(y, x);
507 NdtMapCells::Reduce(&cell, cell_new);
508 }
509 }
510}
511
512bool NdtMapMatrix::GetIntensityImg(cv::Mat* intensity_img) const {
513 *intensity_img = cv::Mat(cv::Size(cols_, rows_), CV_8UC1);
514 for (unsigned int y = 0; y < rows_; ++y) {
515 for (unsigned int x = 0; x < cols_; ++x) {
516 unsigned int id = y * cols_ + x;
517 int min_altitude_index = map3d_cells_[id].min_altitude_index_;
518 intensity_img->at<unsigned char>(y, x) =
519 (unsigned char)(map3d_cells_[id]
520 .cells_[min_altitude_index]
521 .intensity_);
522 }
523 }
524 return true;
525}
526
527} // namespace pyramid_map
528} // namespace msf
529} // namespace localization
530} // namespace apollo
unsigned int map_node_size_y_
The map node size in pixels.
unsigned int map_node_size_x_
The map node size in pixels.
int AddSample(const float intensity, const float altitude, const float resolution, const Eigen::Vector3f &centroid, bool is_road=false)
Add an sample.
int min_altitude_index_
The index of smallest altitude.
int max_altitude_index_
The index of biggest altitude.
static int CalAltitudeIndex(const float resolution, const float altitude)
Calculate altitude index from altitude.
std::vector< int > road_cell_indices_
The indices of road surface.
static float CalAltitude(const float resolution, const int altitude_index)
Calculate altitude from altitude index.
static void Reduce(NdtMapCells *cell, const NdtMapCells &cell_new)
Combine two MapCell instances (Reduce).
size_t GetBinarySize() const
Get the binary size of the object.
size_t LoadBinary(const unsigned char *buf)
Load the map cell from a binary chunk.
std::unordered_map< int, NdtMapSingleCell > cells_
The multiple altitudes of the cell.
size_t CreateBinary(unsigned char *buf, size_t buf_size) const
Create the binary.
The data structure of ndt Map matrix.
virtual bool GetIntensityImg(cv::Mat *intensity_img) const
get intensity image of node.
static void Reduce(NdtMapMatrix *cells, const NdtMapMatrix &cells_new)
Combine two NdtMapMatrix instances (Reduce).
unsigned int GetRows() const
Get the size of row.
virtual size_t LoadBinary(const unsigned char *buf)
Load the map cell from a binary chunk.
unsigned int GetCols() const
Get the size of cols.
virtual void Reset()
Reset the matrix item to default value.
virtual size_t GetBinarySize() const
Get the binary size of the object.
virtual size_t CreateBinary(unsigned char *buf, size_t buf_size) const
Create the binary.
virtual void Init(const BaseMapConfig &config)
Initialize the matrix with the config.
const NdtMapCells & GetMapCell(unsigned int row, unsigned int col) const
Get a const map cell.
The data structure of a single ndt map cell.
void MergeCell(const float intensity, const float intensity_var, const unsigned int road_pt_count, const unsigned int count, const Eigen::Vector3f &centroid, const Eigen::Matrix3f &centroid_cov)
Merge two cells.
unsigned int road_pt_count_
The number of samples belonging to road surface.
size_t LoadBinary(const unsigned char *buf)
Load the map cell from a binary chunk.
Eigen::Vector3f centroid_
the centroid of the cell.
unsigned int count_
The number of samples in the cell.
NdtMapSingleCell & operator=(const NdtMapSingleCell &ref)
Overloading the assign operator.
void AddSample(const float intensity, const float altitude, const Eigen::Vector3f &centroid, bool is_road=false)
Add an sample to the single 3d map cell.
void CentroidEigenSolver(const Eigen::Matrix3f &centroid_cov)
static void Reduce(NdtMapSingleCell *cell, const NdtMapSingleCell &cell_new)
Combine two NdtMapSingleCell instances (Reduce).
Eigen::Matrix3f centroid_average_cov_
the pose covariance of the cell.
unsigned char is_icov_available_
the inverse covariance available flag.
Eigen::Matrix3f centroid_icov_
the pose inverse covariance of the cell.
const unsigned int minimum_points_threshold_
minimum number of points needed.
size_t CreateBinary(unsigned char *buf, size_t buf_size) const
Create the binary.
size_t GetBinarySize() const
Get the binary size of the object.
class register implement
Definition arena_queue.h:37