Nav2 Navigation Stack - rolling  main
ROS 2 Navigation Stack
eig3.c
1 /*
2  * Player - One Hell of a Robot Server
3  * Copyright (C) 2000 Brian Gerkey & Kasper Stoy
4  * gerkey@usc.edu kaspers@robotics.usc.edu
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 /* Eigen decomposition code for symmetric 3x3 matrices, copied from the public
22  domain Java Matrix library JAMA. */
23 
24 #include <math.h>
25 
26 #ifndef MAX
27 #define MAX(a, b) ((a) > (b) ? (a) : (b))
28 #endif
29 
30 #ifdef _MSC_VER
31 #define n 3
32 #else
33 static int n = 3;
34 #endif
35 
36 // Symmetric Householder reduction to tridiagonal form.
37 
38 static void tred2(double V[n][n], double d[n], double e[n])
39 {
40 // This is derived from the Algol procedures tred2 by
41 // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
42 // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
43 // Fortran subroutine in EISPACK.
44 
45  int i, j, k;
46  double f, g, hh;
47  for (j = 0; j < n; j++) {
48  d[j] = V[n - 1][j];
49  }
50 
51  // Householder reduction to tridiagonal form.
52 
53  for (i = n - 1; i > 0; i--) {
54  // Scale to avoid under/overflow.
55 
56  double scale = 0.0;
57  double h = 0.0;
58  for (k = 0; k < i; k++) {
59  scale = scale + fabs(d[k]);
60  }
61  if (scale == 0.0) {
62  e[i] = d[i - 1];
63  for (j = 0; j < i; j++) {
64  d[j] = V[i - 1][j];
65  V[i][j] = 0.0;
66  V[j][i] = 0.0;
67  }
68  } else {
69  // Generate Householder vector.
70  for (k = 0; k < i; k++) {
71  d[k] /= scale;
72  h += d[k] * d[k];
73  }
74  f = d[i - 1];
75  g = sqrt(h);
76  if (f > 0) {
77  g = -g;
78  }
79  e[i] = scale * g;
80  h = h - f * g;
81  d[i - 1] = f - g;
82  for (j = 0; j < i; j++) {
83  e[j] = 0.0;
84  }
85 
86  // Apply similarity transformation to remaining columns.
87 
88  for (j = 0; j < i; j++) {
89  f = d[j];
90  V[j][i] = f;
91  g = e[j] + V[j][j] * f;
92  for (k = j + 1; k <= i - 1; k++) {
93  g += V[k][j] * d[k];
94  e[k] += V[k][j] * f;
95  }
96  e[j] = g;
97  }
98  f = 0.0;
99  for (j = 0; j < i; j++) {
100  e[j] /= h;
101  f += e[j] * d[j];
102  }
103  hh = f / (h + h);
104  for (j = 0; j < i; j++) {
105  e[j] -= hh * d[j];
106  }
107  for (j = 0; j < i; j++) {
108  f = d[j];
109  g = e[j];
110  for (k = j; k <= i - 1; k++) {
111  V[k][j] -= (f * e[k] + g * d[k]);
112  }
113  d[j] = V[i - 1][j];
114  V[i][j] = 0.0;
115  }
116  }
117  d[i] = h;
118  }
119 
120  // Accumulate transformations.
121 
122  for (i = 0; i < n - 1; i++) {
123  V[n - 1][i] = V[i][i];
124  V[i][i] = 1.0;
125  const double h = d[i + 1];
126  if (h != 0.0) {
127  for (k = 0; k <= i; k++) {
128  d[k] = V[k][i + 1] / h;
129  }
130  for (j = 0; j <= i; j++) {
131  g = 0.0;
132  for (k = 0; k <= i; k++) {
133  g += V[k][i + 1] * V[k][j];
134  }
135  for (k = 0; k <= i; k++) {
136  V[k][j] -= g * d[k];
137  }
138  }
139  }
140  for (k = 0; k <= i; k++) {
141  V[k][i + 1] = 0.0;
142  }
143  }
144  for (j = 0; j < n; j++) {
145  d[j] = V[n - 1][j];
146  V[n - 1][j] = 0.0;
147  }
148  V[n - 1][n - 1] = 1.0;
149  e[0] = 0.0;
150 }
151 
152 // Symmetric tridiagonal QL algorithm.
153 
154 static void tql2(double V[n][n], double d[n], double e[n])
155 {
156 // This is derived from the Algol procedures tql2, by
157 // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
158 // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
159 // Fortran subroutine in EISPACK.
160  int i, j, m, l, k;
161  double g, p, r, dl1, h, f, tst1, eps;
162  double c, c2, c3, el1, s, s2;
163 
164  for (i = 1; i < n; i++) {
165  e[i - 1] = e[i];
166  }
167  e[n - 1] = 0.0;
168 
169  f = 0.0;
170  tst1 = 0.0;
171  eps = pow(2.0, -52.0);
172  for (l = 0; l < n; l++) {
173  // Find small subdiagonal element
174  tst1 = MAX(tst1, fabs(d[l]) + fabs(e[l]));
175  m = l;
176  while (m < n) {
177  if (fabs(e[m]) <= eps * tst1) {
178  break;
179  }
180  m++;
181  }
182 
183  // If m == l, d[l] is an eigenvalue,
184  // otherwise, iterate.
185 
186  if (m > l) {
187  int iter = 0;
188  do {
189  iter = iter + 1; // (Could check iteration count here.)
190 
191  // Compute implicit shift
192 
193  g = d[l];
194  p = (d[l + 1] - g) / (2.0 * e[l]);
195  r = hypot(p, 1.0);
196  if (p < 0) {
197  r = -r;
198  }
199  d[l] = e[l] / (p + r);
200  d[l + 1] = e[l] * (p + r);
201  dl1 = d[l + 1];
202  h = g - d[l];
203  for (i = l + 2; i < n; i++) {
204  d[i] -= h;
205  }
206  f = f + h;
207 
208  // Implicit QL transformation.
209 
210  p = d[m];
211  c = 1.0;
212  c2 = c;
213  c3 = c;
214  el1 = e[l + 1];
215  s = 0.0;
216  s2 = 0.0;
217  for (i = m - 1; i >= l; i--) {
218  c3 = c2;
219  c2 = c;
220  s2 = s;
221  g = c * e[i];
222  h = c * p;
223  r = hypot(p, e[i]);
224  e[i + 1] = s * r;
225  s = e[i] / r;
226  c = p / r;
227  p = c * d[i] - s * g;
228  d[i + 1] = h + s * (c * g + s * d[i]);
229 
230  // Accumulate transformation.
231 
232  for (k = 0; k < n; k++) {
233  h = V[k][i + 1];
234  V[k][i + 1] = s * V[k][i] + c * h;
235  V[k][i] = c * V[k][i] - s * h;
236  }
237  }
238  p = -s * s2 * c3 * el1 * e[l] / dl1;
239  e[l] = s * p;
240  d[l] = c * p;
241 
242  // Check for convergence.
243  } while (fabs(e[l]) > eps * tst1);
244  }
245  d[l] = d[l] + f;
246  e[l] = 0.0;
247  }
248  // Sort eigenvalues and corresponding vectors.
249 
250  for (i = 0; i < n - 1; i++) {
251  k = i;
252  p = d[i];
253  for (j = i + 1; j < n; j++) {
254  if (d[j] < p) {
255  k = j;
256  p = d[j];
257  }
258  }
259  if (k != i) {
260  d[k] = d[i];
261  d[i] = p;
262  for (j = 0; j < n; j++) {
263  p = V[j][i];
264  V[j][i] = V[j][k];
265  V[j][k] = p;
266  }
267  }
268  }
269 }
270 
271 void eigen_decomposition(double A[n][n], double V[n][n], double d[n])
272 {
273  int i, j;
274  double e[n]; // NOLINT
275  for (i = 0; i < n; i++) {
276  for (j = 0; j < n; j++) {
277  V[i][j] = A[i][j];
278  }
279  }
280  tred2(V, d, e);
281  tql2(V, d, e);
282 }