169 lines
4.4 KiB
Text
169 lines
4.4 KiB
Text
|
/*
|
||
|
* elch6Dslerp implementation
|
||
|
*
|
||
|
* Copyright (C) Jochen Sprickerhof
|
||
|
*
|
||
|
* Released under the GPL version 3.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @file ELCH implementation using SLERP
|
||
|
* @author Jochen Sprickerhof. Institute of Computer Science, University of Osnabrueck, Germany.
|
||
|
*/
|
||
|
|
||
|
#include "slam6d/elch6Dslerp.h"
|
||
|
|
||
|
#include "slam6d/metaScan.h"
|
||
|
#include "slam6d/lum6Dquat.h"
|
||
|
#include "slam6d/globals.icc"
|
||
|
|
||
|
#include <iostream>
|
||
|
using std::cout;
|
||
|
using std::cerr;
|
||
|
using std::endl;
|
||
|
|
||
|
#include <fstream>
|
||
|
using std::ofstream;
|
||
|
|
||
|
#include <cstring>
|
||
|
|
||
|
#include <boost/graph/graph_traits.hpp>
|
||
|
using boost::graph_traits;
|
||
|
using namespace NEWMAT;
|
||
|
/**
|
||
|
* ELCH loop closing function using SLERP
|
||
|
* matches first and last scan of a loop with ICP
|
||
|
* distributes the error
|
||
|
*
|
||
|
* @param allScans all laser scans
|
||
|
* @param first index of first laser scan in the loop
|
||
|
* @param last indes of last laser scan in the loop
|
||
|
* @param g graph for loop optimization
|
||
|
*/
|
||
|
void elch6Dslerp::close_loop(const vector <Scan *> &allScans, int first, int last, graph_t &g)
|
||
|
{
|
||
|
int n = num_vertices(g);
|
||
|
graph_t grb[4];
|
||
|
graph_traits <graph_t>::edge_iterator ei = edges(g).first;
|
||
|
int num_arcs = num_edges(g);
|
||
|
int li = 0;
|
||
|
#ifdef _OPENMP
|
||
|
#pragma omp parallel for firstprivate(li, ei)
|
||
|
#endif
|
||
|
for(int i = 0; i < num_arcs; i++) {
|
||
|
for(;i > li; li++, ei++) ;
|
||
|
for(;i < li; li--, ei--) ;
|
||
|
Matrix C(7, 7);
|
||
|
int from = source(*ei, g);
|
||
|
int to = target(*ei, g);
|
||
|
lum6DQuat::covarianceQuat(allScans[from], allScans[to], my_icp6D->get_nns_method(), my_icp6D->get_rnd(), my_icp6D->get_max_dist_match2(), &C);
|
||
|
C = C.i();
|
||
|
for(int j = 0; j < 3; j++) {
|
||
|
#ifdef _OPENMP
|
||
|
#pragma omp critical
|
||
|
#endif
|
||
|
add_edge(from, to, fabs(C(j + 1, j + 1)), grb[j]);
|
||
|
}
|
||
|
#ifdef _OPENMP
|
||
|
#pragma omp critical
|
||
|
#endif
|
||
|
add_edge(from, to, fabs(C(4, 4)) + fabs(C(5, 5)) + fabs(C(6, 6)) + fabs(C(7, 7)), grb[3]);
|
||
|
li++;
|
||
|
ei++;
|
||
|
}
|
||
|
|
||
|
double *weights[4];
|
||
|
for(int i = 0; i < 4; i++) {
|
||
|
weights[i] = new double[n];
|
||
|
graph_balancer(grb[i], first, last, weights[i]);
|
||
|
}
|
||
|
|
||
|
vector <Scan *> meta_start;
|
||
|
for(int i = first - 2; i <= first + 2; i++) {
|
||
|
if(i >= 0) {
|
||
|
meta_start.push_back(allScans[i]);
|
||
|
}
|
||
|
}
|
||
|
MetaScan *start = new MetaScan(meta_start, false, false);
|
||
|
|
||
|
//static size of metascan
|
||
|
int offset_last_start = 2;
|
||
|
int offset_last_end = 0;
|
||
|
|
||
|
vector <Scan *> meta_end;
|
||
|
for(int i = last - offset_last_start; i <= last + offset_last_end && i < n; i++) {
|
||
|
meta_end.push_back(allScans[i]);
|
||
|
}
|
||
|
MetaScan *end = new MetaScan(meta_end, false, false);
|
||
|
|
||
|
double Pl0[16];
|
||
|
memcpy(Pl0, allScans[last]->get_transMat(), 16 * sizeof(double));
|
||
|
|
||
|
my_icp6D->match(start, end);
|
||
|
|
||
|
delete start;
|
||
|
delete end;
|
||
|
|
||
|
// store ICP
|
||
|
double Pp0[16];
|
||
|
memcpy(Pp0, allScans[last]->get_transMat(), 16 * sizeof(double));
|
||
|
|
||
|
//compute Delta
|
||
|
double Pf0[16], Pf0_inv[16], tmp1[16], tmp2[16], deltaf[16];
|
||
|
memcpy(Pf0, allScans[first]->get_transMat(), 16 * sizeof(double));
|
||
|
M4inv(Pf0, Pf0_inv);
|
||
|
|
||
|
MMult(Pf0_inv, Pl0, tmp1);
|
||
|
M4inv(tmp1, tmp2);
|
||
|
MMult(Pp0, tmp2, tmp1);
|
||
|
MMult(Pf0_inv, tmp1, deltaf);
|
||
|
|
||
|
double deltaT[3], deltaQ[4];
|
||
|
Matrix4ToQuat(deltaf, deltaQ, deltaT);
|
||
|
|
||
|
if(!quiet) {
|
||
|
double axisangle[4];
|
||
|
axisangle[0] = deltaQ[0];
|
||
|
axisangle[1] = deltaQ[1];
|
||
|
axisangle[2] = deltaQ[2];
|
||
|
axisangle[3] = deltaQ[3];
|
||
|
QuatToAA(axisangle);
|
||
|
cout << "Delta: " << deltaT[0] << " " << deltaT[1] << " " << deltaT[2] << " " << axisangle[0] << " " << axisangle[1] << " " << axisangle[2] << " " << axisangle[3] << endl;
|
||
|
}
|
||
|
|
||
|
//transform scans
|
||
|
double idQ[4] = {1, 0, 0, 0}, rPos[3], rPosQuat[4], delta0[16];
|
||
|
|
||
|
rPos[0] = deltaT[0] * weights[0][0];
|
||
|
rPos[1] = deltaT[1] * weights[1][0];
|
||
|
rPos[2] = deltaT[2] * weights[2][0];
|
||
|
slerp(idQ, deltaQ, weights[3][0], rPosQuat);
|
||
|
QuatToMatrix4(rPosQuat, rPos, tmp1);
|
||
|
M4inv(tmp1, tmp2);
|
||
|
MMult(Pf0, tmp2, delta0);
|
||
|
|
||
|
#ifdef _OPENMP
|
||
|
#pragma omp parallel for private(rPos, rPosQuat, tmp1, tmp2)
|
||
|
#endif
|
||
|
for(int i = 1; i < n; i++) {
|
||
|
if(i >= last - offset_last_start && i <= last + offset_last_end) {
|
||
|
MMult(delta0, Pf0_inv, tmp1);
|
||
|
} else {
|
||
|
rPos[0] = deltaT[0] * weights[0][i];
|
||
|
rPos[1] = deltaT[1] * weights[1][i];
|
||
|
rPos[2] = deltaT[2] * weights[2][i];
|
||
|
slerp(idQ, deltaQ, weights[3][i], rPosQuat);
|
||
|
QuatToMatrix4(rPosQuat, rPos, tmp1);
|
||
|
MMult(delta0, tmp1, tmp2);
|
||
|
MMult(tmp2, Pf0_inv, tmp1);
|
||
|
}
|
||
|
allScans[i]->transform(tmp1, Scan::ELCH, i == n-1 ? 2 : 1);
|
||
|
}
|
||
|
|
||
|
for(int i = 0; i < 4; i++) {
|
||
|
delete [] weights[i];
|
||
|
}
|
||
|
|
||
|
}
|