Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
GaussHelmert.cpp
1 #include "GaussHelmert.hh"
2 
3 #include <Base/Math/Vector.hh>
4 #include <Base/Math/Matrix.hh>
5 #include <MathAlgo/SVD.hh>
6 
7 using namespace BIAS;
8 using namespace std;
9 
10 
13  : Debug(), MaxNumIter_(40), Precision_(1e-8)
14 {}
15 
18 {}
19 
21 Solve(Vector<double>& observations, const Matrix<double>& obs_cov,
23 {
24  // the number of observations
25  const int N = (int)observations.size();
26 
27  double sigma_2_hat = 1.0;
28  Vector<double> x_hat = x;
29  Vector<double> l_hat = observations;
30  Vector<double> v_hat(N);
31  v_hat.SetZero();
32  Matrix<double> Sigma_ll = obs_cov;
33  SVD svd;
34  Matrix<double> Sigma_ll_plus = svd.Invert(Sigma_ll);
35  Matrix<double> A, B, H;
36  A = GetA_(l_hat, x_hat);
37  B = GetB_(l_hat, x_hat);
38  H = GetH_(x_hat);
39 
40  // number of constraints on observations and unknowns
41  const int G = A.num_rows();
42  // number of unknowns
43  const int U = A.num_cols();
44  // number of constraints on unknowns
45  const int Hn = H.num_cols();
46 
47  const int R = G + Hn - U;
48 
49  Matrix<double> Weight, WeightInverse, ATWeightInverse, ATWeightInverseA;
50  Matrix<double> HT, normal_matrix(Hn+U, Hn+U);
51  Vector<double> w_g, w_h, ATWeightInverse_w_g, normal_vector(Hn+U), x_mu;
52  Vector<double> delta_x_hat(U), mu(Hn), lambda;
53 
54  int res = 0;
55  int num_iter = 0;
56  do {
57 
58  A = GetA_(l_hat, x_hat);
59  B = GetB_(l_hat, x_hat);
60  H = GetH_(x_hat);
61 
62  ComputeNormalSystem_(A, B, H, Sigma_ll, x_hat, l_hat, v_hat,
63  normal_matrix, normal_vector);
64 
65  // solve the system and get x_hat and mu
66  if ((res = svd.Solve(normal_matrix, normal_vector, x_mu))!=0){
67  BIASERR("error solving normal equation "<<res);
68  return -1;
69  }
70 
71  for (int r=0; r<U; r++){
72  delta_x_hat[r] = x_mu[r];
73  }
74  for (int r=U; r<U+Hn; r++){
75  mu[r-U] = x_mu[r];
76  }
77 
78  // compute lambda
79  lambda = WeightInverse * ( A * delta_x_hat - w_g );
80 
81  // compute v
82  v_hat = -1.0 * Sigma_ll * B * lambda;
83 
84  // update x_hat and l_hat
85  x_hat += delta_x_hat;
86  l_hat += v_hat;
87 
88  sigma_2_hat = v_hat.ScalarProduct(Sigma_ll_plus * v_hat) / (double)R;
89 
90  Sigma_ll += sigma_2_hat * Sigma_ll;
91  Sigma_ll_plus = svd.Invert(Sigma_ll);
92 
93  num_iter++;
94 
95  } while (num_iter<MaxNumIter_ && sigma_2_hat>Precision_);
96 
97  // compute the covariance matrix
98  ComputeNormalSystem_(A, B, H, Sigma_ll, x_hat, l_hat, v_hat,
99  normal_matrix, normal_vector);
100  Matrix<double> tmp_cov = svd.Invert(normal_matrix);
101  for (int r=0; r<U; r++){
102  for (int c=0; c<U; c++){
103  cov[r][c] = tmp_cov[r][c] * sigma_2_hat;
104  }
105  }
106  x = x_hat;
107  observations = l_hat;
108 
109  return 0;
110 }
111 
112 
115  const Matrix<double>& H, const Matrix<double>& Sigma_ll,
116  const Vector<double>& x_hat, const Vector<double>& l_hat,
117  const Vector<double>& v_hat,
118  Matrix<double>& normal_matrix, Vector<double>& normal_vec)
119 {
120  Matrix<double> Weight, WeightInverse, ATWeightInverse, ATWeightInverseA, HT;
121  Vector<double> w_g, w_h, ATWeightInverse_w_g;
122  SVD svd;
123 
124  // number of unknowns
125  const int U = A.num_cols();
126  // number of constraints on unknowns
127  const int Hn = H.num_cols();
128 
129  Weight = B.Transpose() * Sigma_ll * B;
130  WeightInverse = svd.Invert(Weight);
131 
132  ATWeightInverse = A.Transpose() * WeightInverse;
133  ATWeightInverseA = ATWeightInverse * A;
134  HT = H.Transpose();
135 
136  w_g = -1.0 * g_(l_hat, x_hat) - B.Transpose() * v_hat;
137  w_h = -1.0 * h_(x_hat);
138  ATWeightInverse_w_g = ATWeightInverse * w_g;
139 
140  normal_matrix.SetZero();
141 
142  // fill the normal vector
143  for (int r=0; r<U; r++){
144  normal_vec[r] = ATWeightInverse_w_g[r];
145  }
146  for (int r=U; r<U+Hn; r++){
147  normal_vec[r] = w_h[r-U];
148  }
149 
150  // fill the normal matrix
151  for (int r=0; r<U; r++){
152  for (int c=0; c<U; c++){
153  normal_matrix[r][c] = ATWeightInverseA[r][c];
154  }
155  }
156  for (int r=0; r<U; r++){ // H
157  for (int c=U; c<U+Hn; c++){
158  normal_matrix[r][c] = H[r][c-U];
159  }
160  }
161  for (int r=U; r<U+Hn; r++){ // HT
162  for (int c=0; c<U; c++){
163  normal_matrix[r][c] = HT[r-U][c];
164  }
165  }
166 }
T ScalarProduct(const Vector< T > &argvec) const
scalar product (inner product) of two vectors returning a scalr
Definition: Vector.hh:355
virtual ~GaussHelmert()
computes and holds the singular value decomposition of a rectangular (not necessarily quadratic) Matr...
Definition: SVD.hh:92
Subscript num_cols() const
Definition: cmat.h:320
Vector< double > Solve(const Vector< double > &y) const
Definition: SVD.cpp:135
Matrix< T > Transpose() const
transpose function, storing data destination matrix
Definition: Matrix.hh:823
void SetZero()
equivalent to matrix call
Definition: Vector.hh:156
void SetZero()
Sets all values to zero.
Definition: Matrix.hh:856
int Solve(BIAS::Vector< double > &observations, const BIAS::Matrix< double > &obs_cov, BIAS::Vector< double > &x, BIAS::Matrix< double > &cov)
Matrix< double > Invert()
returns pseudoinverse of A = U * S * V^T A^+ = V * S^+ * U^T
Definition: SVD.cpp:214
GaussHelmert()
protected constructor to prohibit instantiation of class
Subscript num_rows() const
Definition: cmat.h:319
Subscript size() const
Definition: vec.h:262
void ComputeNormalSystem_(const Matrix< double > &A, const Matrix< double > &B, const Matrix< double > &H, const Matrix< double > &Sigma_ll, const Vector< double > &x_hat, const Vector< double > &l_hat, const Vector< double > &v_hat, Matrix< double > &normal_matrix, Vector< double > &normal_vector)