#include <visp/vpColVector.h>
#include <visp/vpExponentialMap.h>
#include <visp/vpHomogeneousMatrix.h>
#include <visp/vpMatrix.h>
vpHomogeneousMatrix pose_gauss_newton(
#if VISP_VERSION_INT >= VP_VERSION_INT(2, 10, 0)
const
#endif
std::vector< vpColVector > &wX, const std::vector< vpColVector > &x, const vpHomogeneousMatrix &cTw)
{
int npoints = (int)wX.size();
vpMatrix J(2*npoints, 6), Jp;
vpColVector err, sd(2*npoints), s(2*npoints), xq(npoints*2), xn(npoints*2);
vpHomogeneousMatrix cTw_ = cTw;
double residual=0, residual_prev, lambda = 0.25;
for (int i = 0; i < x.size(); i ++) {
xn[i*2] = x[i][0];
xn[i*2+1] = x[i][1];
}
do {
for (int i = 0; i < npoints; i++) {
vpColVector cX = cTw_ * wX[i];
double Xi = cX[0];
double Yi = cX[1];
double Zi = cX[2];
double xi = Xi / Zi;
double yi = Yi / Zi;
xq[i*2] = xi;
xq[i*2+1] = yi;
J[i*2][0] = -1 / Zi;
J[i*2][1] = 0;
J[i*2][2] = xi / Zi;
J[i*2][3] = xi * yi;
J[i*2][4] = -(1 + xi * xi);
J[i*2][5] = yi;
J[i*2+1][0] = 0;
J[i*2+1][1] = -1 / Zi;
J[i*2+1][2] = yi / Zi;
J[i*2+1][3] = 1 + yi * yi;
J[i*2+1][4] = -xi * yi;
J[i*2+1][5] = -xi;
}
vpColVector e_q = xq - xn;
J.pseudoInverse(Jp);
vpColVector dq = -lambda * Jp * e_q;
cTw_ = vpExponentialMap::direct(dq).inverse() * cTw_;
residual_prev = residual;
residual = e_q.sumSquare();
} while (fabs(residual - residual_prev) > 0);
return cTw_;
}
int main()
{
int npoints = 4;
std::vector< vpColVector > wX(npoints);
std::vector< vpColVector > x(npoints);
for (int i = 0; i < npoints; i++) {
wX[i].resize(4);
x[i].resize(3);
}
vpHomogeneousMatrix cTw_truth(-0.1, 0.1, 0.5, vpMath::rad(5), vpMath::rad(0), vpMath::rad(45));
double L = 0.2;
wX[0][0] = -L; wX[0][1] = -L; wX[0][2] = 0; wX[0][3] = 1;
wX[1][0] = 2*L; wX[1][1] = -L; wX[1][2] = 0; wX[1][3] = 1;
wX[2][0] = L; wX[2][1] = L; wX[2][2] = 0; wX[2][3] = 1;
wX[3][0] = -L; wX[3][1] = L; wX[3][2] = 0; wX[3][3] = 1;
for(int i = 0; i < npoints; i++) {
vpColVector cX = cTw_truth * wX[i];
x[i][0] = cX[0] / cX[2];
x[i][1] = cX[1] / cX[2];
x[i][2] = 1;
}
vpHomogeneousMatrix cTw(-0.05, 0.05, 0.45, vpMath::rad(1), vpMath::rad(0), vpMath::rad(35));
cTw = pose_gauss_newton(wX, x, cTw);
std::cout << "cTw (ground truth):\n" << cTw_truth << std::endl;
std::cout << "cTw (from non linear method):\n" << cTw << std::endl;
return 0;
}