Apollo  6.0
Open source self driving car software
i_util.h
Go to the documentation of this file.
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 
24 namespace apollo {
25 namespace perception {
26 namespace common {
27 
28 template <typename T>
29 inline 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 
55 template <typename T>
56 inline 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.
102 template <typename T>
103 inline 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.
110 template <typename T>
111 inline 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.
120 template <typename T>
121 inline 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 ]
136 template <typename T>
137 inline 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
149 template <typename T>
150 inline 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.
163 template <typename T>
164 inline 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.
172 template <typename T>
173 inline 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.
196 template <typename T>
197 inline 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 common
214 } // namespace perception
215 } // namespace apollo
void IZero3(T a[3])
Definition: i_blas.h:334
void IBackprojectThroughKRt(const T *x, const T *K, const T *R, const T *t, T depth, T *X)
Definition: i_util.h:173
T IL2Norm3(const T x[3])
Definition: i_blas.h:2812
void IProjectThroughKRt(const T *K, const T *R, const T *t, const T *X, T *x)
Definition: i_util.h:121
PlanningContext is the runtime context in planning. It is persistent across multiple frames...
Definition: atomic_hash_map.h:25
void IAdd3(const T x[3], const T y[3], T z[3])
Definition: i_blas.h:808
float IRec(float a)
Definition: i_basic.h:69
const size_t A
Definition: util.h:160
void IProjectThroughExtrinsic(const T *R, const T *t, const T *X, T *x)
Definition: i_util.h:103
void IUnprojectThroughIntrinsic(const T *K, const T *x, T *X)
Definition: i_util.h:137
void IProjectThroughIntrinsic(const T *K, const T *X, T *x)
Definition: i_util.h:111
void IEigSymmetric3x3Closed(const T *A, T *EV, T *Q)
Definition: i_util.h:56
void ISub3(const T x[3], const T y[3], T z[3])
Definition: i_blas.h:1405
float IDiv(float a, float b)
Definition: i_basic.h:35
void IMultAx3x3(const T A[9], const T x[3], T Ax[3])
Definition: i_blas.h:4358
bool IPointInFrontOfCamera(const T *X, const T *cop, const T *prv)
Definition: i_util.h:150
T IDot3(const T x[3], const T y[3])
Definition: i_blas.h:2260
bool IBackprojectPlaneIntersectionCanonical(const T *x, const T *K, const T *pi, T *X)
Definition: i_util.h:197
void IScale3(T x[3], T sf)
Definition: i_blas.h:1868
void IBackprojectCanonical(const T *x, const T *K, T depth, T *X)
Definition: i_util.h:164
void IEigSymmetric2x2Closed(const T *A, T *EV, T *Q)
Definition: i_util.h:29