Apollo 10.0
自动驾驶开放平台
localization_pose_buffer.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 <iomanip>
20
21#include "Eigen/Dense"
22
23#include "cyber/common/log.h"
25
26namespace apollo {
27namespace localization {
28namespace ndt {
29
30const unsigned int LocalizationPoseBuffer::s_buffer_size_ = 20;
31
33 lidar_poses_.resize(s_buffer_size_);
34 used_buffer_size_ = 0;
35 head_index_ = 0;
36 has_initialized_ = false;
37}
38
40
42 double timestamp, const Eigen::Affine3d& locator_pose,
43 const Eigen::Affine3d& novatel_pose) {
44 if (!has_initialized_) {
45 lidar_poses_[head_index_].locator_pose = locator_pose;
46 lidar_poses_[head_index_].locator_pose.linear() = novatel_pose.linear();
47 lidar_poses_[head_index_].novatel_pose = novatel_pose;
48 lidar_poses_[head_index_].timestamp = timestamp;
49 ++used_buffer_size_;
50 has_initialized_ = true;
51 } else {
52 // add 10Hz pose
53 unsigned int empty_position =
54 (head_index_ + used_buffer_size_) % s_buffer_size_;
55 lidar_poses_[empty_position].locator_pose = locator_pose;
56 lidar_poses_[empty_position].novatel_pose = novatel_pose;
57 lidar_poses_[empty_position].timestamp = timestamp;
58
59 if (used_buffer_size_ == s_buffer_size_) {
60 head_index_ = (head_index_ + 1) % s_buffer_size_;
61 } else {
62 ++used_buffer_size_;
63 }
64 }
65}
66
68 double timestamp, const Eigen::Affine3d& novatel_pose) {
69 Eigen::Affine3d pose = novatel_pose;
70 if (used_buffer_size_ > 0) {
71 pose.translation()[0] = 0;
72 pose.translation()[1] = 0;
73 pose.translation()[2] = 0;
74 Eigen::Affine3d predict_pose;
75 double weight = 0.0;
76
77 Eigen::Quaterniond novatel_quat(novatel_pose.linear());
78 novatel_quat.normalize();
80 novatel_quat.w(), novatel_quat.x(), novatel_quat.y(), novatel_quat.z());
81 Eigen::Vector3d pose_ev;
82 pose_ev[0] = 0;
83 pose_ev[1] = 0;
84 pose_ev[2] = 0;
85
86 for (unsigned int c = 0, i = head_index_; c < used_buffer_size_;
87 ++c, i = (i + 1) % s_buffer_size_) {
88 predict_pose.translation() = lidar_poses_[i].locator_pose.translation() -
89 lidar_poses_[i].novatel_pose.translation() +
90 novatel_pose.translation();
91 pose.translation() += predict_pose.translation();
92
93 Eigen::Quaterniond pair_locator_quat(
94 lidar_poses_[i].locator_pose.linear());
95 pair_locator_quat.normalize();
96 Eigen::Quaterniond pair_novatel_quat(
97 lidar_poses_[i].novatel_pose.linear());
98 pair_novatel_quat.normalize();
99 Eigen::Quaterniond predict_pose_quat =
100 pair_locator_quat * pair_novatel_quat.inverse() * novatel_quat;
101 predict_pose_quat.normalized();
102
103 common::math::EulerAnglesZXYd predict_pose_ev(
104 predict_pose_quat.w(), predict_pose_quat.x(), predict_pose_quat.y(),
105 predict_pose_quat.z());
106 double predict_yaw = predict_pose_ev.yaw();
107 if (novatel_ev.yaw() > 0) {
108 if (novatel_ev.yaw() - predict_pose_ev.yaw() > M_PI) {
109 predict_yaw = predict_pose_ev.yaw() + M_PI * 2.0;
110 }
111 } else {
112 if (predict_pose_ev.yaw() - novatel_ev.yaw() > M_PI) {
113 predict_yaw = predict_pose_ev.yaw() - M_PI * 2.0;
114 }
115 }
116 pose_ev[2] += predict_yaw;
117 weight += 1;
118 }
119 pose.translation() *= (1.0 / weight);
120 pose_ev[0] = novatel_ev.pitch();
121 pose_ev[1] = novatel_ev.roll();
122 pose_ev[2] *= (1.0 / weight);
123 if (std::abs(pose_ev[2]) > M_PI) {
124 if (pose_ev[2] > 0) {
125 pose_ev[2] -= 2.0 * M_PI;
126 } else {
127 pose_ev[2] += 2.0 * M_PI;
128 }
129 }
130 common::math::EulerAnglesZXYd pose_euler(pose_ev[1], pose_ev[0],
131 pose_ev[2]);
132 Eigen::Quaterniond tmp_qbn = pose_euler.ToQuaternion();
133 tmp_qbn.normalize();
134 pose.linear() = tmp_qbn.toRotationMatrix();
135 }
136 return pose;
137}
138
139} // namespace ndt
140} // namespace localization
141} // namespace apollo
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
Defines the EulerAnglesZXY class.
EulerAnglesZXY< double > EulerAnglesZXYd
class register implement
Definition arena_queue.h:37