svd_eigen_Macie.hpp
Go to the documentation of this file.
1 // Copyright (C) 2008 Ruben Smits <ruben dot smits at mech dot kuleuven dot be>
2 
3 // Version: 1.0
4 // Author: Ruben Smits <ruben dot smits at mech dot kuleuven dot be>
5 // Maintainer: Ruben Smits <ruben dot smits at mech dot kuleuven dot be>
6 // URL: http://www.orocos.org/kdl
7 
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 
22 
23 //implementation of svd according to (Maciejewski and Klein,1989)
24 //and (Braun, Ulrey, Maciejewski and Siegel,2002)
25 
31 #ifndef SVD_EIGEN_MACIE
32 #define SVD_EIGEN_MACIE
33 
34 #include <Eigen/Core>
35 using namespace Eigen;
36 
37 
38 namespace KDL
39 {
40 
59  int svd_eigen_Macie(const MatrixXd& A,MatrixXd& U,VectorXd& S, MatrixXd& V,
60  MatrixXd& B, VectorXd& tempi,
61  double threshold,bool toggle)
62  {
63  bool rotate = true;
64  unsigned int sweeps=0;
65  unsigned int rotations=0;
66  if(toggle){
67  //Calculate B from new A and previous V
68  B=A.lazyProduct(V);
69  while(rotate){
70  rotate=false;
71  rotations=0;
72  //Perform rotations between columns of B
73  for(unsigned int i=0;i<B.cols();i++){
74  for(unsigned int j=i+1;j<B.cols();j++){
75  //calculate plane rotation
76  double p = B.col(i).dot(B.col(j));
77  double qi =B.col(i).dot(B.col(i));
78  double qj = B.col(j).dot(B.col(j));
79  double q=qi-qj;
80  double alpha = pow(p,2.0)/(qi*qj);
81  //if columns are orthogonal with precision
82  //threshold, don't perform rotation and continue
83  if(alpha<threshold)
84  continue;
85  rotations++;
86  double c = sqrt(4*pow(p,2.0)+pow(q,2.0));
87  double cos,sin;
88  if(q>=0){
89  cos=sqrt((c+q)/(2*c));
90  sin=p/(c*cos);
91  }else{
92  if(p<0)
93  sin=-sqrt((c-q)/(2*c));
94  else
95  sin=sqrt((c-q)/(2*c));
96  cos=p/(c*sin);
97  }
98 
99  //Apply plane rotation to columns of B
100  tempi = cos*B.col(i) + sin*B.col(j);
101  B.col(j) = - sin*B.col(i) + cos*B.col(j);
102  B.col(i) = tempi;
103 
104  //Apply plane rotation to columns of V
105  tempi.head(V.rows()) = cos*V.col(i) + sin*V.col(j);
106  V.col(j) = - sin*V.col(i) + cos*V.col(j);
107  V.col(i) = tempi.head(V.rows());
108 
109  rotate=true;
110  }
111  }
112  //Only calculate new U and S if there were any rotations
113  if(rotations!=0){
114  for(unsigned int i=0;i<U.rows();i++) {
115  if(i<B.cols()){
116  double si=sqrt(B.col(i).dot(B.col(i)));
117  if(si==0)
118  U.col(i) = B.col(i);
119  else
120  U.col(i) = B.col(i)/si;
121  S(i)=si;
122  }
123  else
124  U.col(i) = 0*tempi;
125  }
126  sweeps++;
127  }
128  }
129  return sweeps;
130  }else{
131  //Calculate B from new A and previous U'
132  B = U.transpose().lazyProduct(A);
133  while(rotate){
134  rotate=false;
135  rotations=0;
136  //Perform rotations between rows of B
137  for(unsigned int i=0;i<B.cols();i++){
138  for(unsigned int j=i+1;j<B.cols();j++){
139  //calculate plane rotation
140  double p = B.row(i).dot(B.row(j));
141  double qi = B.row(i).dot(B.row(i));
142  double qj = B.row(j).dot(B.row(j));
143 
144  double q=qi-qj;
145  double alpha = pow(p,2.0)/(qi*qj);
146  //if columns are orthogonal with precision
147  //threshold, don't perform rotation and
148  //continue
149  if(alpha<threshold)
150  continue;
151  rotations++;
152  double c = sqrt(4*pow(p,2.0)+pow(q,2.0));
153  double cos,sin;
154  if(q>=0){
155  cos=sqrt((c+q)/(2*c));
156  sin=p/(c*cos);
157  }else{
158  if(p<0)
159  sin=-sqrt((c-q)/(2*c));
160  else
161  sin=sqrt((c-q)/(2*c));
162  cos=p/(c*sin);
163  }
164 
165  //Apply plane rotation to rows of B
166  tempi.head(B.cols()) = cos*B.row(i) + sin*B.row(j);
167  B.row(j) = - sin*B.row(i) + cos*B.row(j);
168  B.row(i) = tempi.head(B.cols());
169 
170 
171  //Apply plane rotation to rows of U
172  tempi.head(U.rows()) = cos*U.col(i) + sin*U.col(j);
173  U.col(j) = - sin*U.col(i) + cos*U.col(j);
174  U.col(i) = tempi.head(U.rows());
175 
176  rotate=true;
177  }
178  }
179 
180  //Only calculate new U and S if there were any rotations
181  if(rotations!=0){
182  for(unsigned int i=0;i<V.rows();i++) {
183  double si=sqrt(B.row(i).dot(B.row(i)));
184  if(si==0)
185  V.col(i) = B.row(i);
186  else
187  V.col(i) = B.row(i)/si;
188  S(i)=si;
189  }
190  sweeps++;
191  }
192  }
193  return sweeps;
194  }
195  }
196 
197 
198 }
199 #endif
int svd_eigen_Macie(const MatrixXd &A, MatrixXd &U, VectorXd &S, MatrixXd &V, MatrixXd &B, VectorXd &tempi, double threshold, bool toggle)
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:369
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
Definition: rall1d.h:361
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:321
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:313


orocos_kdl
Author(s):
autogenerated on Sat Jun 15 2019 19:07:36