Apollo 11.0
自动驾驶开放平台
plane_motion.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
19#include <limits>
20#include <list>
21
22#include "cyber/common/log.h"
23
24namespace apollo {
25namespace perception {
26namespace camera {
27
30 if (mat_motion_sensor_.rows() == 3 && mat_motion_sensor_.cols() == 3) {
31 is_3d_motion_ = false;
32 } else if (mat_motion_sensor_.rows() == 4 && mat_motion_sensor_.cols() == 4) {
33 is_3d_motion_ = true;
34 } else {
35 AERROR << "Unknow motion matrix size : " << mat_motion_sensor_.rows() << " "
36 << mat_motion_sensor_.cols();
37 }
38}
39
41 if (mot_buffer_ != nullptr) {
42 mot_buffer_->clear();
43 mot_buffer_ = nullptr;
44 }
45}
46
47// Generate the inverse motion for past trajectory
48void PlaneMotion::generate_motion_matrix(base::VehicleStatus *vehicledata) {
49 float time_d = static_cast<float>(vehicledata->time_d);
50 if (!is_3d_motion_) {
51 base::MotionType motion_2d = base::MotionType::Identity();
52 float theta = time_d * vehicledata->yaw_rate;
53 Eigen::Rotation2Df rot2d(theta);
54 Eigen::Vector2f trans;
55 float velocity = static_cast<float>(
56 sqrt(vehicledata->velocity_x * vehicledata->velocity_x +
57 vehicledata->velocity_y * vehicledata->velocity_y));
58 float displacement = time_d * velocity;
59 trans(0) = static_cast<float>(displacement * cos(theta));
60 trans(1) = static_cast<float>(displacement * sin(theta));
61 // trans(0) = time_d * vehicledata->velocity_x;
62 // trans(1) = time_d * vehicledata->velocity_y;
63
64 motion_2d.block(0, 0, 2, 2) = rot2d.toRotationMatrix().transpose();
65 motion_2d.block(0, 2, 2, 1) = -rot2d.toRotationMatrix().transpose() * trans;
66 ACHECK(vehicledata->motion.rows() == motion_2d.rows());
67 ACHECK(vehicledata->motion.cols() == motion_2d.cols());
68 vehicledata->motion = motion_2d;
69 } else {
70 base::MotionType motion_3d = base::MotionType::Identity();
71 float roll_delta = time_d * vehicledata->roll_rate;
72 float pitch_delta = time_d * vehicledata->pitch_rate;
73 float yaw_delta = time_d * vehicledata->yaw_rate;
74
75 Eigen::AngleAxisf roll_angle(roll_delta, Eigen::Vector3f::UnitX());
76 Eigen::AngleAxisf pitch_angle(pitch_delta, Eigen::Vector3f::UnitY());
77 Eigen::AngleAxisf yaw_angle(yaw_delta, Eigen::Vector3f::UnitZ());
78
79 Eigen::Quaternion<float> q = roll_angle * pitch_angle * yaw_angle;
80 Eigen::Matrix3f rot3d = q.matrix();
81
82 float displacement = time_d * vehicledata->velocity;
83 Eigen::Vector3f trans;
84 trans(0) =
85 static_cast<float>(sqrt(displacement * displacement /
86 (tan(yaw_delta) * tan(yaw_delta) +
87 tan(pitch_delta) * tan(pitch_delta) + 1)));
88 trans(1) = static_cast<float>(tan(yaw_delta) * trans(0));
89 trans(2) = static_cast<float>(tan(pitch_delta) * trans(0));
90
91 motion_3d.block(0, 0, 3, 3) = rot3d.transpose();
92 motion_3d.block(0, 3, 3, 1) = -rot3d.transpose() * trans;
93 ACHECK(vehicledata->motion.rows() == motion_3d.rows());
94 ACHECK(vehicledata->motion.cols() == motion_3d.cols());
95 vehicledata->motion = motion_3d;
96 }
97}
98
99void PlaneMotion::accumulate_motion(const double start_time,
100 const double end_time) {
101 // accumulate CAN+IMU / Localization motion
102 auto iter = raw_motion_queue_.begin();
103 for (; iter != raw_motion_queue_.end() && iter->time_ts <= end_time; ++iter) {
104 if (iter->time_ts < start_time) {
105 continue;
106 }
107 mat_motion_sensor_ *= iter->motion;
108 time_difference_ += static_cast<float>(iter->time_d);
109 }
110 // clean raw_motion_queue useless history
111 while (raw_motion_queue_.begin() != iter) {
112 raw_motion_queue_.pop_front();
113 }
114}
115
116void PlaneMotion::update_motion_buffer(const base::VehicleStatus &vehicledata,
117 const double pre_image_timestamp,
118 const double image_timestamp) {
119 std::lock_guard<std::mutex> lock(mutex_);
120 // compute the projection from pevious frames to the last frame
121 for (size_t k = 0; k < mot_buffer_->size(); ++k) {
122 mot_buffer_->at(k).motion *= mat_motion_sensor_;
123 }
124
125 // set time_diff as image_time_diff
126 time_difference_ = static_cast<float>(image_timestamp - pre_image_timestamp);
127
128 // a new motion between images
129 mot_buffer_->push_back(vehicledata);
130 mot_buffer_->back().time_d = time_difference_;
131 // update motion
132 mot_buffer_->back().motion = mat_motion_sensor_;
133 mot_buffer_->back().time_ts = image_timestamp;
134 // reset motion buffer
135 mat_motion_sensor_ =
136 base::MotionType::Identity(); // reset image accumulated motion
137 time_difference_ = 0.0f; // reset the accumulated time difference
138}
139
142 std::lock_guard<std::mutex> lock(mutex_);
143 ADEBUG << "mot_buffer_->size(): " << mot_buffer_->size();
144
145 for (auto rit = mot_buffer_->rbegin(); rit != mot_buffer_->rend(); ++rit) {
146 if (std::abs(rit->time_ts - timestamp) <
147 std::numeric_limits<double>::epsilon()) {
148 *vs = *rit;
149 return true;
150 }
151 }
152 return false;
153}
154
156 std::lock_guard<std::mutex> lock(mutex_);
157 return *mot_buffer_;
158}
159
160void PlaneMotion::add_new_motion(double pre_image_timestamp,
161 double image_timestamp,
162 int motion_operation_flag,
163 base::VehicleStatus *vehicledata) {
164 while (!raw_motion_queue_.empty() &&
165 vehicledata->time_ts < raw_motion_queue_.back().time_ts) {
166 raw_motion_queue_.pop_back();
167 ADEBUG << "pop ts : back ts" << vehicledata->time_ts << " "
168 << raw_motion_queue_.back().time_ts << " "
169 << raw_motion_queue_.size();
170 }
171
172 if (motion_operation_flag != RESET) {
173 generate_motion_matrix(vehicledata);
174 raw_motion_queue_.push_back(*vehicledata);
175 if (static_cast<int>(raw_motion_queue_.size()) > buffer_size_ * 10) {
176 AWARN << "MotionQueue is too large, try sync motion/image timestep";
177 }
178
179 switch (motion_operation_flag) {
180 case ACCUM_MOTION:
181 // do nothing
182 break;
184 accumulate_motion(pre_image_timestamp, image_timestamp);
185 update_motion_buffer(*vehicledata, pre_image_timestamp,
186 image_timestamp);
187 break;
188 default:
189 AERROR << "motion operation flag:wrong type";
190 return;
191 }
192 } else {
193 mot_buffer_->clear();
194 vehicledata->time_d = 0;
195 vehicledata->time_ts = image_timestamp;
196 vehicledata->motion = base::MotionType::Identity();
197 mot_buffer_->push_back(*vehicledata);
198 ADEBUG << "pop and rest raw_buffer, mot_buffer: "
199 << raw_motion_queue_.size();
200 }
201}
202} // namespace camera
203} // namespace perception
204} // namespace apollo
bool find_motion_with_timestamp(double timestamp, base::VehicleStatus *vs)
void add_new_motion(double pre_image_timestamp, double image_timestamp, int motion_operation_flag, base::VehicleStatus *vehicledata)
#define ACHECK(cond)
Definition log.h:80
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AWARN
Definition log.h:43
boost::circular_buffer< VehicleStatus > MotionBuffer
class register implement
Definition arena_queue.h:37