Visual Servoing Platform  version 3.6.1 under development (2024-12-17)
vpMatrix_covariance.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Covariance matrix computation.
32  */
33 
34 #include <cmath> // std::fabs()
35 #include <limits> // numeric_limits
36 
37 #include <visp3/core/vpColVector.h>
38 #include <visp3/core/vpConfig.h>
39 #include <visp3/core/vpHomogeneousMatrix.h>
40 #include <visp3/core/vpMatrix.h>
41 #include <visp3/core/vpMatrixException.h>
42 #include <visp3/core/vpTranslationVector.h>
43 
44 BEGIN_VISP_NAMESPACE
56 {
57  // double denom = ((double)(A.getRows()) - (double)(A.getCols())); // To
58  // consider OLS Estimate for sigma
59  double denom = (static_cast<double>(A.getRows())); // To consider MLE Estimate for sigma
60 
61  if (denom <= std::numeric_limits<double>::epsilon()) {
63  "Impossible to compute covariance matrix: not enough data");
64  }
65 
66  // double sigma2 = ( ((b.t())*b) - ( (b.t())*A*x ) ); // Should be
67  // equivalent to line bellow.
68  double sigma2 = (b - (A * x)).t() * (b - (A * x));
69 
70  sigma2 /= denom;
71 
72  return (A.t() * A).pseudoInverse(A.getCols() * std::numeric_limits<double>::epsilon()) * sigma2;
73 }
74 
89  const vpMatrix &W)
90 {
91  double denom = 0.0;
92  vpMatrix W2(W.getCols(), W.getCols());
93  unsigned int w_cols = W.getCols();
94  for (unsigned int i = 0; i < w_cols; ++i) {
95  denom += W[i][i];
96  W2[i][i] = W[i][i] * W[i][i];
97  }
98 
99  if (denom <= std::numeric_limits<double>::epsilon()) {
101  "Impossible to compute covariance matrix: not enough data");
102  }
103 
104  // double sigma2 = ( ((W*b).t())*W*b - ( ((W*b).t())*W*A*x ) ); // Should
105  // be equivalent to line bellow.
106  double sigma2 = ((W * b) - (W * A * x)).t() * ((W * b) - (W * A * x));
107  sigma2 /= denom;
108 
109  return (A.t() * W2 * A).pseudoInverse(A.getCols() * std::numeric_limits<double>::epsilon()) * sigma2;
110 }
111 
124  const vpMatrix &Ls)
125 {
126  vpMatrix Js;
127  vpColVector deltaP;
128  vpMatrix::computeCovarianceMatrixVVS(cMo, deltaS, Ls, Js, deltaP);
129 
130  return vpMatrix::computeCovarianceMatrix(Js, deltaP, deltaS);
131 }
132 
149  const vpMatrix &Ls, const vpMatrix &W)
150 {
151  vpMatrix Js;
152  vpColVector deltaP;
153  vpMatrix::computeCovarianceMatrixVVS(cMo, deltaS, Ls, Js, deltaP);
154 
155  return vpMatrix::computeCovarianceMatrix(Js, deltaP, deltaS, W);
156 }
157 
158 void vpMatrix::computeCovarianceMatrixVVS(const vpHomogeneousMatrix &cMo, const vpColVector &deltaS, const vpMatrix &Ls,
159  vpMatrix &Js, vpColVector &deltaP)
160 {
161  // building Lp
162  vpMatrix LpInv(6, 6);
163  LpInv = 0;
164  const unsigned int index_0 = 0;
165  const unsigned int index_1 = 1;
166  const unsigned int index_2 = 2;
167  LpInv[index_0][index_0] = -1.0;
168  LpInv[index_1][index_1] = -1.0;
169  LpInv[index_2][index_2] = -1.0;
170 
171  vpTranslationVector ctoInit;
172 
173  cMo.extract(ctoInit);
174  vpMatrix ctoInitSkew = ctoInit.skew();
175 
176  vpThetaUVector thetau;
177  cMo.extract(thetau);
178 
179  vpColVector tu(3);
180  const unsigned int val_3 = 3;
181  for (unsigned int i = 0; i < val_3; ++i) {
182  tu[i] = thetau[i];
183  }
184 
185  double theta = sqrt(tu.sumSquare());
186 
187  // --comment: declare variable Lthetau of three by three of type vpMatrix
188  vpMatrix LthetauInvAnalytic(3, 3);
189  vpMatrix I3(3, 3);
190  I3.eye();
191  // --comment: Lthetau equals -I3;
192  LthetauInvAnalytic = -I3;
193 
194  if ((theta / (2.0 * M_PI)) > std::numeric_limits<double>::epsilon()) {
195  // Computing [theta/2 u]_x
196  vpColVector theta2u(3);
197  for (unsigned int i = 0; i < val_3; ++i) {
198  theta2u[i] = tu[i] / 2.0;
199  }
200  vpMatrix theta2u_skew = vpColVector::skew(theta2u);
201 
202  vpColVector u(3);
203  for (unsigned int i = 0; i < val_3; ++i) {
204  u[i] = tu[i] / theta;
205  }
206  vpMatrix u_skew = vpColVector::skew(u);
207 
208  LthetauInvAnalytic +=
209  -((vpMath::sqr(vpMath::sinc(theta / 2.0)) * theta2u_skew) - ((1.0 - vpMath::sinc(theta)) * u_skew * u_skew));
210  }
211 
212  // --comment: vpMatrix LthetauInv equals Lthetau dot inverseByLU()
213 
214  ctoInitSkew = ctoInitSkew * LthetauInvAnalytic;
215 
216  const unsigned int index_3 = 3;
217  for (unsigned int a = 0; a < val_3; ++a) {
218  for (unsigned int b = 0; b < val_3; ++b) {
219  LpInv[a][b + index_3] = ctoInitSkew[a][b];
220  }
221  }
222 
223  for (unsigned int a = 0; a < val_3; ++a) {
224  for (unsigned int b = 0; b < val_3; ++b) {
225  LpInv[a + index_3][b + index_3] = LthetauInvAnalytic[a][b];
226  }
227  }
228 
229  // Building Js
230  Js = Ls * LpInv;
231 
232  // building deltaP
233  deltaP = Js.pseudoInverse(Js.getRows() * std::numeric_limits<double>::epsilon()) * deltaS;
234 }
235 END_VISP_NAMESPACE
unsigned int getCols() const
Definition: vpArray2D.h:337
unsigned int getRows() const
Definition: vpArray2D.h:347
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
static vpMatrix skew(const vpColVector &v)
@ divideByZeroError
Division by zero.
Definition: vpException.h:70
Implementation of an homogeneous matrix and operations on such kind of matrices.
void extract(vpRotationMatrix &R) const
static double sinc(double x)
Definition: vpMath.cpp:268
static double sqr(double x)
Definition: vpMath.h:203
error that can be emitted by the vpMatrix class and its derivatives
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:169
static vpMatrix computeCovarianceMatrixVVS(const vpHomogeneousMatrix &cMo, const vpColVector &deltaS, const vpMatrix &Ls, const vpMatrix &W)
vpMatrix pseudoInverse(double svThreshold=1e-6) const
static vpMatrix computeCovarianceMatrix(const vpMatrix &A, const vpColVector &x, const vpColVector &b)
vpMatrix t() const
Implementation of a rotation vector as axis-angle minimal representation.
Class that consider the case of a translation vector.