planners/prm/PL_PrmIjg.cpp

Go to the documentation of this file.
00001 #pragma warning( disable : 4786 )
00002 
00003 #include <synchronization/semaphore.h>
00004 #include <algorithm>
00005 #include "CollisionDetectors/CD_Bool.h"
00006 #include "color/colorf.h"
00007 #include "debug/debug.h"
00008 #include "math/astar.h"
00009 #include "PL_PrmIjg.h"
00010 #include <gl\gl.h>
00011 #include "smoothers\SmootherBase.h"
00012 
00013 PL_PrmIjg::PL_PrmIjg():
00014     m_PlanComplete( false ),
00015     m_NumberOfTimesContinued( 0 )
00016 {
00017     m_Graphs.reserve( 10000 );
00018 }
00019 
00020 PL_PrmIjg::~PL_PrmIjg()
00021 {
00022 }
00023 
00024 //=============================================================================
00025 // AddNodeToGraph
00026 //
00027 // generates a random configuraiton in CSpace
00028 //=============================================================================
00029 bool PL_PrmIjg::AddNodeToGraph( const int graphNum, const Configuration& config )
00030 {
00031     bool configInCollision = collisionDetector->IsInterfering( config );
00032     bool graphInCollision = !m_GraphInFreeSpace[ graphNum ];
00033     if( configInCollision != graphInCollision )
00034     {
00035         return false;
00036     }
00037 
00038     //
00039     // Get the graph
00040     //
00041     PrmGraph& graph = m_Graphs[ graphNum ];
00042 
00043     //
00044     // Connect the node to the closest other node in the graph
00045     //
00046     int closestNode = -1;
00047     double closestNodeValue = 9999999999; //make this DBL_MAX?
00048     unsigned size = graph.GetNumNodes();
00049     unsigned i;
00050     for( i = 0; i < size; ++i )
00051     {
00052         const Configuration& c = graph.GetNodeData( i );
00053         double distance = ( c - config ).MagSquared();
00054         if( distance < closestNodeValue )
00055         {
00056             closestNodeValue = distance;
00057             closestNode = i;
00058         }
00059     }
00060 /*
00061     //
00062     // Find the closest edge in the graph to this point - more often than
00063     // not, new points will connect best to interior points of existing
00064     // edges
00065     //
00066     int closestEdge = -1;
00067     double closestEdgeValue = 9999999999;
00068     size = graph.GetNumEdges();
00069     for( i = 0; i < size; ++i )
00070     {
00071         const Graph::Edge& e = graph.GetEdge( i );
00072         int n0 = e.m_Node0;
00073         int n1 = e.m_Node1;
00074         const Configuration& c0 = graph.GetNodeData( n0 );
00075         const Configuration& c1 = graph.GetNodeData( n1 );
00076         double distance = DistanceSquared( c0, c1, config );
00077         if( distance < closestEdgeValue )
00078         {
00079             closestEdgeValue = distance;
00080             closestEdge = i;
00081         }
00082     }
00083 
00084     if( closestEdgeValue < closestNodeValue )
00085     //if( false )
00086     {
00087         //
00088         // We need to subdivide an edge in the graph
00089         //
00090         const Graph::Edge& e = graph.GetEdge( closestEdge );
00091         int n0 = e.m_Node0;
00092         int n1 = e.m_Node1;
00093         const Configuration& c0 = graph.GetNodeData( n0 );
00094         const Configuration& c1 = graph.GetNodeData( n1 );
00095         Configuration& closestPoint = ClosestPoint( c0, c1, config );
00096         bool completelyFree = !collisionDetector->IsInterferingLinear( config, closestPoint );
00097         if( completelyFree )
00098         {
00099             int subdividedNode = graph.AddNode( closestPoint );
00100             int newNode = graph.AddNode( config );
00101             graph.AddEdge( n0, subdividedNode );
00102             graph.AddEdge( n1, subdividedNode );
00103             graph.AddEdge( newNode, subdividedNode );
00104             return true;
00105         }
00106     }
00107 */
00108     //
00109     // Add an edge connection to the closest node
00110     //
00111     if( closestNode != -1 )
00112     {
00113         Configuration closestConfig = graph.GetNodeData( closestNode );
00114         IJG_Assert( config.DOF() != 0 );
00115         IJG_Assert( closestConfig.DOF() != 0 );
00116         //IJG_Assert( completelyFree != completelyInCollision );
00117         if( graphInCollision )
00118         {   
00119             bool completelyInCollision = collisionDetector->IsCompletelyWithinObstacles( config, closestConfig );
00120             if( completelyInCollision )
00121             {
00122                 int nodeNum = graph.AddNode( config );
00123                 graph.AddEdge( nodeNum, closestNode );
00124                 return true;
00125             }
00126         }
00127 
00128         if( !graphInCollision )
00129         {
00130             bool completelyFree = !collisionDetector->IsInterferingLinear( config, closestConfig );
00131             if( completelyFree )
00132             {
00133                 int nodeNum = graph.AddNode( config );
00134                 graph.AddEdge( nodeNum, closestNode );
00135                 return true;
00136             }
00137         }
00138     }
00139     return false;
00140 }
00141 
00142 //=============================================================================
00143 // CreateNewGraph
00144 //
00145 // Creates a new graph with this configuration as a seed
00146 //=============================================================================
00147 int PL_PrmIjg::CreateNewGraph( const Configuration& config )
00148 {
00149     //
00150     // Add a graph to the array of graphs
00151     //
00152     int currentSize = m_Graphs.size();
00153     m_Graphs.resize( currentSize + 1 );
00154     int size = currentSize + 1;
00155     PrmGraph& graph = m_Graphs[ size - 1 ];
00156     graph.AddNode( config );
00157 
00158     //
00159     // Add a boolean flag to the list of bools
00160     //
00161     bool interfering = collisionDetector->IsInterfering( config );
00162     m_GraphInFreeSpace.push_back( !interfering );
00163     return size - 1;
00164 }
00165 
00166 //=============================================================================
00167 // GenerateRandomConfig
00168 //
00169 // generates a random configuraiton in CSpace
00170 //=============================================================================
00171 bool PL_PrmIjg::DrawExplicit() const
00172 {
00173         // Lock Graph for Drawing
00174         Semaphore semaphore( this->guid );
00175         semaphore.Lock();
00176 
00177     //
00178     // Draw all the nodes
00179     //
00180         glClearColor( 0.0f, 0.0f, 0.2f, 1.0f );
00181         glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00182         glDisable( GL_LIGHTING );
00183         glShadeModel( GL_SMOOTH );
00184     glPointSize( 2.0 );
00185 
00186     Color::Colorf freeNodeColor     = Color::green;
00187     Color::Colorf obstacleNodeColor = Color::red;
00188     Color::Colorf freeEdgeColor     = freeNodeColor - Color::opaque * 0.5;
00189     Color::Colorf obstacleEdgeColor = obstacleNodeColor - Color::opaque * 0.5;
00190 
00191 
00192     int i;
00193     int size = m_Graphs.size();
00194     for( i = 0; i < size; ++i )
00195     {
00196         //
00197         // Get the graph
00198         //
00199         const PrmGraph& graph = m_Graphs[ i ];
00200         const bool isInFreeSpace = m_GraphInFreeSpace[ i ];
00201         if( isInFreeSpace )
00202         {
00203             freeNodeColor.GlDraw();
00204         }
00205         else
00206         {
00207             obstacleNodeColor.GlDraw();
00208         }
00209         SetColor( i );
00210 
00211         //
00212         // Draw all the points
00213         //
00214         glBegin( GL_POINTS );
00215         {
00216             const int size = graph.GetNumNodes();
00217             int i;
00218             for( i = 0; i < size; ++i )
00219             {
00220                 const Configuration& node = graph.GetNodeData( i );
00221                 Draw( node );
00222             }
00223         }
00224         glEnd();
00225 
00226         //
00227         // Draw all the edges
00228         //
00229         if( isInFreeSpace )
00230         {
00231             Color::green;
00232             freeEdgeColor.GlDraw();
00233         }
00234         else
00235         {
00236             obstacleEdgeColor.GlDraw();
00237         }
00238         SetColor( i );
00239 
00240 
00241         glLineWidth( 1.0f );
00242         glBegin( GL_LINES );
00243         {
00244             const int size = graph.GetNumEdges();
00245             int i;
00246             for( i = 0; i < size; ++i )
00247             {
00248                 const Graph::Edge& e = graph.GetEdge( i );
00249                 const Configuration& c0 = graph.GetNodeData( e.m_Node0 );
00250                 const Configuration& c1 = graph.GetNodeData( e.m_Node1 );
00251                 Draw( c0 );
00252                 Draw( c1 );
00253             }
00254         }
00255         glEnd();
00256     }
00257 
00258         // Unlock Semaphore
00259         semaphore.Unlock();
00260         Sleep( 15 );
00261 
00262     return true;
00263 }
00264 
00265 //=============================================================================
00266 // DrawOverlay
00267 //
00268 // draws a configuration in "world" space
00269 //=============================================================================
00270 void PL_PrmIjg::DrawOverlay( const Configuration& config ) const
00271 {
00272     float x = 0.0f;
00273     float y = 0.0f;
00274     float z = 0.0f;
00275     const unsigned int DOF = config.DOF();
00276     if( DOF > 0 )
00277     {
00278         x = config[ 0 ];
00279     }
00280     if( DOF > 1 )
00281     {
00282         y = config[ 1 ];
00283     }
00284     if( DOF > 2 )
00285     {
00286         z = config[ 2 ];
00287     }
00288     glVertex3f( y, -x, z );
00289 }
00290 
00291 //=============================================================================
00292 // DrawUniversePortion
00293 //
00294 // Gets the path out of the graph, now that we know there is one
00295 //=============================================================================
00296 void PL_PrmIjg::DrawUniversePortion() const
00297 {
00298     //
00299     // I've only written this for 2dof translational robots
00300     //
00301     unsigned int dof = collisionDetector->DOF();
00302     if( dof != 2 )
00303     {
00304         return;
00305     }
00306 
00307         // Lock Graph for Drawing
00308         Semaphore semaphore( this->guid );
00309         semaphore.Lock();
00310 
00311     //
00312     // Draw all the nodes
00313     //
00314         glDisable( GL_LIGHTING );
00315         glShadeModel( GL_SMOOTH );
00316     glPointSize( 2.0 );
00317 
00318     Color::Colorf freeNodeColor     = Color::green;
00319     Color::Colorf obstacleNodeColor = Color::red;
00320     Color::Colorf freeEdgeColor     = freeNodeColor - Color::opaque * 0.5;
00321     Color::Colorf obstacleEdgeColor = obstacleNodeColor - Color::opaque * 0.5;
00322 
00323 
00324     int i;
00325     int size = m_Graphs.size();
00326     for( i = 0; i < size; ++i )
00327     {
00328         //
00329         // Get the graph
00330         //
00331         const PrmGraph& graph = m_Graphs[ i ];
00332         const bool isInFreeSpace = m_GraphInFreeSpace[ i ];
00333         if( isInFreeSpace )
00334         {
00335             freeNodeColor.GlDraw();
00336         }
00337         else
00338         {
00339             obstacleNodeColor.GlDraw();
00340         }
00341         SetColor( i );
00342 
00343         //
00344         // Draw all the points
00345         //
00346         glBegin( GL_POINTS );
00347         {
00348             const int size = graph.GetNumNodes();
00349             int i;
00350             for( i = 0; i < size; ++i )
00351             {
00352                 const Configuration& node = graph.GetNodeData( i );
00353                 DrawOverlay( node );
00354             }
00355         }
00356         glEnd();
00357 
00358         //
00359         // Draw all the edges
00360         //
00361         if( isInFreeSpace )
00362         {
00363             Color::green;
00364             freeEdgeColor.GlDraw();
00365         }
00366         else
00367         {
00368             obstacleEdgeColor.GlDraw();
00369         }
00370         SetColor( i );
00371 
00372 
00373         glLineWidth( 1.0f );
00374         glBegin( GL_LINES );
00375         {
00376             const int size = graph.GetNumEdges();
00377             int i;
00378             for( i = 0; i < size; ++i )
00379             {
00380                 const Graph::Edge& e = graph.GetEdge( i );
00381                 const Configuration& c0 = graph.GetNodeData( e.m_Node0 );
00382                 const Configuration& c1 = graph.GetNodeData( e.m_Node1 );
00383                 DrawOverlay( c0 );
00384                 DrawOverlay( c1 );
00385             }
00386         }
00387         glEnd();
00388     }
00389 
00390         // Unlock Semaphore
00391         semaphore.Unlock();
00392         Sleep( 15 );
00393 }
00394 
00395 //=============================================================================
00396 // GenerateRandomConfig
00397 //
00398 // generates a random configuraiton in CSpace
00399 //=============================================================================
00400 Configuration PL_PrmIjg::GenerateRandomConfig() const
00401 {
00402         int dof = GetStartConfig().DOF() ;
00403         Configuration returnme ;
00404         returnme.SetLength( dof ) ;
00405 
00406         for( int i = 0; i < dof; i++ )
00407         {
00408                 double max = collisionDetector->JointMax( i ) ;
00409                 double min = collisionDetector->JointMin( i ) ;
00410                 double random = double( rand() ) / RAND_MAX ; //this is a random number between [0..1]
00411                 returnme[ i ] = min + ( max - min ) * random ;
00412         }
00413 
00414         return returnme ;
00415 }
00416 
00417 //=============================================================================
00418 // MergeGraphs
00419 //
00420 // merges two formerly disjoint subgraphs together
00421 //=============================================================================
00422 void PL_PrmIjg::MergeGraphs( const int base, const int merge, const Configuration& config )
00423 {
00424     //
00425     // Check if we're done
00426     //
00427     if( ( base == 0 ) && ( merge == 1 ) )
00428     {
00429         m_PlanComplete = true;
00430     }
00431 
00432     PrmGraph& baseGraph = m_Graphs[ base ];
00433     PrmGraph& mergeGraph = m_Graphs[ merge ];
00434 
00435     baseGraph.Add( mergeGraph );
00436     mergeGraph.Clear();     //really aught to erase this graph outright
00437 
00438     //
00439     // find the nodes that match config
00440     //
00441     int firstMatch = -1;
00442     int i;
00443     int size = baseGraph.GetNumNodes();
00444     for( i = 0; i < size; ++i )
00445     {
00446         const Configuration& baseConfig = baseGraph.GetNodeData( i );
00447         double difference = ( baseConfig - config ).Magnitude();
00448         if( baseConfig == config )
00449         {
00450             firstMatch = i;
00451             break;
00452         }
00453     }
00454 
00455     bool graphsConnected = false;
00456     IJG_Assert( firstMatch != -1 );
00457     for( ++i; i < size; ++i )
00458     {
00459         if( baseGraph.GetNodeData( i ) == config )
00460         {
00461             graphsConnected = true;
00462             baseGraph.AddEdge( firstMatch, i );
00463         }
00464     }
00465     IJG_Assert( graphsConnected );
00466 }
00467 
00468 //=============================================================================
00469 // Plan
00470 //
00471 // does all the palnning work
00472 //=============================================================================
00473 bool PL_PrmIjg::Plan ()
00474 {
00475         // Lock Graph for Drawing
00476         Semaphore semaphore( this->guid );
00477         semaphore.Lock();
00478 
00479     //
00480     // check if we're starting or continuing
00481     //
00482     if( m_Graphs.size() == 0 )
00483     {
00484 
00485         //
00486         // starting
00487         //
00488         CreateNewGraph( GetStartConfig() );
00489         CreateNewGraph( GetGoalConfig() );
00490     }
00491     else
00492     {
00493         //
00494         // continuing
00495         //
00496         ++m_NumberOfTimesContinued;
00497         srand( m_NumberOfTimesContinued );
00498     }
00499 
00500     // Start the timer
00501         StartTimer();
00502 
00503     while( ( !m_PlanComplete ) && ( !HasTimeLimitExpired() ) )
00504     {
00505         semaphore.Unlock();
00506         semaphore.Lock();
00507         Configuration config = GenerateRandomConfig();
00508 
00509         //
00510         // Try adding the new config to all the graphs 1 by 1
00511         //
00512         std::vector< int > graphsAddedTo;
00513         int i;
00514         int size = m_Graphs.size();
00515         bool successfullyAdded = false;
00516         for( i = 0; i < size; ++i )
00517         {
00518             bool addedToThisGraph = AddNodeToGraph( i, config );
00519             successfullyAdded |= addedToThisGraph;
00520             if( addedToThisGraph )
00521             {
00522                 IJG_Assert( m_Graphs[ i ].ContainsNode( config ) );
00523                 graphsAddedTo.push_back( i );
00524             }
00525         }
00526 
00527         //
00528         // This caused a join of 2 or more subgraphs
00529         //
00530         if( graphsAddedTo.size() > 1 )
00531         {
00532             std::sort( graphsAddedTo.begin(), graphsAddedTo.end() );
00533             int baseGraphNum = graphsAddedTo[ 0 ];
00534             int i;
00535             int size = graphsAddedTo.size();
00536             for( i = 1; i < size; ++i )
00537             {
00538                 int mergeGraphNum = graphsAddedTo[ i ];
00539                 MergeGraphs( baseGraphNum, mergeGraphNum, config );
00540                 Graph::GraphBase& g = m_Graphs[ baseGraphNum ];
00541                 bool ok = g.CheckIntegrity();
00542                 if( !ok )
00543                 {
00544                     this->PrintGraph( baseGraphNum );
00545                 }
00546                 IJG_Assert( ok );
00547             }
00548         }
00549 
00550         //
00551         // This is an entirely new subgraph
00552         //
00553         if( !successfullyAdded )
00554         {
00555             if( !collisionDetector->IsInterfering( config ) )
00556             {
00557                 CreateNewGraph( config );
00558             }
00559         }
00560     }
00561 
00562     //
00563     // Do a graph search from the start to the goal, to actually get the path
00564     //
00565     if( !HasTimeLimitExpired() )
00566     {
00567         //
00568         // which is the node that we're searching for?
00569         //
00570         int goalNodeNum = -1;
00571         int i;
00572         int size = m_Graphs[ 0 ].GetNumNodes();
00573         for( i = 0; i < size; ++i )
00574         {
00575             const Configuration& c = m_Graphs[ 0 ].GetNodeData( i );
00576             if( c == GetGoalConfig() )
00577             {
00578                 goalNodeNum = i;
00579                 break;
00580             }
00581         }
00582         IJG_Assert( goalNodeNum != -1 );
00583 
00584         Graph::Astar search;
00585         search.Search( m_Graphs[ 0 ], 0, goalNodeNum );
00586         std::vector< int > results = search.GetPath();
00587 
00588         size = results.size();
00589         for( i = 0; i < size; ++i )
00590         {
00591             int nodeNumber = results[ i ];
00592             const Configuration& c = m_Graphs[ 0 ].GetNodeData( nodeNumber );
00593             path.AppendPoint( c );
00594         }
00595     }
00596 
00597         if( this->m_Smoother != NULL )
00598         {
00599                 this->m_Smoother->SetPath( &this->path );
00600                 this->m_Smoother->SetCollisionDetector( this->collisionDetector );
00601                 m_Smoother->Smooth();
00602                 this->path = m_Smoother->GetPath();
00603                 m_Smoother->SetPath( NULL );
00604         }
00605 
00606     semaphore.Unlock();
00607     if( HasTimeLimitExpired() )
00608     {
00609         return false;
00610     }
00611         return true ;
00612 }
00613 
00614 //=============================================================================
00615 // PlanMultiThread
00616 //
00617 // does all the palnning work
00618 //=============================================================================
00619 void PL_PrmIjg::PlanMultiThread (void* data)
00620 {
00621     //nothing???
00622 }
00623 
00624 //=============================================================================
00625 // PrintGraph
00626 //
00627 // prints out the graph for debugging purposes
00628 //=============================================================================
00629 void PL_PrmIjg::PrintGraph( const int graphNum ) const
00630 {
00631     const PrmGraph& graph = m_Graphs[ graphNum ];
00632 
00633     //
00634     // Print all the node data values
00635     //
00636     int i;
00637     int size = graph.GetNumNodes();
00638     for( i = 0; i < size; ++i )
00639     {
00640         const Configuration& config = graph.GetNodeData( i );
00641         printf( "%d\t", i );
00642         config.Output();
00643         printf( "\n" );
00644     }
00645 
00646     //
00647     // Print all of the edges
00648     //
00649     printf( "Edges\n" );
00650     size = graph.GetNumEdges();
00651     for( i = 0; i < size; ++i )
00652     {
00653         const Graph::Edge& e = graph.GetEdge( i );
00654         printf( "[%d]\t%d\t%d\n", i, e.m_Node0, e.m_Node1 );
00655     }
00656 
00657     //
00658     // Print which nodes contain which edges
00659     //
00660     printf( "Nodes\n" );
00661     size = graph.GetNumNodes();
00662     for( i = 0; i < size; ++i )
00663     {
00664         printf( "[%d]\t", i );
00665         const Graph::Node& n = graph.GetNode( i );
00666         int edgeSize = n.GetNumEdges();
00667         int j;
00668         for( j = 0; j < edgeSize; ++j )
00669         {
00670             int edge = n.GetEdgeNumber( j );
00671             printf( "%d\t", edge );
00672         }
00673         printf( "\n" );
00674     }
00675 }
00676 
00677 //=============================================================================
00678 // SetColor
00679 //
00680 // sets the GL color to a distinct color
00681 //=============================================================================
00682 void  PL_PrmIjg::SetColor( const int i )
00683 {
00684     int modulo = i % 4;
00685     switch( modulo )
00686     {
00687     case 0:
00688     {
00689         Color::red_50.GlDraw();
00690         return;
00691     }
00692     case 1:
00693     {
00694         Color::green_50.GlDraw();
00695         return;
00696     }
00697     case 2:
00698     {
00699         Color::yellow_50.GlDraw();
00700         return;
00701     }
00702     case 3:
00703     {
00704         Color::cyan_50.GlDraw();
00705         return;
00706     }
00707     default:
00708         Color::white.GlDraw();
00709         return;
00710     }
00711 }

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