collisiondetectors/CD_Vcollide.cpp

Go to the documentation of this file.
00001 #pragma warning( disable : 4786 )
00002 #include "synchronization\semaphore.h"
00003 #include "robots\r_openchain.h"
00004 #include "CollisionDetectors\CD_Vcollide.h"
00005 #include "geometry\Facet.h"
00006 #include "geometry\ObjectGroup.h"
00007 #include "Kinematics\LinkBase.h"
00008 #include "Universe/universe.h"
00009 #include "geometry\geo_rangesensor\Range_Sensor.h"
00010 
00011 
00012 // Class CD_Vcollide 
00013 
00014 
00015 CD_Vcollide::CD_Vcollide (Universe& universe)
00016 : 
00017     universePointer( NULL ),
00018         CollisionDetectorBase( universe ),
00019         CD_BasicStyle( universe ),
00020         CD_Linear( universe ),
00021         CD_LinearContinuous( universe ),
00022         vcollide( NULL )
00023 {
00024 
00025         vcollide = new VCollide ;
00026 
00027         //go through all the entities that are in the entity list, and add all the meshes to the vcollide
00028         bool success = true ;
00029         for( int j = 0; j < entities.size(); j++ )
00030         {
00031                 Entity* theEntity = entities[ j ] ;
00032                 entities[ j ]->SetFrameManager( &theFrameManager ) ;
00033                 success &= AddEntityToVcollide( entities[ j ] ) ;
00034         }
00035         CD_Bool::allGeometryUsed = success ;    //this tells us if all the geometry was used in the collision detector
00036 
00037         //unfortunately, it appears we need to call these here, as well as in the CD_BasicStyle constructor
00038         PermActivateAll() ;
00039         PermDeactivateFramesWithThemselves() ;
00040 
00041     //
00042     // deactivaste frames with their parents
00043     //
00044     std::vector< LinkBase* > links = universe.GetAllLinks();
00045     int i;
00046     int size = links.size();
00047     for( i = 0; i < size; i++ )
00048     {
00049         LinkBase* link = links[ i ];
00050         int baseframe = link->BaseFrameNum();
00051 
00052         int j;
00053         int controlledSize = link->controlledFrames.size();
00054         for( j = 0; j < controlledSize; j++ )
00055         {
00056             int controlledFrame = link->controlledFrames[ j ];
00057             DeactivateFrames( baseframe, controlledFrame );
00058         }
00059     }
00060         
00061   //## end CD_Vcollide::CD_Vcollide%928344296.body
00062 }
00063 
00064 CD_Vcollide::CD_Vcollide (const CD_Vcollide& right)
00065   //## begin CD_Vcollide::CD_Vcollide%930249730.hasinit preserve=no
00066       : universePointer(NULL)
00067   //## end CD_Vcollide::CD_Vcollide%930249730.hasinit
00068   //## begin CD_Vcollide::CD_Vcollide%930249730.initialization preserve=yes
00069         ,CollisionDetectorBase( right ),
00070         CD_BasicStyle( right ),
00071         CD_Linear( right ),
00072         CD_LinearContinuous( right ),
00073         vcollide( NULL )
00074   //## end CD_Vcollide::CD_Vcollide%930249730.initialization
00075 {
00076   //## begin CD_Vcollide::CD_Vcollide%930249730.body preserve=yes
00077 
00078         //IMPROVE: cheat by using a retained pointer to the universe
00079 
00080         //the entities will be recopied later on - the ones copied in CD_BasicStyle are deleted
00081         vcollide = new VCollide ;
00082         
00083         meshes.reserve( right.meshes.size() ) ;
00084         for( int i = 0; i < right.meshes.size(); i++ )
00085         {
00086                 int numMeshes = meshes.size() ;
00087                 Mesh* addMe = right.meshes[ i ] ; 
00088                 this->AddEntityToVcollide( addMe ) ;
00089                 //meshes.push_back( dynamic_cast< Mesh* >( right.meshes[ i ]->Clone() ) ) ;
00090         }
00091 
00092   //## end CD_Vcollide::CD_Vcollide%930249730.body
00093 }
00094 
00095 
00096 CD_Vcollide::~CD_Vcollide()
00097 {
00098   //## begin CD_Vcollide::~CD_Vcollide%.body preserve=yes
00099     int i;
00100         for( i = 0; i < meshes.size(); i++ )
00101         {
00102                 Mesh* deleteMe = meshes[ i ] ;
00103                 delete deleteMe ;
00104                 meshes[ i ] = NULL ;
00105         }
00106         meshes.clear() ;
00107 
00108         for( i = 0; i < vcollideIndexes.size(); i++ )
00109         {
00110                 vcollide->DeleteObject( vcollideIndexes[ i ] ) ;
00111         }
00112         vcollideIndexes.clear() ;
00113         dirtyElements.clear() ;
00114         for( i = 0; i < linkVcollide.size(); i++ )
00115         {
00116                 linkVcollide[ i ].clear() ;
00117         }
00118         linkVcollide.clear() ;
00119 
00120         delete vcollide ;
00121   //## end CD_Vcollide::~CD_Vcollide%.body
00122 }
00123 
00124 
00125 
00126 //## Other Operations (implementation)
00127 CollisionDetectorBase* CD_Vcollide::Clone () const
00128 {
00129   //## begin CD_Vcollide::Clone%928344287.body preserve=yes
00130         CD_Vcollide* newVC = new CD_Vcollide( *this ) ;
00131         CD_InterfaceToCollisionQueries* CDitc = dynamic_cast< CD_Bool* >( newVC ) ;
00132         CollisionDetectorBase* returnMe = dynamic_cast< CollisionDetectorBase* >( CDitc );
00133         return returnMe ;
00134   //## end CD_Vcollide::Clone%928344287.body
00135 }
00136 
00137 bool CD_Vcollide::IsInterfering (const Configuration& config)
00138 {
00139   //## begin CD_Vcollide::IsInterfering%928344289.body preserve=yes
00140         CD_Bool::IncrementCallCount();
00141 
00142         Semaphore semaphore( this->guid );
00143         semaphore.Lock();
00144         SetConfiguration( config ) ;
00145 
00146         //improve: you only need to update the frames that have actually changed, no?
00147 
00148         //go through all the links and look at the meshes that are there to update their frames
00149         for( int i = 0; i < meshes.size(); i++ )
00150         {
00151                 const Mesh* mesh = meshes[ i ] ;
00152 
00153                 Matrix4x4 m1 = mesh->GetTransform() ; 
00154 
00155                 int vcollideIndex = vcollideIndexes[ i ] ;
00156                 assert( vcollideIndex >= 0 ) ;
00157 
00158                 //IMPROVE: find a way to do this via a funciton call
00159                 vcollide->UpdateTrans( vcollideIndex, m1.values ) ;
00160         }
00161         
00162         //IMPROVE: this is a hack
00163 //      this->DeactivateAllFrames() ;
00164 
00165         int success = vcollide->Collide() ;
00166         assert( success == VC_OK ) ;
00167         VCReportType vcrep ;
00168         int numCollisions = vcollide->Report( 1, &vcrep ) ;
00169         bool returnMe = false;
00170         if( numCollisions == 0 )                //IMPROVE: don't bother with the report
00171         {
00172                 returnMe = false;
00173         }
00174         else
00175         {
00176                 returnMe = true;
00177         }
00178         semaphore.Unlock();
00179         return returnMe;
00180   //## end CD_Vcollide::IsInterfering%928344289.body
00181 }
00182 
00183 bool CD_Vcollide::IsInterfering (const Frame &pose)
00184 {
00185         Semaphore semaphore( this->guid );
00186         semaphore.Lock();
00187 
00188         int vcollideIndex = -1;
00189         for( int i = 0; i < meshes.size(); i++ )
00190         {               
00191                 if (meshes[ i ]->BaseFrame() == 1)
00192                 {
00193                         vcollideIndex = vcollideIndexes[ i ] ;
00194                         break;
00195                 }
00196         }
00197 
00198         assert( vcollideIndex != -1 );
00199         if (vcollideIndex == -1)
00200                 return false;
00201 
00202         Matrix4x4 m1;
00203         m1.SetValues(pose);
00204         vcollide->UpdateTrans( vcollideIndex, m1.values ) ;
00205         
00206         int success = vcollide->Collide() ;
00207         assert( success == VC_OK ) ;
00208         VCReportType vcrep ;
00209         int numCollisions = vcollide->Report( 1, &vcrep ) ;
00210         bool returnMe = false;
00211         if( numCollisions == 0 )                //IMPROVE: don't bother with the report
00212         {
00213                 returnMe = false;
00214         }
00215         else
00216         {
00217                 returnMe = true;
00218         }
00219         semaphore.Unlock();
00220         return returnMe;
00221 }
00222 
00223 bool CD_Vcollide::AddEntityToVcollide (const Entity* entity)
00224 {
00225   //## begin CD_Vcollide::AddEntityToVcollide%928344302.body preserve=yes
00226         //IMPROVE: I think there's a memory leak in here
00227 
00228         //make sure we have this base frame set up properly in the map
00229         int size = linkVcollide.size() ;
00230         int baseFrame = entity->BaseFrame() ;
00231         while( linkVcollide.size() < baseFrame + 1 )
00232         {
00233                 std::set< unsigned int > setOfVcollideMeshes ;
00234                 linkVcollide.push_back( setOfVcollideMeshes );
00235         }
00236 
00237         const Mesh* mesh = dynamic_cast< const Mesh* >( entity ) ;
00238         if( mesh != NULL )
00239         {
00240                 int vcollideIndex = AddMeshToVcollide( *mesh ) ;
00241                 return true ;
00242         }
00243         const ObjectGroup* group = dynamic_cast< const ObjectGroup* >( entity ) ;
00244         if( group != NULL )
00245         {
00246                 bool returnMe = true ;
00247                 for( int i = 0; i < group->Size(); i++ )
00248                 {
00249                         const ObjectBase* addme = ( *group )[ i ] ;
00250                         returnMe &= AddEntityToVcollide( addme ) ;
00251                 }
00252                 return returnMe ;
00253         }
00254 
00255         const R_OpenChain* rOpenChain = dynamic_cast< const R_OpenChain* >( entity ) ;
00256         if( rOpenChain != NULL )
00257         {
00258                 //IMPROVE: do some extra stuff here
00259                 return true ;
00260         }
00261 
00262         const Range_Sensor* camera = dynamic_cast< const Range_Sensor* >( entity ) ;
00263         if( camera != NULL )
00264         {
00265                 //cameras don't need to be added to the simple version of vcollide, only meshes
00266                 return true ;
00267         }
00268 
00269         return false ;
00270   //## end CD_Vcollide::AddEntityToVcollide%928344302.body
00271 }
00272 
00273 int CD_Vcollide::AddMeshToVcollide (const Mesh& mesh)
00274 {
00275   //## begin CD_Vcollide::AddMeshToVcollide%928373069.body preserve=yes
00276         //IMPROVE: Function contains a memory leak
00277 
00278         Mesh* addMe = dynamic_cast< Mesh*>( mesh.Clone() ) ;
00279         meshes.push_back( addMe ) ;
00280 
00281         //ask vcollide to create a new object
00282         int vcollideIndex = -1 ;
00283         int success = vcollide->NewObject( &vcollideIndex );
00284         assert( success == VC_OK ) ;
00285 
00286         //need to add each triangle to vcollide individually
00287     int size = mesh.GetFacets().size();
00288     int i;
00289         for( i = 0; i < size; ++i )
00290         {
00291                 Facet face = mesh.GetFacets()[ i ] ;
00292                 int edges = face.vertexNumbers.size() ;
00293                 assert( edges == 3 ) ;
00294                 double v1[ 3 ] ;
00295                 double v2[ 3 ] ;
00296                 double v3[ 3 ] ;
00297 
00298                 //copy the vertex points of the mesh into the arrays above
00299                 for( int j = 0; j < 3; j++ )
00300                 {
00301                         int meshSize  = mesh.GetVertexes().size() ;
00302                         int faceSize = face.vertexNumbers.size() ;
00303                         //int vertexNumber = face.vertexNumbers[ 2 ] ;
00304                         v1[ j ] = mesh.GetVertexes()[ face.vertexNumbers[ 0 ] ][ j ] ;
00305                         v2[ j ] = mesh.GetVertexes()[ face.vertexNumbers[ 1 ] ][ j ] ;
00306                         v3[ j ] = mesh.GetVertexes()[ face.vertexNumbers[ 2 ] ][ j ] ;
00307                 }
00308                 vcollide->AddTri( v1, v2, v3 ) ;
00309         }
00310 
00311         //tell VCollide that we're done adding the object
00312         success = vcollide->EndObject() ;
00313         if( success == VC_ERR_EMPTY_OBJECT )
00314         {
00315                 assert( false ) ;
00316         }
00317         assert( success == VC_OK ) ;
00318 
00319         //need to update the list of baseframe - mesh references
00320         int baseFrame = mesh.BaseFrame() ;
00321 
00322         std::set< unsigned int > theSet = linkVcollide[ baseFrame ] ;
00323         theSet.insert( vcollideIndex ) ;
00324         linkVcollide[ baseFrame ] = theSet ;    //IMPROVE: use a reference here instead
00325         size = theSet.size() ;
00326         size = linkVcollide[ baseFrame ].size() ;
00327 
00328         vcollideIndexes.push_back( vcollideIndex ) ;
00329         return vcollideIndex ;
00330   //## end CD_Vcollide::AddMeshToVcollide%928373069.body
00331 }
00332 
00333 void CD_Vcollide::DeactivateFrames (const unsigned int frame1, const unsigned int frame2)
00334 {
00335   //## begin CD_Vcollide::DeactivateFrames%928449848.body preserve=yes
00336         if( frame2 > frame1 )
00337         {
00338                 DeactivateFrames( frame2, frame1 ) ;
00339                 return ;
00340         }
00341         CD_BasicStyle::DeactivateFrames( frame1, frame2 ) ;
00342         int lSize = linkVcollide.size() ;
00343 
00344         //if we're deactivating a frame with no geometry, just return
00345         if( lSize <= frame1 )
00346         {
00347                 return ;
00348         }
00349         if( lSize <= frame2 )
00350         {
00351                 return ;
00352         }
00353 
00354         int size1 = linkVcollide[ frame1 ].size() ;
00355         std::set< unsigned int >::iterator i1 ;
00356         std::set< unsigned int >::iterator i2 ;
00357 
00358         for( i1 = linkVcollide[ frame1 ].begin(); i1 != linkVcollide[ frame1 ].end() ; i1++ )
00359         {
00360                 int index1 = *i1 ;
00361                 for( i2 = linkVcollide[ frame2 ].begin(); i2 != linkVcollide[ frame2 ].end(); i2++ )
00362                 {
00363                         int index2 = *i2 ;
00364                         if( index1 != index2 )
00365                         {
00366                                 int success = vcollide->DeactivatePair( index1, index2 ) ;
00367                                 success &= vcollide->DeactivatePair( index2, index1 ) ;
00368                                 assert( success == 1 ) ;
00369                         }
00370                 }
00371         }
00372   //## end CD_Vcollide::DeactivateFrames%928449848.body
00373 }
00374 
00375 void CD_Vcollide::UpdateMovedLink (const unsigned int linkNum) const
00376 {
00377   //## begin CD_Vcollide::UpdateMovedLink%928449851.body preserve=yes
00378         //IMPROVE: is this ever called?
00379         links[ linkNum ]->UpdateFrames() ;
00380   //## end CD_Vcollide::UpdateMovedLink%928449851.body
00381 }
00382 
00383 void CD_Vcollide::ActivateFrames (const unsigned int frame1, const unsigned int frame2)
00384 {
00385   //## begin CD_Vcollide::ActivateFrames%931291665.body preserve=yes
00386         if( !FramePairPermEnabled( frame1, frame2 ) )   //IMPROVE: NOT SIGN?
00387         {
00388                 return ;        //if the pair is permanantly disabled, then don't activate it
00389         }
00390 
00391         if( frame2 > frame1 )
00392         {
00393                 ActivateFrames( frame2, frame1 ) ;
00394                 return ;
00395         }
00396 
00397         CD_BasicStyle::ActivateFrames( frame1, frame2 ) ;
00398         int lSize = linkVcollide.size() ;
00399 
00400         //if we're activating a frame with no geometry, just return
00401         if( lSize <= frame1 )
00402         {
00403                 return ;
00404         }
00405         if( lSize <= frame2 )
00406         {
00407                 return ;
00408         }
00409 
00410         int size1 = linkVcollide[ frame1 ].size() ;
00411         std::set< unsigned int >::iterator i1 ;
00412         std::set< unsigned int >::iterator i2 ;
00413 
00414         int geometriesInFrame1 = linkVcollide[ frame1 ].size() ;
00415         int geometriesInFrame2 = linkVcollide[ frame2 ].size() ;
00416 
00417         for( i1 = linkVcollide[ frame1 ].begin(); i1 != linkVcollide[ frame1 ].end() ; i1++ )
00418         {
00419                 int index1 = *i1 ;
00420                 for( i2 = linkVcollide[ frame2 ].begin(); i2 != linkVcollide[ frame2 ].end(); i2++ )
00421                 {
00422                         int index2 = *i2 ;
00423                         if( index1 != index2 )
00424                         {
00425                                 vcollide->ActivatePair( index1, index2 ) ;
00426                                 vcollide->ActivatePair( index2, index1 ) ;
00427                                 //IMPROVE: this has not been tested
00428                         }
00429                 }
00430         }
00431   //## end CD_Vcollide::ActivateFrames%931291665.body
00432 }
00433 
00434 // Additional Declarations
00435   //## begin CD_Vcollide%37548423012E.declarations preserve=yes
00436   //## end CD_Vcollide%37548423012E.declarations
00437 
00438 //## begin module%37548423012E.epilog preserve=yes
00439 //## end module%37548423012E.epilog

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