Apollo 11.0
自动驾驶开放平台
localization_lidar.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 *****************************************************************************/
16
18
19namespace apollo {
20namespace localization {
21namespace msf {
22
24 : lidar_locator_(new LidarLocator()),
25 search_range_x_(21),
26 search_range_y_(21),
27 node_size_x_(1024),
28 node_size_y_(1024),
29 resolution_(0.125),
30 lidar_map_node_(nullptr),
31 config_("lossy_map"),
32 map_(&config_),
33 map_node_pool_(25, 8),
34 resolution_id_(0),
35 is_map_loaded_(false),
36 vehicle_lidar_height_(1.7),
37 pre_vehicle_ground_height_(0.0),
38 is_pre_ground_height_valid_(false),
39 velodyne_extrinsic_(Eigen::Affine3d::Identity()) {
40 map_left_top_corner_ = Eigen::Vector2d::Zero();
41}
42
44 if (lidar_map_node_) {
45 delete lidar_map_node_;
46 lidar_map_node_ = nullptr;
47 }
48
49 delete lidar_locator_;
50 lidar_locator_ = nullptr;
51}
52
53bool LocalizationLidar::Init(const std::string& map_path,
54 const unsigned int search_range_x,
55 const unsigned int search_range_y,
56 const int zone_id,
57 const unsigned int resolution_id) {
58 // init map
59 resolution_id_ = resolution_id;
60 zone_id_ = zone_id;
61 if (!map_.SetMapFolderPath(map_path)) {
62 LOG(FATAL) << "Reflectance map folder is invalid!";
63 return false;
64 }
66 map_.InitMapNodeCaches(12, 24);
68
69 // init locator
73
75
76 search_range_x_ = search_range_x;
77 search_range_y_ = search_range_y;
79 static_cast<float>(resolution_), node_size_x_,
81 return true;
82}
83
84void LocalizationLidar::SetVelodyneExtrinsic(const Eigen::Affine3d& pose) {
86 Eigen::Vector3d trans = pose.translation();
87 Eigen::Quaterniond quat = Eigen::Quaterniond(pose.linear());
88
89 lidar_locator_->SetVelodyneExtrinsic(trans.x(), trans.y(), trans.z(),
90 quat.x(), quat.y(), quat.z(), quat.w());
91}
92
94 vehicle_lidar_height_ = height;
95 AINFO << "Set height: " << vehicle_lidar_height_;
96}
97
98void LocalizationLidar::SetValidThreshold(float valid_threashold) {
99 lidar_locator_->SetValidThreshold(valid_threashold);
100}
101
103 lidar_locator_->SetImageAlignMode(mode);
104}
105
107 lidar_locator_->SetLocalizationMode(mode);
108}
109
111 lidar_locator_->SetDeltaYawLimit(limit);
112}
113
115 lidar_locator_->SetDeltaPitchRollLimit(limit);
116}
117
118int LocalizationLidar::Update(const unsigned int frame_idx,
119 const Eigen::Affine3d& pose,
120 const Eigen::Vector3d velocity,
121 const LidarFrame& lidar_frame, bool use_avx) {
122 // check whether loaded map
123 if (!is_map_loaded_) {
124 map_.LoadMapArea(pose.translation(), resolution_id_, zone_id_,
126 is_map_loaded_ = true;
127 AINFO << "Reflectance locator map first loading is done.";
128 }
129
130 Eigen::Affine3d imu_pose = pose;
131 RefineAltitudeFromMap(&imu_pose);
132 // load all needed map
133 Eigen::Vector3d pose_trans = imu_pose.translation();
134 Eigen::Quaterniond pose_quat(imu_pose.linear());
135 pose_quat.normalize();
136 map_.LoadMapArea(pose_trans, resolution_id_, zone_id_, 0, 0);
137
138 // preload map for next locate
139 map_.PreloadMapArea(pose_trans, velocity, resolution_id_, zone_id_);
140
141 // generate composed map for compare
142 ComposeMapNode(pose_trans);
143
144 // pass map node to locator
145 int node_width = lidar_map_node_->width;
146 int node_height = lidar_map_node_->height;
147 int node_level_num = 1;
148 lidar_locator_->SetMapNodeData(
149 node_width, node_height, node_level_num, &(lidar_map_node_->intensities),
152 lidar_locator_->SetMapNodeLeftTopCorner(map_left_top_corner_(0),
154
155 // pass lidar points to locator
156 int size = static_cast<int>(lidar_frame.pt_xs.size());
157 lidar_locator_->SetPointCloudData(
158 size, lidar_frame.pt_xs.data(), lidar_frame.pt_ys.data(),
159 lidar_frame.pt_zs.data(), lidar_frame.intensities.data());
160
161 // compute
162 int error = lidar_locator_->Compute(
163 pose_trans(0), pose_trans(1), pose_trans(2), pose_quat.x(), pose_quat.y(),
164 pose_quat.z(), pose_quat.w(), use_avx);
165
166 return error;
167}
168
169void LocalizationLidar::GetResult(Eigen::Affine3d* location,
170 Eigen::Matrix3d* covariance,
171 double* location_score) {
172 if (!location || !covariance) {
173 return;
174 }
175 double x = 0.0;
176 double y = 0.0;
177 double z = 0.0;
178 double qx = 0.0;
179 double qy = 0.0;
180 double qz = 0.0;
181 double qw = 1.0;
182 lidar_locator_->GetLocationPose(&x, &y, &z, &qx, &qy, &qz, &qw);
183
184 Eigen::Quaterniond quatd(qw, qx, qy, qz);
185 Eigen::Translation3d transd(Eigen::Vector3d(x, y, z));
186 *location = transd * quatd;
187
188 RefineAltitudeFromMap(location);
189
190 int width = 0;
191 int height = 0;
192 const double* data = nullptr;
193 lidar_locator_->GetLocationCovariance(&data, &width, &height);
194
195 *location_score = lidar_locator_->GetLocationScore();
196
197 if (width >= 3 && height >= 3 && data != nullptr) {
198 for (int row = 0; row < 3; ++row) {
199 for (int col = 0; col < 3; ++col) {
200 (*covariance)(row, col) = data[row * 3 + col];
201 }
202 }
203 }
204}
205
207 Eigen::MatrixXd* distribution) {
208 CHECK_NOTNULL(distribution);
209
210 int width = 0;
211 int height = 0;
212 const double* data = nullptr;
213 lidar_locator_->GetSSDDistribution(&data, &width, &height);
214
215 if (width > 0 && height > 0 && data != nullptr) {
216 *distribution = Eigen::MatrixXd::Zero(height, width);
217 for (int row = 0; row < height; ++row) {
218 for (int col = 0; col < width; ++col) {
219 (*distribution)(row, col) = data[row * width + col];
220 }
221 }
222 }
223}
224
225void LocalizationLidar::RefineAltitudeFromMap(Eigen::Affine3d* pose) {
226 CHECK_NOTNULL(pose);
227
228 Eigen::Affine3d lidar_pose = *pose * velodyne_extrinsic_;
229 Eigen::Vector3d lidar_trans = lidar_pose.translation();
230
231 // Read the altitude from the map
233 map_.GetMapConfig(), lidar_trans, resolution_id_, zone_id_);
234 PyramidMapNode* node =
235 static_cast<PyramidMapNode*>(map_.GetMapNodeSafe(index));
236 PyramidMapMatrix& matrix =
237 static_cast<PyramidMapMatrix&>(node->GetMapCellMatrix());
238
239 const double height_diff = vehicle_lidar_height_;
240
243 pre_vehicle_ground_height_ = lidar_pose.translation()(2) - height_diff;
244 }
245
246 float vehicle_ground_alt = 0.0f;
247 unsigned int x = 0;
248 unsigned int y = 0;
249 if (node->GetCoordinate(lidar_trans, &x, &y)) {
250 unsigned int count = *matrix.GetCountSafe(y, x);
251 if (count > 0) {
252 if (matrix.HasGroundAltitude()) {
253 const float* ground_alt = matrix.GetGroundAltitudeSafe(y, x);
254 if (ground_alt) {
255 vehicle_ground_alt = *ground_alt;
256 }
257 } else {
258 const float* altitude = matrix.GetAltitudeSafe(y, x);
259 if (altitude) {
260 vehicle_ground_alt = *altitude;
261 }
262 }
263 } else {
264 vehicle_ground_alt = static_cast<float>(pre_vehicle_ground_height_);
265 }
266 }
267
268 lidar_pose.translation()(2) = vehicle_ground_alt + height_diff;
269 Eigen::Affine3d transform_tmp = lidar_pose * velodyne_extrinsic_.inverse();
270 pose->translation() = transform_tmp.translation();
271}
272
273void LocalizationLidar::ComposeMapNode(const Eigen::Vector3d& trans) {
274 Eigen::Vector2d center(trans(0), trans(1));
275 Eigen::Vector2d left_top_corner(center(0) - node_size_x_ * resolution_ / 2.0,
276 center(1) - node_size_y_ * resolution_ / 2.0);
277
278 // get map node index 2x2
279 MapNodeIndex map_node_idx[2][2];
280 // top left corner
281 map_node_idx[0][0] = MapNodeIndex::GetMapNodeIndex(
282 map_.GetMapConfig(), left_top_corner, resolution_id_, zone_id_);
283 // top right corner
284 map_node_idx[0][1] = map_node_idx[0][0];
285 map_node_idx[0][1].n_ += 1;
286 // bottom left corner
287 map_node_idx[1][0] = map_node_idx[0][0];
288 map_node_idx[1][0].m_ += 1;
289 // bottom right corner
290 map_node_idx[1][1] = map_node_idx[0][0];
291 map_node_idx[1][1].n_ += 1;
292 map_node_idx[1][1].m_ += 1;
293
294 // get map node 2x2
295 PyramidMapNode* map_node[2][2] = {nullptr};
296 for (unsigned int y = 0; y < 2; ++y) {
297 for (unsigned int x = 0; x < 2; ++x) {
298 map_node[y][x] =
299 static_cast<PyramidMapNode*>(map_.GetMapNodeSafe(map_node_idx[y][x]));
300 }
301 }
302
303 // compose map node
304 unsigned int coord_x = 0;
305 unsigned int coord_y = 0;
306 map_node[0][0]->GetCoordinate(left_top_corner, &coord_x, &coord_y);
307 map_left_top_corner_ = map_node[0][0]->GetCoordinate(coord_x, coord_y);
308
309 int coord_xi = coord_x;
310 int coord_yi = coord_y;
311 int range_xs[2][2] = {0};
312 int range_ys[2][2] = {0};
313 range_xs[0][0] = node_size_x_ - coord_xi;
314 range_xs[1][0] = node_size_x_ - coord_xi;
315 range_xs[0][1] = coord_xi;
316 range_xs[1][1] = coord_xi;
317 range_ys[0][0] = node_size_y_ - coord_yi;
318 range_ys[0][1] = node_size_y_ - coord_yi;
319 range_ys[1][0] = coord_yi;
320 range_ys[1][1] = coord_yi;
321
322 int src_xs[2][2] = {0};
323 int src_ys[2][2] = {0};
324 src_xs[0][0] = coord_xi;
325 src_xs[1][0] = coord_xi;
326 src_xs[0][1] = 0;
327 src_xs[1][1] = 0;
328 src_ys[0][0] = coord_yi;
329 src_ys[0][1] = coord_yi;
330 src_ys[1][0] = 0;
331 src_ys[1][1] = 0;
332
333 int dst_xs[2][2] = {0};
334 int dst_ys[2][2] = {0};
335 dst_xs[0][0] = 0;
336 dst_xs[1][0] = 0;
337 dst_xs[0][1] = node_size_x_ - coord_xi;
338 dst_xs[1][1] = node_size_x_ - coord_xi;
339 dst_ys[0][0] = 0;
340 dst_ys[0][1] = 0;
341 dst_ys[1][0] = node_size_y_ - coord_yi;
342 dst_ys[1][1] = node_size_y_ - coord_yi;
343
344 for (int i = 0; i < 2; ++i) {
345 for (int j = 0; j < 2; ++j) {
346 int range_x = range_xs[i][j];
347 int range_y = range_ys[i][j];
348 int src_x = src_xs[i][j];
349 int src_y = src_ys[i][j];
350 int dst_x = dst_xs[i][j];
351 int dst_y = dst_ys[i][j];
352 PyramidMapMatrix& map_cells =
353 static_cast<PyramidMapMatrix&>(map_node[i][j]->GetMapCellMatrix());
354 FloatMatrix* intensity_matrix = map_cells.GetIntensityMatrix(0);
355 FloatMatrix* intensity_var_matrix = map_cells.GetIntensityVarMatrix(0);
356 FloatMatrix* altitude_matrix = map_cells.GetAltitudeMatrix(0);
357 UIntMatrix* count_matrix = map_cells.GetCountMatrix(0);
358 for (int y = 0; y < range_y; ++y) {
359 int dst_base_x = (dst_y + y) * node_size_x_ + dst_x;
360 for (int x = 0; x < range_x; ++x) {
361 int dst_idx = dst_base_x + x;
362 lidar_map_node_->intensities[dst_idx] =
363 (*intensity_matrix)[src_y + y][src_x + x];
365 (*intensity_var_matrix)[src_y + y][src_x + x];
366 lidar_map_node_->altitudes[dst_idx] =
367 (*altitude_matrix)[src_y + y][src_x + x];
368 lidar_map_node_->count[dst_idx] =
369 (*count_matrix)[src_y + y][src_x + x];
370 }
371 }
372 }
373 }
374}
375
376} // namespace msf
377} // namespace localization
378} // namespace apollo
int Update(const unsigned int frame_idx, const Eigen::Affine3d &pose, const Eigen::Vector3d velocity, const LidarFrame &lidar_frame, bool use_avx=false)
bool Init(const std::string &map_path, const unsigned int search_range_x, const unsigned int search_range_y, const int zone_id, const unsigned int resolution_id=0)
void GetResult(Eigen::Affine3d *location, Eigen::Matrix3d *covariance, double *location_score)
void ComposeMapNode(const Eigen::Vector3d &trans)
void GetLocalizationDistribution(Eigen::MatrixXd *distribution)
void SetVelodyneExtrinsic(const Eigen::Affine3d &pose)
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.
unsigned int map_node_size_x_
The map node size in pixels.
void Initial(const BaseMapConfig *map_config, bool is_fixed_size=true)
Initialize the pool.
const BaseMapMatrix & GetMapCellMatrix() const
Get map cell matrix.
bool SetMapFolderPath(const std::string folder_path)
Set the directory of the map.
Definition base_map.cc:106
BaseMapNode * GetMapNodeSafe(const MapNodeIndex &index)
Return the map node, if it's not in the cache, safely load it.
Definition base_map.cc:63
virtual void InitMapNodeCaches(int cacheL1_size, int cahceL2_size)
Definition base_map.cc:40
const BaseMapConfig & GetMapConfig() const
Get the map config.
Definition base_map.h:97
virtual bool LoadMapArea(const Eigen::Vector3d &seed_pt3d, unsigned int resolution_id, unsigned int zone_id, int filter_size_x, int filter_size_y)
Load map nodes for the location calculate of this frame.
Definition base_map.cc:394
virtual void PreloadMapArea(const Eigen::Vector3d &location, const Eigen::Vector3d &trans_diff, unsigned int resolution_id, unsigned int zone_id)
Preload map nodes for the next frame location calculation.
Definition base_map.cc:263
void AttachMapNodePool(BaseMapNodePool *p_map_node_pool)
Attach map node pointer.
Definition base_map.cc:53
unsigned int m_
The map node ID at the northing direction.
unsigned int n_
The map node ID at the easting direction.
static MapNodeIndex GetMapNodeIndex(const BaseMapConfig &option, const Eigen::Vector3d &coordinate, unsigned int resolution_id, int zone_id)
Construct a map node index, given a global coordinate, eigen version.
const float * GetAltitudeSafe(unsigned int row, unsigned int col, unsigned int level=0) const
Get an altitude value by check.
const unsigned int * GetCountSafe(unsigned int row, unsigned int col, unsigned int level=0) const
Get a count value by check.
const float * GetGroundAltitudeSafe(unsigned int row, unsigned int col, unsigned int level=0) const
Get an altitude ground value by check.
bool GetCoordinate(const Eigen::Vector2d &coordinate, unsigned int level, unsigned int *x, unsigned int *y) const
Given the global coordinate, get the local 2D coordinate of the map cell matrix.
#define AINFO
Definition log.h:42
class register implement
Definition arena_queue.h:37
std::vector< unsigned char > intensities