Apollo 10.0
自动驾驶开放平台
localization_lidar_process.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
19#include "yaml-cpp/yaml.h"
20
21#include "cyber/common/file.h"
22#include "cyber/common/log.h"
23#include "cyber/time/clock.h"
25
26namespace apollo {
27namespace localization {
28namespace msf {
29
32
34 : locator_(new LocalizationLidar()),
35 pose_forecastor_(new PoseForcast()),
36 map_path_(""),
37 lidar_extrinsic_file_(""),
38 lidar_height_file_(""),
39 localization_mode_(2),
40 yaw_align_mode_(2),
41 lidar_filter_size_(17),
42 delta_yaw_limit_(0.25 * 3.14159 / 180.0),
43 init_delta_yaw_limit_(1.5 * 3.14159 / 180.0),
44 compensate_pitch_roll_limit_(0.035),
45 utm_zone_id_(50),
46 map_coverage_theshold_(0.8),
47 lidar_extrinsic_(TransformD::Identity()),
48 lidar_height_(),
49 is_get_first_lidar_msg_(false),
50 cur_predict_location_(TransformD::Identity()),
51 pre_predict_location_(TransformD::Identity()),
52 velocity_(Vector3D::Zero()),
53 pre_location_(TransformD::Identity()),
54 location_(TransformD::Identity()),
55 pre_location_time_(0.0),
56 location_covariance_(Matrix3D::Zero()),
57 lidar_status_(LidarState::NOT_VALID),
58 reinit_flag_(false),
59 imu_lidar_max_delay_time_(0.5),
60 is_unstable_reset_(true),
61 unstable_count_(0),
62 unstable_threshold_(0.3),
63 out_map_count_(0),
64 forecast_integ_state_(ForecastState::NOT_VALID),
65 forecast_timer_(-1) {}
66
68 delete locator_;
69 locator_ = nullptr;
70
71 delete pose_forecastor_;
72 pose_forecastor_ = nullptr;
73}
74
76 // initial_success_ = false;
77 map_path_ = params.map_path;
78 lidar_extrinsic_file_ = params.lidar_extrinsic_file;
79 lidar_height_file_ = params.lidar_height_file;
80 localization_mode_ = params.localization_mode;
81 yaw_align_mode_ = params.lidar_yaw_align_mode;
82 utm_zone_id_ = params.utm_zone_id;
83 map_coverage_theshold_ = params.map_coverage_theshold;
84 imu_lidar_max_delay_time_ = params.imu_lidar_max_delay_time;
85
86 lidar_filter_size_ = params.lidar_filter_size;
87
88 is_unstable_reset_ = params.is_lidar_unstable_reset;
89 unstable_threshold_ = params.unstable_reset_threshold;
90 if_use_avx_ = params.if_use_avx;
91
92 lidar_status_ = LidarState::NOT_VALID;
93
94 // reload_map_flag_ = false;
95 reinit_flag_ = false;
96
97 // buffer
98 out_map_count_ = 0;
99
100 is_get_first_lidar_msg_ = false;
101 cur_predict_location_ = TransformD::Identity();
102 pre_predict_location_ = TransformD::Identity();
103 pre_location_ = TransformD::Identity();
104 velocity_ = Vector3D::Zero();
105 location_ = TransformD::Identity();
106 location_covariance_ = Matrix3D::Zero();
108 local_lidar_quality_ = LocalLidarQuality::MSF_LOCAL_LIDAR_BAD;
109
110 bool success = LoadLidarExtrinsic(lidar_extrinsic_file_, &lidar_extrinsic_);
111 if (!success) {
112 AERROR << "LocalizationLidar: Fail to access the lidar"
113 " extrinsic file: "
114 << lidar_extrinsic_file_;
116 "Fail to access the lidar extrinsic file");
117 }
118
119 success = LoadLidarHeight(lidar_height_file_, &lidar_height_);
120 if (!success) {
121 AWARN << "LocalizationLidar: Fail to load the lidar"
122 " height file: "
123 << lidar_height_file_ << " Will use default value!";
124 lidar_height_.height = params.lidar_height_default;
125 }
126
127 if (!locator_->Init(map_path_, lidar_filter_size_, lidar_filter_size_,
128 utm_zone_id_)) {
131 "Fail to load localization map!");
132 }
133
134 locator_->SetVelodyneExtrinsic(lidar_extrinsic_);
135 locator_->SetLocalizationMode(localization_mode_);
136 locator_->SetImageAlignMode(yaw_align_mode_);
137 locator_->SetValidThreshold(static_cast<float>(map_coverage_theshold_));
138 locator_->SetVehicleHeight(lidar_height_.height);
139 locator_->SetDeltaPitchRollLimit(compensate_pitch_roll_limit_);
140
141 const double deg_to_rad = 0.017453292519943;
142 const double max_gyro_input = 200 * deg_to_rad; // 200 degree
143 const double max_acc_input = 5.0; // 5.0 m/s^2
144 pose_forecastor_->SetMaxListNum(400);
145 pose_forecastor_->SetMaxAccelInput(max_acc_input);
146 pose_forecastor_->SetMaxGyroInput(max_gyro_input);
147 pose_forecastor_->SetZoneId(utm_zone_id_);
148
149 return Status::OK();
150}
151
152double LocalizationLidarProcess::ComputeDeltaYawLimit(
153 const int64_t index_cur, const int64_t index_stable, const double limit_min,
154 const double limit_max) {
155 if (index_cur > index_stable) {
156 return limit_min;
157 }
158
159 double ratio = static_cast<double>(index_cur);
160 ratio /= static_cast<double>(index_stable);
161 return limit_min * ratio + limit_max * (1.0 - ratio);
162}
163
165 if (!CheckState()) {
166 AERROR << "PcdProcess: Receive an invalid lidar msg!";
167 return;
168 }
169
170 // pcd process cost time
171 Timer timer;
172 timer.Start();
173
174 static unsigned int pcd_index = 0;
175
176 if (!GetPredictPose(lidar_frame.measurement_time, &cur_predict_location_,
177 &forecast_integ_state_)) {
178 AINFO << "PcdProcess: Discard a lidar msg because can't get predict pose. "
179 << "More info see log in function GetPredictPose.";
180 return;
181 }
182
183 if (forecast_integ_state_ != ForecastState::INCREMENT) {
184 forecast_timer_ = -1;
185 }
186 ++forecast_timer_;
187
188 locator_->SetDeltaYawLimit(ComputeDeltaYawLimit(
189 forecast_timer_, 10, delta_yaw_limit_, init_delta_yaw_limit_));
190
191 if (!is_get_first_lidar_msg_) {
192 pre_predict_location_ = cur_predict_location_;
193 pre_location_ = cur_predict_location_;
194 velocity_ = Vector3D::Zero();
195 is_get_first_lidar_msg_ = true;
196 }
197
198 velocity_ = cur_predict_location_.translation() - pre_location_.translation();
199
200 int ret = locator_->Update(pcd_index++, cur_predict_location_, velocity_,
201 lidar_frame, if_use_avx_);
202
203 UpdateState(ret, lidar_frame.measurement_time);
204
205 timer.End("Lidar process");
206}
207
209 TransformD* location,
210 Matrix3D* covariance) const {
211 CHECK_NOTNULL(lidar_status);
212 CHECK_NOTNULL(location);
213 CHECK_NOTNULL(covariance);
214
215 *lidar_status = static_cast<int>(lidar_status_);
216 *location = location_;
217 *covariance = location_covariance_;
218}
219
221 if (lidar_local_msg == nullptr) {
222 return static_cast<int>(LidarState::NOT_VALID);
223 }
224
225 lidar_local_msg->set_measurement_time(pre_location_time_);
226
227 apollo::common::Header* headerpb = lidar_local_msg->mutable_header();
228 headerpb->set_timestamp_sec(pre_location_time_);
229
230 apollo::localization::Pose* posepb = lidar_local_msg->mutable_pose();
231 apollo::common::PointENU* position = posepb->mutable_position();
232 position->set_x(location_.translation()(0));
233 position->set_y(location_.translation()(1));
234 position->set_z(location_.translation()(2));
235
236 apollo::common::Quaternion* quaternion = posepb->mutable_orientation();
237 Eigen::Quaterniond quat(location_.linear());
238 quaternion->set_qx(quat.x());
239 quaternion->set_qy(quat.y());
240 quaternion->set_qz(quat.z());
241 quaternion->set_qw(quat.w());
242
244 lidar_local_msg->mutable_uncertainty();
245
246 apollo::common::Point3D* position_std_dev =
247 uncertainty->mutable_position_std_dev();
248 position_std_dev->set_x(location_covariance_(0, 0));
249 position_std_dev->set_y(location_covariance_(1, 1));
250 position_std_dev->set_z(0.0);
251
252 static constexpr double yaw_covariance = 0.15 * 0.15 * DEG_TO_RAD2;
253 apollo::common::Point3D* orientation_std_dev =
254 uncertainty->mutable_orientation_std_dev();
255 orientation_std_dev->set_x(0.0);
256 orientation_std_dev->set_y(0.0);
257 orientation_std_dev->set_z(yaw_covariance);
258
259 MsfStatus* msf_status = lidar_local_msg->mutable_msf_status();
260 msf_status->set_local_lidar_status(local_lidar_status_);
261 msf_status->set_local_lidar_quality(local_lidar_quality_);
262
263 return static_cast<int>(lidar_status_);
264}
265
266void LocalizationLidarProcess::IntegPvaProcess(const InsPva& sins_pva_msg) {
267 pose_forecastor_->PushInspvaData(sins_pva_msg);
268}
269
270void LocalizationLidarProcess::RawImuProcess(const ImuData& imu_msg) {
271 pose_forecastor_->PushImuData(imu_msg);
272}
273
274bool LocalizationLidarProcess::GetPredictPose(const double lidar_time,
275 TransformD* predict_pose,
276 ForecastState* forecast_state) {
277 CHECK_NOTNULL(predict_pose);
278 CHECK_NOTNULL(forecast_state);
279
280 double latest_imu_time = pose_forecastor_->GetLastestImuTime();
281 if (latest_imu_time - lidar_time > imu_lidar_max_delay_time_) {
282 AERROR << std::setprecision(16) << "LocalizationLidar GetPredictPose: "
283 << "Lidar msg too old! "
284 << "lidar time: " << lidar_time
285 << "delay time: " << latest_imu_time - lidar_time;
286 return false;
287 }
288
289 Pose forecast_pose;
290 int state = -1;
291 if (lidar_status_ != LidarState::OK) {
292 Pose init_pose;
293 state = pose_forecastor_->GetBestForcastPose(lidar_time, -1, init_pose,
294 &forecast_pose);
295 } else {
296 Pose init_pose;
297 init_pose.x = pre_location_.translation()(0);
298 init_pose.y = pre_location_.translation()(1);
299 init_pose.z = pre_location_.translation()(2);
300 Eigen::Quaterniond quatd(pre_location_.linear());
301 init_pose.qx = quatd.x();
302 init_pose.qy = quatd.y();
303 init_pose.qz = quatd.z();
304 init_pose.qw = quatd.w();
305
306 state = pose_forecastor_->GetBestForcastPose(lidar_time, pre_location_time_,
307 init_pose, &forecast_pose);
308 }
309
310 if (state < 0) {
311 AINFO << "LocalizationLidar GetPredictPose: "
312 << "Receive a lidar msg, but can't query predict pose.";
313 *forecast_state = ForecastState::NOT_VALID;
314 return false;
315 }
316
317 if (std::abs(forecast_pose.x) < 10.0 || std::abs(forecast_pose.y) < 10.0) {
318 AERROR << "LocalizationLidar Fatal Error: invalid pose!";
319 return false;
320 }
321
322 Eigen::Quaterniond quatd(forecast_pose.qw, forecast_pose.qx, forecast_pose.qy,
323 forecast_pose.qz);
324 Eigen::Translation3d transd(
325 Eigen::Vector3d(forecast_pose.x, forecast_pose.y, forecast_pose.z));
326 *predict_pose = transd * quatd;
327
328 if (state == 0) {
329 *forecast_state = ForecastState::INITIAL;
330 } else {
331 *forecast_state = ForecastState::INCREMENT;
332 AINFO << "The delta translation input lidar localization: " << lidar_time
333 << " " << forecast_pose.x - pre_location_.translation()(0) << " "
334 << forecast_pose.y - pre_location_.translation()(1) << " "
335 << forecast_pose.z - pre_location_.translation()(2);
336 }
337
338 return true;
339}
340
341bool LocalizationLidarProcess::CheckState() { return true; }
342
343void LocalizationLidarProcess::UpdateState(const int ret, const double time) {
344 if (ret == 0) { // OK
345 double location_score = 0.0;
346 locator_->GetResult(&location_, &location_covariance_, &location_score);
347 lidar_status_ = LidarState::OK;
348
349 double local_uncertainty_x = std::sqrt(location_covariance_(0, 0));
350 double local_uncertainty_y = std::sqrt(location_covariance_(1, 1));
351
352 local_uncertainty_x = local_uncertainty_x > 0.1 ? local_uncertainty_x : 0.1;
353 local_uncertainty_y = local_uncertainty_y > 0.1 ? local_uncertainty_y : 0.1;
354 // check covariance
355 double cur_location_std_area =
356 std::sqrt(local_uncertainty_x * local_uncertainty_x +
357 local_uncertainty_y * local_uncertainty_y);
358 if (cur_location_std_area > unstable_threshold_ || location_score < 0.8) {
359 local_lidar_quality_ = LocalLidarQuality::MSF_LOCAL_LIDAR_BAD;
360 } else if (cur_location_std_area <= unstable_threshold_ &&
361 location_score < 0.85) {
362 local_lidar_quality_ = LocalLidarQuality::MSF_LOCAL_LIDAR_NOT_BAD;
363 } else if (cur_location_std_area <= unstable_threshold_ &&
364 location_score < 0.95) {
365 local_lidar_quality_ = LocalLidarQuality::MSF_LOCAL_LIDAR_GOOD;
366 } else if (cur_location_std_area <= unstable_threshold_) {
368 }
369
370 if (local_lidar_quality_ == LocalLidarQuality::MSF_LOCAL_LIDAR_BAD) {
371 ++unstable_count_;
372 local_lidar_status_ = LocalLidarStatus::MSF_LOCAL_LIDAR_NOT_GOOD;
373 } else {
374 unstable_count_ = 0;
375 local_lidar_status_ = LocalLidarStatus::MSF_LOCAL_LIDAR_NORMAL;
376 }
377
378 // check if lidar need reset
379 if (unstable_count_ >= 2 && is_unstable_reset_) {
380 unstable_count_ = 2;
381 reinit_flag_ = true;
382 AWARN << "Reinit lidar localization due to big covariance";
383 lidar_status_ = LidarState::NOT_STABLE;
384 } else {
385 lidar_status_ = LidarState::OK;
386 if (out_map_count_ > 0) {
387 --out_map_count_;
388 }
389 }
390 pre_location_ = location_;
391 pre_location_time_ = time;
392
393 } else if (ret == -2) { // out of map
395 double location_score = 0.0;
396 locator_->GetResult(&location_, &location_covariance_, &location_score);
397 lidar_status_ = LidarState::NOT_STABLE;
398 pre_location_ = location_;
399 pre_location_time_ = time;
400 if (out_map_count_ < 10) {
401 ++out_map_count_;
402 } else {
403 reinit_flag_ = true;
404 }
405 } else { // NOT_VALID
406 AERROR << "LocalizationLidar: The reflection map load failed!";
407 lidar_status_ = LidarState::NOT_VALID;
408 }
409}
410
411bool LocalizationLidarProcess::LoadLidarExtrinsic(const std::string& file_path,
412 TransformD* lidar_extrinsic) {
413 CHECK_NOTNULL(lidar_extrinsic);
414
415 YAML::Node config = YAML::LoadFile(file_path);
416 if (config["transform"]) {
417 if (config["transform"]["translation"]) {
418 lidar_extrinsic->translation()(0) =
419 config["transform"]["translation"]["x"].as<double>();
420 lidar_extrinsic->translation()(1) =
421 config["transform"]["translation"]["y"].as<double>();
422 lidar_extrinsic->translation()(2) =
423 config["transform"]["translation"]["z"].as<double>();
424 if (config["transform"]["rotation"]) {
425 double qx = config["transform"]["rotation"]["x"].as<double>();
426 double qy = config["transform"]["rotation"]["y"].as<double>();
427 double qz = config["transform"]["rotation"]["z"].as<double>();
428 double qw = config["transform"]["rotation"]["w"].as<double>();
429 lidar_extrinsic->linear() =
430 Eigen::Quaterniond(qw, qx, qy, qz).toRotationMatrix();
431 return true;
432 }
433 }
434 }
435 return false;
436}
437
438bool LocalizationLidarProcess::LoadLidarHeight(const std::string& file_path,
439 LidarHeight* height) {
440 CHECK_NOTNULL(height);
441
442 if (!cyber::common::PathExists(file_path)) {
443 return false;
444 }
445
446 YAML::Node config = YAML::LoadFile(file_path);
447 if (config["vehicle"]) {
448 if (config["vehicle"]["parameters"]) {
449 height->height = config["vehicle"]["parameters"]["height"].as<double>();
450 height->height_var =
451 config["vehicle"]["parameters"]["height_var"].as<double>();
452 return true;
453 }
454 }
455 return false;
456}
457
458} // namespace msf
459} // namespace localization
460} // namespace apollo
A general class to denote the return status of an API call.
Definition status.h:43
static Status OK()
generate a success status.
Definition status.h:60
int64_t End(const std::string &msg)
Definition perf_util.cc:55
apollo::common::Status Init(const LocalizationIntegParam &params)
void GetResult(int *lidar_status, TransformD *location, Matrix3D *covariance) const
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 SetVelodyneExtrinsic(const Eigen::Affine3d &pose)
The class of LocalizationLidarProcess
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
bool PathExists(const std::string &path)
Check if the path exists.
Definition file.cc:195
uint32_t height
Height of point cloud
class register implement
Definition arena_queue.h:37