Apollo 10.0
自动驾驶开放平台
ndt_localization.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 "Eigen/Geometry"
20#include "yaml-cpp/yaml.h"
21
22#include "cyber/common/file.h"
23#include "cyber/common/log.h"
24#include "cyber/time/clock.h"
27#include "modules/common_msgs/sensor_msgs/gnss_best_pose.pb.h"
29
30namespace apollo {
31namespace localization {
32namespace ndt {
33
35 tf_buffer_ = apollo::transform::Buffer::Instance();
36 tf_buffer_->Init();
37
38 resolution_id_ = 0;
39 zone_id_ = FLAGS_local_utm_zone_id;
40 online_resolution_ = FLAGS_online_resolution;
41 ndt_debug_log_flag_ = FLAGS_ndt_debug_log_flag;
42 tf_source_frame_id_ = FLAGS_broadcast_tf_frame_id;
43 tf_target_frame_id_ = FLAGS_broadcast_tf_child_frame_id;
44 std::string lidar_height_file = FLAGS_lidar_height_file;
45 std::string lidar_extrinsics_file = FLAGS_lidar_extrinsics_file;
46 bad_score_count_threshold_ = FLAGS_ndt_bad_score_count_threshold;
47 warnning_ndt_score_ = FLAGS_ndt_warnning_ndt_score;
48 error_ndt_score_ = FLAGS_ndt_error_ndt_score;
49
50 std::string map_path_ =
51 FLAGS_map_dir + "/" + FLAGS_ndt_map_dir + "/" + FLAGS_local_map_name;
52 AINFO << "map folder: " << map_path_;
53 velodyne_extrinsic_ = Eigen::Affine3d::Identity();
54 bool success =
55 LoadLidarExtrinsic(lidar_extrinsics_file, &velodyne_extrinsic_);
56 if (!success) {
57 AERROR << "LocalizationLidar: Fail to access the lidar"
58 " extrinsic file: "
59 << lidar_extrinsics_file;
60 return;
61 }
62 Eigen::Quaterniond ext_quat(velodyne_extrinsic_.linear());
63 AINFO << "lidar extrinsics: " << velodyne_extrinsic_.translation().x() << ", "
64 << velodyne_extrinsic_.translation().y() << ", "
65 << velodyne_extrinsic_.translation().z() << ", " << ext_quat.x() << ", "
66 << ext_quat.y() << ", " << ext_quat.z() << ", " << ext_quat.w();
67
68 success = LoadLidarHeight(lidar_height_file, &lidar_height_);
69 if (!success) {
70 AWARN << "LocalizationLidar: Fail to load the lidar"
71 " height file: "
72 << lidar_height_file << " Will use default value!";
73 lidar_height_.height = FLAGS_lidar_height_default;
74 }
75
76 // try load zone id from local_map folder
77 if (FLAGS_if_utm_zone_id_from_folder) {
78 bool success = LoadZoneIdFromFolder(map_path_, &zone_id_);
79 if (!success) {
80 AWARN << "Can't load utm zone id from map folder, use default value.";
81 }
82 }
83 AINFO << "utm zone id: " << zone_id_;
84
85 lidar_locator_.SetMapFolderPath(map_path_);
86 lidar_locator_.SetVelodyneExtrinsic(velodyne_extrinsic_);
87 lidar_locator_.SetLidarHeight(lidar_height_.height);
88 lidar_locator_.SetOnlineCloudResolution(
89 static_cast<float>(online_resolution_));
90
91 odometry_buffer_.clear();
92 odometry_buffer_size_ = 0;
93
94 is_service_started_ = false;
95}
96// receive odometry message
98 const std::shared_ptr<localization::Gps>& odometry_msg) {
99 double odometry_time = odometry_msg->header().timestamp_sec();
100 static double pre_odometry_time = odometry_time;
101 double time_delay = odometry_time - pre_odometry_time;
102 if (time_delay > 0.1) {
103 AINFO << "Odometry message loss more than 10ms, the pre time and cur time: "
104 << pre_odometry_time << ", " << odometry_time;
105 } else if (time_delay < 0.0) {
106 AINFO << "Odometry message's time is earlier than last one, "
107 << "the pre time and cur time: " << pre_odometry_time << ", "
108 << odometry_time;
109 }
110 pre_odometry_time = odometry_time;
111 Eigen::Affine3d odometry_pose = Eigen::Affine3d::Identity();
112 if (odometry_msg->has_localization()) {
113 odometry_pose.translation()[0] =
114 odometry_msg->localization().position().x();
115 odometry_pose.translation()[1] =
116 odometry_msg->localization().position().y();
117 odometry_pose.translation()[2] =
118 odometry_msg->localization().position().z();
119 Eigen::Quaterniond tmp_quat(
120 odometry_msg->localization().orientation().qw(),
121 odometry_msg->localization().orientation().qx(),
122 odometry_msg->localization().orientation().qy(),
123 odometry_msg->localization().orientation().qz());
124 odometry_pose.linear() = tmp_quat.toRotationMatrix();
125 }
126 if (ZeroOdometry(odometry_pose)) {
127 AINFO << "Detect Zero Odometry";
128 return;
129 }
130
131 TimeStampPose timestamp_pose;
132 timestamp_pose.timestamp = odometry_time;
133 timestamp_pose.pose = odometry_pose;
134 {
135 std::lock_guard<std::mutex> lock(odometry_buffer_mutex_);
136 if (odometry_buffer_size_ < max_odometry_buffer_size_) {
137 odometry_buffer_.push_back(timestamp_pose);
138 odometry_buffer_size_++;
139 } else {
140 odometry_buffer_.pop_front();
141 odometry_buffer_.push_back(timestamp_pose);
142 }
143 }
144
145 if (ndt_debug_log_flag_) {
146 AINFO << "NDTLocalization Debug Log: odometry msg: "
147 << std::setprecision(15) << "time: " << odometry_time << ", "
148 << "x: " << odometry_msg->localization().position().x() << ", "
149 << "y: " << odometry_msg->localization().position().y() << ", "
150 << "z: " << odometry_msg->localization().position().z() << ", "
151 << "qx: " << odometry_msg->localization().orientation().qx() << ", "
152 << "qy: " << odometry_msg->localization().orientation().qy() << ", "
153 << "qz: " << odometry_msg->localization().orientation().qz() << ", "
154 << "qw: " << odometry_msg->localization().orientation().qw();
155 }
156
157 Eigen::Affine3d localization_pose = Eigen::Affine3d::Identity();
158 if (lidar_locator_.IsInitialized()) {
159 localization_pose =
160 pose_buffer_.UpdateOdometryPose(odometry_time, odometry_pose);
161 }
162 ComposeLocalizationEstimate(localization_pose, odometry_msg,
163 &localization_result_);
164 drivers::gnss::InsStat odometry_status;
165 FindNearestOdometryStatus(odometry_time, &odometry_status);
166 ComposeLocalizationStatus(odometry_status, &localization_status_);
167 is_service_started_ = true;
168}
169
170// receive lidar pointcloud message
172 const std::shared_ptr<drivers::PointCloud>& lidar_msg) {
173 static unsigned int frame_idx = 0;
174 LidarFrame lidar_frame;
175 LidarMsgTransfer(lidar_msg, &lidar_frame);
176
177 double time_stamp = lidar_frame.measurement_time;
178 Eigen::Affine3d odometry_pose = Eigen::Affine3d::Identity();
179 if (!QueryPoseFromBuffer(time_stamp, &odometry_pose)) {
180 if (!QueryPoseFromTF(time_stamp, &odometry_pose)) {
181 AERROR << "Can not query forecast pose";
182 return;
183 }
184 AINFO << "Query pose from TF";
185 } else {
186 AINFO << "Query pose from buffer";
187 }
188 if (!lidar_locator_.IsInitialized()) {
189 lidar_locator_.Init(odometry_pose, resolution_id_, zone_id_);
190 return;
191 }
192 lidar_locator_.Update(frame_idx++, odometry_pose, lidar_frame);
193 lidar_pose_ = lidar_locator_.GetPose();
194 pose_buffer_.UpdateLidarPose(time_stamp, lidar_pose_, odometry_pose);
195 ComposeLidarResult(time_stamp, lidar_pose_, &lidar_localization_result_);
196 ndt_score_ = lidar_locator_.GetFitnessScore();
197 if (ndt_score_ > warnning_ndt_score_) {
198 bad_score_count_++;
199 } else {
200 bad_score_count_ = 0;
201 }
202 if (ndt_debug_log_flag_) {
203 Eigen::Quaterniond tmp_quat(lidar_pose_.linear());
204 AINFO << "NDTLocalization Debug Log: lidar pose: " << std::setprecision(15)
205 << "time: " << time_stamp << ", "
206 << "x: " << lidar_pose_.translation()[0] << ", "
207 << "y: " << lidar_pose_.translation()[1] << ", "
208 << "z: " << lidar_pose_.translation()[2] << ", "
209 << "qx: " << tmp_quat.x() << ", "
210 << "qy: " << tmp_quat.y() << ", "
211 << "qz: " << tmp_quat.z() << ", "
212 << "qw: " << tmp_quat.w();
213
214 Eigen::Quaterniond qbn(odometry_pose.linear());
215 AINFO << "NDTLocalization Debug Log: odometry for lidar pose: "
216 << std::setprecision(15) << "time: " << time_stamp << ", "
217 << "x: " << odometry_pose.translation()[0] << ", "
218 << "y: " << odometry_pose.translation()[1] << ", "
219 << "z: " << odometry_pose.translation()[2] << ", "
220 << "qx: " << qbn.x() << ", "
221 << "qy: " << qbn.y() << ", "
222 << "qz: " << qbn.z() << ", "
223 << "qw: " << qbn.w();
224 }
225}
226
228 const std::shared_ptr<drivers::gnss::InsStat>& status_msg) {
229 std::unique_lock<std::mutex> lock(odometry_status_list_mutex_);
230 if (odometry_status_list_.size() < odometry_status_list_max_size_) {
231 odometry_status_list_.push_back(*status_msg);
232 } else {
233 odometry_status_list_.pop_front();
234 odometry_status_list_.push_back(*status_msg);
235 }
236}
237// output localization result
239 LocalizationEstimate* localization) const {
240 *localization = localization_result_;
241}
242
244 LocalizationEstimate* localization) const {
245 *localization = lidar_localization_result_;
246}
247
249 LocalizationStatus* localization_status) const {
250 *localization_status = localization_status_;
251}
252
253bool NDTLocalization::IsServiceStarted() { return is_service_started_; }
254
255void NDTLocalization::FillLocalizationMsgHeader(
256 LocalizationEstimate* localization) {
257 auto* header = localization->mutable_header();
258 double timestamp = apollo::cyber::Clock::NowInSeconds();
259 header->set_module_name(module_name_);
260 header->set_timestamp_sec(timestamp);
261 header->set_sequence_num(++localization_seq_num_);
262}
263
264void NDTLocalization::ComposeLocalizationEstimate(
265 const Eigen::Affine3d& pose,
266 const std::shared_ptr<localization::Gps>& odometry_msg,
267 LocalizationEstimate* localization) {
268 localization->Clear();
269 FillLocalizationMsgHeader(localization);
270
271 localization->set_measurement_time(odometry_msg->header().timestamp_sec());
272 auto mutable_pose = localization->mutable_pose();
273 mutable_pose->mutable_position()->set_x(pose.translation().x());
274 mutable_pose->mutable_position()->set_y(pose.translation().y());
275 mutable_pose->mutable_position()->set_z(pose.translation().z());
276
277 Eigen::Quaterniond quat(pose.linear());
278 mutable_pose->mutable_orientation()->set_qw(quat.w());
279 mutable_pose->mutable_orientation()->set_qx(quat.x());
280 mutable_pose->mutable_orientation()->set_qy(quat.y());
281 mutable_pose->mutable_orientation()->set_qz(quat.z());
282 double heading =
283 common::math::QuaternionToHeading(quat.w(), quat.x(), quat.y(), quat.z());
284 mutable_pose->set_heading(heading);
285
286 common::math::EulerAnglesZXYd euler(quat.w(), quat.x(), quat.y(), quat.z());
287 mutable_pose->mutable_euler_angles()->set_x(euler.pitch());
288 mutable_pose->mutable_euler_angles()->set_y(euler.roll());
289 mutable_pose->mutable_euler_angles()->set_z(euler.yaw());
290
291 const auto& odometry_pose = odometry_msg->localization();
292 if (odometry_pose.has_linear_velocity()) {
293 mutable_pose->mutable_linear_velocity()->CopyFrom(
294 odometry_pose.linear_velocity());
295 }
296 if (odometry_pose.has_linear_acceleration()) {
297 mutable_pose->mutable_linear_acceleration()->CopyFrom(
298 odometry_pose.linear_acceleration());
299 }
300 if (odometry_pose.has_angular_velocity()) {
301 mutable_pose->mutable_angular_velocity()->CopyFrom(
302 odometry_pose.angular_velocity());
303 }
304 if (odometry_pose.has_linear_acceleration_vrf()) {
305 mutable_pose->mutable_linear_acceleration_vrf()->CopyFrom(
306 odometry_pose.linear_acceleration_vrf());
307 }
308 if (odometry_pose.has_angular_velocity_vrf()) {
309 mutable_pose->mutable_angular_velocity_vrf()->CopyFrom(
310 odometry_pose.angular_velocity_vrf());
311 }
312}
313
314void NDTLocalization::ComposeLidarResult(double time_stamp,
315 const Eigen::Affine3d& pose,
316 LocalizationEstimate* localization) {
317 localization->Clear();
318 FillLocalizationMsgHeader(localization);
319
320 localization->set_measurement_time(time_stamp);
321 auto mutable_pose = localization->mutable_pose();
322 mutable_pose->mutable_position()->set_x(pose.translation().x());
323 mutable_pose->mutable_position()->set_y(pose.translation().y());
324 mutable_pose->mutable_position()->set_z(pose.translation().z());
325
326 Eigen::Quaterniond quat(pose.linear());
327 mutable_pose->mutable_orientation()->set_qw(quat.w());
328 mutable_pose->mutable_orientation()->set_qx(quat.x());
329 mutable_pose->mutable_orientation()->set_qy(quat.y());
330 mutable_pose->mutable_orientation()->set_qz(quat.z());
331 double heading =
332 common::math::QuaternionToHeading(quat.w(), quat.x(), quat.y(), quat.z());
333 mutable_pose->set_heading(heading);
334
335 common::math::EulerAnglesZXYd euler(quat.w(), quat.x(), quat.y(), quat.z());
336 mutable_pose->mutable_euler_angles()->set_x(euler.pitch());
337 mutable_pose->mutable_euler_angles()->set_y(euler.roll());
338 mutable_pose->mutable_euler_angles()->set_z(euler.yaw());
339}
340
341bool NDTLocalization::QueryPoseFromTF(double time, Eigen::Affine3d* pose) {
342 cyber::Time query_time(time);
343 const float time_out = 0.01f;
344 std::string err_msg = "";
345 bool can_transform = tf_buffer_->canTransform(
346 tf_target_frame_id_, tf_source_frame_id_, query_time, time_out, &err_msg);
347 if (!can_transform) {
348 AERROR << "Can not transform: " << err_msg;
349 return false;
350 }
352 try {
353 query_transform = tf_buffer_->lookupTransform(
354 tf_target_frame_id_, tf_source_frame_id_, query_time);
355 } catch (tf2::TransformException ex) {
356 AERROR << ex.what();
357 return false;
358 }
359 pose->translation()[0] = query_transform.transform().translation().x();
360 pose->translation()[1] = query_transform.transform().translation().y();
361 pose->translation()[2] = query_transform.transform().translation().z();
362 Eigen::Quaterniond tmp_quat(query_transform.transform().rotation().qw(),
363 query_transform.transform().rotation().qx(),
364 query_transform.transform().rotation().qy(),
365 query_transform.transform().rotation().qz());
366 pose->linear() = tmp_quat.toRotationMatrix();
367 return true;
368}
369
370void NDTLocalization::ComposeLocalizationStatus(
371 const drivers::gnss::InsStat& status,
372 LocalizationStatus* localization_status) {
373 apollo::common::Header* header = localization_status->mutable_header();
375 header->set_timestamp_sec(timestamp);
376 localization_status->set_measurement_time(status.header().timestamp_sec());
377
378 if (!status.has_pos_type()) {
379 localization_status->set_fusion_status(MeasureState::ERROR);
380 localization_status->set_state_message(
381 "Error: Current Localization Status Is Missing.");
382 return;
383 }
384
385 auto pos_type = static_cast<drivers::gnss::SolutionType>(status.pos_type());
386 if (ndt_score_ < warnning_ndt_score_ &&
388 localization_status->set_fusion_status(MeasureState::OK);
389 localization_status->set_state_message("");
390 } else if (bad_score_count_ > bad_score_count_threshold_ ||
391 ndt_score_ > error_ndt_score_ ||
394 localization_status->set_fusion_status(MeasureState::ERROR);
395 localization_status->set_state_message(
396 "Error: Current Localization Is Very Unstable.");
397 } else {
398 localization_status->set_fusion_status(MeasureState::WARNNING);
399 localization_status->set_state_message(
400 "Warning: Current Localization Is Unstable.");
401 }
402}
403
404bool NDTLocalization::QueryPoseFromBuffer(double time, Eigen::Affine3d* pose) {
405 CHECK_NOTNULL(pose);
406
407 TimeStampPose pre_pose;
408 TimeStampPose next_pose;
409 {
410 std::lock_guard<std::mutex> lock(odometry_buffer_mutex_);
411 TimeStampPose timestamp_pose = odometry_buffer_.back();
412 // check abnormal timestamp
413 if (time > timestamp_pose.timestamp) {
414 AERROR << "query time is newer than latest odometry time, it doesn't "
415 "make sense!";
416 return false;
417 }
418 // search from reverse direction
419 auto iter = odometry_buffer_.crbegin();
420 for (; iter != odometry_buffer_.crend(); ++iter) {
421 if (iter->timestamp < time) {
422 break;
423 }
424 }
425 if (iter == odometry_buffer_.crend()) {
426 AINFO << "Cannot find matching pose from odometry buffer";
427 return false;
428 }
429 pre_pose = *iter;
430 next_pose = *(--iter);
431 }
432 // interpolation
433 double v1 =
434 (next_pose.timestamp - time) / (next_pose.timestamp - pre_pose.timestamp);
435 double v2 =
436 (time - pre_pose.timestamp) / (next_pose.timestamp - pre_pose.timestamp);
437 pose->translation() =
438 pre_pose.pose.translation() * v1 + next_pose.pose.translation() * v2;
439
440 Eigen::Quaterniond pre_quat(pre_pose.pose.linear());
441
442 common::math::EulerAnglesZXYd pre_euler(pre_quat.w(), pre_quat.x(),
443 pre_quat.y(), pre_quat.z());
444
445 Eigen::Quaterniond next_quat(next_pose.pose.linear());
446 common::math::EulerAnglesZXYd next_euler(next_quat.w(), next_quat.x(),
447 next_quat.y(), next_quat.z());
448
449 double tmp_euler[3] = {};
450 tmp_euler[0] = pre_euler.pitch() * v1 + next_euler.pitch() * v2;
451 tmp_euler[1] = pre_euler.roll() * v1 + next_euler.roll() * v2;
452 tmp_euler[2] = pre_euler.yaw() * v1 + next_euler.yaw() * v2;
453 common::math::EulerAnglesZXYd euler(tmp_euler[1], tmp_euler[0], tmp_euler[2]);
454 Eigen::Quaterniond quat = euler.ToQuaternion();
455 quat.normalize();
456 pose->linear() = quat.toRotationMatrix();
457 return true;
458}
459
460bool NDTLocalization::ZeroOdometry(const Eigen::Affine3d& pose) {
461 double x = pose.translation().x();
462 double y = pose.translation().y();
463 double z = pose.translation().z();
464 double norm = std::sqrt(x * x + y * y + z * z);
465 if (norm <= 0.01) {
466 return true;
467 }
468 return false;
469}
470
471void NDTLocalization::LidarMsgTransfer(
472 const std::shared_ptr<drivers::PointCloud>& msg, LidarFrame* lidar_frame) {
473 CHECK_NOTNULL(lidar_frame);
474
475 if (msg->height() > 1 && msg->width() > 1) {
476 for (unsigned int i = 0; i < msg->height(); ++i) {
477 for (unsigned int j = 0; j < msg->width(); ++j) {
478 Eigen::Vector3f pt3d;
479 pt3d[0] = msg->point(i * msg->width() + j).x();
480 pt3d[1] = msg->point(i * msg->width() + j).y();
481 pt3d[2] = msg->point(i * msg->width() + j).z();
482 if (!std::isnan(pt3d[0])) {
483 Eigen::Vector3f pt3d_tem = pt3d;
484
485 if (pt3d_tem[2] > max_height_) {
486 continue;
487 }
488 unsigned char intensity = static_cast<unsigned char>(
489 msg->point(i * msg->width() + j).intensity());
490 lidar_frame->pt_xs.push_back(pt3d[0]);
491 lidar_frame->pt_ys.push_back(pt3d[1]);
492 lidar_frame->pt_zs.push_back(pt3d[2]);
493 lidar_frame->intensities.push_back(intensity);
494 }
495 }
496 }
497 } else {
498 AINFO << "Receiving un-organized-point-cloud, width " << msg->width()
499 << " height " << msg->height() << "size " << msg->point_size();
500 for (int i = 0; i < msg->point_size(); ++i) {
501 Eigen::Vector3f pt3d;
502 pt3d[0] = msg->point(i).x();
503 pt3d[1] = msg->point(i).y();
504 pt3d[2] = msg->point(i).z();
505 if (!std::isnan(pt3d[0])) {
506 Eigen::Vector3f pt3d_tem = pt3d;
507
508 if (pt3d_tem[2] > max_height_) {
509 continue;
510 }
511 unsigned char intensity =
512 static_cast<unsigned char>(msg->point(i).intensity());
513 lidar_frame->pt_xs.push_back(pt3d[0]);
514 lidar_frame->pt_ys.push_back(pt3d[1]);
515 lidar_frame->pt_zs.push_back(pt3d[2]);
516 lidar_frame->intensities.push_back(intensity);
517 }
518 }
519 }
520
521 lidar_frame->measurement_time =
522 cyber::Time(msg->measurement_time()).ToSecond();
523 if (ndt_debug_log_flag_) {
524 AINFO << std::setprecision(15)
525 << "NDTLocalization Debug Log: velodyne msg. "
526 << "[time:" << lidar_frame->measurement_time
527 << "][height:" << msg->height() << "][width:" << msg->width()
528 << "][point_cnt:" << msg->point_size() << "]";
529 }
530}
531
532bool NDTLocalization::LoadLidarExtrinsic(const std::string& file_path,
533 Eigen::Affine3d* lidar_extrinsic) {
534 CHECK_NOTNULL(lidar_extrinsic);
535
536 YAML::Node config = YAML::LoadFile(file_path);
537 if (config["transform"]) {
538 if (config["transform"]["translation"]) {
539 lidar_extrinsic->translation()(0) =
540 config["transform"]["translation"]["x"].as<double>();
541 lidar_extrinsic->translation()(1) =
542 config["transform"]["translation"]["y"].as<double>();
543 lidar_extrinsic->translation()(2) =
544 config["transform"]["translation"]["z"].as<double>();
545 if (config["transform"]["rotation"]) {
546 double qx = config["transform"]["rotation"]["x"].as<double>();
547 double qy = config["transform"]["rotation"]["y"].as<double>();
548 double qz = config["transform"]["rotation"]["z"].as<double>();
549 double qw = config["transform"]["rotation"]["w"].as<double>();
550 lidar_extrinsic->linear() =
551 Eigen::Quaterniond(qw, qx, qy, qz).toRotationMatrix();
552 return true;
553 }
554 }
555 }
556 return false;
557}
558
559bool NDTLocalization::LoadLidarHeight(const std::string& file_path,
560 LidarHeight* height) {
561 CHECK_NOTNULL(height);
562
563 if (!cyber::common::PathExists(file_path)) {
564 return false;
565 }
566
567 YAML::Node config = YAML::LoadFile(file_path);
568 if (config["vehicle"]) {
569 if (config["vehicle"]["parameters"]) {
570 height->height = config["vehicle"]["parameters"]["height"].as<double>();
571 height->height_var =
572 config["vehicle"]["parameters"]["height_var"].as<double>();
573 return true;
574 }
575 }
576 return false;
577}
578
579bool NDTLocalization::LoadZoneIdFromFolder(const std::string& folder_path,
580 int* zone_id) {
581 std::string map_zone_id_folder;
582 if (cyber::common::DirectoryExists(folder_path + "/map/000/north")) {
583 map_zone_id_folder = folder_path + "/map/000/north";
584 } else if (cyber::common::DirectoryExists(folder_path + "/map/000/south")) {
585 map_zone_id_folder = folder_path + "/map/000/south";
586 } else {
587 return false;
588 }
589
590 auto folder_list = cyber::common::ListSubPaths(map_zone_id_folder);
591 for (auto itr = folder_list.begin(); itr != folder_list.end(); ++itr) {
592 *zone_id = std::stoi(*itr);
593 return true;
594 }
595 return false;
596}
597
598bool NDTLocalization::FindNearestOdometryStatus(
599 const double odometry_timestamp, drivers::gnss::InsStat* status) {
600 CHECK_NOTNULL(status);
601
602 std::unique_lock<std::mutex> lock(odometry_status_list_mutex_);
603 auto odometry_status_list = odometry_status_list_;
604 lock.unlock();
605
606 double timestamp_diff_sec = 1e8;
607 auto nearest_itr = odometry_status_list.end();
608 for (auto itr = odometry_status_list.begin();
609 itr != odometry_status_list.end(); ++itr) {
610 double diff = std::abs(itr->header().timestamp_sec() - odometry_timestamp);
611 if (diff < timestamp_diff_sec) {
612 timestamp_diff_sec = diff;
613 nearest_itr = itr;
614 }
615 }
616
617 if (nearest_itr == odometry_status_list.end()) {
618 return false;
619 }
620
621 if (timestamp_diff_sec > odometry_status_time_diff_threshold_) {
622 return false;
623 }
624
625 *status = *nearest_itr;
626 return true;
627}
628
629} // namespace ndt
630} // namespace localization
631} // namespace apollo
static double NowInSeconds()
gets the current time in second.
Definition clock.cc:56
void SetVelodyneExtrinsic(const Eigen::Affine3d &extrinsic)
Set the extrinsic calibration.
bool IsInitialized() const
Is the locator initialized.
void SetMapFolderPath(const std::string folder_path)
Set the map folder.
int Update(unsigned int frame_idx, const Eigen::Affine3d &pose, const LidarFrame &lidar_frame)
Update the histogram filter.
void Init(const Eigen::Affine3d &init_location, unsigned int resolution_id, int zone_id)
Initialize the locator.
void SetOnlineCloudResolution(const float &online_resolution)
Set online cloud resolution.
Eigen::Affine3d GetPose() const
Get the current optimal pose result.
void SetLidarHeight(double height)
Set the lidar height.
double GetFitnessScore() const
Get ndt matching score
Eigen::Affine3d UpdateOdometryPose(double timestamp, const Eigen::Affine3d &novatel_pose)
receive an odometry pose and estimate the output pose according to last lidar pose recorded.
void UpdateLidarPose(double timestamp, const Eigen::Affine3d &locator_pose, const Eigen::Affine3d &novatel_pose)
receive a pair of lidar pose and odometry pose which almost have the same timestame
void LidarCallback(const std::shared_ptr< drivers::PointCloud > &lidar_msg)
receive lidar pointcloud message
void GetLidarLocalization(LocalizationEstimate *lidar_localization) const
get ndt localization result
void OdometryCallback(const std::shared_ptr< localization::Gps > &odometry_msg)
receive odometry message
void OdometryStatusCallback(const std::shared_ptr< drivers::gnss::InsStat > &status_msg)
receive ins status message
void GetLocalizationStatus(LocalizationStatus *localization_status) const
get localization status
void GetLocalization(LocalizationEstimate *localization) const
output localization result
virtual bool canTransform(const std::string &target_frame, const std::string &source_frame, const cyber::Time &target_time, const float timeout_second=0.01f, std::string *errstr=nullptr) const
Test if a transform is possible
Definition buffer.cc:195
int Init()
Constructor for a Buffer object
Definition buffer.cc:38
virtual TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const cyber::Time &time, const float timeout_second=0.01f) const
Get the transform between two frames by frame ID.
Definition buffer.cc:168
The gflags used by localization module
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
EulerAnglesZXY< double > EulerAnglesZXYd
double QuaternionToHeading(const double qw, const double qx, const double qy, const double qz)
Definition quaternion.h:56
bool PathExists(const std::string &path)
Check if the path exists.
Definition file.cc:195
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
std::vector< std::string > ListSubPaths(const std::string &directory_path, const unsigned char d_type)
List sub-paths.
Definition file.cc:353
uint32_t height
Height of point cloud
class register implement
Definition arena_queue.h:37
Contains a number of helper functions related to quaternions.
EIGEN_MAKE_ALIGNED_OPERATOR_NEW double timestamp
optional apollo::common::Quaternion rotation
optional apollo::common::Point3D translation