g2o
Toggle main menu visibility
Loading...
Searching...
No Matches
g2o
core
optimization_algorithm_levenberg.cpp
Go to the documentation of this file.
1
// g2o - General Graph Optimization
2
// Copyright (C) 2011 R. Kuemmerle, G. Grisetti, W. Burgard
3
// All rights reserved.
4
//
5
// Redistribution and use in source and binary forms, with or without
6
// modification, are permitted provided that the following conditions are
7
// met:
8
//
9
// * Redistributions of source code must retain the above copyright notice,
10
// this list of conditions and the following disclaimer.
11
// * Redistributions in binary form must reproduce the above copyright
12
// notice, this list of conditions and the following disclaimer in the
13
// documentation and/or other materials provided with the distribution.
14
//
15
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27
#include "
optimization_algorithm_levenberg.h
"
28
29
#include <cassert>
30
#include <iostream>
31
32
#include "
batch_stats.h
"
33
#include "
g2o/stuff/logger.h
"
34
#include "
g2o/stuff/timeutil.h
"
35
#include "
solver.h
"
36
#include "
sparse_optimizer.h
"
37
using namespace
std
;
38
39
namespace
g2o
{
40
41
OptimizationAlgorithmLevenberg::OptimizationAlgorithmLevenberg
(
42
std::unique_ptr<Solver>
solver
)
43
:
OptimizationAlgorithmWithHessian
(*
solver
.get()),
44
_currentLambda
(
cst
(-1.)),
45
_tau
(
cst
(1e-5)),
46
_goodStepLowerScale
(
cst
(1. / 3.)),
47
_goodStepUpperScale
(
cst
(2. / 3.)),
48
_ni
(
cst
(2.)),
49
_levenbergIterations
(0),
50
m_solver
{
std
::move(
solver
)} {
51
_userLambdaInit
=
52
_properties
.makeProperty<
Property<double>
>(
"initialLambda"
, 0.);
53
_maxTrialsAfterFailure
=
54
_properties
.makeProperty<
Property<int>
>(
"maxTrialsAfterFailure"
, 10);
55
}
56
57
OptimizationAlgorithmLevenberg::~OptimizationAlgorithmLevenberg
() {}
58
59
OptimizationAlgorithm::SolverResult
OptimizationAlgorithmLevenberg::solve
(
60
int
iteration,
bool
online) {
61
assert(
_optimizer
&&
"_optimizer not set"
);
62
assert(
_solver
.optimizer() ==
_optimizer
&&
63
"underlying linear solver operates on different graph"
);
64
65
if
(iteration == 0 &&
66
!online) {
// built up the CCS structure, here due to easy time measure
67
bool
ok =
_solver
.buildStructure();
68
if
(!ok) {
69
G2O_WARN
(
"{}: Failure while building CCS structure"
,
__PRETTY_FUNCTION__
);
70
return
OptimizationAlgorithm::Fail;
71
}
72
}
73
74
double
t =
get_monotonic_time
();
75
_optimizer
->computeActiveErrors();
76
G2OBatchStatistics
* globalStats =
G2OBatchStatistics::globalStats
();
77
if
(globalStats) {
78
globalStats->
timeResiduals
=
get_monotonic_time
() - t;
79
t =
get_monotonic_time
();
80
}
81
82
double
currentChi =
_optimizer
->activeRobustChi2();
83
84
_solver
.buildSystem();
85
if
(globalStats) {
86
globalStats->
timeQuadraticForm
=
get_monotonic_time
() - t;
87
}
88
89
// core part of the Levenbarg algorithm
90
if
(iteration == 0) {
91
_currentLambda
=
computeLambdaInit
();
92
_ni
= 2;
93
}
94
95
double
rho = 0;
96
int
& qmax =
_levenbergIterations
;
97
qmax = 0;
98
do
{
99
_optimizer
->push();
100
if
(globalStats) {
101
globalStats->
levenbergIterations
++;
102
t =
get_monotonic_time
();
103
}
104
// update the diagonal of the system matrix
105
_solver
.setLambda(
_currentLambda
,
true
);
106
bool
ok2 =
_solver
.solve();
107
if
(globalStats) {
108
globalStats->
timeLinearSolution
+=
get_monotonic_time
() - t;
109
t =
get_monotonic_time
();
110
}
111
_optimizer
->update(
_solver
.x());
112
if
(globalStats) {
113
globalStats->
timeUpdate
=
get_monotonic_time
() - t;
114
}
115
116
// restore the diagonal
117
_solver
.restoreDiagonal();
118
119
_optimizer
->computeActiveErrors();
120
double
tempChi =
_optimizer
->activeRobustChi2();
121
122
if
(!ok2) tempChi = std::numeric_limits<double>::max();
123
124
rho = (currentChi - tempChi);
125
double
scale =
126
ok2 ?
computeScale
() +
cst
(1e-3) : 1;
// make sure it's non-zero :)
127
rho /= scale;
128
129
if
(rho > 0 &&
g2o_isfinite
(tempChi) && ok2) {
// last step was good
130
double
alpha = 1. - pow((2 * rho - 1), 3);
131
// crop lambda between minimum and maximum factors
132
alpha = (std::min)(alpha,
_goodStepUpperScale
);
133
double
scaleFactor = (std::max)(
_goodStepLowerScale
, alpha);
134
_currentLambda
*= scaleFactor;
135
_ni
= 2;
136
currentChi = tempChi;
137
_optimizer
->discardTop();
138
}
else
{
139
_currentLambda
*=
_ni
;
140
_ni
*= 2;
141
_optimizer
->pop();
// restore the last state before trying to optimize
142
if
(!
g2o_isfinite
(
_currentLambda
))
break
;
143
}
144
qmax++;
145
}
while
(rho < 0 && qmax < _maxTrialsAfterFailure->value() &&
146
!
_optimizer
->terminate());
147
148
if
(qmax ==
_maxTrialsAfterFailure
->value() || rho == 0 ||
149
!
g2o_isfinite
(
_currentLambda
))
150
return
Terminate
;
151
return
OK
;
152
}
153
154
double
OptimizationAlgorithmLevenberg::computeLambdaInit
()
const
{
155
if
(
_userLambdaInit
->value() > 0)
return
_userLambdaInit
->value();
156
double
maxDiagonal = 0;
157
for
(
size_t
k = 0; k <
_optimizer
->indexMapping().size(); k++) {
158
OptimizableGraph::Vertex
* v =
_optimizer
->indexMapping()[k];
159
assert(v);
160
int
dim = v->
dimension
();
161
for
(
int
j = 0; j < dim; ++j) {
162
maxDiagonal = std::max(fabs(v->
hessian
(j, j)), maxDiagonal);
163
}
164
}
165
return
_tau
* maxDiagonal;
166
}
167
168
double
OptimizationAlgorithmLevenberg::computeScale
()
const
{
169
double
scale = 0;
170
for
(
size_t
j = 0; j <
_solver
.vectorSize(); j++) {
171
scale +=
172
_solver
.x()[j] * (
_currentLambda
*
_solver
.x()[j] +
_solver
.b()[j]);
173
}
174
return
scale;
175
}
176
177
void
OptimizationAlgorithmLevenberg::setMaxTrialsAfterFailure
(
int
max_trials) {
178
_maxTrialsAfterFailure
->setValue(max_trials);
179
}
180
181
void
OptimizationAlgorithmLevenberg::setUserLambdaInit
(
double
lambda) {
182
_userLambdaInit
->setValue(lambda);
183
}
184
185
void
OptimizationAlgorithmLevenberg::printVerbose
(std::ostream& os)
const
{
186
os <<
"\t schur= "
<<
_solver
.schur()
187
<<
"\t lambda= "
<< FIXED(
_currentLambda
)
188
<<
"\t levenbergIter= "
<<
_levenbergIterations
;
189
}
190
191
}
// namespace g2o
batch_stats.h
g2o::OptimizableGraph::Vertex
A general case Vertex for optimization.
Definition
optimizable_graph.h:108
g2o::OptimizableGraph::Vertex::hessian
virtual const double & hessian(int i, int j) const =0
get the element from the hessian matrix
g2o::OptimizableGraph::Vertex::dimension
int dimension() const
dimension of the estimated state belonging to this node
Definition
optimizable_graph.h:348
g2o::OptimizationAlgorithmLevenberg::_userLambdaInit
Property< double > * _userLambdaInit
Definition
optimization_algorithm_levenberg.h:77
g2o::OptimizationAlgorithmLevenberg::setMaxTrialsAfterFailure
void setMaxTrialsAfterFailure(int max_trials)
Definition
optimization_algorithm_levenberg.cpp:177
g2o::OptimizationAlgorithmLevenberg::_goodStepUpperScale
double _goodStepUpperScale
Definition
optimization_algorithm_levenberg.h:82
g2o::OptimizationAlgorithmLevenberg::_maxTrialsAfterFailure
Property< int > * _maxTrialsAfterFailure
Definition
optimization_algorithm_levenberg.h:76
g2o::OptimizationAlgorithmLevenberg::computeLambdaInit
double computeLambdaInit() const
Definition
optimization_algorithm_levenberg.cpp:154
g2o::OptimizationAlgorithmLevenberg::_levenbergIterations
int _levenbergIterations
Definition
optimization_algorithm_levenberg.h:85
g2o::OptimizationAlgorithmLevenberg::m_solver
std::unique_ptr< Solver > m_solver
Definition
optimization_algorithm_levenberg.h:96
g2o::OptimizationAlgorithmLevenberg::OptimizationAlgorithmLevenberg
OptimizationAlgorithmLevenberg(std::unique_ptr< Solver > solver)
Definition
optimization_algorithm_levenberg.cpp:41
g2o::OptimizationAlgorithmLevenberg::_goodStepLowerScale
double _goodStepLowerScale
Definition
optimization_algorithm_levenberg.h:80
g2o::OptimizationAlgorithmLevenberg::printVerbose
virtual void printVerbose(std::ostream &os) const
Definition
optimization_algorithm_levenberg.cpp:185
g2o::OptimizationAlgorithmLevenberg::solve
virtual SolverResult solve(int iteration, bool online=false)
Definition
optimization_algorithm_levenberg.cpp:59
g2o::OptimizationAlgorithmLevenberg::_ni
double _ni
Definition
optimization_algorithm_levenberg.h:84
g2o::OptimizationAlgorithmLevenberg::~OptimizationAlgorithmLevenberg
virtual ~OptimizationAlgorithmLevenberg()
Definition
optimization_algorithm_levenberg.cpp:57
g2o::OptimizationAlgorithmLevenberg::setUserLambdaInit
void setUserLambdaInit(double lambda)
Definition
optimization_algorithm_levenberg.cpp:181
g2o::OptimizationAlgorithmLevenberg::computeScale
double computeScale() const
Definition
optimization_algorithm_levenberg.cpp:168
g2o::OptimizationAlgorithmLevenberg::_tau
double _tau
Definition
optimization_algorithm_levenberg.h:79
g2o::OptimizationAlgorithmLevenberg::_currentLambda
double _currentLambda
Definition
optimization_algorithm_levenberg.h:78
g2o::OptimizationAlgorithmWithHessian::solver
Solver & solver()
return the underlying solver used to solve the linear system
Definition
optimization_algorithm_with_hessian.h:61
g2o::OptimizationAlgorithmWithHessian::OptimizationAlgorithmWithHessian
OptimizationAlgorithmWithHessian(Solver &solver)
Definition
optimization_algorithm_with_hessian.cpp:39
g2o::OptimizationAlgorithmWithHessian::_solver
Solver & _solver
Definition
optimization_algorithm_with_hessian.h:70
g2o::OptimizationAlgorithm::_optimizer
SparseOptimizer * _optimizer
the optimizer the solver is working on
Definition
optimization_algorithm.h:109
g2o::OptimizationAlgorithm::_properties
PropertyMap _properties
Definition
optimization_algorithm.h:110
g2o::Property
Definition
property.h:52
G2O_WARN
#define G2O_WARN(...)
logger.h
g2o_isfinite
#define g2o_isfinite(x)
Definition
macros.h:102
__PRETTY_FUNCTION__
#define __PRETTY_FUNCTION__
Definition
macros.h:90
g2o
Definition
dl_wrapper.cpp:55
g2o::cst
constexpr double cst(long double v)
Definition
misc.h:60
g2o::get_monotonic_time
double get_monotonic_time()
Definition
timeutil.cpp:43
std
Definition
jet.h:876
Terminate
Terminate
Definition
optimization_algorithm.h:48
OK
OK
Definition
optimization_algorithm.h:48
optimization_algorithm_levenberg.h
solver.h
sparse_optimizer.h
g2o::G2OBatchStatistics
statistics about the optimization
Definition
batch_stats.h:40
g2o::G2OBatchStatistics::timeLinearSolution
double timeLinearSolution
Definition
batch_stats.h:59
g2o::G2OBatchStatistics::timeResiduals
double timeResiduals
residuals
Definition
batch_stats.h:49
g2o::G2OBatchStatistics::globalStats
static G2OBatchStatistics * globalStats()
Definition
batch_stats.h:77
g2o::G2OBatchStatistics::timeUpdate
double timeUpdate
time to apply the update
Definition
batch_stats.h:64
g2o::G2OBatchStatistics::levenbergIterations
int levenbergIterations
number of iterations performed by LM
Definition
batch_stats.h:52
g2o::G2OBatchStatistics::timeQuadraticForm
double timeQuadraticForm
construct the quadratic form in the graph
Definition
batch_stats.h:51
timeutil.h
utility functions for handling time related stuff
Generated on
for g2o by
1.17.0