g2o
Loading...
Searching...
No Matches
Classes | Functions
static_dynamic_function_fit.cpp File Reference
#include <random>
#include <unsupported/Eigen/Polynomials>
#include "g2o/core/base_binary_edge.h"
#include "g2o/core/base_dynamic_vertex.h"
#include "g2o/core/base_unary_edge.h"
#include "g2o/core/base_vertex.h"
#include "g2o/core/block_solver.h"
#include "g2o/core/optimization_algorithm_levenberg.h"
#include "g2o/core/sparse_optimizer.h"
#include "g2o/solvers/eigen/linear_solver_eigen.h"
#include "g2o/stuff/sampler.h"
Include dependency graph for static_dynamic_function_fit.cpp:

Go to the source code of this file.

Classes

class  FPolynomialCoefficientVertex
 
class  PPolynomialCoefficientVertex
 
struct  FunctionObservation
 
class  MultipleValueEdge
 

Functions

int main (int argc, const char *argv[])
 

Function Documentation

◆ main()

int main ( int  argc,
const char *  argv[] 
)

Definition at line 172 of file static_dynamic_function_fit.cpp.

172 {
173 // Random number generator
174 std::default_random_engine generator;
175
176 // Create the coefficients for the f-polynomial (all drawn randomly)
177 Eigen::Vector3d f;
178 for (int i = 0; i < 3; ++i) {
179 f[i] = g2o::sampleUniform(-1, 1);
180 }
181
182 // Number of dimensions of the polynomial; the default is 4
183 int polynomialDimension = 4;
184 if (argc > 1) {
185 polynomialDimension = atoi(argv[1]);
186 }
187
188 // Create the coefficients for the polynomial (all drawn randomly)
189 Eigen::VectorXd p(polynomialDimension);
190 for (int i = 0; i < polynomialDimension; ++i) {
191 p[i] = g2o::sampleUniform(-1, 1);
192 }
193
194 std::cout << "Ground truth vectors f=" << f.transpose()
195 << "; p=" << p.transpose() << std::endl;
196
197 // The number of observations in the polynomial; the defaultis 6
198 int obs = 6;
199 if (argc > 2) {
200 obs = atoi(argv[2]);
201 }
202
203 // The number of observations will be randomly sampled each time.
204
205 // Sample the observations. This is a set of function
206 // observations. The cardinality of each observation set is random.
207 double sigmaZ = 0.1;
208 std::vector<FunctionObservation> observations(obs);
209 std::uniform_int_distribution<int> cardinalitySampler(1, 5);
210
211 for (int i = 0; i < obs; ++i) {
212 FunctionObservation& fo = observations[i];
213 int numObs = cardinalitySampler(generator);
214 fo.x.resize(numObs);
215 fo.z.resize(numObs);
216 for (int o = 0; o < numObs; ++o) {
217 fo.x[o] = g2o::sampleUniform(-5, 5);
218 double x3 = pow(fo.x[o], 3);
219 fo.z[o] = Eigen::poly_eval(f, fo.x[o]) +
220 x3 * (Eigen::poly_eval(p, fo.x[o])) +
221 sigmaZ * g2o::sampleGaussian();
222 }
223 }
224
225 // Construct the graph and set up the solver and optimiser
226 std::unique_ptr<g2o::BlockSolverX::LinearSolverType> linearSolver =
227 std::make_unique<
229
230 // Set up the solver
231 std::unique_ptr<g2o::BlockSolverX> blockSolver =
232 std::make_unique<g2o::BlockSolverX>(std::move(linearSolver));
233
234 // Set up the optimisation algorithm
235 g2o::OptimizationAlgorithm* optimisationAlgorithm =
236 new g2o::OptimizationAlgorithmLevenberg(std::move(blockSolver));
237
238 // Create the graph and configure it
239 std::unique_ptr<g2o::SparseOptimizer> optimizer =
240 std::make_unique<g2o::SparseOptimizer>();
241 optimizer->setVerbose(true);
242 optimizer->setAlgorithm(optimisationAlgorithm);
243
244 // Create the f vertex; its dimensions are known
246 pf->setId(0);
247 optimizer->addVertex(pf);
248
249 // Create the vertex; note its dimension is currently is undefined
251 pv->setId(1);
252 optimizer->addVertex(pv);
253
254 // Create the information matrix
255 double omega = 1 / (sigmaZ * sigmaZ);
256
257 // Create the edges
258 for (int i = 0; i < obs; ++i) {
259 MultipleValueEdge* mve = new MultipleValueEdge(observations[i], omega);
260 mve->setVertex(0, pf);
261 mve->setVertex(1, pv);
262 optimizer->addEdge(mve);
263 }
264
265 // Now run the same optimization problem for different choices of
266 // dimension of the polynomial vertex. This shows how we can
267 // dynamically change the vertex dimensions in an alreacy
268 // constructed graph. Note that you must call initializeOptimization
269 // before you can optimize after a state dimension has changed.
270 for (int testDimension = 1; testDimension <= polynomialDimension;
271 ++testDimension) {
272 pv->setDimension(testDimension);
273 optimizer->initializeOptimization();
274 optimizer->optimize(10);
275 std::cout << "Computed parameters: f=" << pf->estimate().transpose()
276 << "; p=" << pv->estimate().transpose() << std::endl;
277 }
278 for (int testDimension = polynomialDimension - 1; testDimension >= 1;
279 --testDimension) {
280 pv->setDimension(testDimension);
281 optimizer->initializeOptimization();
282 optimizer->optimize(10);
283 std::cout << "Computed parameters: f= " << pf->estimate().transpose()
284 << "; p=" << pv->estimate().transpose() << std::endl;
285 }
286}
virtual bool setDimension(int newDimension)
const EstimateType & estimate() const
return the current estimate of the vertex
void setVertex(size_t i, Vertex *v)
linear solver which uses the sparse Cholesky solver from Eigen
Implementation of the Levenberg Algorithm.
Generic interface for a non-linear solver operating on a graph.
Jet< T, N > pow(const Jet< T, N > &f, double g)
Definition jet.h:743
double sampleUniform(double min, double max, std::mt19937 *generator)
Definition sampler.cpp:35
double sampleGaussian(std::mt19937 *generator)
Definition sampler.cpp:40

References g2o::BaseVertex< D, T >::estimate(), g2o::sampleGaussian(), g2o::sampleUniform(), g2o::BaseDynamicVertex< T >::setDimension(), g2o::OptimizableGraph::Vertex::setId(), g2o::HyperGraph::Edge::setVertex(), FunctionObservation::x, and FunctionObservation::z.