Visual Servoing Platform
version 3.7.0
Toggle main menu visibility
Loading...
Searching...
No Matches
vpMatrix_pseudo_inverse.cpp
1
/*
2
* ViSP, open source Visual Servoing Platform software.
3
* Copyright (C) 2005 - 2025 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
* Pseudo inverse computation.
32
*/
33
34
#include <visp3/core/vpConfig.h>
35
#include <visp3/core/vpMatrix.h>
36
37
#if defined(VISP_HAVE_SIMDLIB)
38
#include <Simd/SimdLib.h>
39
#endif
40
41
#ifdef VISP_HAVE_LAPACK
42
#ifdef VISP_HAVE_GSL
43
#include <gsl/gsl_eigen.h>
44
#include <gsl/gsl_linalg.h>
45
#include <gsl/gsl_math.h>
46
#elif defined(VISP_HAVE_MKL)
47
#include <mkl.h>
48
#endif
49
#endif
50
51
BEGIN_VISP_NAMESPACE
52
53
#ifndef DOXYGEN_SHOULD_SKIP_THIS
54
55
void
compute_pseudo_inverse(
const
vpMatrix
&U,
const
vpColVector
&sv,
const
vpMatrix
&V,
unsigned
int
nrows,
56
unsigned
int
ncols,
double
svThreshold,
vpMatrix
&Ap,
int
&rank_out,
int
*rank_in,
57
vpMatrix
*imA,
vpMatrix
*imAt,
vpMatrix
*kerAt);
58
59
void
compute_pseudo_inverse(
const
vpMatrix
&U,
const
vpColVector
&sv,
const
vpMatrix
&V,
unsigned
int
nrows,
60
unsigned
int
ncols,
double
svThreshold,
vpMatrix
&Ap,
int
&rank_out,
int
*rank_in,
61
vpMatrix
*imA,
vpMatrix
*imAt,
vpMatrix
*kerAt)
62
{
63
Ap.
resize
(ncols, nrows,
true
,
false
);
64
65
// compute the highest singular value and the rank of h
66
double
maxsv = sv[0];
67
68
rank_out = 0;
69
70
unsigned
int
sv_size = sv.
size
();
71
for
(
unsigned
int
i = 0;
i
< sv_size; ++
i
) {
72
if
(sv[i] >(maxsv * svThreshold)) {
73
++rank_out;
74
}
75
}
76
77
unsigned
int
rank =
static_cast<
unsigned
int
>
(rank_out);
78
if
(rank_in) {
79
rank =
static_cast<
unsigned
int
>
(*rank_in);
80
}
81
82
for
(
unsigned
int
i = 0;
i
< ncols; ++
i
) {
83
for
(
unsigned
int
j = 0;
j
< nrows; ++
j
) {
84
for
(
unsigned
int
k = 0; k < rank; ++k) {
85
Ap[
i
][
j
] += (V[
i
][k] * U[
j
][k]) / sv[k];
86
}
87
}
88
}
89
90
// Compute im(A)
91
if
(imA) {
92
imA->
resize
(nrows, rank);
93
94
for
(
unsigned
int
i = 0;
i
< nrows; ++
i
) {
95
for
(
unsigned
int
j = 0;
j
< rank; ++
j
) {
96
(*imA)[
i
][
j
] = U[
i
][
j
];
97
}
98
}
99
}
100
101
// Compute im(At)
102
if
(imAt) {
103
imAt->
resize
(ncols, rank);
104
for
(
unsigned
int
i = 0;
i
< ncols; ++
i
) {
105
for
(
unsigned
int
j = 0;
j
< rank; ++
j
) {
106
(*imAt)[
i
][
j
] = V[
i
][
j
];
107
}
108
}
109
}
110
111
// Compute ker(At)
112
if
(kerAt) {
113
kerAt->
resize
(ncols - rank, ncols);
114
if
(rank != ncols) {
115
unsigned
int
v_rows = V.
getRows
();
116
for
(
unsigned
int
k = 0; k < (ncols - rank); ++k) {
117
unsigned
j
= k + rank;
118
for
(
unsigned
int
i = 0;
i
< v_rows; ++
i
) {
119
(*kerAt)[k][
i
] = V[
i
][
j
];
120
}
121
}
122
}
123
}
124
}
125
126
#endif
// #ifndef DOXYGEN_SHOULD_SKIP_THIS
127
186
unsigned
int
vpMatrix::pseudoInverse
(
vpMatrix
&Ap,
double
svThreshold)
const
187
{
188
#if defined(VISP_HAVE_LAPACK)
189
return
pseudoInverseLapack
(Ap, svThreshold);
190
#elif defined(VISP_HAVE_EIGEN3)
191
return
pseudoInverseEigen3
(Ap, svThreshold);
192
#elif defined(VISP_HAVE_OPENCV)
// Require opencv >= 2.1.1
193
return
pseudoInverseOpenCV
(Ap, svThreshold);
194
#else
195
(void)Ap;
196
(void)svThreshold;
197
throw
(
vpException
(
vpException::fatalError
,
"Cannot compute pseudo-inverse. "
198
"Install Lapack, Eigen3 or OpenCV 3rd party"
));
199
#endif
200
}
201
266
int
vpMatrix::pseudoInverse
(
vpMatrix
&Ap,
int
rank_in)
const
267
{
268
#if defined(VISP_HAVE_LAPACK)
269
return
pseudoInverseLapack
(Ap, rank_in);
270
#elif defined(VISP_HAVE_EIGEN3)
271
return
pseudoInverseEigen3
(Ap, rank_in);
272
#elif defined(VISP_HAVE_OPENCV)
// Require opencv >= 2.1.1
273
return
pseudoInverseOpenCV
(Ap, rank_in);
274
#else
275
(void)Ap;
276
(void)rank_in;
277
throw
(
vpException
(
vpException::fatalError
,
"Cannot compute pseudo-inverse. "
278
"Install Lapack, Eigen3 or OpenCV 3rd party"
));
279
#endif
280
}
281
336
vpMatrix
vpMatrix::pseudoInverse
(
double
svThreshold)
const
337
{
338
#if defined(VISP_HAVE_LAPACK)
339
return
pseudoInverseLapack
(svThreshold);
340
#elif defined(VISP_HAVE_EIGEN3)
341
return
pseudoInverseEigen3
(svThreshold);
342
#elif defined(VISP_HAVE_OPENCV)
// Require opencv >= 2.1.1
343
return
pseudoInverseOpenCV
(svThreshold);
344
#else
345
(void)svThreshold;
346
throw
(
vpException
(
vpException::fatalError
,
"Cannot compute pseudo-inverse. "
347
"Install Lapack, Eigen3 or OpenCV 3rd party"
));
348
#endif
349
}
350
405
vpMatrix
vpMatrix::pseudoInverse
(
int
rank_in)
const
406
{
407
#if defined(VISP_HAVE_LAPACK)
408
return
pseudoInverseLapack
(rank_in);
409
#elif defined(VISP_HAVE_EIGEN3)
410
return
pseudoInverseEigen3
(rank_in);
411
#elif defined(VISP_HAVE_OPENCV)
// Require opencv >= 2.1.1
412
return
pseudoInverseOpenCV
(rank_in);
413
#else
414
(void)rank_in;
415
throw
(
vpException
(
vpException::fatalError
,
"Cannot compute pseudo-inverse. "
416
"Install Lapack, Eigen3 or OpenCV 3rd party"
));
417
#endif
418
}
419
485
unsigned
int
vpMatrix::pseudoInverse
(
vpMatrix
&Ap,
vpColVector
&sv,
double
svThreshold)
const
486
{
487
#if defined(VISP_HAVE_LAPACK)
488
return
pseudoInverseLapack
(Ap, sv, svThreshold);
489
#elif defined(VISP_HAVE_EIGEN3)
490
return
pseudoInverseEigen3
(Ap, sv, svThreshold);
491
#elif defined(VISP_HAVE_OPENCV)
// Require opencv >= 2.1.1
492
return
pseudoInverseOpenCV
(Ap, sv, svThreshold);
493
#else
494
(void)Ap;
495
(void)sv;
496
(void)svThreshold;
497
throw
(
vpException
(
vpException::fatalError
,
"Cannot compute pseudo-inverse. "
498
"Install Lapack, Eigen3 or OpenCV 3rd party"
));
499
#endif
500
}
501
572
int
vpMatrix::pseudoInverse
(
vpMatrix
&Ap,
vpColVector
&sv,
int
rank_in)
const
573
{
574
#if defined(VISP_HAVE_LAPACK)
575
return
pseudoInverseLapack
(Ap, sv, rank_in);
576
#elif defined(VISP_HAVE_EIGEN3)
577
return
pseudoInverseEigen3
(Ap, sv, rank_in);
578
#elif defined(VISP_HAVE_OPENCV)
// Require opencv >= 2.1.1
579
return
pseudoInverseOpenCV
(Ap, sv, rank_in);
580
#else
581
(void)Ap;
582
(void)sv;
583
(void)rank_in;
584
throw
(
vpException
(
vpException::fatalError
,
"Cannot compute pseudo-inverse. "
585
"Install Lapack, Eigen3 or OpenCV 3rd party"
));
586
#endif
587
}
588
666
unsigned
int
vpMatrix::pseudoInverse
(
vpMatrix
&Ap,
vpColVector
&sv,
double
svThreshold,
vpMatrix
&imA,
vpMatrix
&imAt)
const
667
{
668
vpMatrix
kerAt;
669
return
pseudoInverse
(Ap, sv, svThreshold, imA, imAt, kerAt);
670
}
671
754
int
vpMatrix::pseudoInverse
(
vpMatrix
&Ap,
vpColVector
&sv,
int
rank_in,
vpMatrix
&imA,
vpMatrix
&imAt)
const
755
{
756
vpMatrix
kerAt;
757
return
pseudoInverse
(Ap, sv, rank_in, imA, imAt, kerAt);
758
}
759
865
unsigned
int
vpMatrix::pseudoInverse
(
vpMatrix
&Ap,
vpColVector
&sv,
double
svThreshold,
vpMatrix
&imA,
vpMatrix
&imAt,
866
vpMatrix
&kerAt)
const
867
{
868
#if defined(VISP_HAVE_LAPACK)
869
return
pseudoInverseLapack
(Ap, sv, svThreshold, imA, imAt, kerAt);
870
#elif defined(VISP_HAVE_EIGEN3)
871
return
pseudoInverseEigen3
(Ap, sv, svThreshold, imA, imAt, kerAt);
872
#elif defined(VISP_HAVE_OPENCV)
// Require opencv >= 2.1.1
873
return
pseudoInverseOpenCV
(Ap, sv, svThreshold, imA, imAt, kerAt);
874
#else
875
(void)Ap;
876
(void)sv;
877
(void)svThreshold;
878
(void)imA;
879
(void)imAt;
880
(void)kerAt;
881
throw
(
vpException
(
vpException::fatalError
,
"Cannot compute pseudo-inverse. "
882
"Install Lapack, Eigen3 or OpenCV 3rd party"
));
883
#endif
884
}
885
996
int
vpMatrix::pseudoInverse
(
vpMatrix
&Ap,
vpColVector
&sv,
int
rank_in,
vpMatrix
&imA,
vpMatrix
&imAt,
997
vpMatrix
&kerAt)
const
998
{
999
#if defined(VISP_HAVE_LAPACK)
1000
return
pseudoInverseLapack
(Ap, sv, rank_in, imA, imAt, kerAt);
1001
#elif defined(VISP_HAVE_EIGEN3)
1002
return
pseudoInverseEigen3
(Ap, sv, rank_in, imA, imAt, kerAt);
1003
#elif defined(VISP_HAVE_OPENCV)
// Require opencv >= 2.1.1
1004
return
pseudoInverseOpenCV
(Ap, sv, rank_in, imA, imAt, kerAt);
1005
#else
1006
(void)Ap;
1007
(void)sv;
1008
(void)rank_in;
1009
(void)imA;
1010
(void)imAt;
1011
(void)kerAt;
1012
throw
(
vpException
(
vpException::fatalError
,
"Cannot compute pseudo-inverse. "
1013
"Install Lapack, Eigen3 or OpenCV 3rd party"
));
1014
#endif
1015
}
1016
1029
vpMatrix
vpMatrix::dampedInverse
(
const
double
&ratioOfMaxSvd)
const
1030
{
1031
vpColVector
w;
1032
vpMatrix
V, Mcpy(*
this
);
1033
Mcpy.
svd
(w, V);
1034
double
maxSingularValue = w.getMaxValue();
1035
vpMatrix
I;
1036
I.eye(this->
colNum
);
1037
double
lambda = ratioOfMaxSvd * maxSingularValue;
1038
vpMatrix
dampedInv = ((lambda * I) + (this->
transpose
() * (*this))).
inverseByLU
()* this->
transpose
();
1039
return
dampedInv;
1040
}
1041
1042
END_VISP_NAMESPACE
vpArray2D::resize
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition
vpArray2D.h:448
vpArray2D::size
unsigned int size() const
Return the number of elements of the 2D array.
Definition
vpArray2D.h:435
vpArray2D::getRows
unsigned int getRows() const
Definition
vpArray2D.h:433
vpArray2D< double >::colNum
unsigned int colNum
Definition
vpArray2D.h:1203
vpColVector
Implementation of column vector and the associated operations.
Definition
vpColVector.h:191
vpException
error that can be emitted by ViSP classes.
Definition
vpException.h:60
vpException::fatalError
@ fatalError
Fatal error.
Definition
vpException.h:72
vpMatrix
Implementation of a matrix and operations on matrices.
Definition
vpMatrix.h:175
vpMatrix::pseudoInverseOpenCV
vpMatrix pseudoInverseOpenCV(double svThreshold=1e-6) const
vpMatrix::pseudoInverseEigen3
vpMatrix pseudoInverseEigen3(double svThreshold=1e-6) const
vpMatrix::dampedInverse
vpMatrix dampedInverse(const double &ratioOfMaxSvd=1e-4) const
Definition
vpMatrix_pseudo_inverse.cpp:1029
vpMatrix::inverseByLU
vpMatrix inverseByLU() const
Definition
vpMatrix_lu.cpp:130
vpMatrix::svd
void svd(vpColVector &w, vpMatrix &V)
Definition
vpMatrix_svd.cpp:259
vpMatrix::vpMatrix
vpMatrix()
Definition
vpMatrix.h:191
vpMatrix::pseudoInverseLapack
vpMatrix pseudoInverseLapack(double svThreshold=1e-6) const
vpMatrix::pseudoInverse
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Definition
vpMatrix_pseudo_inverse.cpp:336
vpMatrix::transpose
vpMatrix transpose() const
Definition
vpMatrix_operations.cpp:53
BEGIN_VISP_NAMESPACE
Definition
vpMbtDistanceCircle.cpp:55
yolo-centering-task-afma6.j
j
Definition
yolo-centering-task-afma6.py:329
yolo-centering-task-afma6.i
i
Definition
yolo-centering-task-afma6.py:329
modules
core
src
math
matrix
vpMatrix_pseudo_inverse.cpp
Generated by
1.17.0