00001 #ifndef ICP_GICP_HPP
00002 #define ICP_GICP_HPP
00003
00004 #include "jmath/jblas.hpp"
00005 #include "kernel/jafarMacro.hpp"
00006 #include "geom/t3dEuler.hpp"
00007 #include <lbfgs.h>
00008 #include <ANN.h>
00009 #include <gsl/gsl_vector.h>
00010 namespace jafar {
00011 namespace icp {
00021 class GICP {
00022 private:
00024 ANNpointArray m_model_points;
00026 ANNpointArray m_scene_points;
00028 ANNkd_tree *m_model_tree;
00029 ANNkd_tree *m_scene_tree;
00031 unsigned int m_model_nb_points;
00033 unsigned int m_scene_nb_points;
00034
00035 jblas::mat R,t;
00036 int m_K;
00037 double m_epsilon;
00038 double m_max_dist;
00040
00041 typedef std::vector< jblas::mat_column_major > covariances;
00042
00044 covariances m_scene_covs;
00046 covariances m_model_covs;
00048 int m_max_iter;
00050 int m_lbfgs_max_iter;
00052 lbfgs_parameter_t m_lbfgs_param;
00054 double m_lbfgs_ftol;
00056 double m_lbfgs_gtol;
00058 double* m_x;
00060 double m_fx;
00061 int nb_matches;
00062 geom::T3D *initial_t3d;
00063 geom::T3D *final_t3d;
00064 std::vector<jblas::mat_column_major> mahalanobis;
00065
00066
00067 ANNidx *indexes;
00068 std::vector< ANNdist > distances;
00069
00070 static double _evaluate(void* instance,
00071 const double *x,
00072 double *g,
00073 const int n,
00074 const double step);
00075 double evaluate(const double *x,
00076 double *g,
00077 const int n,
00078 const double step);
00079
00080 static int _progress(void* instance,
00081 const double *x,
00082 const double *g,
00083 const double fx,
00084 const double xnorm,
00085 const double gnorm,
00086 const double step,
00087 int n,
00088 int k,
00089 int ls);
00090
00091 int progress(const double *x,
00092 const double *g,
00093 const double fx,
00094 const double xnorm,
00095 const double gnorm,
00096 const double step,
00097 int n,
00098 int k,
00099 int ls);
00100
00101
00102 inline double trace_at_b(const jblas::mat &a, const jblas::mat& b) {
00103 JFR_ASSERT(a.size1() == b.size2(), "matrices need to be multipliable")
00104 double trace = 0.;
00105 int n = a.size1();
00106 for(int i = 0; i < n; i++)
00107 for(int j = 0; j < n; j++)
00108 trace+= a(j,i) * b(i,j);
00109
00110 return trace;
00111 }
00112
00113 public:
00114 GICP(size_t max_nb_points = 1024, double epsilon = 1e-3, double max_dist = 5.,
00115 int K = 20, int max_iter = 100,
00116 int inner_max_iter = 8, double ftol = 0.01, double gtol = 0.01) :
00117 m_K(K), m_epsilon(epsilon), m_max_dist(max_dist), m_max_iter(max_iter),
00118 m_lbfgs_max_iter(inner_max_iter), m_lbfgs_ftol(ftol), m_lbfgs_gtol(gtol),
00119 m_model_nb_points(0), m_scene_nb_points(0),
00120 mahalanobis(0),
00121 indexes(0),
00122 distances(0)
00123 {
00124 m_model_points = annAllocPts(max_nb_points, 3);
00125 m_scene_points = annAllocPts(max_nb_points, 3);
00126 }
00127
00128 GICP(const jblas::mat& model, jblas::mat& scene,
00129 double epsilon = 1e-3, double max_dist = 5.,
00130 int K = 20, int max_iter = 100,
00131 int inner_max_iter = 8, double ftol = 0.01, double gtol = 0.01) :
00132 m_K(K), m_epsilon(epsilon), m_max_dist(max_dist), m_max_iter(max_iter),
00133 m_lbfgs_max_iter(inner_max_iter), m_lbfgs_ftol(ftol), m_lbfgs_gtol(gtol),
00134
00135
00136 m_model_nb_points(model.size1()),
00137 m_scene_nb_points(scene.size1()),
00138 mahalanobis(0)
00139 {
00140 using namespace std;
00141 m_model_points = annAllocPts(m_model_nb_points, 3);
00142 m_scene_points = annAllocPts(m_scene_nb_points, 3);
00143 for (unsigned int mrow = 0; mrow < m_model_nb_points; mrow++) {
00144 m_model_points[mrow][0] = model(mrow,0);
00145 m_model_points[mrow][1] = model(mrow,1);
00146 m_model_points[mrow][2] = model(mrow,2);
00147 }
00148 cout << "loaded "<<m_model_nb_points<<" points for the model"<<endl;
00149 for (unsigned int srow = 0; srow < m_scene_nb_points; srow++) {
00150 m_scene_points[srow][0] = scene(srow,0);
00151 m_scene_points[srow][1] = scene(srow,1);
00152 m_scene_points[srow][2] = scene(srow,2);
00153 }
00154 cout << "loaded "<<m_scene_nb_points<<" points for the scene"<<endl;
00155 }
00156
00157 void addModelEntry(const jblas::vec3& entry)
00158 {
00159 m_model_points[m_model_nb_points][0] = entry[0];
00160 m_model_points[m_model_nb_points][1] = entry[1];
00161 m_model_points[m_model_nb_points][2] = entry[2];
00162 ++m_model_nb_points;
00163 }
00164
00165 void addSceneEntry(const jblas::vec3& entry)
00166 {
00167 m_scene_points[m_scene_nb_points][0] = entry[0];
00168 m_scene_points[m_scene_nb_points][1] = entry[1];
00169 m_scene_points[m_scene_nb_points][2] = entry[2];
00170 ++m_scene_nb_points;
00171 }
00172
00173 inline void transform(const geom::T3D* t, jblas::vec3& pt) {
00174 jblas::mat44 M = t->getM();
00175 assert(M(3,3) == 1);
00176 double x, y, z;
00177 x = (M(0,0) * pt[0]) + (M(0,1) * pt[1]) + (M(0,2) * pt[2]) + M(0,3);
00178 y = (M(1,0) * pt[0]) + (M(1,1) * pt[1]) + (M(1,2) * pt[2]) + M(1,3);
00179 z = (M(2,0) * pt[0]) + (M(2,1) * pt[1]) + (M(2,2) * pt[2]) + M(2,3);
00180 pt[0] = x;
00181 pt[1] = y;
00182 pt[2] = z;
00183 }
00184
00186 void computeCovarianceMatrices(const ANNpointArray& points,
00187 size_t nb_points,
00188 ANNkd_tree* points_tree,
00189 covariances& points_covariances);
00190
00192 int align(const ANNpointArray& model_points, unsigned int nb_model_points,
00193 const covariances& model_covariances,
00194 const ANNpointArray& scene_points, ANNkd_tree* scene_tree,
00195 const covariances& scene_covariances,
00196 const geom::T3D *guess, geom::T3D *t);
00197 int align_gsl(const ANNpointArray& model, unsigned int nb_model_points,
00198 const covariances& model_covariances,
00199 const ANNpointArray& scene, ANNkd_tree* scene_tree,
00200 const covariances& scene_covariances,
00201 const geom::T3D *guess, geom::T3D *t);
00203 void run(geom::T3DEuler *guess = NULL)
00204 {
00205 using namespace std;
00206
00207 m_model_tree = new ANNkd_tree(m_model_points, m_model_nb_points, 3, 10);
00208 cout << "m_model_index created" << endl;
00209 computeCovarianceMatrices(m_model_points, m_model_nb_points, m_model_tree, m_model_covs);
00210
00211 m_scene_tree = new ANNkd_tree(m_scene_points, m_scene_nb_points, 3, 10);
00212 cout << "m_scene_index created" << endl;
00213 computeCovarianceMatrices(m_scene_points, m_scene_nb_points, m_scene_tree, m_scene_covs);
00214
00215 final_t3d = geom::T3D::create(geom::T3D::EULER);
00216 initial_t3d = geom::T3D::create(geom::T3D::EULER);
00217 initial_t3d->set(jblas::identity_mat(3,3), jblas::zero_vec(3));
00218 final_t3d->set(jblas::identity_mat(3,3), jblas::zero_vec(3));
00219 if(guess != NULL)
00220 {
00221 initial_t3d = guess;
00222 }
00223
00224
00225
00226 align_gsl(m_model_points, m_model_nb_points, m_model_covs, m_scene_points, m_scene_tree, m_scene_covs, initial_t3d, final_t3d);
00227
00228 cout << "initial t3d" << initial_t3d->getM() << endl;
00229 cout << "final t3d" << final_t3d->getM() << endl;
00230 }
00231 double f(const gsl_vector *x, void *params);
00232 void df(const gsl_vector *x, void *params, gsl_vector *g);
00233 void fdf(const gsl_vector *x, void *params, double *f, gsl_vector *g);
00234 geom::T3D* get_final_t3d()
00235 {
00236 return final_t3d;
00237 }
00238 };
00239 }
00240 }
00241
00242 #endif