00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <cstdlib>
00021 #include <iomanip>
00022 #include <cmath>
00023
00024 #include <boost/numeric/ublas/io.hpp>
00025 #include <boost/numeric/ublas/vector.hpp>
00026 #include <boost/numeric/ublas/vector_proxy.hpp>
00027 #include <boost/numeric/ublas/matrix.hpp>
00028 #include <boost/numeric/ublas/matrix_proxy.hpp>
00029 #include <boost/numeric/bindings/traits/ublas_matrix.hpp>
00030 #include <boost/numeric/bindings/traits/ublas_vector.hpp>
00031 #include <boost/numeric/bindings/lapack/lapack.hpp>
00032 #include <boost/numeric/ublas/symmetric.hpp>
00033
00034 #include "uvsim/utilities/utilities.h"
00035 #include "uvsim/visualization/PointCloud.h"
00036 #include "uvsim/visualization/SimpleViewer.h"
00037 #include "uvsim/visualization/Ellipsoid.h"
00038 #include <cmath>
00039
00040 using namespace boost::numeric::ublas;
00041 using namespace uvsim;
00042 using namespace boost::numeric::bindings::lapack;
00043
00044 double abs(double x)
00045 {
00046 if (x<0) return -x;
00047 else return x;
00048 }
00049
00050 double costFunc(vector<double> x, vector<double> y, vector<double> z, int n, vector<double> center, vector<double> radii)
00051 {
00052 double cost = 0, p, t;
00053 vector<double> unit(3), point(3);
00054 for (int i=0;i<n;i++)
00055 {
00056 point(0) = x(i);
00057 point(1) = y(i);
00058 point(2) = z(i);
00059 unit = (point-center)/norm_2(point-center);
00060 t = sqrt(1/(
00061 unit(0)*unit(0)/(radii(0)*radii(0)) +
00062 unit(1)*unit(1)/(radii(1)*radii(1)) +
00063 unit(2)*unit(2)/(radii(2)*radii(2))
00064 ));
00065 p = norm_2(point-center);
00066 cost = cost + abs(p-t);
00067
00068
00069
00070
00071
00072
00073
00074
00075 }
00076 return cost;
00077 }
00078
00079 void nonlinSolv(vector<double> initialGuess, vector<double> &solution)
00080 {
00081
00082 }
00083
00084 int main (int argc, char const* argv[])
00085 {
00086
00087 const static int freqImu = 520, freqMagCalib = 100;
00088 int maxN = 1000;
00089 int fps = 20;
00090 osg::Vec3d manipCenter(512,512,512);
00091 double manipDistance = 1000;
00092 float frameSize = 5;
00093
00094
00095 const static int freqRatio = freqImu/freqMagCalib;
00096 std::cout << "Frequency Ratio: " << freqRatio << std::endl;
00097 if (freqRatio <=0)
00098 {
00099 std::cout << "The frequency of the imu: " << freqImu
00100 << " must be faster than that of the calibration: " <<
00101 freqMagCalib << "." << std::endl;
00102 exit(-1);
00103 }
00104
00105
00106 vector<double> x(maxN), y(maxN), z(maxN), center(3), radii(3), bias(3), scaleFactor(3);
00107 matrix<double> temp(6,6);
00108
00109
00110 srand(time(0));
00111
00112
00113 int n = 0;
00114
00115
00116 osg::Group *root = new osg::Group;
00117 double fogStart=100, fogEnd=1000;
00118 SimpleViewer simpleViewer(0,fps,root,manipDistance,manipCenter,frameSize,10000,100000);
00119 simpleViewer.start();
00120
00121
00122 double a, b, c, cx, cy, cz, nx, ny, nz, r1, r2;
00123
00124
00125 a = 100;
00126 b = 100;
00127 c = 100;
00128
00129
00130 cx = 512;
00131 cy = 512;
00132 cz = 512;
00133
00134
00135 nx = 10;
00136 ny = 10;
00137 nz = 10;
00138
00139
00140 r1 = .25;
00141 r2 = .5;
00142
00143
00144 Ellipsoid *linearEllipsoid, *trueEllipsoid, *nonlinearEllipsoid;
00145 trueEllipsoid = new Ellipsoid(osg::Vec3d(a,b,c),osg::Vec3d(cx,cy,cz),3,osg::Vec4d(255,255,102,1));
00146 root->addChild(trueEllipsoid->pointCloud->root.get());
00147
00148
00149 osg::Vec3Array *points = new osg::Vec3Array;
00150 osg::Vec4Array *colors = new osg::Vec4Array;
00151 PointCloud *pointCloud = new PointCloud(5,points,colors);
00152 root->addChild((pointCloud->root).get());
00153
00154
00155 n = 0;
00156 for (double theta=0;theta<r1*2*M_PI;theta+=M_PI/40)
00157 {
00158 for (double phi=0;phi<r2*M_PI;phi+=M_PI/20)
00159 {
00160 x(n) = a*sin(phi)*cos(theta) + cx + nx*(rand()/float(RAND_MAX)-0.5);
00161 y(n) = b*sin(phi)*sin(theta) + cy + ny*(rand()/float(RAND_MAX)-0.5);
00162 z(n) = c*cos(phi) + cz + nz*(rand()/float(RAND_MAX)-0.5);
00163 std::cout << "n: " << n;
00164 std::cout << "\tx,y,z: " << x(n) << ", " << y(n) << ", " << z(n) << std::endl;
00165
00166
00167 points->push_back(osg::Vec3(x(n),y(n),z(n)));
00168 colors->push_back(osg::Vec4(1,0,0,1));
00169
00170
00171 if (n++ > maxN)
00172 {
00173 std::cout << "Too many points." << std::endl;
00174 exit(1);
00175 };
00176 }
00177 }
00178 pointCloud->updateSize();
00179
00180
00181 std::cout << "Creating design matrix." << std::endl;
00182 matrix<double> D(n,6);
00183 for (int i=0;i<n;i++)
00184 {
00185 D(i,0) = x(i)*x(i);
00186 D(i,1) = y(i)*y(i);
00187 D(i,2) = z(i)*z(i);
00188 D(i,3) = 2*x(i);
00189 D(i,4) = 2*y(i);
00190 D(i,5) = 2*z(i);
00191 }
00192 std::cout << "Design matrix. " << std::endl;
00193 std::cout << "D: " << D << std::endl;
00194
00195
00196 if (n < 1000)
00197 {
00198 std::cout << "Solving for bias and scale factors. " << std::endl;
00199 matrix<double> v(6,1);
00200 matrix<double> K(3,3);
00201 K(0,0) = 1;
00202 K(1,2) = 3;
00203 K(2,0) =.3;
00204 K(1,1) =.4;
00205 std::cout << K << std::endl;
00206 std::cout << pinv(K) << std::endl;
00207 v = prod(pinv(D),ones(n,1));
00208 double gam = 1 + ( v(3,0)*v(3,0) / v(0,0) + v(4,0)*v(4,0) / v(1,0) +
00209 v(5,0)*v(5,0) / v(2,0) );
00210 for (int i=0;i<3;i++)
00211 {
00212 center(i) = -v(i+3,0)/v(i,0);
00213 bias(i) = -center(i);
00214 radii(i) = sqrt(gam/v(i,0));
00215 scaleFactor(i) = 1/radii(i);
00216 }
00217
00218
00219 std::cout << std::setprecision(8);
00220 std::cout << "v: " << v << std::endl;
00221 std::cout << "center: " << center << std::endl;
00222 std::cout << "radii: " << radii << std::endl;
00223 std::cout << "bias: " << bias << std::endl;
00224 std::cout << "scale factor: " << scaleFactor << std::endl;
00225
00226
00227 linearEllipsoid = new Ellipsoid(osg::Vec3d(radii(0),radii(1),radii(2)),osg::Vec3d(center(0),center(1),center(2)));
00228 root->addChild(linearEllipsoid->pointCloud->root.get());
00229 }
00230 else
00231 {
00232 std::cout << "N too large to compute svd" << std::endl;
00233 }
00234
00235
00236 vector<double> centerNL(3), radiiNL(3);
00237 centerNL = center;
00238 radiiNL = 1.1*radii;
00239 std::cout << "cost: " << costFunc(x,y,z,n,centerNL,radiiNL) << std::endl;
00240
00241
00242 nonlinearEllipsoid = new Ellipsoid(osg::Vec3d(radiiNL(0),radiiNL(1),radiiNL(2)),
00243 osg::Vec3d(centerNL(0),centerNL(1),centerNL(2)),3,osg::Vec4d(0,0,1,1));
00244 root->addChild(nonlinearEllipsoid->pointCloud->root.get());
00245
00246 simpleViewer.join();
00247 return 0;
00248 }
00249
00250