00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <base/Math>
00026
00027 #include <base/SVD>
00028
00029 using base::Math;
00030
00031 using base::Matrix;
00032 using base::Vector;
00033 using base::swap;
00034 using base::SVD;
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #ifdef BUILDOLDIKOR
00046 #ifdef USEOLDIKOR_NULLSPACE
00047 extern "C" {
00048 #include <robot/control/oldikor/IKOR/general.h>
00049 #include <robot/control/oldikor/IKOR/headers.h>
00050 #include <robot/control/oldikor/UTILS/matrix.h>
00051 }
00052 #endif
00053 #else
00054 #undef USEOLDIKOR_NULLSPACE
00055 #endif
00056
00057
00058
00059 Real Math::angleDifference(Real angle1, Real angle2)
00060 {
00061 Real a1 = normalizeAngle(angle1);
00062 Real a2 = normalizeAngle(angle2);
00063 if (a1 >= 0) {
00064 if (a2 >= 0)
00065 return a1-a2;
00066 else {
00067 if ((a1-a2) <= consts::Pi)
00068 return a1-a2;
00069 else
00070 return (-consts::Pi-a2)-(consts::Pi-a1);
00071 }
00072 }
00073 else {
00074 if (a2 < 0)
00075 return a1-a2;
00076 else {
00077 if ((a1-a2) > -consts::Pi)
00078 return a1-a2;
00079 else
00080 return (consts::Pi-a2)-(-consts::Pi-a1);
00081 }
00082 }
00083 }
00084
00085
00086
00087
00088
00089
00090
00091 void Math::decomposeLUP(const Matrix& A, Matrix& L, Matrix& U, Vector& Pi, Real epsilon)
00092 {
00093 const Int n = A.size1();
00094
00095 Assertm( (L.size1() == n) && (L.size2() == n)
00096 && (U.size1() == n) && (U.size2() == n) && (Pi.size() == n),
00097 "L,U,Pi are square and of same dimension as A");
00098
00099 Real p,a;
00100 Int kp,i,j,k;
00101 Matrix AA(A);
00102
00103 for(i=0; i<n; i++) Pi[i] = i;
00104 for(k=0; k<n-1; k++) {
00105 p = Real(0); kp = 0;
00106 for(i=k; i<n; i++) {
00107 a = Real(abs(AA(i,k)));
00108 if ( a > p ) {
00109 p = a;
00110 kp = i;
00111 }
00112 }
00113 if (equals(p,0,epsilon))
00114 throw std::invalid_argument(Exception("Matrix A is singular"));
00115
00116 swap(Pi[k],Pi[kp]);
00117 for(i=0; i<n;i++) swap(AA(k,i),AA(kp,i));
00118
00119 for(i=k+1; i<n;i++) {
00120 AA(i,k) /= AA(k,k);
00121 for(j=k+1; j<n; j++)
00122 AA(i,j) -= AA(i,k)*AA(k,j);
00123 }
00124 }
00125
00126 for(i=0;i<n;i++) {
00127 for(j=0;j<n;j++)
00128 if (i>j) {
00129 L(i,j) = AA(i,j); U(i,j) = 0;
00130 }
00131 else {
00132 U(i,j) = AA(i,j); L(i,j) = 0;
00133 }
00134 L(i,i) = Real(1);
00135
00136 }
00137
00138 }
00139
00140
00141 Vector Math::solveLUP(const Matrix& L, const Matrix& U, const Vector& Pi, const Vector& b)
00142 {
00143 Int n = L.size1();
00144
00145 Assertm( (b.size() == n) && (L.size1() == n)
00146 && (U.size1()==n) || (U.size2() == n) && (Pi.size() == n),
00147 "L,U,Pi must are square and of same dimension (that of b)");
00148
00149 SInt i,j;
00150 Vector y(n), x(n);
00151 Real s;
00152
00153 for(i=0;i<SInt(n);i++) {
00154 s = 0;
00155 for(j=0;j<i;j++) s += L(i,j)*y[j];
00156 y[i] = b[Int(Pi[i])] - s;
00157 }
00158
00159 for(i=n-1;i>=0;i--) {
00160 s = 0;
00161 for(j=i+1;j<SInt(n);j++) s += U(i,j)*x[j];
00162 x[i] = (y[i] - s)/(U(i,i));
00163 }
00164 return x;
00165 }
00166
00167
00168
00169
00170 Matrix Math::inverse(const Matrix& A, Real epsilon)
00171 {
00172 const Int nr = A.size1();
00173 const Int nc = A.size2();
00174
00175 if (nr == nc) {
00176
00177 Matrix X(nr,nc);
00178 Vector x(nr);
00179
00180 Matrix L(nr,nc),U(nr,nc);
00181 Vector Pi(nr);
00182
00183 decomposeLUP(A, L, U, Pi, epsilon);
00184
00185 for(Int c=0; c<nc; c++) {
00186 x = solveLUP(L,U,Pi,unitVector(nc,c));
00187 for(Int r=0; r<nr; r++) X(r,c) = x[r];
00188 }
00189
00190 return X;
00191 }
00192 else
00193 throw std::invalid_argument(Exception("Can't invert a non-square matrix"));
00194
00195 }
00196
00197
00198 Matrix Math::nullSpace(const Matrix& A, Int& nullSpaceRank, Real& k2)
00199 {
00200 if ((A.size1() == 0) || (A.size2() == 0))
00201 throw std::invalid_argument(Exception("Can't compute null-space of a 0x0 matrix!"));
00202
00203 #ifndef USEOLDIKOR_NULLSPACE
00204
00205
00206
00207
00208 Assert(A.size1() <= A.size2());
00209
00210 const Int R = A.size1();
00211 const Int C = A.size2();
00212
00213
00214 Matrix Asqr(C,C);
00215 if (R < C) {
00216 matrixRange(Asqr,Range(0,R), Range(0,C)) = A;
00217 matrixRange(Asqr,Range(R,C), Range(0,C)) = zeroMatrix(C-R,C);
00218 }
00219 else
00220 Asqr = A;
00221
00222 SVD svd(Asqr);
00223
00224
00225 const Matrix& V(svd.V());
00226 Vector S(svd.diag());
00227
00228 IVector order(C);
00229 for(Int i=0; i<C; i++) order[i]=i;
00230
00231 for(SInt i=C-1; i>0; i--)
00232 for(SInt j=i-1; j>=0; j--)
00233 if ( Math::abs(S[i]) > Math::abs(S[j]) ) {
00234 base::swap(S[i],S[j]);
00235 base::swap(order[i],order[j]);
00236 }
00237
00238 Real s_min;
00239 if (R<=C)
00240 s_min = Math::abs(S[R-1]);
00241 else
00242 s_min = Math::abs(S[C-1]);
00243 Real s_max = Math::abs(S[0]);
00244
00245
00246 Matrix ns(C,C);
00247 nullSpaceRank=0;
00248 while (Math::abs(S[C-1-nullSpaceRank]) < SVD::minSingValue) {
00249 for(Int j=0; j<C; j++)
00250 ns(j,nullSpaceRank) = V(j,order[C-1-nullSpaceRank]);
00251 nullSpaceRank++;
00252 if (nullSpaceRank == C) break;
00253 }
00254
00255 if (nullSpaceRank < C) {
00256 if ( (Math::abs(s_min)>=SVD::minSingValue) && (Math::abs(s_min/s_max) < SVD::minSingValue)) {
00257 for(Int j=0; j<C; j++)
00258 ns(j,nullSpaceRank) = V(order[j],C-1-nullSpaceRank);
00259 nullSpaceRank++;
00260 }
00261 }
00262
00263 if (equals(s_min,0,SVD::minSingValue))
00264 k2 = consts::maxReal;
00265 else
00266 k2 = s_max/s_min;
00267
00268 Matrix n(C,nullSpaceRank);
00269 if ((C > 0) && (nullSpaceRank > 0))
00270 n = matrixRange(ns, Range(0,C), Range(0,nullSpaceRank));
00271
00272 return n;
00273
00274 #else
00275
00276
00277
00278 MATRIX *a = mat_malloc(A.size1(), A.size2());
00279 for(Int r=0; r<A.size1(); r++)
00280 for(Int c=0; c<A.size2(); c++)
00281 a->p[r][c] = A(r,c);
00282
00283
00284 MATRIX *n = mat_malloc(A.size2(), A.size1());
00285 int n_rank;
00286 float K2;
00287 mat_null(a, &n_rank, n, &K2);
00288
00289 nullSpaceRank = n_rank;
00290 k2 = K2;
00291
00292 Matrix nn(A.size2(), nullSpaceRank);
00293 for(Int r=0; r<A.size2(); r++)
00294 for(Int c=0; c<nullSpaceRank; c++)
00295 nn(r,c) = n->p[r][c];
00296
00297 mat_free(a);
00298 mat_free(n);
00299
00300 return nn;
00301 #endif
00302 }
00303
00304
00305 Matrix Math::pseudoInverse(const Matrix& A)
00306 {
00307
00308 const Int M=A.size1();
00309 const Int N=A.size2();
00310
00311
00312
00313
00314
00315
00316 if (M<N) {
00317 Matrix pA(N,N);
00318 matrixRange(pA,Range(0,M), Range(0,N)) = A;
00319 matrixRange(pA,Range(M,N), Range(0,N)) = zeroMatrix(N-M,N);
00320
00321 Matrix pAinv( SVD(pA).inv() );
00322
00323 return matrixRange(pAinv, Range(0,N), Range(0,M));
00324 }
00325
00326
00327 return SVD(A).inv();
00328 }
00329
00330