basic/geometry/geo_rangesensor/Range_Sensor.cpp

Go to the documentation of this file.
00001 // Range_Sensor
00002 #include "Range_Sensor.h"
00003 
00004 // Ray Tracing Specific Headers
00005 #include "raytrace.h"
00006 #include "MgcCylinder.h"
00007 #include "MgcDistLin3Lin3.h"
00008 #include "MgcIntrLin3Cyln.h"
00009 #include "MgcLine3.h"
00010 #include "MgcMath.h"
00011 #include "MgcRay3.h"
00012 #include "MgcSegment3.h"
00013 #include "MgcVector3.h"
00014 #include "MgcRTLib.h"
00015 #include "MgcBox3.h"
00016 #include "MgcFrustum.h"
00017 #include "MgcIntrBox3Frustum.h"
00018 #include "MgcIntrLin3Box3.h"
00019 #include "MgcContBox.h"
00020 #include "MgcGaussPointsFit.h"
00021 #include "MgcEigen.h"
00022 
00023 // Class Range_Sensor 
00024 
00025 Range_Sensor::Range_Sensor (FrameManager* frameManager)
00026 : ObjectBase( frameManager )
00027 {
00028   //TRACE("\nRange_Sensor::Range_Sensor");
00029   this->angle = 0.785;
00030   this->maxrange = 125.0;
00031   this->maxerror = 0;
00032   this->user_ray_range_y = 256;
00033   this->user_ray_range_z = 256;
00034   this->DisplayingBitmapEnabled = true;
00035   
00036   //Initially camera is at theFrame, and theFrame is identity matrix
00037   
00038   bp = NULL;
00039   amDisplayingBitmap = false;
00040 
00041   //set these basic vars at construction time
00042   lower_ray_lim_y = RAY_ARRAY_LIMIT/2-user_ray_range_y/2+1;
00043   upper_ray_lim_y = RAY_ARRAY_LIMIT/2+user_ray_range_y/2;
00044 
00045   lower_ray_lim_z = RAY_ARRAY_LIMIT/2-user_ray_range_z/2+1;
00046   upper_ray_lim_z = RAY_ARRAY_LIMIT/2+user_ray_range_z/2;
00047 
00048   ray_half_limit = RAY_ARRAY_LIMIT/2;
00049 
00050   //theFrame is pos of camera relative to link frame in GetTransform()
00051   absFrame = GetTransform() * theFrame;
00052 
00053 }
00054 
00055 Range_Sensor::Range_Sensor (const Range_Sensor& right)
00056 :       ObjectBase( right )
00057 {
00058   //TRACE("\nRange_Sensor::Range_Sensor (const Range_Sensor& right)???");
00059   this->angle = right.angle;
00060   this->maxrange = right.maxrange;
00061   this->maxerror = right.maxerror;
00062   this->user_ray_range_y = right.user_ray_range_y;
00063   this->user_ray_range_z = right.user_ray_range_z;
00064   this->DisplayingBitmapEnabled = right.DisplayingBitmapEnabled;
00065   
00066   //new cameras won't get a copy of the 2D window until it is regenerated by this camera object
00067   amDisplayingBitmap = false;
00068   
00069   //set these basic vars at construction time
00070   lower_ray_lim_y = RAY_ARRAY_LIMIT/2-user_ray_range_y/2+1;
00071   upper_ray_lim_y = RAY_ARRAY_LIMIT/2+user_ray_range_y/2;
00072 
00073   lower_ray_lim_z = RAY_ARRAY_LIMIT/2-user_ray_range_z/2+1;
00074   upper_ray_lim_z = RAY_ARRAY_LIMIT/2+user_ray_range_z/2;
00075 
00076   ray_half_limit = RAY_ARRAY_LIMIT/2;
00077 
00078   //theFrame is already copied by the ObjectBase constructor.
00079   //this->theFrame = right.theFrame;
00080 
00081   //theFrame is pos of camera relative to link frame in GetTransform()
00082   absFrame = GetTransform() * theFrame;
00083 }
00084 
00085 
00086 Range_Sensor::~Range_Sensor()
00087 {
00088   //TRACE("\nRange_Sensor::~Range_Sensor");
00089   if (amDisplayingBitmap)
00090   {
00091         //Calling EndOutput here seems to cause a crash sometimes, sometimes not
00092     //bp->EndOutput();
00093     delete bp;
00094   }
00095 }
00096 
00097 Entity* Range_Sensor::Clone () const
00098 {
00099   //TRACE("\nRange_Sensor::Clone ()");
00100   //shallow copy, good enough for now
00101   return new Range_Sensor( *this ) ;
00102 }
00103 
00104 bool Range_Sensor::IsInterfering (const Entity* entity) const
00105 {
00106   //TRACE("\nRange_Sensor::IsInterfering");
00107   //assert( false ) ;
00108   return false ;
00109 }
00110 
00111 bool Range_Sensor::CanCheckInterference (const Entity* entity) const
00112 {
00113   //TRACE("\nRange_Sensor::CanCheckInterference");
00114   //assert( false ) ;
00115   return false ;
00116 }
00117 
00118 void Range_Sensor::Serialize (ostream& os) const
00119 {  
00120   //TRACE("\nRange_Sensor::Serialize");
00121   using std::endl ;
00122   os << "#camera_jonathan" << endl ;
00123   
00124   os << "#name " << GetName() << endl;
00125   os << "#linknum " << BaseFrame() << endl;
00126   os << "#resolution-y " << user_ray_range_y << endl;
00127   os << "#resolution-z " << user_ray_range_z << endl;
00128   os << "#angle " << angle << endl;
00129   os << "#maxrange " << maxrange << endl;
00130   os << "#maxerror " << maxerror << endl;
00131   os << "#depthmapwindow " << DisplayingBitmapEnabled << endl;
00132   os << "#transform ";
00133   
00134   int tempi, tempj;
00135   for (tempi = 0; tempi < 4; tempi++)
00136   {
00137     for (tempj = 0; tempj < 4; tempj++)
00138     {
00139       os << this->theFrame.values[tempi][tempj] << " ";
00140     }
00141   }
00142   os << endl;
00143   os << "#end_camera_jonathan" << endl;
00144 }
00145 
00146 void Range_Sensor::Deserialize (istream& is)
00147 {
00148   
00149   //TRACE("\nRange_Sensor::Deserialize");
00150   char marker[ 300 ] = "" ;
00151   int linknum;
00152   
00153   eatwhite( is ) ;
00154   is.getline( marker, 300, ' ' ) ;
00155   assert( strcmp( marker, "#name" ) == 0 ) ;
00156   is.getline(marker, 300, '\n') ;
00157   SetName (marker);
00158   //TRACE ("\nname is %s",marker);
00159   
00160   eatwhite( is ) ;
00161   is.getline( marker, 300, ' ' ) ;
00162   assert( strcmp( marker, "#linknum" ) == 0 ) ;
00163   linknum = -1 ;
00164   is >> linknum ;
00165   SetBaseFrame (linknum);
00166   
00167   eatwhite( is ) ;
00168   is.getline( marker, 300, ' ' ) ;
00169   assert( strcmp( marker, "#resolution-y" ) == 0 ) ;
00170   is >> user_ray_range_y ;
00171   assert (user_ray_range_y <= RAY_ARRAY_LIMIT);
00172   
00173   eatwhite( is ) ;
00174   is.getline( marker, 300, ' ' ) ;
00175   assert( strcmp( marker, "#resolution-z" ) == 0 ) ;
00176   is >> user_ray_range_z ;
00177   assert (user_ray_range_z <= RAY_ARRAY_LIMIT);
00178   
00179   eatwhite( is ) ;
00180   is.getline( marker, 300, ' ' ) ;
00181   assert( strcmp( marker, "#angle" ) == 0 ) ;
00182   angle = -1 ;
00183   is >> angle ;
00184   
00185   eatwhite( is ) ;
00186   is.getline( marker, 300, ' ' ) ;
00187   assert( strcmp( marker, "#maxrange" ) == 0 ) ;
00188   maxrange = -1 ;
00189   is >> maxrange ;
00190   
00191   eatwhite( is ) ;
00192   is.getline( marker, 300, ' ' ) ;
00193   assert( strcmp( marker, "#maxerror" ) == 0 ) ;
00194   maxerror = -1 ;
00195   is >> maxerror ;
00196   
00197   eatwhite( is ) ;
00198   is.getline( marker, 300, ' ' ) ;
00199   assert( strcmp( marker, "#depthmapwindow" ) == 0 ) ;
00200   is >> DisplayingBitmapEnabled;
00201 
00202   
00203   eatwhite( is ) ;
00204   is.getline( marker, 300, ' '  ) ;
00205   assert( strcmp( marker, "#transform" ) == 0 ) ;
00206   
00207   for (int tempi = 0; tempi < 4; tempi++)
00208   {
00209     for (int tempj = 0; tempj < 4; tempj++)
00210     {
00211       is >> this->theFrame.values[tempi][tempj] ;
00212       //TRACE ("\nCamera theFrame:%f", this->theFrame.values[tempi][tempj]);
00213     }
00214   }
00215   
00216   //TRACE("\nRange_Sensor::Deserialize l%d, res-y%d, res-z%d, an%f, mr%f, ec%f, bme%d",BaseFrame(),user_ray_range_y,user_ray_range_z,angle,maxrange,maxerror,DisplayingBitmapEnabled);
00217   
00218   eatwhite( is ) ;
00219   is.getline( marker, 300 ) ;
00220   assert( strcmp( marker, "#end_camera_jonathan" ) == 0 ) ;
00221 
00222   //set these basic vars at construction time
00223   lower_ray_lim_y = RAY_ARRAY_LIMIT/2-user_ray_range_y/2+1;
00224   upper_ray_lim_y = RAY_ARRAY_LIMIT/2+user_ray_range_y/2;
00225 
00226   lower_ray_lim_z = RAY_ARRAY_LIMIT/2-user_ray_range_z/2+1;
00227   upper_ray_lim_z = RAY_ARRAY_LIMIT/2+user_ray_range_z/2;
00228 
00229   ray_half_limit = RAY_ARRAY_LIMIT/2;
00230 
00231   //theFrame is pos of camera relative to link frame in GetTransform()
00232   absFrame = GetTransform() * theFrame;
00233 
00234 }
00235 
00236 void Range_Sensor::SetAngle (double angle)
00237 {
00238   //TRACE("\nRange_Sensor::SetAngle");
00239   this->angle = angle ;
00240 }
00241 
00242 void Range_Sensor::SetMaxRange (double maxrange)
00243 {
00244   //TRACE("\nRange_Sensor::SetMaxRange");
00245   this->maxrange = maxrange ;
00246 }
00247 
00248 void Range_Sensor::SetMaxError (double maxerror)
00249 {
00250   //TRACE("\nRange_Sensor::SetMaxRange");
00251   this->maxerror = maxerror ;
00252 }
00253 
00254 double Range_Sensor::GetAngle () const
00255 {
00256   //TRACE("\nRange_Sensor::GetAngle");
00257   return angle ;
00258 }
00259 
00260 double Range_Sensor::GetMaxRange () const
00261 {
00262   //TRACE("\nRange_Sensor::GetMaxRange");
00263   return maxrange ;
00264 }
00265 
00266 double Range_Sensor::GetMaxError () const
00267 {
00268   //TRACE("\nRange_Sensor::GetMaxError");
00269   return maxerror ;
00270 }
00271 
00272 void Range_Sensor::AddEntityToDepthMap (const Entity* entity)
00273 {
00274   //TRACE("\nRange_Sensor::AddEntityToDepthMap");
00275   const Mesh* mesh = dynamic_cast< const Mesh* >( entity ) ;
00276   if( mesh != NULL )
00277   {
00278     AddMeshToDepthMap( *mesh ) ;
00279     return;
00280   }
00281   const MPK_Cylinder* mpk_cylinder = dynamic_cast< const MPK_Cylinder * >( entity ) ;
00282   if( mpk_cylinder != NULL )
00283   {
00284     AddCylinderToDepthMap( *mpk_cylinder ) ;
00285     return;
00286   }
00287   const MPK_Sphere* mpk_sphere = dynamic_cast< const MPK_Sphere * >( entity ) ;
00288   if( mpk_sphere != NULL )
00289   {
00290     AddSphereToDepthMap( *mpk_sphere );
00291     return;
00292   }
00293   const MPK_Box* mpk_box = dynamic_cast< const MPK_Box * >( entity ) ;
00294   if( mpk_box != NULL )
00295   {
00296     AddBoxToDepthMap( *mpk_box );
00297     return;
00298   }
00299   
00300   const ObjectGroup* group = dynamic_cast< const ObjectGroup* >( entity ) ;
00301   if( group != NULL )
00302   {
00303     //TRACE("\nObjectGroup Detected");
00304     for( int i = 0; i < group->Size(); i++ )
00305     {
00306       const ObjectBase* addme = ( *group )[ i ] ;
00307       AddEntityToDepthMap( addme ) ;
00308     }
00309     return;
00310   }
00311 }
00312 
00313 void Range_Sensor::AddMeshToDepthMap (const Mesh& mesh)
00314 {
00315   //TRACE("\nRange_Sensor::AddMeshToDepthMap");
00316   double t,u,v;
00317   double v1[3],v2[3],v3[3],edge1[3],edge2[3];
00318   int i,j,k,l,temp;
00319   std::vector<Vector4> absvertexes = mesh.GetVertexes();
00320   
00321   MgcVector3* pointslist = new MgcVector3[absvertexes.size()];
00322   
00323   //pre-transform the vertex list to get absolute distance from (0,0,0)
00324   for (i = 0; i < absvertexes.size(); i++)
00325   {
00326     absvertexes[i] = mesh.GetTransform() * absvertexes[i];
00327     //convert from Vector4 to MgcVector3
00328     pointslist[i][0] = absvertexes[i][0];
00329     pointslist[i][1] = absvertexes[i][1];
00330     pointslist[i][2] = absvertexes[i][2];
00331   }
00332   
00333   MgcBox3 orientedbox;
00334   orientedbox = MgcContOrientedBox (absvertexes.size(), pointslist);
00335   delete [] pointslist;
00336   
00337   MgcRay3 rkRay;
00338   
00339   //TRACE ("\nvals are %f,%f,%f  lb %f,  ub %f",theFrustum.DVector().x, theFrustum.DVector().y,theFrustum.DVector().z,theFrustum.LBound(),theFrustum.UBound());
00340   //TRACE ("\nvals are %f,%f,%f  lb %f,  ub %f",theFrustum.LVector().x, theFrustum.LVector().y,theFrustum.LVector().z,theFrustum.LBound(),theFrustum.UBound());
00341   //TRACE ("\nvals are %f,%f,%f  lb %f,  ub %f",theFrustum.UVector().x, theFrustum.UVector().y,theFrustum.UVector().z,theFrustum.LBound(),theFrustum.UBound());
00342   //TRACE ("\nOrigin:(%f,%f,%f)", theFrustum.Origin().x, theFrustum.Origin().y, theFrustum.Origin().z);
00343     
00344   //for (i = 0; i < absvertexes.size(); i++)
00345   //{
00346   //  TRACE ("\npoints:(%f,%f,%f)", pointslist[i][0],pointslist[i][1],pointslist[i][2]);
00347   //}
00348   
00349   //if we miss the frustum, then quit
00350   if (MgcTestIntersection (orientedbox, theFrustum) == 0)
00351   {
00352     //TRACE("\nFrustum missed, skipping");
00353     return;
00354   }
00355   
00356   bool okaytotest[RAY_ARRAY_LIMIT][RAY_ARRAY_LIMIT];
00357   rkRay.Origin() = theFrustum.Origin();
00358   
00359   //Note: I've tried doing collsion detection with bounding boxes inside the ray loop,
00360   //but precomputing an array of bools like this seems fastest
00361   for (k=lower_ray_lim_y; k < upper_ray_lim_y; k++)
00362   {
00363     for (l=lower_ray_lim_z; l < upper_ray_lim_z; l++)
00364     {
00365       rkRay.Direction()[0] = ray_array->values[k][l][0];
00366       rkRay.Direction()[1] = ray_array->values[k][l][1];
00367       rkRay.Direction()[2] = ray_array->values[k][l][2];
00368       okaytotest[k][l] = MgcTestIntersection (rkRay, orientedbox);
00369     }
00370   }
00371   
00372   //TRACE("\nAttempting mesh coll-det");
00373   //need to add each triangle to ray tracing algorithim individually
00374   const FACETVECTOR& f = mesh.GetFacets();
00375   for( i = 0; i < f.size(); i++ )
00376   {
00377     Facet face = f[ i ] ;
00378     int edges = face.vertexNumbers.size() ;
00379     assert( edges == 3 ) ;
00380     
00381     //copy the vertex points of the mesh into the arrays above
00382     for( j = 0; j < 3; j++ )
00383     {
00384       v1[ j ] = absvertexes[ face.vertexNumbers[ 0 ] ][ j ] ;
00385       v2[ j ] = absvertexes[ face.vertexNumbers[ 1 ] ][ j ] ;
00386       v3[ j ] = absvertexes[ face.vertexNumbers[ 2 ] ][ j ] ;
00387           // find vectors for two edges sharing v1
00388       SUB(edge1, v2, v1);
00389       SUB(edge2, v3, v1);
00390     }
00391     //bool once = false;
00392     //TRACE("\nTri is at (%f,%f,%f)(%f,%f,%f)(%f,%f,%f)",v1[0],v1[1],v1[2],v2[0],v2[1],v2[2],v3[0],v3[1],v3[2]);
00393     for (k=lower_ray_lim_y; k < upper_ray_lim_y; k++)
00394     {
00395       for (l=lower_ray_lim_z; l < upper_ray_lim_z; l++)
00396       {
00397         //if bounding box hit is closer than current closest, continue
00398         if (okaytotest[k][l])
00399         {
00400           temp = intersect_triangle( ray_source, ray_array->values[k][l], v1,v2,v3, edge1,edge2, &t,&u,&v);
00401           if ((temp != 0) && (t < ray_depth_map[k][l]) && (t > 0))
00402           {
00403             ray_depth_map[k][l] = t;
00404             //if (once == false)
00405             //{
00406             //  TRACE("\n **hit ray_depth_map %f",t);
00407             //  once = true;
00408             //}
00409           }
00410         }
00411       }
00412     }
00413   }
00414   //TRACE ("\n  ray source: (%f,%f,%f)", ray_source[0], ray_source[1], ray_source[2]);
00415   //TRACE ("\n  ray was pointing at: (%f,%f,%f)", ray_array->values[128][128][0], ray_array->values[128][128][1], ray_array->values[128][128][2]);
00416   
00417 }
00418 
00419 void Range_Sensor::AddCylinderToDepthMap (const MPK_Cylinder& mpk_cylinder)
00420 {
00421   //TRACE("\nRange_Sensor::AddCylinderToDepthMap");
00422   Vector4 updir;
00423   MgcRay3 rkRay;
00424   MgcCylinder rkCylinder;
00425   double t;
00426   int i,j;
00427   bool intersect_val;
00428   //TRACE("\nCylinder Detected");
00429   
00430   //homogeneous coord for the original position of cylinder before transforming
00431   updir[0] = 0;
00432   updir[1] = 1;
00433   updir[2] = 0;
00434   updir[3] = 0;
00435   
00436   Matrix4x4 absCylFrame;
00437   //note: the cylinder may be associted with any link (not neccescarily that of the camera)
00438   // so is this how I access the full postion of any cylinder in the world?
00439   absCylFrame = mpk_cylinder.GetTransform()*mpk_cylinder.theFrame ;
00440 
00441   //updir holds the upward dir for the cylinder
00442   updir = absCylFrame * updir;
00443   
00444   normalize (updir[0],updir[1],updir[2]);
00445   //TRACE("\n3updir %f,%f,%f",updir[0],updir[1],updir[2]);
00446   
00447   MgcBox3 boundingbox;
00448   MgcVector3 tempdir;
00449   
00450   //set up cylinder bounding box
00451   tempdir.x = absCylFrame.values[0][0]; tempdir.y = absCylFrame.values[1][0]; tempdir.z = absCylFrame.values[2][0];
00452   //normalize(tempdir.x,tempdir.y,tempdir.z);
00453   boundingbox.Axis(0) = tempdir;
00454   
00455   tempdir.x = absCylFrame.values[0][1]; tempdir.y = absCylFrame.values[1][1]; tempdir.z = absCylFrame.values[2][1];
00456   //normalize(tempdir.x,tempdir.y,tempdir.z);
00457   boundingbox.Axis(1) = tempdir;
00458   
00459   tempdir.x = absCylFrame.values[0][2]; tempdir.y = absCylFrame.values[1][2]; tempdir.z = absCylFrame.values[2][2];
00460   //normalize(tempdir.x,tempdir.y,tempdir.z);
00461   boundingbox.Axis(2) = tempdir;
00462   
00463   boundingbox.Extent(0) = mpk_cylinder.Radius();  
00464   boundingbox.Extent(1) = mpk_cylinder.Height()*0.5;
00465   boundingbox.Extent(2) = mpk_cylinder.Radius(); 
00466   
00467   tempdir.x = absCylFrame.values[0][3]; tempdir.y = absCylFrame.values[1][3]; tempdir.z = absCylFrame.values[2][3];
00468   boundingbox.Center() = tempdir;
00469 
00470   //if we miss the frustum, then quit
00471   if (MgcTestIntersection (boundingbox, theFrustum) == 0)
00472   {
00473     return;
00474   }
00475   //TRACE("\nAttempting cylinder coll-det");
00476   
00477   //convert from MPK cylinder to Magic library cylinder
00478   rkCylinder.Center()[0] = absCylFrame.values[0][3];
00479   rkCylinder.Center()[1] = absCylFrame.values[1][3];
00480   rkCylinder.Center()[2] = absCylFrame.values[2][3];
00481   rkCylinder.Direction()[0] = updir[0];
00482   rkCylinder.Direction()[1] = updir[1];
00483   rkCylinder.Direction()[2] = updir[2];
00484   rkCylinder.Height() = mpk_cylinder.Height();
00485   rkCylinder.Radius() = mpk_cylinder.Radius();
00486   rkRay.Origin()[0] = ray_source[0];
00487   rkRay.Origin()[1] = ray_source[1];
00488   rkRay.Origin()[2] = ray_source[2];
00489   
00490   //for (i = 0; i < 4; i++)
00491   //{
00492 //              TRACE("\n");
00493 //              for (j = 0; j < 4; j++)
00494 //              {
00495 //                      TRACE (" absCylFrame %f",absCylFrame.values[i][j]);
00496 //              }
00497 //  }
00498 
00499 //  TRACE("\nradius %f, height %f",rkCylinder.Radius(),rkCylinder.Height());
00500 //  TRACE("\nCenter %f,%f,%f",rkCylinder.Center()[0],rkCylinder.Center()[1],rkCylinder.Center()[2]);
00501 //  TRACE("\nRay Source %f,%f,%f",rkRay.Origin()[0],rkRay.Origin()[1],rkRay.Origin()[2]);
00502 //  TRACE("\nRay Dir %f,%f,%f",ray_array->values[128][128][0],ray_array->values[128][128][1],ray_array->values[128][128][2]);
00503   
00504   //test for if and where intersection between cylinder and rays
00505   for (i=lower_ray_lim_y; i< upper_ray_lim_y; i++)
00506   {
00507     for (j=lower_ray_lim_z; j < upper_ray_lim_z; j++)
00508     {
00509       rkRay.Direction()[0] = ray_array->values[i][j][0];
00510       rkRay.Direction()[1] = ray_array->values[i][j][1];
00511       rkRay.Direction()[2] = ray_array->values[i][j][2];
00512 
00513       intersect_val = MgcFindIntersection (rkRay,rkCylinder,t);
00514       if ((intersect_val == true) && (t < ray_depth_map[i][j]) && (t > 0))
00515       {
00516         ray_depth_map[i][j] = t;
00517       }
00518     }
00519   }
00520 }
00521 
00522 void Range_Sensor::AddSphereToDepthMap (const MPK_Sphere& mpk_sphere)
00523 {
00524   //TRACE("\nRange_Sensor::AddSphereToDepthMap");
00525   double center[3];
00526   double t;
00527   int i,j,intersect_val;
00528   //TRACE("\nSphere Detected");
00529   
00530   Vector4 absSphFrame;
00531   //note: the sphere may be associted with any link (not neccescarily that of the camera)
00532   // so is this how I access the full postion of any sphere in the world?
00533   absSphFrame = mpk_sphere.GetTransform() * mpk_sphere.Position();
00534 
00535   //for (i = 0; i < 4; i++)
00536   //{
00537 //              for (j = 0; j < 4; j++)
00538 //              {
00539 //                      TRACE ("\nabsSphFrame%f",absSphFrame[j]);
00540 //              }
00541 //  }
00542   
00543   center[0] = absSphFrame[0];
00544   center[1] = absSphFrame[1];
00545   center[2] = absSphFrame[2];
00546 
00547   MgcBox3 boundingbox;
00548   MgcVector3 tempdir;
00549   
00550   //set up bounding box for sphere
00551   //default sphere orientation (arbitrary)
00552   tempdir.x = 1; tempdir.y = 0; tempdir.z = 0;
00553   //normalize(tempdir.x,tempdir.y,tempdir.z);
00554   boundingbox.Axis(0) = tempdir;
00555   
00556   tempdir.x = 0; tempdir.y = 1; tempdir.z = 0;
00557   //normalize(tempdir.x,tempdir.y,tempdir.z);
00558   boundingbox.Axis(1) = tempdir;
00559   
00560   tempdir.x = 0; tempdir.y = 0; tempdir.z = 1;
00561   //normalize(tempdir.x,tempdir.y,tempdir.z);
00562   boundingbox.Axis(2) = tempdir;
00563   
00564   boundingbox.Extent(0) = mpk_sphere.Radius();
00565   boundingbox.Extent(1) = mpk_sphere.Radius();
00566   boundingbox.Extent(2) = mpk_sphere.Radius();
00567   
00568   tempdir.x = absSphFrame[0]; tempdir.y = absSphFrame[1]; tempdir.z = absSphFrame[2];
00569   boundingbox.Center() = tempdir;
00570 
00571   //if we miss the frustum, then quit
00572   if (MgcTestIntersection (boundingbox, theFrustum) == 0)
00573   {
00574     return;
00575   }
00576   //TRACE("\nAttempting sphere coll-det");
00577   
00578   //test for if and where intersection between sphere and rays
00579   for (i=lower_ray_lim_y; i< upper_ray_lim_y; i++)
00580   {
00581     for (j=lower_ray_lim_z; j < upper_ray_lim_z; j++)
00582     {
00583       intersect_val = intersect_sphere(ray_source, ray_array->values[i][j], 
00584         center, mpk_sphere.Radius(), t, this->maxrange);
00585       if ((intersect_val != 0) && (t < ray_depth_map[i][j]) && (t > 0))
00586       {
00587         ray_depth_map[i][j] = t;
00588       }
00589     }
00590   }
00591 }
00592 
00593 void Range_Sensor::AddBoxToDepthMap (const MPK_Box& mpk_box)
00594 {
00595   //TRACE("\nRange_Sensor::AddBoxToDepthMap");
00596   
00597   int i,j;
00598   Matrix4x4 absBoxFrame;
00599   //note: the sphere may be associted with any link (not neccescarily that of the camera)
00600   // so is this how I access the full postion of any sphere in the world?
00601   absBoxFrame = mpk_box.GetTransform()*mpk_box.theFrame ;
00602   
00603   //the bounding box will be exactly defined by an oriented bounding box
00604   MgcBox3 boundingbox;
00605   MgcVector3 tempdir;
00606   
00607   tempdir.x = absBoxFrame.values[0][0]; tempdir.y = absBoxFrame.values[1][0]; tempdir.z = absBoxFrame.values[2][0];
00608   //normalize(tempdir.x,tempdir.y,tempdir.z);
00609   boundingbox.Axis(0) = tempdir;
00610   
00611   tempdir.x = absBoxFrame.values[0][1]; tempdir.y = absBoxFrame.values[1][1]; tempdir.z = absBoxFrame.values[2][1];
00612   //normalize(tempdir.x,tempdir.y,tempdir.z);
00613   boundingbox.Axis(1) = tempdir;
00614   
00615   tempdir.x = absBoxFrame.values[0][2]; tempdir.y = absBoxFrame.values[1][2]; tempdir.z = absBoxFrame.values[2][2];
00616   //normalize(tempdir.x,tempdir.y,tempdir.z);
00617   boundingbox.Axis(2) = tempdir;
00618   
00619   boundingbox.Extent(0) = mpk_box.Length()*0.5;  
00620   boundingbox.Extent(1) = mpk_box.Width()*0.5;
00621   boundingbox.Extent(2) = mpk_box.Height()*0.5; 
00622   
00623   tempdir.x = absBoxFrame.values[0][3]; tempdir.y = absBoxFrame.values[1][3]; tempdir.z = absBoxFrame.values[2][3];
00624   boundingbox.Center() = tempdir;
00625 
00626   //if we miss the frustum, then quit
00627   if (MgcTestIntersection (boundingbox, theFrustum) == 0)
00628   {
00629     return;
00630   }
00631   //TRACE("\nAttempting box coll-det");
00632   
00633   MgcRay3 rkRay;
00634   bool intersect_val;
00635   double t;
00636 
00637   //for (i = 0; i < 4; i++)
00638   //{
00639   //  TRACE("\n");
00640 //              for (j = 0; j < 4; j++)
00641 //              {
00642 //                      TRACE ("absSphFrame%f",absBoxFrame.values[i][j]);
00643 //              }
00644 //  }
00645 
00646 //  TRACE ("\naxis(0) are: %f,%f,%f",boundingbox.Axis(0).x,boundingbox.Axis(0).y,boundingbox.Axis(0).z);
00647 //  TRACE ("\naxis(1) are: %f,%f,%f",boundingbox.Axis(1).x,boundingbox.Axis(1).y,boundingbox.Axis(1).z);
00648 //  TRACE ("\naxis(2) are: %f,%f,%f",boundingbox.Axis(2).x,boundingbox.Axis(2).y,boundingbox.Axis(2).z);
00649 //  TRACE ("\nextents are: %f,%f,%f",boundingbox.Extent(0),boundingbox.Extent(1),boundingbox.Extent(2));
00650 //  TRACE ("\ncenter is: %f,%f,%f",boundingbox.Center().x,boundingbox.Center().y,boundingbox.Center().z);
00651 
00652   rkRay.Origin()[0] = ray_source[0];
00653   rkRay.Origin()[1] = ray_source[1];
00654   rkRay.Origin()[2] = ray_source[2];
00655   
00656   //test for if and where intersection between box and rays
00657   for (i=lower_ray_lim_y; i < upper_ray_lim_y; i++)
00658   {
00659     for (j=lower_ray_lim_z; j < upper_ray_lim_z; j++)
00660     {
00661       rkRay.Direction()[0] = ray_array->values[i][j][0];
00662       rkRay.Direction()[1] = ray_array->values[i][j][1];
00663       rkRay.Direction()[2] = ray_array->values[i][j][2];
00664       intersect_val = MgcFindIntersection (rkRay, boundingbox, t);
00665       if ((intersect_val == true) && (t < ray_depth_map[i][j]) && (t > 0))
00666       {
00667         ray_depth_map[i][j] = t;
00668       }
00669     }
00670   }
00671 }
00672 
00673 void Range_Sensor::Generate_Ray_Array ()
00674 {
00675   //TRACE("\nRange_Sensor::Generate_Ray_Array");
00676   int i,j;
00677   
00678   //generate inital ray array
00679   
00680   double newdir[3], temp[3];
00681   
00682   //tempvalues stores normalized rotation matrix needing scaling according to this->angle
00683   double tempvalues[3][3]; 
00684   
00685   //update the abs frame (relative to (0,0,0)) before taking a picture.
00686   //theFrame is pos of camera relative to link frame in GetTransform()
00687   absFrame = GetTransform() * theFrame;
00688 
00689   ray_source[0] = this->absFrame.values[0][3];
00690   ray_source[1] = this->absFrame.values[1][3];
00691   ray_source[2] = this->absFrame.values[2][3];
00692   
00693   //shoot rays in x direction from 0,0,0
00694   newdir[0] = ray_half_limit*this->absFrame.values[0][0];
00695   newdir[1] = ray_half_limit*this->absFrame.values[1][0];
00696   newdir[2] = ray_half_limit*this->absFrame.values[2][0];
00697   
00698   //calculate maximum extents for pre-normalized y,z directions
00699   angleratio = tan((this->angle)/2);
00700   for (i=0; i< 3; i++)
00701   {
00702     for (j=0; j < 3; j++)
00703     {
00704       tempvalues[i][j] = angleratio * this->absFrame.values[i][j];
00705     }
00706   }
00707   
00708   //define ray targets in y direction
00709   for (i = 0; i < RAY_ARRAY_LIMIT; i++)
00710   {
00711     temp[0] = newdir[0] + (i - ray_half_limit)*tempvalues[0][1];
00712     temp[1] = newdir[1] + (i - ray_half_limit)*tempvalues[1][1];
00713     temp[2] = newdir[2] + (i - ray_half_limit)*tempvalues[2][1];
00714     //define ray targets in z direction
00715     for (j = 0; j < RAY_ARRAY_LIMIT; j++)
00716     {
00717       ray_array->values[i][j][0] =  temp[0] + (j - ray_half_limit)*tempvalues[0][2];
00718       ray_array->values[i][j][1] =  temp[1] + (j - ray_half_limit)*tempvalues[1][2];
00719       ray_array->values[i][j][2] =  temp[2] + (j - ray_half_limit)*tempvalues[2][2];
00720       normalize ( ray_array->values[i][j][0],ray_array->values[i][j][1], ray_array->values[i][j][2] );
00721     }
00722   }
00723   // now, ray array has been generated
00724   // make no-intersection case ray_depth_map
00725   for (i=lower_ray_lim_y; i < upper_ray_lim_y; i++)
00726   {
00727     for (j=lower_ray_lim_z; j < upper_ray_lim_z; j++)
00728     {
00729       ray_depth_map[i][j] = maxrange;
00730     }
00731   }
00732   //TRACE("\nmaxrange is: %f,%f",this->maxrange, ray_depth_map[128][128]);
00733 
00734   MgcVector3 tempdir;
00735   
00736   //generate view frustum from camera location variables.
00737   tempdir.x = absFrame.values[0][3]; tempdir.y = absFrame.values[1][3]; tempdir.z = absFrame.values[2][3];
00738   theFrustum.Origin() = tempdir;
00739   
00740   tempdir.x = absFrame.values[0][0]; tempdir.y = absFrame.values[1][0]; tempdir.z = absFrame.values[2][0];
00741   //normalize(tempdir.x,tempdir.y,tempdir.z);
00742   theFrustum.DVector() = tempdir;
00743   
00744   tempdir.x = absFrame.values[0][1]; tempdir.y = absFrame.values[1][1]; tempdir.z = absFrame.values[2][1];
00745   //normalize(tempdir.x,tempdir.y,tempdir.z);
00746   theFrustum.LVector() = tempdir;
00747   
00748   tempdir.x = absFrame.values[0][2]; tempdir.y = absFrame.values[1][2]; tempdir.z = absFrame.values[2][2];
00749   //normalize(tempdir.x,tempdir.y,tempdir.z);
00750   theFrustum.UVector() = tempdir;
00751   
00752   theFrustum.LBound() = minrange * angleratio * user_ray_range_y / RAY_ARRAY_LIMIT;
00753   theFrustum.UBound() = minrange * angleratio * user_ray_range_z / RAY_ARRAY_LIMIT; 
00754   //to change sensor shape, change resolution instead of angleratio
00755 
00756   theFrustum.DMin() = minrange;
00757   theFrustum.DMax() = maxrange;
00758   theFrustum.Update(); //always call Update() after setting up MgcFrustum
00759 
00760 }
00761 
00762 
00763 void Range_Sensor::Generate_Coord_Map ()
00764 {
00765   //TRACE("\nRange_Sensor::Generate_Coord_Map");
00766   int i,j;
00767   if (maxerror > 0)
00768   {
00769     //TRACE ("\nGenerating Error in ray_depth_map");
00770   }
00771 
00772   //generate ray_coord_map using depths in ray_depth_map and dirs in ray_array->values
00773   for (i = 0; i < RAY_ARRAY_LIMIT; i++)
00774   {
00775     for (j = 0; j < RAY_ARRAY_LIMIT; j++)
00776     {
00777       //introduce error if necesscary
00778           if (maxerror > 0)
00779       {
00780         double temperror = (2.0*double( rand() ) / RAND_MAX-1.0);
00781         ray_depth_map[i][j] = ray_depth_map[i][j] * (1.0 + maxerror * temperror);
00782       }
00783       ray_coord_map[i][j][0]=ray_source[0]+ray_depth_map[i][j]*ray_array->values[i][j][0];
00784       ray_coord_map[i][j][1]=ray_source[1]+ray_depth_map[i][j]*ray_array->values[i][j][1];
00785       ray_coord_map[i][j][2]=ray_source[2]+ray_depth_map[i][j]*ray_array->values[i][j][2];
00786     }
00787   }
00788 }
00789 
00790 void Range_Sensor::Take_Picture (const std::vector< Entity* > allEntities, bool display2DMap)
00791 {
00792   //TRACE("\nRange_Sensor::Take_Picture");
00793   int i;  
00794     
00795   memset (ray_source,0,sizeof(ray_source));
00796   memset (ray_depth_map,0,sizeof(ray_depth_map));
00797   memset (ray_coord_map,0,sizeof(ray_coord_map));  
00798   
00799   ray_array = new ray_array_space;
00800   
00801   //generate the normalized ray vector map and initial, worst case ray_depth_map;
00802   Generate_Ray_Array ();
00803   
00804   //now, scan through all objects to find the nearest intersection ray.
00805   int size = allEntities.size() ;
00806   for( i = 0; i < size; i++ )
00807   {
00808     AddEntityToDepthMap (allEntities[ i ]);      
00809   }
00810   
00811   //convert ray_depth_map to ray_coord_map.
00812   Generate_Coord_Map ();
00813   
00814   delete ray_array;
00815   
00816   //if user has enabled the 2D display of ray_depth_map and we aren't in multithreaded mode
00817   if (DisplayingBitmapEnabled && display2DMap)
00818   {
00819     if (amDisplayingBitmap)
00820     {
00821       //Calling EndOutput here seems to cause a crash sometimes, sometimes not
00822       //bp->EndOutput();
00823       delete bp;
00824     }
00825     bp = new O_Bitmap;
00826     assert (bp != NULL);
00827     
00828     amDisplayingBitmap = true;
00829  
00830     bp->StartOutput() ;         //IMPROVE: remember to end output somewhere
00831     bp->SetResolution( user_ray_range_z, user_ray_range_y ) ;
00832     bp->NameDialog( GetName() ) ;
00833     
00834         int y,z;
00835         //display depth map pixels to screen in proper order
00836     for ( y=lower_ray_lim_y; y < upper_ray_lim_y; y++)
00837         {
00838       for (z=lower_ray_lim_z; z < upper_ray_lim_z; z++)
00839           {
00840         bp->PutPixel( z-lower_ray_lim_z, y-lower_ray_lim_y, 1.0 - ray_depth_map[y][z]/maxrange ) ;
00841       }
00842     }
00843     
00844     bp->Display() ;
00845   }
00846 }
00847 
00848 bool Range_Sensor::Verify() const
00849 {
00850         return true;
00851 }

Generated on Sat Apr 1 21:30:32 2006 for Motion Planning Kernel by  doxygen 1.4.6-NO