planners/PL_GraphBase.cpp

Go to the documentation of this file.
00001 //=========================================================================
00002 //
00003 //  File:  PL_GraphBase.cpp
00004 //
00005 //  Created 07-Feb-01 by Shane Schneider
00006 //
00007 //              Planner Base for planners requiring a graph data structure
00008 //              Contains the actual graph structure as well as several draw and
00009 //              computation functions.
00010 
00011 
00012 
00013 // PL_GraphBase
00014 #include "synchronization/semaphore.h"
00015 #include "color/colorf.h"
00016 #include "Planners\PL_GraphBase.h"
00017 
00018 #include <assert.h>
00019 #include <math.h>
00020 #include <math/math2.h>
00021 #include <iosfwd>
00022 #include <iostream>
00023 
00024 
00025 // fix gl path...
00026 // #include <gl/glos.h>
00027 #include "opengl/glos.h"
00028 #include <gl/gl.h>
00029 
00030 using std::endl;
00031 
00032 //--------------------- Constants ---------------
00033 // File Constants
00034 static const char FILEEXT[] = ".gph";
00035 static const char FILEHEADER[] = "GRAPHBASE";
00036 const int  PL_GraphBase::NIL_ID = -1;
00037 // Other constants
00038 const double COMPTOL = 1e-8;
00039 
00040 // Class PL_GraphBase 
00041 
00042 // Default Constructor
00043 PL_GraphBase::PL_GraphBase()
00044 {
00045         // Assign the file header and extension for this type
00046         strcpy( fileext, FILEEXT );
00047         strcpy( fileheader, FILEHEADER );
00048 
00049         // Clear the Graph
00050         ClearGraph();
00051 
00052         // Normalize the Default Distance Weight
00053         NormDistWeight();
00054 
00055         // DEBUGGING:  Ensure this parent constructor is being called
00056         TRACE("PL_GraphBase Default constructor completed.\n");
00057 
00058 
00059 }
00060 
00061 
00062 PL_GraphBase::~PL_GraphBase()
00063 {
00064         // Default Destructor
00065 }
00066 
00067 
00068 //=============================================================================
00069 // DrawExplicit
00070 //
00071 // Purpose: Draws the planner data to the planner window when called
00072 //=============================================================================
00073 bool PL_GraphBase::DrawExplicit () const
00074 {
00075     double Xcor; 
00076     double Ycor;
00077     double Zcor;    // temp coordinate variables
00078     node   n1;      // index for the various nodes during iterations
00079     edge   e1;      // index for iteration of edges
00080         
00081         // Lock Graph for Drawing
00082         Semaphore semaphore( this->guid );
00083         semaphore.Lock();
00084 
00085         // Setup GL Environment
00086         glClearColor( 0.0f, 0.0f, 0.2f, 1.0f );
00087         glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00088         BOOL lightingState = glIsEnabled( GL_LIGHTING );
00089         glDisable( GL_LIGHTING );
00090 
00091         // Create Shading Effects that will allow edges to have two end colours.
00092         //  IMPROVE:  Does this change the shading for others.  If so, is there a way
00093         //                    to check for current shading mode and save it.
00094         glShadeModel( GL_SMOOTH );
00095 
00096         // The depth function is set to its default of GL_LESS.  This means that any object closer to the viewport
00097         // will have its colour displayed for that pixel.  This means closer objects will be drawn on top of further
00098         // objects.  Any objects that are in the same plane, will have the colour of the object drawn first.
00099 
00100         // Draw Child Planner Specific Information
00101         DrawSpecific();
00102 
00103 
00104         // Draw all NODES first, as these are to be seen on top of any edges.
00105         glPointSize( 5.0f );    // Set size of points associated with the nodes.
00106 
00107         // Draw the Start and Goal nodes as these want to be predominately seen.
00108         glBegin( GL_POINTS );
00109                 // Draw the Startnode, if valid.
00110                 if ( startNode != nil )
00111                 {
00112             Color::yellow.GlDraw();
00113                         GetCoords( startNode, Xcor, Ycor, Zcor );
00114                         glVertex3d( Xcor, Ycor, Zcor );
00115                 }
00116 
00117                 // Draw the Goalnode, if valid.
00118                 if ( goalNode != nil )
00119                 {
00120             Color::cyan.GlDraw();
00121                         GetCoords( goalNode, Xcor, Ycor, Zcor );
00122                         glVertex3d( Xcor, Ycor, Zcor );
00123                 }
00124         glEnd();
00125 
00126         // Draw all remainning nodes.
00127         glBegin(GL_POINTS);
00128                 // Search all nodes of the graph and draw them unless they are start and goal.
00129         Color::red.GlDraw();
00130                 forall_nodes( n1, G )
00131                 {
00132                         if ( ( n1 != startNode ) && ( n1 != goalNode ) )
00133                         {
00134                                 GetCoords( n1, Xcor, Ycor, Zcor );      // Get Coordinates of the current node
00135                                 glVertex3d( Xcor, Ycor, Zcor );
00136                         }
00137                 }
00138         glEnd();
00139 
00140 
00141         // Draw EDGES joining the nodes
00142         // Draw the tentative path through the nodes, if it exists, by drawing edges connects the nodes of 
00143         // the path.
00144         if ( !graphPath.empty() )
00145         {
00146                 glLineWidth( 3.0f );
00147                 glBegin(GL_LINES);
00148                         node n1 = graphPath.tail();
00149         
00150                         // Search through the nodes of the graphPath, starting with
00151                         // the goalNode (last node listed in path) and ending on startNode (first node)
00152                         node firstNode = graphPath.head();
00153                         while ( n1 != firstNode )
00154                         {
00155                                 // get the source node coordinates
00156                                 GetCoords( n1, Xcor, Ycor, Zcor );
00157                 Color::orange.GlDraw();
00158                                 glVertex3d( Xcor, Ycor, Zcor ); // add source vertex for edge line
00159 
00160                                 // advance to prev node (target vertex of edge)
00161                                 n1 = graphPath.pred( n1 );
00162 
00163                                 // get the target node coordinates
00164                                 GetCoords( n1, Xcor, Ycor, Zcor );
00165                 Color::yellow.GlDraw();
00166                                 glVertex3d( Xcor, Ycor, Zcor ); // add target vertex for edge line
00167 
00168                                 // for next iteration, want to use the current node and node index as the source for the next node.  
00169                                 // Will automatically fall out when the end of the list is reached and the last node serves as the target 
00170                                 // for the last edge only.
00171                         } 
00172                         
00173                 glEnd();
00174         }
00175 
00176 
00177         // Draw all Edges joining the nodes of the graph.
00178         glLineWidth( 1.0f );
00179         glBegin(GL_LINES);
00180                 // Draw all connecting edges
00181                 forall_edges(e1,G)
00182                 {
00183                         GetCoords( G.source(e1), Xcor, Ycor, Zcor );    // get coordinates of source node;
00184             Color::blue.GlDraw();
00185                         glVertex3d( Xcor, Ycor, Zcor ); // add source vertex for edge line.
00186 
00187                         GetCoords( G.target(e1), Xcor, Ycor, Zcor );    // get coordinates of target node;
00188             Color::white.GlDraw();
00189                         glVertex3d( Xcor, Ycor, Zcor ); // add target vertex for edge line.
00190                 }
00191         glEnd();
00192 
00193         // Clean up Environment
00194         if( lightingState != FALSE )
00195         {
00196                 glEnable( GL_LIGHTING );
00197         }
00198 
00199         // Unlock Semaphore
00200         semaphore.Unlock();
00201 
00202         return true;
00203 }
00204 
00205 
00206 //=============================================================================
00207 // Load
00208 //
00209 // Purpose: Loads partailly complete planner data from the disk
00210 //=============================================================================
00211 bool PL_GraphBase::Load (const char *filename)
00212 {
00213         Semaphore semaphore( this->guid );
00214         semaphore.Lock();
00215 
00216         // Create file name with the extension.
00217         char tempstring[ 256 ] = "" ;
00218         strcpy( tempstring, filename ) ;
00219         strcat( tempstring, fileext ) ; 
00220 
00221         // Open the file
00222         std::ifstream infile( tempstring, std::ios::in );
00223         if( infile.good() == false )
00224         {
00225                 semaphore.Unlock();
00226                 MessageBox( NULL, "Could not open filename specified", "ERROR", MB_OK );
00227                 return false;
00228         }
00229 
00230         // Check the Header
00231         infile >> tempstring;
00232         if ( strcmp( tempstring, fileheader ) != 0 )
00233         {
00234                 infile.close();
00235                 semaphore.Unlock();
00236                 MessageBox( NULL, "Incompatible Base Graph File Loaded", "ERROR", MB_OK );
00237                 return false;
00238         }
00239 
00240         // Clear the old graph and parameters
00241         this->ClearGraph();
00242 
00243         // Load the contents of the file
00244         bool success = this->LoadContents( infile );
00245         if ( !success )
00246         {
00247                 infile.close();
00248                 semaphore.Unlock();
00249                 MessageBox( NULL, "Could not load graph or parameters from file", "ERROR", MB_OK );
00250                 return false;
00251         }
00252 
00253         // Close the file
00254         infile.close();
00255 
00256         semaphore.Unlock();
00257         return true;
00258 }
00259 
00260 //=============================================================================
00261 // LoadContents
00262 //
00263 // Purpose: Loads the graph and other related base planner parameters to the the
00264 //                  given ifstream.
00265 //      
00266 //                      Returns success of load.
00267 //=============================================================================
00268 bool PL_GraphBase::LoadContents( std::ifstream& infile )
00269 {
00270         // Load the Graph
00271         int result = G.read( infile );
00272         if ( result != 0 )
00273         {
00274                 MessageBox( NULL, "Graph Load Error", "ERROR", MB_OK );
00275                 return false;
00276         }
00277 
00278         // Load the Start and Goal Nodes
00279         int nodeID;
00280     Configuration newStartConfig;
00281         infile >> nodeID >> newStartConfig;
00282     SetStartConfig( newStartConfig );
00283         // Since graphs are optimized when loaded, the nodeID may not be valid,
00284         // use the FindConfig to find the correct node associated with the start and goal configs in the graph.
00285 //      startNode = TranslateNodeID( nodeID );
00286         startNode = FindConfig( GetStartConfig() );     
00287         
00288 
00289     Configuration newGoalConfig;
00290         infile >> nodeID >> newGoalConfig;
00291     SetGoalConfig( newGoalConfig );
00292 //      goalNode = TranslateNodeID( nodeID );
00293         goalNode = FindConfig( GetGoalConfig() );
00294 
00295         //Load the DistVector
00296         infile >> distWeight;
00297 
00298         return true;
00299         
00300 }
00301 
00302 
00303 //=============================================================================
00304 // Does Planning
00305 //
00306 // Purpose: performs the planning task
00307 //=============================================================================
00308 bool PL_GraphBase::Plan ()
00309 {
00310         assert( false );                //this is an abstract base class, and should never be called
00311         return false;
00312 }
00313 
00314 //=============================================================================
00315 // Save
00316 //
00317 // Purpose: Saves partial plan data to disk
00318 //=============================================================================
00319 bool PL_GraphBase::Save (const char *filename) const
00320 {
00321         Semaphore semaphore( this->guid );
00322         semaphore.Lock();
00323 
00324         // Create file name with the extension.
00325         char filenameWithExtension[ 256 ] = "" ;
00326         strcpy( filenameWithExtension, filename ) ;
00327         strcat( filenameWithExtension, fileext ) ;      
00328 
00329         // Open the file
00330         std::ofstream outfile( filenameWithExtension, std::ios::out );
00331         if( outfile.good() == false )
00332         {
00333                 semaphore.Unlock();
00334                 MessageBox( NULL, "Could not open filename specified", "ERROR", MB_OK );
00335                 return false;
00336         }
00337 
00338         // Add the Header Information
00339         outfile << fileheader << endl;
00340 
00341 
00342         // Save the contents of the planner
00343         bool success = this->SaveContents( outfile );
00344         ASSERT ( success );
00345 
00346         // Close the file
00347         outfile.close();
00348 
00349         semaphore.Unlock();
00350         return true;
00351 }
00352 
00353 //=============================================================================
00354 // SaveContents
00355 //
00356 // Purpose: Saves the graph and other related base planner parameters to the the
00357 //                  given ofstream.
00358 //      
00359 //                      Returns success of save.
00360 //=============================================================================
00361 bool PL_GraphBase::SaveContents ( std::ofstream& outfile ) const
00362 {
00363         // Save the Graph
00364         G.write( outfile );
00365 
00366         int nodeID;
00367 
00368         // Save Start and Goal Nodes
00369         if ( startNode == nil )
00370         {
00371                 nodeID = NIL_ID;
00372         }
00373         else
00374         {
00375                 nodeID = startNode->id();
00376         }
00377         outfile << nodeID << " " << GetStartConfig() << endl;
00378         if ( goalNode == nil )
00379         {
00380                 nodeID = NIL_ID;
00381         }
00382         else
00383         {
00384                 nodeID = goalNode->id();
00385         }
00386         outfile << nodeID << " " << GetGoalConfig() << endl;
00387 
00388         // Save the DistWeights
00389         outfile << distWeight << endl;
00390 
00391         return true;
00392 }
00393 
00394 
00395 
00396 //=============================================================================
00397 // Clearing Functions
00398 //
00399 // Purpose: Clears the graph and start and goal nodes.
00400 //                  
00401 //=============================================================================
00402 void PL_GraphBase::ClearGraph()
00403 {
00404         // Clear the Graph
00405         if ( !G.empty() )
00406         {
00407                 G.clear();
00408         }
00409 
00410         // Reset the start and goal nodes
00411         startNode = nil;
00412         goalNode = nil;
00413 
00414         // Clear any path
00415         ClearGraphPath();
00416 
00417 }
00418 
00419 void PL_GraphBase::ClearGraphPath()
00420 {
00421         // Clear the path of nodes
00422         if ( !graphPath.empty() )
00423         {
00424                 graphPath.clear();
00425         }
00426 }
00427 
00428 
00429 
00430 
00431 //=============================================================================
00432 // Distance Functions
00433 //
00434 // Purpose: Returns a weighted squared Euclidean distance between two possible nodes (configurations).
00435 //                  Used in selecting closest neighbours and path lengths
00436 //=============================================================================
00437 double PL_GraphBase::Distance ( const node& a, const node& b ) const
00438 // default weighted squared Euclidean Distance
00439 {
00440         return this->Distance( G.inf(a), G.inf(b) );
00441 }
00442 
00443 
00444 double PL_GraphBase::Distance ( const node& a, const node& b, const VectorN& weight ) const
00445 // Weighted Distance
00446 {
00447         return this->Distance( G.inf(a), G.inf(b), weight );
00448 }
00449 
00450 
00451 double PL_GraphBase::Distance ( const Configuration& a, const Configuration& b ) const
00452 // default weighted squared Euclidean Distance
00453 {
00454         return this->Distance( a, b, distWeight );
00455 }
00456 
00457 
00458 double PL_GraphBase::Distance ( const Configuration& a, const Configuration& b, const VectorN& weight ) const
00459 // Weighted Distance
00460 {
00461         // Get the differences between each of the joints
00462         VectorN jointDiff;
00463         jointDiff = DiffV( a, b );
00464 
00465         // Verify weight vector is at least as long as jointDiff.
00466         ASSERT( weight.Length() >= jointDiff.Length() ); 
00467 
00468         // Square and sum each of the joint differences
00469         double distance = 0;
00470         for( int i = 0; i < jointDiff.Length(); i++ )
00471         {
00472                 distance += Sqr( weight[i]*jointDiff[i] );
00473         }
00474 
00475         // Return the squared euclidean distance
00476         return distance;
00477 }
00478 
00479 
00480 VectorN PL_GraphBase::DiffV ( const node& a, const node& b ) const
00481 // Joint Differences
00482 {
00483         return this->DiffV( G.inf(a), G.inf(b) );
00484 }
00485 
00486 
00487 VectorN PL_GraphBase::DiffV ( const Configuration& a, const Configuration& b ) const
00488 // Absolute Joint Differences
00489 {
00490 
00491         return collisionDetector->JointDisplacement( a, b );
00492 
00493 }
00494 
00495 
00496 //=============================================================================
00497 // Measure Functions
00498 //
00499 // Purpose: Returns the weighted length (cost) of the given edge.
00500 //                  Length returns the stored value for the edge; Measure calculates a new
00501 //                      length by using the distance function with the end nodes of the edge.
00502 //=============================================================================
00503 double PL_GraphBase::Length( const edge& e1 ) const
00504 // Return stored length (cost) for edge
00505 {
00506         return G.inf(e1);
00507 }
00508 
00509 double PL_GraphBase::Measure( const edge& e1, const VectorN& weight ) const
00510 // Calculate the weighted length (cost) of the edge
00511 {
00512         return Distance( G.target(e1), G.source(e1), weight );
00513 }
00514 
00515 double PL_GraphBase::Measure( const edge& e1 ) const
00516 // Calculate the default weighted length (cost) of the edge
00517 {
00518         return Distance( G.target(e1), G.source(e1) );
00519 }
00520 
00521 
00522 //=============================================================================
00523 // NormDistWeight
00524 //      
00525 // Purpose:  Normalizes the default distance weight used in calculating the 
00526 //               distance between two configurations.
00527 //=============================================================================
00528 void PL_GraphBase::NormDistWeight()
00529 {
00530         // Get the DOF
00531         int dof = 0;
00532         if ( collisionDetector != NULL )
00533         {
00534                 dof = collisionDetector->DOF();
00535         }
00536         
00537         distWeight.SetLength( dof );
00538 
00539         for ( int i = 0; i < dof; i++ )
00540         {
00541                 distWeight[i] = 1;      // Set to unity
00542         }
00543 
00544 }
00545 
00546 //=============================================================================
00547 // GetCspaceRange
00548 //      
00549 // Purpose: Computes the length of the diagonal of the Cspace using the given distance weights.  
00550 //          Used as an indication of the range of distances that can acheived within the Cspace.
00551 //=============================================================================
00552 double PL_GraphBase::GetCspaceRange( const VectorN& weight ) const
00553 {
00554         
00555         // Get the DOF
00556         int dof = 0;
00557         if ( collisionDetector != NULL )
00558         {
00559                 dof = collisionDetector->DOF();
00560         }
00561         
00562         // Create a configuration that represents the bottom corner of the diagonal (all joints at their min).
00563         Configuration minConfig;
00564         minConfig.SetNumDOF( dof );
00565 
00566         // Create a configuration that represents the top corner of the diagonal (all joints at their max).
00567         Configuration maxConfig;
00568         maxConfig.SetNumDOF( dof );
00569 
00570         // Assign the respective joint limits to each joint.
00571         for (int i=0; i < dof; i++ )
00572         {
00573                 double jmin = collisionDetector->JointMin( i );
00574                 double jmax = collisionDetector->JointMax( i );
00575                 
00576                 if ( collisionDetector->JointWraps( i ) )
00577                 {
00578                         // Joint wraps, so take the mid point as the max value.  This will be the furthest away from the jmin.
00579                         jmax = ( jmax + jmin ) / 2;
00580                 }
00581                 
00582                 // Assign the joints
00583                 minConfig[i] = jmin;
00584                 maxConfig[i] = jmax;
00585         }
00586 
00587         // return the distance between the two end points of the diagonal
00588         return Distance( minConfig, maxConfig, weight );
00589 
00590 }
00591 
00592 double PL_GraphBase::GetCspaceRange() const
00593 // Use Default distWeight
00594 {
00595         return GetCspaceRange( distWeight );
00596 }
00597 
00598 
00599         
00600 
00601 //=============================================================================
00602 // Locate Functions
00603 //
00604 // Purpose: Searches the graph and returns the edge/node associated with the
00605 //                      parameters indicated.  If no successful edge/node is found, nil
00606 //                      is returned and can be used by the calling function for error checking
00607 //=============================================================================
00608 node PL_GraphBase::FindConfig( const Configuration& c1 ) const
00609 // Seach ALL nodes in graph, returning the node that matches the configuration
00610 {
00611         node n1;
00612 
00613         // Search the entire graph, returning early if matching node is found.
00614         // Graph is searched in reverse order, assuming the desired configuration is one that
00615         // was recently added.
00616         forall_rev_nodes( n1, G )
00617         {
00618                 if ( c1.Compare( G.inf(n1) , COMPTOL) )
00619                 {
00620                         // Matching node found
00621                         return n1;
00622                 }
00623         }
00624 
00625         // if still in function, no matching node was found
00626         return nil;
00627 }
00628 
00629 edge PL_GraphBase::FindEdge( const node& n1, const node& n2 ) const
00630 // Search all joining edges to n1 for edge that joins to n2.  Return joining edge
00631 {
00632         edge e1;
00633         
00634         // search all edge joining n1
00635         forall_inout_edges( e1, n1 )
00636         {
00637                 // Assume edge is pointing from n1.  Grab the target node
00638                 node othernode = G.target(e1);
00639 
00640                 // check if edge is reversed
00641                 if ( othernode == n1 )
00642                 {
00643                         // edge is reversed and pointing to n1.  Grab the source node.
00644                         othernode = G.source(e1);
00645                 }
00646 
00647                 if ( othernode == n2 )
00648                 {
00649                         // edge is joining n1 (verified because we are searching all edges attached to n1)
00650                         // and n2.  Return early with the edge.
00651                         return e1;
00652                 }
00653         }
00654 
00655         // if we are still in the function, no edge exists between n1 and n2.
00656         return nil;
00657 }
00658 
00659 
00660 //=============================================================================
00661 // GenerateRandomConfig
00662 //
00663 // Purpose: generates a random configuration
00664 //=============================================================================
00665 Configuration PL_GraphBase::GenerateRandomConfig ()
00666 {
00667         int dof = collisionDetector->DOF() ;
00668 
00669         Configuration returnme ;
00670         returnme.SetLength( dof ) ;
00671 
00672         for( int i = 0; i < dof; i++ )
00673         {
00674                 double max = collisionDetector->JointMax( i ) ;
00675                 double min = collisionDetector->JointMin( i ) ;
00676                 double random = 2*( double( rand() ) / RAND_MAX ) - 1; //this is a random number between [-1..1]
00677                 double jointvalue = ( max - min ) * random;
00678 
00679                 // Create a uniform distribution by having the random number go over the limits have wrapping the C-space;
00680                 if ( jointvalue < min )
00681                 {
00682                         jointvalue += (max - min);
00683                 }
00684                 else if ( jointvalue > max )
00685                 {
00686                         jointvalue -= (max - min);
00687                 }
00688 
00689                 returnme[ i ] = jointvalue;
00690         }
00691 
00692         return returnme ;
00693 }
00694 
00695 //=============================================================================
00696 // GenerateRandomConfig
00697 //
00698 // Purpose: generates a random configuration about a centre configuration,
00699 //          within C-space and without wrapping.
00700 //=============================================================================
00701 Configuration PL_GraphBase::GenerateRandomConfig ( const Configuration& centre )
00702 {
00703         enum LimitExceeded
00704         { 
00705                 MAXLIMIT = 1,
00706                 MINLIMIT = -1,
00707                 NEITHER  = 0
00708         };
00709 
00710         int dof = collisionDetector->DOF() ;
00711 
00712         Configuration newconfig;
00713         newconfig.SetLength( dof );
00714         
00715         bool limits_exceeded = false;
00716         LimitExceeded* joint_limit_exceeded = new LimitExceeded[dof];
00717         assert ( joint_limit_exceeded != NULL );
00718         
00719         for( int i = 0; i < dof; i++ )
00720         {
00721                 double max = collisionDetector->JointMax( i ) ;
00722                 double min = collisionDetector->JointMin( i ) ;
00723                 double random = ( double( rand() ) / RAND_MAX ); //this is a random number between [0..1]
00724                 double jointvalue = ( max - min ) * random + min;
00725 
00726                 // Create a distribution about centre by adding the jointvalue to the centre config.
00727                 jointvalue += centre[ i ];
00728 
00729                 // Check if joint exceeds limits
00730                 if ( jointvalue < min ) 
00731                 {
00732                         limits_exceeded = true;
00733                         joint_limit_exceeded[i] = MINLIMIT;
00734                 }
00735                 else if ( jointvalue > max )
00736                 {
00737                         limits_exceeded = true;
00738                         joint_limit_exceeded[i] = MAXLIMIT;
00739                 }
00740                 else
00741                 {
00742                         joint_limit_exceeded[i] = NEITHER;
00743                 }
00744 
00745                 newconfig[ i ] = jointvalue;
00746         }
00747 
00748         // check if any of the limits exceeded
00749         if ( limits_exceeded )
00750         {
00751                 // get slopes between the centre and the new config
00752                 VectorN slope = ( newconfig - centre );
00753                 double t = 1;
00754                 
00755                 // determine how far along the line connecting centre and new config the first limit is exceeded.
00756                 for ( int i = 0; i < dof; i++ )
00757                 {
00758                         double limit;
00759                         if ( joint_limit_exceeded[i] == NEITHER )
00760                         {
00761                                 // this joint does not exceed limit, continue with next iteration
00762                                 continue;
00763                         }
00764                         else if ( joint_limit_exceeded[i] == MINLIMIT )
00765                         {
00766                                 limit = collisionDetector->JointMin(i);
00767                         }
00768                         else
00769                         {
00770                                 limit = collisionDetector->JointMax(i);
00771                         }
00772 
00773                         double s = ( limit - centre[i] ) / slope[i];
00774 
00775                         // find the earliest time the limits are exceeded.
00776                         if ( s < t )
00777                         {
00778                                 // new earlier time
00779                                 t = s;
00780                         }
00781                 }
00782 
00783                 // update the new configuration so it does not exceed the limits
00784                 // by computing the config along the line that is at the first limit.
00785                 newconfig = (slope * t) + centre;
00786         }
00787 
00788         delete [] joint_limit_exceeded;
00789         return newconfig ;
00790 }
00791 
00792 
00793 
00794 //=============================================================================
00795 // GenerateRandomConfig
00796 //
00797 // Purpose: generates a random configuration based on a normal distribution about
00798 //                      the given seed and standard devation.  
00799 //=============================================================================
00800 Configuration PL_GraphBase::GenerateRandomConfig( const Configuration& seed, const double& std_dev )
00801 {
00802         int dof = seed.DOF() ;
00803 
00804         Configuration returnMe;
00805         returnMe.SetLength( dof );
00806         
00807         for( int i=0; i < dof; i++ )
00808         {
00809                 double jointvalue = RandNorm( seed[i], std_dev/distWeight[i] );
00810 
00811                 double jmax = collisionDetector->JointMax( i );
00812                 double jmin = collisionDetector->JointMin( i );
00813                 
00814                 // Use wrapping of the C-space (for all joints) to ensure normal distribution about seed.
00815                 double jrange = jmax - jmin;
00816                 assert( jrange > 0 );
00817                 if ( jrange == 0 )
00818                 {
00819                         jointvalue = jmax;
00820                 }
00821                 while ( jointvalue > jmax )
00822                 {
00823                         jointvalue -= jrange;
00824                 }
00825                 while ( jointvalue < jmin )
00826                 {
00827                         jointvalue += jrange;
00828                 }
00829 
00830                 returnMe[i] = jointvalue;
00831         }
00832 
00833         return returnMe;
00834 
00835 }
00836 
00837 
00838 //=============================================================================
00839 // IsIntering Functions
00840 //
00841 // Purpose: Used to determine if a node/configuration or a straight-line path between
00842 //                      two valid nodes/configurations or along a linear edge is interference free.
00843 //=============================================================================
00844 bool PL_GraphBase::IsInterfering( const edge& e1 )
00845 // Check if path along linear edge is NOT collision free
00846 {
00847         return this->IsInterfering( G.target(e1), G.source(e1) );
00848 }
00849 
00850 bool PL_GraphBase::IsInterfering( const node& n1, const node& n2 )
00851 // Check if linear path between n1 and n2 is NOT collision free
00852 {
00853         return this->IsInterfering( G.inf(n1), G.inf(n2) );
00854 }
00855 
00856 bool PL_GraphBase::IsInterfering( const Configuration& c1, const Configuration& c2 )
00857 // Check if linear path between c1 and c2 is NOT collision free
00858 {
00859         return collisionDetector->IsInterferingLinear( c1, c2 );
00860 }
00861 
00862 bool PL_GraphBase::IsInterfering( const node& n1 )
00863 // Check if n1 is interfering and therefore NOT valid.
00864 {
00865         return this->IsInterfering( G.inf(n1) );
00866 }
00867 
00868 bool PL_GraphBase::IsInterfering( const Configuration& c1 )
00869 // Check if c1 is interfering and therefore NOT valid.
00870 {
00871         return this->collisionDetector->IsInterfering( c1 );
00872 }
00873 
00874 //=============================================================================
00875 // DrawSpecific
00876 //
00877 // Purpose: Draw addition child planner specific information to the planner 
00878 //              window when called.  
00879 //
00880 // Note:    This function is to be implemented in child classes only.  If there
00881 //          is no additional planner specific info, THIS function will be called
00882 //                      and implement nothing new.
00883 //=============================================================================
00884 bool PL_GraphBase::DrawSpecific() const
00885 {
00886         return false;
00887 }
00888 
00889 //=============================================================================
00890 // GetCoords
00891 //
00892 // Purpose: Pass appropriate coordinates by reference for the configuration stored
00893 //                  stored in the given node/configuration.
00894 //=============================================================================
00895 void PL_GraphBase::GetCoords( const node n1, double& Xcor, double& Ycor, double& Zcor ) const 
00896 // Using actual node
00897 {
00898         GetCoords( G.inf(n1), Xcor, Ycor, Zcor);
00899 }
00900 
00901 void PL_GraphBase::GetCoords( const Configuration& c1, double& Xcor, double& Ycor, double& Zcor ) const
00902 // Using configutation
00903 {
00904         // Determine DOF available.
00905         int dof = c1.DOF();
00906 
00907         // Assign each of the Coordinates, if that DOF exists (C-space).  
00908         if ( dof > 0 )
00909         {
00910                 Xcor = c1[0];
00911         }
00912         else
00913         {
00914                 Xcor = 0;
00915         }
00916 
00917         if ( dof > 1 )
00918         {
00919                 Ycor = c1[1];
00920         }
00921         else
00922         {
00923                 Ycor = 0;
00924         }
00925 
00926         if ( dof > 2 )
00927         {
00928                 Zcor = c1[2];
00929         }
00930         else
00931         {
00932                 Zcor = 0;
00933         }
00934 
00935         return;
00936 }
00937 
00938 /*//=============================================================================
00939 // NodeCount
00940 //
00941 // Purpose: Returns the number of nodes in the current graph.
00942 //=============================================================================
00943 int PL_GraphBase::NodeCount() const
00944 {
00945         return G.number_of_nodes();
00946 }
00947 
00948 //=============================================================================
00949 // EdgeCount
00950 //
00951 // Purpose: Returns the number of edges in the current graph.
00952 //=============================================================================
00953 int PL_GraphBase::EdgeCount() const
00954 {
00955         return G.number_of_edges();
00956 }*/
00957 
00958 //=============================================================================
00959 // SetStartConfig
00960 //
00961 // Purpose: Sets the start config and assigns it to a node in the current graph.
00962 //
00963 //                      This function does not connect the start node in the graph, but just
00964 //                      adds it.  It is upto the child classes to connect the node
00965 //                      if desired.
00966 //=============================================================================
00967 void PL_GraphBase::SetStartConfig( const Configuration& config )
00968 {
00969         // Call the parent SetStartConfig to ensure all required initialization is established.
00970         PL_Boolean_Output::SetStartConfig( config );
00971 
00972         // Search the graph to see if this config is already saved.
00973         startNode = FindConfig( config );
00974 
00975         // Add config to graph if it is not already
00976         if ( startNode == nil )
00977         {
00978                 startNode = G.new_node( config );
00979         }
00980 
00981 }
00982 
00983 //=============================================================================
00984 // SetGoalConfig
00985 //
00986 // Purpose: Sets the goal config and assigns it to a node in the current graph.
00987 //
00988 //                      This function does not connect the goal node in the graph, but just
00989 //                      adds it.  It is upto the child classes to connect the node
00990 //                      if desired.
00991 //=============================================================================
00992 void PL_GraphBase::SetGoalConfig( const Configuration& config )
00993 {
00994         // Call the parent SetGoalConfig to ensure all required initialization is established.
00995         PL_Boolean_Output::SetGoalConfig( config );
00996 
00997         // Search the graph to see if this config is already saved.
00998         goalNode = FindConfig( config );
00999 
01000         // Add config to graph if it is not already
01001         if ( goalNode == nil )
01002         {
01003                 goalNode = G.new_node( config );
01004         }
01005 
01006 }
01007 
01008 //=============================================================================
01009 // SetCollisionDetector
01010 //
01011 // Purpose: Assigns the CollisionDetector and extracts the DOF from it to allow
01012 //                  other graph specific parameters to be defined.
01013 //=============================================================================
01014 void PL_GraphBase::SetCollisionDetector (CD_BasicStyle* collisionDetector)
01015 {
01016         // Call the parent's SetCollisionDetector to ensure proper assignment.
01017         PL_Boolean_Output::SetCollisionDetector( collisionDetector );
01018 
01019         // Assign the DOF to the start and goal configurations
01020         int dof = collisionDetector->DOF();
01021 
01022     //IJG_Assert( GetStartConfig().DOF() == dof );
01023     //IJG_Assert( GetGoalConfig().DOF() == dof );
01024         //startConfig.SetNumDOF( dof );
01025         //goalConfig.SetNumDOF( dof );
01026 
01027         // Initialize the Weight Function if not already
01028         if ( distWeight.Length() != dof )
01029         {
01030                 NormDistWeight();
01031         }
01032 
01033 }
01034 
01035 //=============================================================================
01036 // SetDistanceWeights
01037 //
01038 // Purpose: Assigns the distance weight vector for the graph.  If it has changed,
01039 //                      the graph is cleared.
01040 //=============================================================================
01041 void PL_GraphBase::SetDistWeight( const VectorN& weights )
01042 {
01043         if ( distWeight == weights )
01044         {
01045                 return; // no change in distance vector.  Exit early
01046         }
01047 
01048 
01049         // Assign new weights
01050         distWeight = weights;
01051 
01052         // Clear the graph  ( use child clear if it exists )
01053         this->ClearGraph();
01054 
01055 }
01056 
01057 //=============================================================================
01058 // PrioritizeEdge
01059 //
01060 // Purpose: Moves the given edge (or implied edge) between the source and target
01061 //                  nodes of the edge to be the first adj_edge of the "source" node. 
01062 //                      This allows an easy trace back from the goal node to the start node
01063 //                      by following the first adj_edge associated with each node pointing to
01064 //                      the prev node in the chain.  
01065 //
01066 //                      Function returns the success of prioritizing the edge.
01067 //=============================================================================
01068 bool PL_GraphBase::PrioritizeEdge(node sourcenode, edge e1)
01069 // Makes the edge e1 the first adj_edge connect source node to the undirected target node.
01070 // This function assumes the e1 already connects source and target nodes, but not necessarily
01071 // in the correct direction or as the first adj_edge.  This function will make the edge e1
01072 // connect the source node to whatever the current target node is.
01073 {
01074         node targetnode = G.target(e1);
01075 
01076         // since this edge may be reversed, will have to flip it to get the correct node
01077         if (targetnode == sourcenode)
01078         {
01079                 targetnode = G.source(e1);
01080 
01081                 // if target node is still the same as the source, this edge is a self loop and should not be prioritized
01082                 if (targetnode == sourcenode)
01083                 {
01084                         return FALSE;
01085                 }
01086         }
01087 
01088 
01089         edge e2 = G.first_adj_edge(sourcenode); // find current first edge for source node.
01090         if (e2 == nil)
01091         {
01092                 // no adj_edges for source node, therefore can successful append this edge directly.
01093                 G.move_edge( e1, sourcenode, targetnode );  // moves edge to point from source node to target node
01094         }
01095         else if (e1 != e2)
01096         {
01097                 // if not already the first edge
01098                 G.move_edge( e1, e2, targetnode, LEDA::before); // place desired edge before current first edge, pointing from 
01099                                                                                                            // source(e2) to target node.
01100         }
01101 
01102         return TRUE;            // process completed successful
01103 
01104 }
01105 
01106 bool PL_GraphBase::PrioritizeEdge(node prev, node curr)
01107 // Makes the edge that connects from curr node to prev node the first adj_edge for the curr node,
01108 // and sets the direction to point from curr to prev, thus making the curr the source and prev the
01109 // target nodes for the edge.
01110 {
01111         edge e1;
01112         edge e2;
01113 
01114         if (prev == curr)
01115         {
01116                 // same node, there should not be an edge joining the two.
01117                 return FALSE;
01118         }
01119 
01120                 
01121         // Check all edges currently pointing from curr, searching for edge that points to prev
01122         forall_inout_edges(e1, curr)
01123         {
01124                 if (( G.target(e1) == prev ) || ( G.source(e1) == prev ))
01125                 {
01126                         // make edge first in the list (giving it top priority)
01127                         e2 = G.first_adj_edge(curr); // find current first edge for source (current) node.
01128                         if (e2 == nil)
01129                         {
01130                                 // no adj_edges for curr node, therefore can successful append this edge directly.
01131                                 G.move_edge( e1, curr, prev );  // moves edge to point from curr node to prev
01132                         }
01133                         else if (e1 != e2)
01134                         {
01135                                 // if not already the first edge
01136                                 G.move_edge( e1, e2, prev, LEDA::before); // place desired edge before current first edge, pointing from 
01137                                                                                                           // source(e2) to prev node.
01138                         }
01139                         return TRUE;            // process completed successful
01140                 }
01141         }
01142         
01143         // if still in the function, edge does not exisit.
01144         return FALSE;  // process not successful
01145 }
01146 
01147 //=============================================================================
01148 // GetMidPoint
01149 //
01150 // Purpose: Returns the midpoint between two configurations.  
01151 //=============================================================================
01152 Configuration PL_GraphBase::GetMidPoint( const Configuration& a, const Configuration& b ) const
01153 {
01154         VectorN jointdisp = collisionDetector->JointDisplacement( a, b );
01155 
01156         Configuration midpt = a + ( jointdisp / 2 );    // midpt = a + (b-a)/2;
01157 
01158         return midpt;
01159 }
01160 
01161 //=============================================================================
01162 // TranslatePath
01163 //
01164 // Purpose: Will take the collision free path through the nodes of the graph
01165 //                      and create the PA_Points the server requires to animate the path.
01166 //
01167 //                      Function does not check if timer expires.  It will report either 
01168 //                      success or failure.
01169 //=============================================================================
01170 SuccessResultType PL_GraphBase::TranslatePath()
01171 {
01172         // Clear any current path.
01173         path.Clear();
01174 
01175         // Check if a graph path is available.
01176         if ( graphPath.empty() )
01177         {
01178                 // Path is empty.  Set start as the beginning of the path, and return.
01179                 path.AppendPoint( GetStartConfig() );
01180 
01181                 // no path exists.
01182                 return FAIL;
01183         }
01184 
01185         // If still in the function, there is a graphPath.
01186         // Go through all nodes stored in graphPath and assign the configuration they correspond to the
01187         // actual path.
01188         node n1;
01189         forall( n1, graphPath )
01190         {
01191                 path.AppendPoint( G.inf(n1) );
01192         }
01193 
01194 
01195         // Path has been translated and is ready to be animated.
01196         return PASS;
01197 }
01198 
01199 //=============================================================================
01200 // CopySettings
01201 //
01202 // Purpose: copies the settings from a different planner
01203 //=============================================================================
01204 void PL_GraphBase::CopySettings( PlannerBase* original )
01205 {
01206         PL_GraphBase* originalGraphBase = dynamic_cast< PL_GraphBase* >( original );
01207         if( originalGraphBase == NULL )
01208         {
01209                 return;
01210         }
01211         this->distWeight = originalGraphBase->distWeight;
01212 }
01213 
01214 //=============================================================================
01215 // TranslateNodeID
01216 //
01217 // Purpose: Searches the entire graph structure, returning the node (ptr) associated
01218 //                      with the given index.  Used for saving and loading of the graph data.
01219 //=============================================================================
01220 node PL_GraphBase::TranslateNodeID( const int& nodeID ) const
01221 {
01222         // Quick check for nil node
01223         if ( ( nodeID == NIL_ID ) || 
01224                  ( G.empty() )  || 
01225                  ( nodeID > G.number_of_nodes() ) )
01226         {
01227                 return nil;
01228         }
01229 
01230         // Search the graph from an appropriate end
01231         if ( nodeID < (G.number_of_nodes()/2) )
01232         {
01233                 // nodeID in first half of the graph, start searching from the beginning
01234                 node n1;
01235                 forall_nodes( n1, G )
01236                 {
01237                         if ( n1->id() == nodeID )
01238                         {
01239                                 return n1;
01240                         }
01241                 }
01242         }
01243         else
01244         {
01245                 // nodeID is in second half of the graph, start searching from the end
01246                 node n1;
01247                 forall_rev_nodes( n1, G )
01248                 {
01249                         if ( n1->id() == nodeID )
01250                         {
01251                                 return n1;
01252                         }
01253                 }
01254         }
01255 
01256         // if still in this function, an error has occurred.
01257         ASSERT( FALSE );
01258 
01259         return nil;
01260 }

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