Apollo 11.0
自动驾驶开放平台
transform_server.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 *****************************************************************************/
17
18#include "cyber/common/log.h"
20#include "yaml-cpp/yaml.h"
21
22namespace apollo {
23namespace perception {
24namespace camera {
25
26bool TransformServer::Init(const std::vector<std::string> &camera_names,
27 const std::string &params_path) {
28 const std::string params_dir = params_path;
29 // 1. Init lidar height
30 try {
31 YAML::Node lidar_height =
32 YAML::LoadFile(params_dir + "/" + "velodyne128_height.yaml");
33 Eigen::Affine3d trans;
34 trans.linear() = Eigen::Matrix3d::Identity();
35 AINFO << trans.translation() << " "
36 << lidar_height["vehicle"]["parameters"]["height"];
37 trans.translation() << 0.0, 0.0,
38 lidar_height["vehicle"]["parameters"]["height"].as<double>();
39 AddTransform("velodyne128", "ground", trans);
40 } catch (YAML::InvalidNode &in) {
41 AERROR << "load velodyne128 extrisic file error"
42 << " YAML::InvalidNode exception";
43 return false;
44 } catch (YAML::TypedBadConversion<float> &bc) {
45 AERROR << "load velodyne128 extrisic file error, "
46 << "YAML::TypedBadConversion exception";
47 return false;
48 } catch (YAML::Exception &e) {
49 AERROR << "load velodyne128 extrisic file "
50 << " error, YAML exception:" << e.what();
51 return false;
52 }
53 // 2. Init lidar and camera extrinsic
54 std::vector<std::string> extrinsic_filelist;
55 extrinsic_filelist.push_back(params_dir +
56 "/velodyne128_novatel_extrinsics.yaml");
57 for (const auto &camera_name : camera_names) {
58 extrinsic_filelist.push_back(params_dir + "/" + camera_name +
59 "_extrinsics.yaml");
60 }
61
62 for (const auto &yaml_file : extrinsic_filelist) {
63 try {
64 YAML::Node node = YAML::LoadFile(yaml_file);
65 if (node.IsNull()) {
66 AINFO << "Load " << yaml_file << " failed! please check!";
67 return false;
68 }
69 std::string child_frame_id = node["child_frame_id"].as<std::string>();
70 std::string frame_id = node["header"]["frame_id"].as<std::string>();
71 double q[4] = {node["transform"]["rotation"]["w"].as<double>(),
72 node["transform"]["rotation"]["x"].as<double>(),
73 node["transform"]["rotation"]["y"].as<double>(),
74 node["transform"]["rotation"]["z"].as<double>()};
75 double t[3] = {node["transform"]["translation"]["x"].as<double>(),
76 node["transform"]["translation"]["y"].as<double>(),
77 node["transform"]["translation"]["z"].as<double>()};
78 Eigen::Quaterniond qq(q[0], q[1], q[2], q[3]);
79 Eigen::Affine3d trans;
80 trans.linear() = qq.matrix();
81 trans.translation() << t[0], t[1], t[2];
82 if (!AddTransform(child_frame_id, frame_id, trans)) {
83 AINFO << "failed to add transform from " << child_frame_id << " to "
84 << frame_id << std::endl;
85 }
86 } catch (YAML::InvalidNode &in) {
87 AERROR << "load camera extrisic file " << yaml_file
88 << " with error, YAML::InvalidNode exception";
89 return false;
90 } catch (YAML::TypedBadConversion<double> &bc) {
91 AERROR << "load camera extrisic file " << yaml_file
92 << " with error, YAML::TypedBadConversion exception";
93 return false;
94 } catch (YAML::Exception &e) {
95 AERROR << "load camera extrisic file " << yaml_file
96 << " with error, YAML exception:" << e.what();
97 return false;
98 }
99 }
100 return true;
101}
102
103bool TransformServer::LoadFromFile(const std::string &tf_input,
104 float frequency) {
105 if (frequency <= 0) {
106 AERROR << "Error frequency value:" << frequency;
107 return false;
108 }
109 std::ifstream fin(tf_input);
110 Transform tf;
111 int64_t ts;
112 while (fin >> ts) {
113 tf.timestamp = static_cast<double>(ts) * 1e-9;
114 fin >> tf.tx;
115 fin >> tf.ty;
116 fin >> tf.tz;
117 fin >> tf.qx;
118 fin >> tf.qy;
119 fin >> tf.qz;
120 fin >> tf.qw;
121 tf_.push_back(tf);
122 }
123 fin.close();
124 error_limit_ = 1 / frequency / 2.0f;
125 AINFO << "Load tf successfully. count: " << tf_.size()
126 << " error limit:" << error_limit_;
127 return true;
128}
129
130bool TransformServer::QueryPos(double timestamp, Eigen::Affine3d *pose) {
131 for (auto &&tf : tf_) {
132 if (Equal(timestamp, tf.timestamp, error_limit_)) {
133 Eigen::Quaterniond rotation(tf.qw, tf.qx, tf.qy, tf.qz);
134 pose->linear() = rotation.matrix();
135 pose->translation() << tf.tx, tf.ty, tf.tz;
136 AINFO << "Get Pose:\n" << pose->matrix();
137 return true;
138 }
139 }
140 return false;
141}
142
143bool TransformServer::AddTransform(const std::string &child_frame_id,
144 const std::string &frame_id,
145 const Eigen::Affine3d &transform) {
146 vertices_.insert(child_frame_id);
147 vertices_.insert(frame_id);
148
149 auto begin = edges_.lower_bound(child_frame_id);
150 auto end = edges_.upper_bound(child_frame_id);
151
152 for (auto iter = begin; iter != end; ++iter) {
153 if (iter->second.frame_id == frame_id) {
154 return false;
155 }
156 }
157
158 Edge e;
159 e.child_frame_id = child_frame_id;
160 e.frame_id = frame_id;
161 e.transform = transform;
162
163 Edge e_inv;
164 e_inv.child_frame_id = frame_id;
165 e_inv.frame_id = child_frame_id;
166 e_inv.transform = transform.inverse();
167 ADEBUG << "Add transform between " << frame_id << " and " << child_frame_id;
168 edges_.insert({child_frame_id, e});
169 edges_.insert({frame_id, e_inv});
170
171 return true;
172}
173
174bool TransformServer::QueryTransform(const std::string &child_frame_id,
175 const std::string &frame_id,
176 Eigen::Affine3d *transform) {
177 *transform = Eigen::Affine3d::Identity();
178
179 if (child_frame_id == frame_id) {
180 return true;
181 }
182
183 // Vertices does not exist
184 if (vertices_.find(child_frame_id) == vertices_.end() ||
185 vertices_.find(frame_id) == vertices_.end()) {
186 return false;
187 }
188
189 std::map<std::string, bool> visited;
190 for (const auto &item : vertices_) {
191 visited[item] = false;
192 }
193
194 return FindTransform(child_frame_id, frame_id, transform, &visited);
195}
196
197bool TransformServer::FindTransform(const std::string &child_frame_id,
198 const std::string &frame_id,
199 Eigen::Affine3d *transform,
200 std::map<std::string, bool> *visited) {
201 Eigen::Affine3d loc_transform = Eigen::Affine3d::Identity();
202
203 auto begin = edges_.lower_bound(child_frame_id);
204 auto end = edges_.upper_bound(child_frame_id);
205
206 (*visited)[child_frame_id] = true;
207 for (auto iter = begin; iter != end; ++iter) {
208 auto &edge = iter->second;
209 if ((*visited)[edge.frame_id]) {
210 continue;
211 }
212
213 ADEBUG << "from " << edge.child_frame_id << " to " << edge.frame_id
214 << std::endl;
215
216 loc_transform = edge.transform * loc_transform;
217
218 if (edge.frame_id == frame_id) {
219 *transform = loc_transform;
220 return true;
221 }
222
223 Eigen::Affine3d tr = Eigen::Affine3d::Identity();
224 if (FindTransform(edge.frame_id, frame_id, &tr, visited)) {
225 loc_transform = tr * loc_transform;
226 *transform = loc_transform;
227 return true;
228 }
229
230 loc_transform = edge.transform.inverse() * loc_transform;
231 }
232 return false;
233}
234
236 for (auto item : edges_) {
237 AINFO << "----------------" << std::endl;
238 AINFO << item.first << std::endl;
239 AINFO << "edge: " << std::endl;
240 AINFO << "from " << item.second.child_frame_id << " to "
241 << item.second.frame_id << std::endl;
242 Eigen::Affine3d trans = item.second.transform;
243 Eigen::Quaterniond quat(trans.linear());
244 AINFO << "rot: " << quat.x() << " " << quat.y() << " " << quat.z() << " "
245 << quat.w() << std::endl;
246 AINFO << "trans: " << trans.translation()[0] << " "
247 << trans.translation()[1] << " " << trans.translation()[2]
248 << std::endl;
249 }
250}
251
252} // namespace camera
253} // namespace perception
254} // namespace apollo
bool AddTransform(const std::string &child_frame_id, const std::string &frame_id, const Eigen::Affine3d &transform)
bool LoadFromFile(const std::string &tf_input, float frequency=200.0f)
bool QueryTransform(const std::string &child_frame_id, const std::string &frame_id, Eigen::Affine3d *transform)
bool QueryPos(double timestamp, Eigen::Affine3d *pose)
bool Init(const std::vector< std::string > &camera_names, const std::string &params_path)
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
bool Equal(double x, double target, double eps)
Definition util.cc:24
class register implement
Definition arena_queue.h:37