Apollo 10.0
自动驾驶开放平台
i_util.h
浏览该文件的文档.
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#pragma once
17
18#include <utility>
19
20#include "Eigen/Dense"
21
23
24namespace apollo {
25namespace perception {
26namespace algorithm {
27
28template <typename T>
29inline void IEigSymmetric2x2Closed(const T *A, T *EV, T *Q) {
30 if (A == nullptr) {
31 return;
32 }
33 Eigen::Matrix<T, 2, 2> a;
34 a << A[0], A[1], A[2], A[3];
35 Eigen::SelfAdjointEigenSolver<Eigen::Matrix<T, 2, 2>> es(a);
36 if (es.info() != Eigen::Success) {
37 return;
38 }
39
40 Eigen::Matrix<T, 2, 1> D = es.eigenvalues();
41 Eigen::Matrix<T, 2, 2> V = es.eigenvectors();
42 if (fabs(D(0, 0)) < fabs(D(1, 0))) {
43 std::swap(D(0, 0), D(1, 0));
44 std::swap(V(0, 0), V(0, 1));
45 std::swap(V(1, 0), V(1, 1));
46 }
47 EV[0] = D(0, 0);
48 EV[1] = D(1, 0);
49 Q[0] = V(0, 0);
50 Q[1] = V(0, 1);
51 Q[2] = V(1, 0);
52 Q[3] = V(1, 1);
53}
54
55template <typename T>
56inline void IEigSymmetric3x3Closed(const T *A, T *EV, T *Q) {
57 if (A == nullptr) {
58 return;
59 }
60 Eigen::Matrix<T, 3, 3> a;
61 a << A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[8];
62 Eigen::SelfAdjointEigenSolver<Eigen::Matrix<T, 3, 3>> es(a);
63 if (es.info() != Eigen::Success) {
64 return;
65 }
66 Eigen::Matrix<T, 3, 1> D = es.eigenvalues();
67 Eigen::Matrix<T, 3, 3> V = es.eigenvectors();
68 if (fabs(D(1, 0)) < fabs(D(2, 0))) {
69 std::swap(D(1, 0), D(2, 0));
70 for (int i = 0; i < 3; ++i) {
71 std::swap(V(i, 1), V(i, 2));
72 }
73 }
74 if (fabs(D(0, 0)) < fabs(D(1, 0))) {
75 std::swap(D(0, 0), D(1, 0));
76 for (int i = 0; i < 3; ++i) {
77 std::swap(V(i, 0), V(i, 1));
78 }
79 }
80 if (fabs(D(1, 0)) < fabs(D(2, 0))) {
81 std::swap(D(1, 0), D(2, 0));
82 for (int i = 0; i < 3; ++i) {
83 std::swap(V(i, 1), V(i, 2));
84 }
85 }
86
87 EV[0] = D(0, 0);
88 EV[1] = D(1, 0);
89 EV[2] = D(2, 0);
90 Q[0] = V(0, 0);
91 Q[1] = V(0, 1);
92 Q[2] = V(0, 2);
93 Q[3] = V(1, 0);
94 Q[4] = V(1, 1);
95 Q[5] = V(1, 2);
96 Q[6] = V(2, 0);
97 Q[7] = V(2, 1);
98 Q[8] = V(2, 2);
99}
100
101// Compute x=[R|t]*X, assuming R is 3x3 rotation matrix and t is a 3-vector.
102template <typename T>
103inline void IProjectThroughExtrinsic(const T *R, const T *t, const T *X, T *x) {
104 IMultAx3x3(R, X, x);
105 IAdd3(t, x);
106}
107
108// Compute x=K*X, assuming K is 3x3 upper triangular with K[8] = 1.0, do not
109// consider radial distortion.
110template <typename T>
111inline void IProjectThroughIntrinsic(const T *K, const T *X, T *x) {
112 x[0] = K[0] * X[0] + K[1] * X[1] + K[2] * X[2];
113 x[1] = K[4] * X[1] + K[5] * X[2];
114 x[2] = X[2];
115}
116
117// Compute x=K[R|t]*X, assuming K is 3x3 upper triangular with K[8] = 1.0,
118// assuming R is 3x3 rotation matrix and t is a 3-vector, do not consider
119// radial distortion.
120template <typename T>
121inline void IProjectThroughKRt(const T *K, const T *R, const T *t, const T *X,
122 T *x) {
123 T Rtx[3];
124 IProjectThroughExtrinsic(R, t, X, Rtx);
125 IProjectThroughIntrinsic(K, Rtx, x);
126}
127
128// If K is
129// [fx s cx]
130// [0 fy cy]
131// [0 0 1]
132// then K^-1 is
133// [1/fx -s/(fy*fx) s*cy/(fy*fx)-cx/fx]
134// [0 1/fy -cy/fy ]
135// [0 0 1 ]
136template <typename T>
137inline void IUnprojectThroughIntrinsic(const T *K, const T *x, T *X) {
138 T fx_rec = IRec(K[0]);
139 T fy_rec = IRec(K[4]);
140 T fxfy_rec = IRec(K[0] * K[4]);
141 X[0] = fx_rec * x[0] - (K[1] * fxfy_rec) * x[1] +
142 (K[1] * K[5] * fxfy_rec - K[2] * fx_rec) * x[2];
143 X[1] = fy_rec * x[1] - (K[5] * fy_rec) * x[2];
144 X[2] = x[2];
145}
146
147// Check if a point X is in front of the camera, first argument is the center
148// of projection, second is the principal ray (axis) vector
149template <typename T>
150inline bool IPointInFrontOfCamera(const T *X, const T *cop, const T *prv) {
151 T Xmcop[3], v_norm;
152 ISub3(X, cop, Xmcop);
153 v_norm = IL2Norm3(Xmcop);
154 if (v_norm == static_cast<T>(0.0)) {
155 return false; // X is the cop
156 }
157 IScale3(Xmcop, IRec(v_norm));
158 return IDot3(Xmcop, prv) > static_cast<T>(0.0);
159}
160
161// Back project a 2D point x to 3D X given it's depth Z. Assume the camera is
162// canonical K[I|0], K with 0 skew.
163template <typename T>
164inline void IBackprojectCanonical(const T *x, const T *K, T depth, T *X) {
165 X[0] = (x[0] - K[2]) * depth * IRec(K[0]);
166 X[1] = (x[1] - K[5]) * depth * IRec(K[4]);
167 X[2] = depth;
168}
169
170// Back project a 2D point x to 3D X given it's depth Z. Assume the camera is
171// * K[R|t], K with 0 skew.
172template <typename T>
173inline void IBackprojectThroughKRt(const T *x, const T *K, const T *R,
174 const T *t, T depth, T *X) {
175 // K^-1*[u,v,1]':
176 T u = (x[0] - K[2]) * IRec(K[0]);
177 T v = (x[1] - K[5]) * IRec(K[4]);
178 // R^-1*K^-1*[u,v,1]':
179 T ru = R[0] * u + R[3] * v + R[6];
180 T rv = R[1] * u + R[4] * v + R[7];
181 T rw = R[2] * u + R[5] * v + R[8];
182 // R^-1*t:
183 T tu = R[0] * t[0] + R[3] * t[1] + R[6] * t[2];
184 T tv = R[1] * t[0] + R[4] * t[1] + R[7] * t[2];
185 T tw = R[2] * t[0] + R[5] * t[1] + R[8] * t[2];
186 T w = IDiv(depth + tw, rw); // scale factor
187 X[0] = ru * w - tu;
188 X[1] = rv * w - tv;
189 X[2] = depth;
190}
191
192// Back project a 2D point x to 3D X given a plane equation pi in 3D. Assume
193// the camera is canonical K[I|0] (K with 0 skew) and the point X lies on plane
194// pi. The routine returns true if there is a valid intersection, otherwise
195// (e.g., ray is nearly parallel to plane) returns false.
196template <typename T>
197inline bool IBackprojectPlaneIntersectionCanonical(const T *x, const T *K,
198 const T *pi, T *X) {
199 IZero3(X);
200 T umcx = IDiv(x[0] - K[2], K[0]);
201 T vmcy = IDiv(x[1] - K[5], K[4]);
202 T sf = pi[0] * umcx + pi[1] * vmcy + pi[2];
203 if (sf == static_cast<T>(0.0)) {
204 return false;
205 }
206 T Z = -pi[3] / sf;
207 X[0] = Z * umcx;
208 X[1] = Z * vmcy;
209 X[2] = Z;
210 return Z > static_cast<T>(0.0);
211}
212
213} // namespace algorithm
214} // namespace perception
215} // namespace apollo
void IEigSymmetric2x2Closed(const T *A, T *EV, T *Q)
Definition i_util.h:29
void IProjectThroughExtrinsic(const T *R, const T *t, const T *X, T *x)
Definition i_util.h:103
bool IPointInFrontOfCamera(const T *X, const T *cop, const T *prv)
Definition i_util.h:150
void IBackprojectThroughKRt(const T *x, const T *K, const T *R, const T *t, T depth, T *X)
Definition i_util.h:173
void IMultAx3x3(const T A[9], const T x[3], T Ax[3])
Definition i_blas.h:4358
void IUnprojectThroughIntrinsic(const T *K, const T *x, T *X)
Definition i_util.h:137
bool IBackprojectPlaneIntersectionCanonical(const T *x, const T *K, const T *pi, T *X)
Definition i_util.h:197
float IDiv(float a, float b)
Definition i_basic.h:35
void IProjectThroughKRt(const T *K, const T *R, const T *t, const T *X, T *x)
Definition i_util.h:121
void IBackprojectCanonical(const T *x, const T *K, T depth, T *X)
Definition i_util.h:164
void IScale3(T x[3], T sf)
Definition i_blas.h:1868
void IAdd3(const T x[3], const T y[3], T z[3])
Definition i_blas.h:808
T IL2Norm3(const T x[3])
Definition i_blas.h:2812
void IEigSymmetric3x3Closed(const T *A, T *EV, T *Q)
Definition i_util.h:56
void IProjectThroughIntrinsic(const T *K, const T *X, T *x)
Definition i_util.h:111
T IDot3(const T x[3], const T y[3])
Definition i_blas.h:2260
void ISub3(const T x[3], const T y[3], T z[3])
Definition i_blas.h:1405
class register implement
Definition arena_queue.h:37