svd22.c
Go to the documentation of this file.
1 /* Copyright (C) 2013-2016, The Regents of The University of Michigan.
2 All rights reserved.
3 This software was developed in the APRIL Robotics Lab under the
4 direction of Edwin Olson, ebolson@umich.edu. This software may be
5 available under alternative licensing terms; contact the address above.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8 1. Redistributions of source code must retain the above copyright notice, this
9  list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright notice,
11  this list of conditions and the following disclaimer in the documentation
12  and/or other materials provided with the distribution.
13 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 The views and conclusions contained in the software and documentation are those
24 of the authors and should not be interpreted as representing official policies,
25 either expressed or implied, of the Regents of The University of Michigan.
26 */
27 
28 #include <math.h>
29 
88 void svd22(const double A[4], double U[4], double S[2], double V[4])
89 {
90  double A00 = A[0];
91  double A01 = A[1];
92  double A10 = A[2];
93  double A11 = A[3];
94 
95  double B0 = A00 + A11;
96  double B1 = A00 - A11;
97  double B2 = A01 + A10;
98  double B3 = A01 - A10;
99 
100  double PminusT = atan2(B3, B0);
101  double PplusT = atan2(B2, B1);
102 
103  double P = (PminusT + PplusT) / 2;
104  double T = (-PminusT + PplusT) / 2;
105 
106  double CP = cos(P), SP = sin(P);
107  double CT = cos(T), ST = sin(T);
108 
109  U[0] = CT;
110  U[1] = -ST;
111  U[2] = ST;
112  U[3] = CT;
113 
114  V[0] = CP;
115  V[1] = -SP;
116  V[2] = SP;
117  V[3] = CP;
118 
119  // C0 = e+f. There are two ways to compute C0; we pick the one
120  // that is better conditioned.
121  double CPmT = cos(P-T), SPmT = sin(P-T);
122  double C0 = 0;
123  if (fabs(CPmT) > fabs(SPmT))
124  C0 = B0 / CPmT;
125  else
126  C0 = B3 / SPmT;
127 
128  // C1 = e-f. There are two ways to compute C1; we pick the one
129  // that is better conditioned.
130  double CPpT = cos(P+T), SPpT = sin(P+T);
131  double C1 = 0;
132  if (fabs(CPpT) > fabs(SPpT))
133  C1 = B1 / CPpT;
134  else
135  C1 = B2 / SPpT;
136 
137  // e and f are the singular values
138  double e = (C0 + C1) / 2;
139  double f = (C0 - C1) / 2;
140 
141  if (e < 0) {
142  e = -e;
143  U[0] = -U[0];
144  U[2] = -U[2];
145  }
146 
147  if (f < 0) {
148  f = -f;
149  U[1] = -U[1];
150  U[3] = -U[3];
151  }
152 
153  // sort singular values.
154  if (e > f) {
155  // already in big-to-small order.
156  S[0] = e;
157  S[1] = f;
158  } else {
159  // Curiously, this code never seems to get invoked. Why is it
160  // that S[0] always ends up the dominant vector? However,
161  // this code has been tested (flipping the logic forces us to
162  // sort the singular values in ascending order).
163  //
164  // P = [ 0 1 ; 1 0 ]
165  // USV' = (UP)(PSP)(PV')
166  // = (UP)(PSP)(VP)'
167  // = (UP)(PSP)(P'V')'
168  S[0] = f;
169  S[1] = e;
170 
171  // exchange columns of U and V
172  double tmp[2];
173  tmp[0] = U[0];
174  tmp[1] = U[2];
175  U[0] = U[1];
176  U[2] = U[3];
177  U[1] = tmp[0];
178  U[3] = tmp[1];
179 
180  tmp[0] = V[0];
181  tmp[1] = V[2];
182  V[0] = V[1];
183  V[2] = V[3];
184  V[1] = tmp[0];
185  V[3] = tmp[1];
186  }
187 
188  /*
189  double SM[4] = { S[0], 0, 0, S[1] };
190 
191  doubles_print_mat(U, 2, 2, "%20.10g");
192  doubles_print_mat(SM, 2, 2, "%20.10g");
193  doubles_print_mat(V, 2, 2, "%20.10g");
194  printf("A:\n");
195  doubles_print_mat(A, 2, 2, "%20.10g");
196 
197  double SVt[4];
198  doubles_mat_ABt(SM, 2, 2, V, 2, 2, SVt, 2, 2);
199  double USVt[4];
200  doubles_mat_AB(U, 2, 2, SVt, 2, 2, USVt, 2, 2);
201 
202  printf("USVt\n");
203  doubles_print_mat(USVt, 2, 2, "%20.10g");
204 
205  double diff[4];
206  for (int i = 0; i < 4; i++)
207  diff[i] = A[i] - USVt[i];
208 
209  printf("diff\n");
210  doubles_print_mat(diff, 2, 2, "%20.10g");
211 
212  */
213 
214 }
215 
216 
217 // for the matrix [a b; b d]
218 void svd_sym_singular_values(double A00, double A01, double A11,
219  double *Lmin, double *Lmax)
220 {
221  double A10 = A01;
222 
223  double B0 = A00 + A11;
224  double B1 = A00 - A11;
225  double B2 = A01 + A10;
226  double B3 = A01 - A10;
227 
228  double PminusT = atan2(B3, B0);
229  double PplusT = atan2(B2, B1);
230 
231  double P = (PminusT + PplusT) / 2;
232  double T = (-PminusT + PplusT) / 2;
233 
234  // C0 = e+f. There are two ways to compute C0; we pick the one
235  // that is better conditioned.
236  double CPmT = cos(P-T), SPmT = sin(P-T);
237  double C0 = 0;
238  if (fabs(CPmT) > fabs(SPmT))
239  C0 = B0 / CPmT;
240  else
241  C0 = B3 / SPmT;
242 
243  // C1 = e-f. There are two ways to compute C1; we pick the one
244  // that is better conditioned.
245  double CPpT = cos(P+T), SPpT = sin(P+T);
246  double C1 = 0;
247  if (fabs(CPpT) > fabs(SPpT))
248  C1 = B1 / CPpT;
249  else
250  C1 = B2 / SPpT;
251 
252  // e and f are the singular values
253  double e = (C0 + C1) / 2;
254  double f = (C0 - C1) / 2;
255 
256  *Lmin = fmin(e, f);
257  *Lmax = fmax(e, f);
258 }
void svd_sym_singular_values(double A00, double A01, double A11, double *Lmin, double *Lmax)
Definition: svd22.c:218
void svd22(const double A[4], double U[4], double S[2], double V[4])
Definition: svd22.c:88


apriltag
Author(s): Edwin Olson , Max Krogius
autogenerated on Mon Jun 26 2023 02:26:12