00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <mrpt/opengl.h>
00030
00031
00032 #include "CMyEllipsoid.h"
00033 #include <mrpt/math/CMatrix.h>
00034 #include <mrpt/math/geometry.h>
00035 #include <mrpt/math/ops_matrices.h>
00036
00037 #include "opengl_internals.h"
00038
00039 using namespace mrpt;
00040 using namespace mrpt::opengl;
00041 using namespace mrpt::utils;
00042 using namespace mrpt::math;
00043 using namespace std;
00044
00045 IMPLEMENTS_SERIALIZABLE( CMyEllipsoid, CRenderizableDisplayList, mrpt::opengl )
00046
00047
00048
00049
00050 void CMyEllipsoid::render_dl() const
00051 {
00052 #if MRPT_HAS_OPENGL_GLUT
00053 MRPT_START
00054
00055 const size_t dim = m_cov.getColCount();
00056
00057 if(m_eigVal(0,0) != 0.0 && m_eigVal(1,1) != 0.0 && (dim==2 || m_eigVal(2,2) != 0.0) && m_quantiles!=0.0)
00058 {
00059 glEnable(GL_BLEND);
00060 checkOpenGLError();
00061 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00062 checkOpenGLError();
00063 glLineWidth(m_lineWidth);
00064 checkOpenGLError();
00065
00066 if (dim==2)
00067 {
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 double ang;
00083 unsigned int i;
00084
00085
00086 CMatrixDouble M;
00087 M.noalias() = double(m_quantiles) * m_eigVal * m_eigVec.adjoint();
00088
00089 glBegin( GL_LINE_LOOP );
00090
00091
00092 for (i=0,ang=0;i<m_2D_segments;i++,ang+= (M_2PI/m_2D_segments))
00093 {
00094 double ccos = cos(ang);
00095 double ssin = sin(ang);
00096
00097 const float x = ccos * M.get_unsafe(0,0) + ssin * M.get_unsafe(1,0);
00098 const float y = ccos * M.get_unsafe(0,1) + ssin * M.get_unsafe(1,1);
00099
00100 glVertex2f( x,y );
00101 }
00102
00103 glEnd();
00104 }
00105 else
00106 {
00107
00108
00109
00110 GLfloat mat[16];
00111
00112
00113
00114
00115
00116
00117
00118
00119 mat[3] = mat[7] = mat[11] = 0;
00120 mat[15] = 1;
00121 mat[12] = mat[13] = mat[14] = 0;
00122
00123 mat[0] = m_eigVec(0,0); mat[1] = m_eigVec(1,0); mat[2] = m_eigVec(2,0);
00124 mat[4] = m_eigVec(0,1); mat[5] = m_eigVec(1,1); mat[6] = m_eigVec(2,1);
00125 mat[8] = m_eigVec(0,2); mat[9] = m_eigVec(1,2); mat[10] = m_eigVec(2,2);
00126
00127 glDisable(GL_LIGHTING);
00128
00129
00130 glEnable(GL_COLOR_MATERIAL);
00131 glShadeModel(GL_SMOOTH);
00132
00133 GLUquadricObj *obj = gluNewQuadric();
00134 checkOpenGLError();
00135
00136 gluQuadricDrawStyle( obj, m_drawSolid3D ? GLU_FILL : GLU_LINE);
00137
00138 glPushMatrix();
00139 glMultMatrixf( mat );
00140 glScalef(m_eigVal(0,0)*m_quantiles,m_eigVal(1,1)*m_quantiles,m_eigVal(2,2)*m_quantiles);
00141
00142 gluSphere( obj, 1,m_3D_segments,m_3D_segments);
00143 checkOpenGLError();
00144
00145 glPopMatrix();
00146
00147 gluDeleteQuadric(obj);
00148 checkOpenGLError();
00149
00150 glDisable(GL_LIGHTING);
00151 glDisable(GL_LIGHT0);
00152
00153
00154 }
00155
00156
00157 glLineWidth(1.0f);
00158 glDisable(GL_BLEND);
00159 }
00160 MRPT_END_WITH_CLEAN_UP( \
00161 cout << "Covariance matrix leading to error is:" << endl << m_cov << endl; \
00162 );
00163 #endif
00164 }
00165
00166
00167
00168
00169
00170 void CMyEllipsoid::writeToStream(CStream &out,int *version) const
00171 {
00172 if (version)
00173 *version = 1;
00174 else
00175 {
00176 writeToStreamRender(out);
00177 out << m_cov << m_drawSolid3D << m_quantiles << (uint32_t)m_2D_segments << (uint32_t)m_3D_segments << m_lineWidth;
00178 }
00179 }
00180
00181
00182
00183
00184
00185 void CMyEllipsoid::readFromStream(CStream &in,int version)
00186 {
00187 switch(version)
00188 {
00189 case 0:
00190 case 1:
00191 {
00192 uint32_t i;
00193 readFromStreamRender(in);
00194 if (version==0)
00195 {
00196 CMatrix c;
00197 in >> c; m_cov = c.cast<double>();
00198 }
00199 else
00200 {
00201 in >> m_cov;
00202 }
00203
00204 in >> m_drawSolid3D >> m_quantiles;
00205 in >> i; m_2D_segments = i;
00206 in >> i; m_3D_segments = i;
00207 in >> m_lineWidth;
00208
00209
00210 m_prevComputedCov = m_cov;
00211 m_cov.eigenVectors(m_eigVec,m_eigVal);
00212 m_eigVal.Sqrt();
00213
00214 } break;
00215 default:
00216 MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(version)
00217
00218 };
00219 }
00220
00221 bool quickSolveEqn(double a,double b_2,double c,double &t) {
00222 double delta=square(b_2)-a*c;
00223 if (delta==0) return (t=-b_2/a)>=0;
00224 else if (delta>0) {
00225 delta=sqrt(delta);
00226 if ((t=(-b_2-delta)/a)>=0) return true;
00227 else return (t=(-b_2+delta)/a)>=0;
00228 } else return false;
00229 }
00230
00231 bool CMyEllipsoid::traceRay(const mrpt::poses::CPose3D &o,double &dist) const {
00232 if (m_cov.getRowCount()!=3) return false;
00233 TLine3D lin,lin2;
00234 createFromPoseX(o-this->m_pose,lin);
00235 lin.unitarize();
00236 for (size_t i=0;i<3;i++) {
00237 lin2.pBase[i]=0;
00238 lin2.director[i]=0;
00239 for (size_t j=0;j<3;j++) {
00240 double vji=m_eigVec(j,i);
00241 lin2.pBase[i]+=vji*lin.pBase[j];
00242 lin2.director[i]+=vji*lin.director[j];
00243 }
00244 }
00245 double a=0,b_2=0,c=-square(m_quantiles);
00246 for (size_t i=0;i<3;i++) {
00247 double ev=m_eigVal(i,i);
00248 a+=square(lin2.director[i]/ev);
00249 b_2+=lin2.director[i]*lin2.pBase[i]/square(ev);
00250 c+=square(lin2.pBase[i]/ev);
00251 }
00252 return quickSolveEqn(a,b_2,c,dist);
00253 }
00254
00255 void CMyEllipsoid::setCovMatrix( const mrpt::math::CMatrixDouble &m, int resizeToSize)
00256 {
00257 MRPT_START
00258
00259 ASSERT_( m.getColCount() == m.getRowCount() );
00260 ASSERT_( size(m,1)==2 || size(m,1)==3 || (resizeToSize>0 && (resizeToSize==2 || resizeToSize==3)));
00261
00262 m_cov = m;
00263 if (resizeToSize>0 && resizeToSize<(int)size(m,1))
00264 m_cov.setSize(resizeToSize,resizeToSize);
00265
00266 if (m_cov==m_prevComputedCov)
00267 return;
00268
00269 CRenderizableDisplayList::notifyChange();
00270
00271
00272 const double d=m_cov.det();
00273 if (d==0 || d!=d)
00274 {
00275
00276 m_prevComputedCov = m_cov;
00277 m_eigVec.zeros(3,3);
00278 m_eigVal.zeros(3,3);
00279 }
00280 else
00281 {
00282
00283 m_prevComputedCov = m_cov;
00284 m_cov.eigenVectors(m_eigVec,m_eigVal);
00285 m_eigVal.Sqrt();
00286
00287 }
00288
00289
00290 MRPT_END
00291 }
00292
00293 void CMyEllipsoid::setCovMatrix( const mrpt::math::CMatrixFloat &m, int resizeToSize)
00294 {
00295 CRenderizableDisplayList::notifyChange();
00296 setCovMatrix( CMatrixDouble(m), resizeToSize);
00297 }