Apollo 11.0
自动驾驶开放平台
i_plane.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
23
24namespace apollo {
25namespace perception {
26namespace algorithm {
27// General plane equation pi: ax+by+cz+d = 0
28
29// Another 3D Plane Data structure:
30template <typename T>
31struct PlanePara {
33 ICopy4(pi.p, p);
34 ICopy3(pi.t, t);
36 }
38 ICopy4(pi.p, this->p);
39 ICopy3(pi.t, this->t);
40 ICopy2(pi.data_stat, this->data_stat);
41 return (*this);
42 }
43 // first 3 elements: normal with unit norm, last elemet: d
44 T p[4];
45 T t[3]; // centroid
46 // mean distance and standard deviation of
47 // the point to plane distance distribution
49 void Clear() {
50 IZero4(p);
51 IZero3(t);
53 }
54 void Assign(const T *pi) {
55 ICopy4(pi, p);
56 ICopy3(pi + 4, t);
57 ICopy2(pi + 7, data_stat);
58 }
59 bool IsValid() { return (ISqrt(IQquaresum3(p)) > static_cast<T>(0)); }
61};
62
63// Compute the projection (q) of a 3D point (p) on a plane (pi) in 3D space
64template <typename T>
65inline void IPointOnPlaneProjection(const T *pi, const T *p, T *q) {
66 T npi[4];
67 ICopy4(pi, npi);
68 T sf = IRec(IL2Norm3(npi));
69 IScale4(npi, sf); // plane with unit norm
70 sf = -(IDot3(npi, p) + npi[3]);
71 q[0] = p[0] + sf * npi[0];
72 q[1] = p[1] + sf * npi[1];
73 q[2] = p[2] + sf * npi[2];
74}
75
76// Measure point to plane distance in 3D space, point p is in inhomogeneous
77// coordinates
78template <typename T>
79inline T IPlaneToPointDistance(const T *pi, const T *p) {
80 return IDiv(IAbs(IDot3(pi, p) + pi[3]), IL2Norm3(pi));
81}
82
83// Measure point to plane distance in 3D space, point p is in inhomogeneous
84// coordinates
85template <typename T>
86inline T IPlaneToPointDistance(const T *pi, const T *p, T l2_norm3_pi) {
87 return IDiv(IAbs(IDot3(pi, p) + pi[3]), l2_norm3_pi);
88}
89
90// Measure point to plane distance in 3D space, point p is in inhomogeneous
91// coordinates
92template <typename T>
93inline T IPlaneToPointDistanceWUnitNorm(const T *pi, const T *p) {
94 return IAbs(IDot3(pi, p) + pi[3]);
95}
96
97// Measure point to plane distance (signed) in 3D space, point p is in
98// inhomogeneous coordinates
99// distance is positive if p is on the same side of the plane pi as the normal
100// vector and negative if it is on the opposite side
101template <typename T>
102inline T IPlaneToPointSignedDistanceWUnitNorm(const T *pi, const T *p) {
103 return IDot3(pi, p) + pi[3];
104}
105
106// Measure point to plane distance in 3D space, point p is in inhomogeneous
107// coordinates
108template <typename T>
109inline T IPlaneToPointDistanceWNormalizedPlaneNorm(const T *pi, const T *p) {
110 return IAbs(IDot3(pi, p) + pi[3]);
111}
112
113// Measure the normal angle in degree between two planes
114template <typename T>
115inline T IPlaneToPlaneNormalDeltaDegreeZUp(const T *pi_p, const T *pi_q) {
116 T normal_p[3], normal_q[3];
117 ICopy3(pi_p, normal_p);
118 ICopy3(pi_q, normal_q);
119
120 // Z is up
121 if (normal_p[2] < static_cast<T>(0.0)) {
122 INeg3(normal_p);
123 }
124 if (normal_q[2] < static_cast<T>(0.0)) {
125 INeg3(normal_q);
126 }
127
128 IScale3(normal_p, IRec(ISqrt(IQquaresum3(normal_p)))); // normalize
129 IScale3(normal_q, IRec(ISqrt(IQquaresum3(normal_q)))); // normalize
130 return IRadiansToDegree(IAcos(IDot3(normal_p, normal_q)));
131}
132
133// Fit a plane pi (ax+by+cz+d = 0): in 3D space using
134// total least square method (Orthogonal Distance Regression). The input n 3D
135// points are in inhomogeneous coordinates. Array X has Size n * 3 and points
136// are stored as[x0,y0, z0, x1, y1, z1, ...].
137// pi is stored as 4 - vector[a, b, c, d]. x will be destroyed after calling
138// this routine.
139template <typename T>
140inline void IPlaneFitTotalLeastSquare(T *X, T *pi, int n) {
141 IZero4(pi);
142 if (n < 3) {
143 return;
144 }
145 int i, j;
146 T mat_a[9], eigv[3], mat_q[9];
147 // compute the centroid of input Data points
148 T xm = static_cast<T>(0.0);
149 T ym = static_cast<T>(0.0);
150 T zm = static_cast<T>(0.0);
151 for (i = 0, j = 0; i < n; i++) {
152 xm += X[j++];
153 ym += X[j++];
154 zm += X[j++];
155 }
156 xm /= static_cast<T>(n);
157 ym /= static_cast<T>(n);
158 zm /= static_cast<T>(n);
159 for (i = 0, j = 0; i < n; i++) {
160 X[j++] -= xm;
161 X[j++] -= ym;
162 X[j++] -= zm;
163 }
164 IMultAtAnx3(X, mat_a, n);
165 IEigSymmetric3x3Closed(mat_a, eigv, mat_q);
166 // pi's normal vector is the eigen vector of
167 // mat_a corresponding to its smallest eigen value
168 pi[0] = mat_q[2];
169 pi[1] = mat_q[5];
170 pi[2] = mat_q[8];
171 // the optimal plane should pass [xm, ym, zm]:
172 pi[3] = -(pi[0] * xm + pi[1] * ym + pi[2] * zm);
173}
174
175// Fit a plane pi (ax+by+cz+d = 0): in 3D space using
176// total least square method (Orthogonal Distance Regression). The input n 3D
177// points are in inhomogeneous coordinates. Array X has Size 3 * 3 and points
178// are stored as[x0, y0, z0, x1, y1, z1, ...].
179// pi is stored as 4 - vector[a, b, c, d]. x will be destroyed after calling
180// this routine.
181template <typename T>
182inline void IPlaneFitTotalLeastSquare3(T *X, T *pi) {
183 T mat_a[9];
184 T eigv[3];
185 T mat_q[9];
186 // compute the centroid of input Data points
187 IZero4(pi);
188 T xm = (X[0] + X[3] + X[6]) / 3;
189 T ym = (X[1] + X[4] + X[7]) / 3;
190 T zm = (X[2] + X[5] + X[8]) / 3;
191 X[0] -= xm;
192 X[1] -= ym;
193 X[2] -= zm;
194 X[3] -= xm;
195 X[4] -= ym;
196 X[5] -= zm;
197 X[6] -= xm;
198 X[7] -= ym;
199 X[8] -= zm;
200 IMultAtA3x3(X, mat_a);
201 IEigSymmetric3x3Closed(mat_a, eigv, mat_q);
202 // pi's normal vector is the eigen vector of
203 // mat_a corresponding to its smallest eigen value
204 pi[0] = mat_q[2];
205 pi[1] = mat_q[5];
206 pi[2] = mat_q[8];
207 // the optimal plane should pass [xm, ym, zm]:
208 pi[3] = -(pi[0] * xm + pi[1] * ym + pi[2] * zm);
209}
210
211// Fit a plane pi: {[a,b,c,d], [x,y,z]} in 3D space using
212// total least square method (Orthogonal Distance Regression). The input n 3D
213// points are in inhomogeneous coordinates. Array X has Size n * 3 and points
214// are stored as[x0, y0, z0, x1, y1, z1, ...].
215// The routine needs n * 3 positions of scratch space in Xp.
216template <typename T>
217inline void IPlaneFitTotalLeastSquare(const T *X, T *pi, int n, T *Xp,
218 T *centroid, T *err_stat) {
219 IZero4(pi);
220 if (centroid != nullptr) {
221 IZero3(centroid);
222 }
223 if (err_stat != nullptr) {
224 IZero2(err_stat);
225 }
226 if (n < 3) {
227 return;
228 }
229
230 int i, j, n3 = n * 3;
231 T mat_a[9], eigv[3], mat_q[9], t[3];
232 // compute the centroid of input Data points
233 T xm = static_cast<T>(0.0);
234 T ym = static_cast<T>(0.0);
235 T zm = static_cast<T>(0.0);
236 for (i = 0, j = 0; i < n; i++) {
237 xm += X[j++];
238 ym += X[j++];
239 zm += X[j++];
240 }
241 t[0] = xm / n;
242 t[1] = ym / n;
243 t[2] = zm / n;
244 for (i = 0; i < n3; i += 3) {
245 ISub3(X + i, t, Xp + i);
246 }
247 IMultAtANx3(Xp, mat_a, n);
248 IEigSymmetric3x3Closed(mat_a, eigv, mat_q);
249 // pi's normal vector is the eigen vector of
250 // mat_a corresponding to its smallest eigen value
251 pi[0] = mat_q[2];
252 pi[1] = mat_q[5];
253 pi[2] = mat_q[8];
254 IUnitize3(pi);
255 // the optimal plane should pass [xm, ym, zm]:
256 pi[3] = -IDot3(pi, t);
257
258 if (centroid != nullptr) {
259 ICopy3(t, centroid);
260 }
261
262 // Data stat:
263 if (err_stat != nullptr) {
264 const T *cptr_data = X;
265 for (i = 0; i < n; ++i) {
266 Xp[i] = IPlaneToPointDistance(pi, cptr_data);
267 cptr_data += 3;
268 }
269 err_stat[0] = IMean(Xp, n); // mean
270 err_stat[1] = ISdv(Xp, err_stat[0], n); // sdv
271 }
272}
273
274// Fit a plane pi (ax+by+cz+d = 0): in 3D space using
275// total least square method (Orthogonal Distance Regression). The input n 3D
276// points are in inhomogeneous coordinates. Array X has Size n * 3 and points
277// are stored as[x0, y0, z0, x1, y1, z1, ...].
278// pi is stored as 4 - vector[a, b, c, d]. x and indices will be destroyed after
279// calling this routine.
280template <typename T>
281inline void IPlaneFitTotalLeastSquare(T *X, int *indices, T *pi, int m, int n) {
282 IZero4(pi);
283 if (n < 3 || n > m) {
284 return;
285 }
286 IIndexedShuffle(X, indices, m, 3, n);
287 int i, j;
288 T mat_a[9], eigv[3], mat_q[9];
289 // compute the centroid of input Data points
290 T xm = static_cast<T>(0.0);
291 T ym = static_cast<T>(0.0);
292 T zm = static_cast<T>(0.0);
293 for (i = 0, j = 0; i < n; i++) {
294 xm += X[j++];
295 ym += X[j++];
296 zm += X[j++];
297 }
298 xm /= n;
299 ym /= n;
300 zm /= n;
301 for (i = 0, j = 0; i < n; i++) {
302 X[j++] -= xm;
303 X[j++] -= ym;
304 X[j++] -= zm;
305 }
306 IMultAtANx3(X, mat_a, n);
307 IEigSymmetric3x3Closed(mat_a, eigv, mat_q);
308 // pi's normal vector is the eigen vector of
309 // mat_a corresponding to its smallest eigen value
310 pi[0] = mat_q[2];
311 pi[1] = mat_q[5];
312 pi[2] = mat_q[8];
313 // the optimal plane should pass [xm, ym, zm]:
314 pi[3] = -(pi[0] * xm + pi[1] * ym + pi[2] * zm);
315}
316
317// Fit a plane pi (ax+by+cz+d = 0): in 3D space using
318// total least square method (Orthogonal Distance Regression). The input n 3D
319// points are in inhomogeneous coordinates. Array X has Size n * 3 and points
320// are stored as[x0, y0, z0, x1, y1, z1, ...].
321// pi is stored as 4 - vector[a, b, c, d]. x and indices will be destroyed after
322// calling this routine.
323template <typename T>
324inline void IPlaneFitTotalLeastSquare(T *X, int *indices, T *pi, T *centroid,
325 int m, int n) {
326 IZero4(pi);
327 if (n < 3 || n > m) {
328 return;
329 }
330 IIndexedShuffle(X, indices, m, 3, n);
331 int i, j;
332 T mat_a[9], eigv[3], mat_q[9];
333 // compute the centroid of input Data points
334 T xm = static_cast<T>(0.0);
335 T ym = static_cast<T>(0.0);
336 T zm = static_cast<T>(0.0);
337 for (i = 0, j = 0; i < n; i++) {
338 xm += X[j++];
339 ym += X[j++];
340 zm += X[j++];
341 }
342 xm /= n;
343 ym /= n;
344 zm /= n;
345 for (i = 0, j = 0; i < n; i++) {
346 X[j++] -= xm;
347 X[j++] -= ym;
348 X[j++] -= zm;
349 }
350 IMultAtANx3(X, mat_a, n);
351 IEigSymmetric3x3Closed(mat_a, eigv, mat_q);
352 // pi's normal vector is the eigen vector of
353 // mat_a corresponding to its smallest eigen value
354 pi[0] = mat_q[2];
355 pi[1] = mat_q[5];
356 pi[2] = mat_q[8];
357 // the optimal plane should pass [xm, ym, zm]:
358 pi[3] = -(pi[0] * xm + pi[1] * ym + pi[2] * zm);
359
360 if (centroid != nullptr) {
361 centroid[0] = xm;
362 centroid[1] = ym;
363 centroid[2] = zm;
364 }
365}
366
367// Fit a plane i: {[a,b,c,d], [x,y,z]} in 3D space using
368// total least square method (Orthogonal Distance Regression). The input n 3D
369// points are in inhomogeneous coordinates. Array X has Size n * 3 and points
370// are stored as[x0, y0, z0, x1, y1, z1, ...].
371template <typename T>
372inline void IPlaneFitTotalLeastSquareAdv(T *X, int *indices, T *para, int m,
373 int n) {
374 IZero9(para);
375 if (n < 3 || n > m) {
376 return;
377 }
378 int i, j;
379 T *xp = IAlloc<T>(n * 3);
380 for (i = 0; i < n; i++) {
381 j = indices[i];
382 ICopy3(X + j * 3, xp + i * 3);
383 }
384 T mat_a[9], eigv[3], mat_q[9];
385 // compute the centroid of input Data points
386 T xm = static_cast<T>(0.0);
387 T ym = static_cast<T>(0.0);
388 T zm = static_cast<T>(0.0);
389 for (i = 0, j = 0; i < n; i++) {
390 xm += xp[j++];
391 ym += xp[j++];
392 zm += xp[j++];
393 }
394 xm /= n;
395 ym /= n;
396 zm /= n;
397 for (i = 0, j = 0; i < n; i++) {
398 xp[j++] -= xm;
399 xp[j++] -= ym;
400 xp[j++] -= zm;
401 }
402 IMultAtANx3(xp, mat_a, n);
403 IEigSymmetric3x3Closed(mat_a, eigv, mat_q);
404 // pi's normal vector is the eigen vector of
405 // mat_a corresponding to its smallest eigen value
406 para[0] = mat_q[2];
407 para[1] = mat_q[5];
408 para[2] = mat_q[8];
409 IUnitize3(para);
410 // the optimal plane should pass [xm, ym, zm]:
411 para[4] = xm;
412 para[5] = ym;
413 para[6] = zm;
414 para[3] = -IDot3(para, para + 4);
415 // Data stat:
416
417 for (i = 0; i < n; ++i) {
418 j = indices[i];
419 xp[i] = IPlaneToPointDistance(para, X + j * 3);
420 }
421 para[7] = IMean(xp, n);
422 para[8] = ISdv(xp, para[7], n);
423 IFree<T>(&xp);
424}
425
426// Fit a plane pi (ax+by+cz+d = 0) with three 3D points in inhomogeneous
427// space - minimal solution
428template <typename T>
429inline void IPlaneFit(const T *X1, const T *X2, const T *X3, T *pi) {
430 T mat_a[9] = {X1[0], X1[1], X1[2], X2[0], X2[1], X2[2], X3[0], X3[1], X3[2]};
431 IPlaneFitTotalLeastSquare(mat_a, pi, 3);
432}
433
434// Fit a plane pi (ax+by+cz+d = 0) with three 3D points in inhomogeneous
435// space - minimal solution
436template <typename T>
437inline void IPlaneFit(const T *Xs, T *pi) {
438 T mat_a[9];
439 ICopy9(Xs, mat_a);
440 IPlaneFitTotalLeastSquare(mat_a, pi, 3);
441}
442
443// Fit a plane pi (ax+by+cz+d = 0) with three 3D points in inhomogeneous
444// space - minimal solution,
445// note that the input Xs will be destroyed
446template <typename T>
447inline void IPlaneFitDestroyed(T *Xs, T *pi) {
449}
450
451// Fit a plane pi: {[a,b,c,d], [x,y,z]} with three 3D points in inhomogeneous
452// space - minimal solution
453template <typename T>
454inline void IPlaneFitAdv(const T *Xs, T *para) {
455 T mat_a[9], mat_ap[9];
456 PlanePara<T> pi;
457 ICopy9(Xs, mat_a);
458 IPlaneFitTotalLeastSquare(mat_a, pi, mat_ap, 3);
459 ICopy4(pi.p, para);
460 ICopy3(pi.t, para + 4);
461 ICopy2(pi.data_stat, para + 7);
462}
463
464} // namespace algorithm
465} // namespace perception
466} // namespace apollo
void IPlaneFitDestroyed(T *Xs, T *pi)
Definition i_plane.h:447
void IPlaneFitAdv(const T *Xs, T *para)
Definition i_plane.h:454
void IPlaneFitTotalLeastSquareAdv(T *X, int *indices, T *para, int m, int n)
Definition i_plane.h:372
float IRadiansToDegree(float r)
Definition i_basic.h:260
T IPlaneToPointDistance(const T *pi, const T *p)
Definition i_plane.h:79
T IMean(const T *x, int n)
Definition i_blas.h:2434
T IPlaneToPointDistanceWNormalizedPlaneNorm(const T *pi, const T *p)
Definition i_plane.h:109
void ICopy9(const T src[9], T dst[9])
Definition i_blas.h:91
void IIndexedShuffle(T *a, int *indices, int n, int element_size, int nr_indexed_elements, bool is_sort_indices=true)
Definition i_sort.h:80
void IPlaneFitTotalLeastSquare3(T *X, T *pi)
Definition i_plane.h:182
void ICopy3(const T src[3], T dst[3])
Definition i_blas.h:40
void IMultAtAnx3(const T *A, T AtA[9], int n)
Definition i_blas.h:4840
T IPlaneToPointDistanceWUnitNorm(const T *pi, const T *p)
Definition i_plane.h:93
float IDiv(float a, float b)
Definition i_basic.h:35
T IPlaneToPointSignedDistanceWUnitNorm(const T *pi, const T *p)
Definition i_plane.h:102
void IMultAtA3x3(const T A[9], T AtA[9])
Definition i_blas.h:4830
void ICopy2(const T src[2], T dst[2])
Definition i_blas.h:35
T IPlaneToPlaneNormalDeltaDegreeZUp(const T *pi_p, const T *pi_q)
Definition i_plane.h:115
void IPlaneFitTotalLeastSquare(T *X, T *pi, int n)
Definition i_plane.h:140
T ISdv(const T *x, T mean, int n)
Definition i_blas.h:2500
void IPlaneFit(const T *X1, const T *X2, const T *X3, T *pi)
Definition i_plane.h:429
void IScale3(T x[3], T sf)
Definition i_blas.h:1868
float IAcos(float alpha)
Definition i_basic.h:239
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 IScale4(T x[4], T sf)
Definition i_blas.h:1874
void ICopy4(const T src[4], T dst[4])
Definition i_blas.h:46
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
void IPointOnPlaneProjection(const T *pi, const T *p, T *q)
Definition i_plane.h:65
class register implement
Definition arena_queue.h:37
PlanePara(const PlanePara< T > &pi)
Definition i_plane.h:32
PlanePara & operator=(const PlanePara< T > &pi)
Definition i_plane.h:37