planners/ik_aca/IK_ACA.cpp

Go to the documentation of this file.
00001 //=========================================================================
00002 //
00003 //  File:  IK_ACA.cpp
00004 //
00005 //  Created 31-Jul-01 by Shane Schneider
00006 //
00007 //              Inverse ACA planner for inverse kinematics.
00008 //              Contains the inheritance from InvKinBase.
00009 
00010 
00011 
00012 // IK_ACA
00013 #include "synchronization/semaphore.h"
00014 #include "robots/R_OpenChain.h"
00015 #include "IK_ACA.h"
00016 
00017 #include <assert.h>
00018 #include <math.h>
00019 #include <math/math2.h>
00020 #include <math/vector4.h>
00021 #include <math/matrix4x4.h>
00022 #include <iosfwd>
00023 #include <iostream>
00024 #include <limits.h>
00025 
00026 #include "Kinematics/DH_Link.h"
00027 
00028 
00029 // fix gl path...
00030 // #include <gl/glos.h>
00031 #ifndef NOGL
00032 #include "opengl/glos.h"
00033 #include <gl/gl.h>
00034 #endif
00035 
00036 using std::endl;
00037 
00038 //--------------------- Constants ---------------
00039 // File Constants
00040 static const char FILEEXT[] = ".ikaca";
00041 static const char FILEHEADER[] = "INVERSE_ACA_PLANNER";
00042 // Other Constants
00043 static const Vector4 PX (1,0,0);
00044 static const Vector4 PY (0,1,0);
00045 static const Vector4 PZ (0,0,1);
00046 static const double INFINITY = LONG_MAX; 
00047 static const double DEFAULT_TOL = 0.02;
00048 static const double DEFAULT_TOL1 = 0.005;
00049 static const int DEFAULT_EMBRYOS_PER_NODE = 3;
00050 static const double SAMPLING_TIME = 0.5;
00051 
00052 #define _USE_ORIENTATION_
00053 // Class IK_ACA 
00054 
00055 // Default Constructor
00056 IK_ACA::IK_ACA()
00057 {
00058         // Assign the file header and extension for this type
00059         strcpy( fileext, FILEEXT );
00060         strcpy( fileheader, FILEHEADER );
00061 
00062         // Initialize the embryo count
00063         embryosPerLandmark = DEFAULT_EMBRYOS_PER_NODE;
00064 
00065         // Initialize the embryo node maps.
00066         embryo = new node_map<Configuration>[embryosPerLandmark];
00067         assert( embryo != NULL );
00068 
00069         for ( int i = 0; i < embryosPerLandmark; i++ )
00070         {
00071                 embryo[i].init(G);
00072         }
00073 
00074         // Clears the searchPath
00075         searchPath.clear();
00076 
00077         // Initialize searchLandmark
00078         searchLandmark = nil;
00079 
00080         // Initialize the best params
00081         InitBestParams();
00082 }
00083 
00084 
00085 IK_ACA::~IK_ACA()
00086 {
00087         // Default Destructor
00088         if ( embryo != NULL )
00089         {
00090                 delete [] embryo;
00091                 embryo = NULL;
00092         }
00093 }
00094 
00095 //=============================================================================
00096 // DrawExplicit
00097 //
00098 // Purpose: Draws the planner data to the planner window when called
00099 //=============================================================================
00100 bool IK_ACA::DrawExplicit () const
00101 {
00102         // use the GraphBase DrawExplicit and add planner specific drawing in DrawSpecific.
00103         return PL_GraphBase::DrawExplicit();
00104 }
00105 
00106 
00107 //=============================================================================
00108 // Load
00109 //
00110 // Purpose: Loads partailly complete planner data from the disk
00111 //=============================================================================
00112 bool IK_ACA::Load (const char *filename)
00113 {
00114         // Use GraphBase load routines.
00115         return PL_GraphBase::Load( filename );
00116 }
00117 
00118 //=============================================================================
00119 // LoadContents
00120 //
00121 // Purpose: Loads the graph and other related base planner parameters to the the
00122 //                  given ifstream.
00123 //      
00124 //                      Returns success of load.
00125 //=============================================================================
00126 bool IK_ACA::LoadContents( std::ifstream& infile )
00127 {
00128         // Load the Graph and other base parameters
00129         bool success = PL_GraphBase::LoadContents( infile );
00130         if ( !success )
00131         {
00132                 return false;
00133         }
00134 
00135         // Load the goal frame
00136         VectorN goalFrameVector;
00137         infile >> goalFrameVector;
00138         SetGoalFrame( goalFrameVector );
00139 
00140         
00141         // Load the ACA Specific Parameters here...
00142         
00143         // Prepare for Embryo Information
00144         infile >> embryosPerLandmark;
00145         if ( embryosPerLandmark < 1 )
00146         {
00147                 embryosPerLandmark = 1;
00148         }
00149         if ( embryo != NULL )
00150         {
00151                 delete [] embryo;
00152         }
00153         embryo = new node_map<Configuration>[embryosPerLandmark];
00154         assert( embryo != NULL );
00155         for ( int i = 0; i < embryosPerLandmark; i++ )
00156         {
00157                 embryo[i].init(G);
00158         }
00159 
00160 
00161         // Load Embryo Information
00162         node n1;
00163         forall_nodes( n1, G )
00164         {
00165                 int nodeID;
00166                 infile >> nodeID;
00167                 for( int i = 0; i < embryosPerLandmark; i++ )
00168                 {
00169                         infile >> embryo[i][n1];
00170                 }
00171         }
00172 
00173         InitNewSearch();
00174 
00175         return true;
00176 }
00177 
00178 
00179 //=============================================================================
00180 // Does Planning
00181 //
00182 // Purpose: performs the planning task
00183 //=============================================================================
00184 bool IK_ACA::Plan ()
00185 {
00186         // quick checks
00187         if ( IsInterfering( GetStartConfig() ) )
00188         {
00189                 // there is a collision with the start configuration...report failure
00190                 return false;
00191         }
00192 
00193 /*      if ( goalFrame.Compare(GetToolFrame( goalConfig ),DEFAULT_TOL) )
00194         {
00195                 // solution has already been found
00196                 return true;
00197         }*/
00198 
00199         // Start the timer
00200         StartTimer();
00201 
00202         // Establish the semaphore
00203         Semaphore semaphore( guid );
00204         if( this->m_UseSemaphores == true )
00205         {
00206                 semaphore.Lock();
00207         }
00208 
00209         // remove the goal node if it exists in the graph
00210         if ( ( goalNode != nil ) && ( goalNode != startNode ) )
00211         {
00212                 G.del_node( goalNode );
00213         }
00214         goalNode = nil;
00215 
00216         // erase the graph path
00217         ClearGraphPath();
00218 
00219         // Start the search
00220         SuccessResultType success = FAIL;
00221         
00222         // add inverse ACA planning alogrithm here...
00223         while ( true )
00224         {
00225                 // Find the global mininium starting from the last landmark;
00226                 if ( searchLandmark != nil )
00227                 {
00228                         semaphore.Unlock();
00229                         success = Search( searchLandmark );
00230                         semaphore.Lock();
00231                 }
00232 
00233                 if ( success != FAIL )
00234                 {
00235                         break;
00236                 }
00237 
00238                 // Last seach was not successful.  Use another landmark.
00239                 if (( searchLandmark != nil) && ( searchLandmark != G.last_node() ))
00240                 {
00241                         // use next landmark in tree
00242                         searchLandmark = G.succ_node( searchLandmark );
00243                 }
00244                 else
00245                 {
00246                         // add new landmark to tree
00247                         searchLandmark = Explore();
00248                 }
00249 
00250                 // Pause for drawing
00251                 semaphore.Unlock();
00252                 semaphore.Lock();
00253         }
00254 
00255         // Pause for drawing
00256         semaphore.Unlock();
00257         semaphore.Lock();
00258         
00259         if ( success == PASS )
00260         {
00261                 // A successful path has been found.  Record it.
00262                 ComputePath( searchLandmark, searchPath );
00263 
00264                 // best path is the solved path, so clear old best path
00265                 bestPath.clear();
00266 
00267                 // Unlock the semaphore before leaving.
00268                 semaphore.Unlock();
00269                 return true;
00270         }
00271         else
00272         {
00273                 // No successful path was found, record the best one.
00274                 //ComputePath( bestLandmark, bestPath );
00275 
00276                 // only show the best path on the graph, clear searchPath
00277                 searchPath.clear();
00278 
00279                 // Unlock the semaphore before leaving.
00280                 semaphore.Unlock();
00281                 return false;
00282         }
00283 }
00284 
00285 //=============================================================================
00286 // Save
00287 //
00288 // Purpose: Saves partial plan data to disk
00289 //=============================================================================
00290 bool IK_ACA::Save (const char *filename) const
00291 {
00292         // Use GraphBase save routines.
00293         return PL_GraphBase::Save( filename );
00294 }
00295 
00296 //=============================================================================
00297 // SaveContents
00298 //
00299 // Purpose: Saves the graph and other related base planner parameters to the the
00300 //                  given ofstream.
00301 //      
00302 //                      Returns success of save.
00303 //=============================================================================
00304 bool IK_ACA::SaveContents ( std::ofstream& outfile ) const
00305 {
00306         // Save the Graph and parent parameters
00307         bool success = PL_GraphBase::SaveContents( outfile );
00308         if ( !success )
00309         {
00310                 return false;
00311         }
00312 
00313         // Save the goal frame
00314         outfile << GetGoalFrameVector() << endl;
00315 
00316         // Save the ACA specific parameters here...
00317 
00318         // Save the embryo count.
00319         outfile << embryosPerLandmark << endl;
00320 
00321         // Save Embryo Information
00322         node n1;
00323         forall_nodes( n1, G )
00324         {
00325                 outfile << n1->id();
00326 
00327                 for( int i = 0; i < embryosPerLandmark; i++ )
00328                 {
00329                         outfile << embryo[i][n1];
00330                 }
00331 
00332                 outfile << endl;
00333         }
00334         
00335         
00336         return true;
00337 }
00338 
00339 
00340 
00341 
00342 //=============================================================================
00343 // DrawSpecific
00344 //
00345 // Purpose: Draw Inverse ACA planner specific info.  
00346 //                      This function will draw all the connecting edges between the embyros
00347 //                      and their parent landmarks. 
00348 //
00349 //=============================================================================
00350 bool IK_ACA::DrawSpecific() const
00351 {
00352         node landmark;
00353         double Xcor, Ycor, Zcor;
00354 
00355 #ifndef NOGL
00356         // Draw the edges connecting the end of the embyros to their parent landmark (node).
00357         glLineWidth( 1.0f );
00358         glBegin(GL_LINES);
00359                 // Draw all connecting edges
00360                 glColor3f(0.4f,0.4f,0.4f);      // set colour to grey
00361                 forall_nodes(landmark,G)
00362                 {
00363                         for( int i = 0; i < embryosPerLandmark; i++ )
00364                         {
00365                                 GetCoords( embryo[i][landmark], Xcor, Ycor, Zcor );     // get coordinates of source node;
00366                                 glVertex3f( (float)Xcor, (float)Ycor, (float)Zcor );    // add source vertex for edge line.
00367 
00368                                 GetCoords( landmark, Xcor, Ycor, Zcor );        // get coordinates of target node;
00369                                 glVertex3f( (float)Xcor, (float)Ycor, (float)Zcor );    // add target vertex for edge line.
00370                         }
00371                 }
00372 
00373                 // draw the lines that indicate the progress of the search routine
00374                 if ( !searchPath.empty() )
00375                 {
00376                         list_item index = searchPath.last();
00377                         list_item first = searchPath.first();
00378                         glColor3f(0.0f,1.0f,0.0f);              // set colour to green
00379                         
00380                         while ( first != index )
00381                         {
00382                                 GetCoords( searchPath.inf( index ), Xcor, Ycor, Zcor );
00383                                 glVertex3f( (float)Xcor, (float)Ycor, (float)Zcor );    // add source vertex for last line.
00384 
00385                                 index = searchPath.pred( index );
00386                                 
00387                                 GetCoords( searchPath.inf( index ), Xcor, Ycor, Zcor );
00388                                 glVertex3f( (float)Xcor, (float)Ycor, (float)Zcor );    // add target vertex for edge line.
00389                         }
00390                 }
00391 
00392                 // draw the lines that indicate the best path so far
00393                 if ( !bestPath.empty() )
00394                 {
00395                         list_item index = bestPath.last();
00396                         list_item first = bestPath.first();
00397                         glColor3f(0.5f,0.0f,0.625f);            // set colour to dark purple
00398                         
00399                         while ( first != index )
00400                         {
00401                                 GetCoords( bestPath.inf( index ), Xcor, Ycor, Zcor );
00402                                 glVertex3f( (float)Xcor, (float)Ycor, (float)Zcor );    // add source vertex for last line.
00403 
00404                                 index = bestPath.pred( index );
00405                                 
00406                                 GetCoords( bestPath.inf( index ), Xcor, Ycor, Zcor );
00407                                 glVertex3f( (float)Xcor, (float)Ycor, (float)Zcor );    // add target vertex for edge line.
00408                         }
00409                 }
00410 
00411         glEnd();
00412 #endif
00413         return true;
00414 }
00415 
00416 
00417 //=============================================================================
00418 // SetStartConfig
00419 //
00420 // Purpose: Sets the start config and assigns it as first node in the current graph.
00421 //
00422 //=============================================================================
00423 void IK_ACA::SetStartConfig( const Configuration& config )
00424 {
00425         // Check if the configuration has changed.
00426         if (( startNode != nil ) && ( GetStartConfig() == config ))
00427         {
00428                 // no change in configuration.  Can exit early.
00429                 return;
00430         }
00431 
00432         // A new configuration has been requested.  Need to clear the current graph and search parameters
00433         ClearGraph();
00434         searchPath.clear();
00435         
00436         // Call the graph base SetStartConfig to ensure all required initialization is established
00437         // and the start config will be added as the first landmark.
00438         PL_GraphBase::SetStartConfig( config );
00439 
00440         // Verify the startNode was initiated.
00441     assert( startNode != nil );
00442 
00443         // Create an embryo for the start landmark.
00444         CreateEmbryos( startNode );
00445 
00446         // Initialize a new search
00447         this->InitNewSearch();
00448         
00449 
00450 }
00451 
00452 //=============================================================================
00453 // SetGoalConfig
00454 //
00455 // Purpose: Resolves ambiguity by ensuring only the InvKinBase version of
00456 //                      SetGoalConfig is called.
00457 //=============================================================================
00458 void IK_ACA::SetGoalConfig( const Configuration& config )
00459 {
00460         // Check if new goal config (frame) was requested.
00461         if ( config != GetGoalConfig() )
00462         {
00463                 // Assign new goal config (frame)
00464                 IK_InvKinBase::SetGoalConfig( config );
00465         }
00466 
00467 }
00468 
00469 //=============================================================================
00470 // AssignGoalConfig
00471 //
00472 // Purpose: After planner is completed, this function is called to save the 
00473 //                      the computed configuration as the goal configuration and node
00474 //                      in the graph.  
00475 //=============================================================================
00476 void IK_ACA::AssignGoalConfig( const Configuration& config )
00477 {
00478         // Call parent's version of AssignGoalConfig
00479         IK_InvKinBase::AssignGoalConfig( config );
00480 
00481         // Add the goal node to the graph.
00482         PL_GraphBase::SetGoalConfig( config );
00483 
00484         // Assign all embryos of goal to itself.
00485         for ( int i = 0; i < embryosPerLandmark; i++ )
00486         {
00487                 embryo[i][goalNode] = config;
00488         }
00489 
00490 }
00491 
00492 
00493 
00494 //=============================================================================
00495 // SetCollisionDetector
00496 //
00497 // Purpose: Resolves ambiguity by ensuring the GraphBase version of
00498 //                      SetCollisionDetector is called.
00499 //=============================================================================
00500 /*void IK_ACA::SetCollisionDetector (CD_BasicStyle* collisionDetector)
00501 {
00502         // Call the parent's SetCollisionDetector to ensure proper assignment.
00503         PL_GraphBase::SetCollisionDetector( collisionDetector );
00504 
00505 }
00506 */
00507 
00508 
00509 //=============================================================================
00510 // CopySettings
00511 //
00512 // Purpose: copies the settings from a different planner
00513 //=============================================================================
00514 void IK_ACA::CopySettings( PlannerBase* original )
00515 {
00516         // Call parent copy settings
00517         IK_InvKinBase::CopySettings( original );
00518         PL_GraphBase::CopySettings( original );
00519 
00520         IK_ACA* originalACA = dynamic_cast< IK_ACA* >( original );
00521         if( originalACA == NULL )
00522         {
00523                 return;
00524         }
00525 
00526         //copy ACA specific parameters here...
00527         SetEmbryosPerLandmark( originalACA->embryosPerLandmark );
00528         
00529         // Initialize a new search
00530         InitNewSearch();
00531 
00532 
00533 }
00534 
00535 //=============================================================================
00536 // CreateEmbryos
00537 //
00538 // Purpose: creates required number of new valid embyro for given landmark.
00539 //=============================================================================
00540 void IK_ACA::CreateEmbryos (const node& landmark )
00541 {
00542         for (int i = 0; i < embryosPerLandmark; i++ )
00543         {
00544                 CreateEmbryo( landmark, i );
00545         }
00546 
00547 }
00548 
00549 
00550 //=============================================================================
00551 // CreateEmbryo
00552 //
00553 // Purpose: creates a new valid embyro and assigns it to the given landmark.
00554 //=============================================================================
00555 void IK_ACA::CreateEmbryo(const node& landmark, const int& embryoID)
00556 {
00557         // propose a new configuration.
00558         //Configuration newconfig = GenerateRandomConfig();
00559         Configuration landmarkConfig = G.inf( landmark );
00560         Configuration newconfig = GenerateRandomConfig( landmarkConfig ); 
00561         Configuration start = GetStartConfig();
00562         //newconfig[0] = start[0];
00563         //newconfig[1] = start[1];
00564         //newconfig[5] = start[5];
00565 
00566         //LogMessage("ik-aca.log", "==============================");
00567         //LogVector("ik-aca.log", landmarkConfig, "Configuration get in explore");
00568         //LogVector("ik-aca.log", newconfig, "Configuration get in explore");
00569 
00570         // verify new config has a straight-line path from landmark.
00571         if ( IsInterfering( landmarkConfig, newconfig ) )
00572         {
00573                 // Collision occurred.  Use the mid point between landmark and collision as the
00574                 // new config for the embyro.
00575                 newconfig = PL_GraphBase::collisionDetector->GetLastIntersection();
00576                 newconfig = GetMidPoint( landmarkConfig, newconfig );
00577                 //LogMessage("ik-aca.log", "Get mid point....");
00578 
00579         }
00580 
00581         // Assign new config as the embyro config associated with the landmark.
00582         embryo[embryoID][landmark] = newconfig;
00583         //LogVector("ik-aca.log", newconfig, "Configuration get in explore");
00584 
00585 }
00586 
00587 //=============================================================================
00588 // Explore
00589 //
00590 // Purpose: Explores C-space by updating the road map.  
00591 //                      Takes the furtherst embyro in the road map and converts it
00592 //                      into a landmark, and creates two new embyros.  
00593 //              
00594 //                      This function returns the new landmark so it can be used for the next
00595 //                      iteration of search.
00596 //
00597 //=============================================================================
00598 node IK_ACA::Explore()
00599 {
00600         double landmark_dist = 0;
00601 
00602         node n1, n2, parentNode;
00603         double distance, min_dist;
00604         int embryoID;
00605 
00606         // find the embryo that is the farthest
00607         forall_nodes(n1, G)
00608         {
00609                 for( int i = 0; i < embryosPerLandmark; i++)
00610                 {
00611                         min_dist = INFINITY;
00612                         forall_nodes(n2, G)
00613                         {
00614                                 distance = Distance( embryo[i][n1] , G.inf(n2) );
00615                                 if ( distance < min_dist )
00616                                 {
00617                                         min_dist = distance;
00618                                 }
00619                         }
00620         
00621                         if ( min_dist > landmark_dist )
00622                         {
00623                                 // record current embryo's parent, its ID, and its landmark distance.
00624                                 parentNode = n1;
00625                                 embryoID = i;
00626                                 landmark_dist = min_dist;
00627                         }
00628                 }
00629         }
00630 
00631         // Convert embryo into a new node and add it to the end of the node list.
00632         n1 = G.new_node( G.last_node(), embryo[embryoID][parentNode], LEDA::after);
00633 
00634         // Record straight-line path from old embryo to its parent and represent it as an edge in roadmap.
00635         distance = sqrt( Distance( n1, parentNode ) );
00636         G.new_edge( n1, parentNode, distance );
00637 
00638 
00639         // Create new embryos for old embryo and new landmark.
00640         CreateEmbryo( parentNode, embryoID );     // old embryo's parent who needs a replacement embryo.
00641         CreateEmbryos( n1 );    // new landmark in road map.
00642 
00643         // return the new landmark
00644         return n1;
00645         
00646 }
00647 
00648 
00649 //=============================================================================
00650 // Search
00651 //
00652 // Purpose: Performs the search algorithm for ACA.  Will start from a 
00653 //                  given configuration and apply the cost minimizing function
00654 //                      until a local min configuration is found
00655 //
00656 // NOTE:        This function uses a semaphore, so all semaphores must be unlocked
00657 //                      prioir to this function being called.
00658 //=============================================================================
00659 SuccessResultType IK_ACA::Search( const node& landmark )
00660 {
00661         // Establish the semaphore
00662         Semaphore semaphore( guid );
00663         if( this->m_UseSemaphores == true )
00664         {
00665                 semaphore.Lock();
00666         }
00667 
00668         // Clear the current search path and start fresh with the land mark.
00669         searchPath.clear();
00670         searchPath.append( G.inf(landmark) );
00671 
00672         while ( !HasTimeLimitExpired() )
00673         {
00674                 list<Configuration> minPath;
00675                 Configuration q0 = searchPath.back();
00676                 Configuration q1 = MinimizeDistance( q0 , minPath );
00677 
00678                 // get the latest tool frame
00679                 Matrix4x4 toolFrame = GetToolFrame( q1 );
00680 
00681                 // check if solution has been found
00682                 if ( q1.Compare( q0 , DEFAULT_TOL1 ) )
00683                 {
00684                         // local minimum has been found.  Need to start again with new landmark
00685 
00686                         // check if local min is the best so far
00687                         double dist_sq = FrameDistance( goalFrame, toolFrame );
00688                         if ( dist_sq < bestDistance_sq )
00689                         {
00690                                 // this config is closer than previous best, record it.
00691                                 bestDistance_sq = dist_sq;
00692                                 bestLandmark = landmark;
00693                                 bestPath = searchPath;
00694                         }
00695 
00696                         // report failure so we can start again.
00697                         semaphore.Unlock();
00698                         return FAIL;
00699                 }
00700 
00701                 // add new config to search path
00702                 if ( !IsInterfering( q0, q1 ) )
00703                 {
00704                         // direct straight-line path exists from previous iteration, add new config directly.
00705                         searchPath.append( q1 );
00706                 }
00707                 else
00708                 {
00709                         // path has collision, use the collision free path generated from minimizing configs
00710                         searchPath.conc( minPath , LEDA::after );
00711                 }
00712                 
00713                 // check if tool frame now matches goal.
00714 //#ifdef _USE_POSITION_ONLY_
00715                 double distToGoal = FrameDistance(goalFrame, toolFrame);
00716                 if ( distToGoal < DEFAULT_TOL )
00717 //#else
00718 //              if ( toolFrame.Compare( goalFrame , DEFAULT_TOL ) )
00719 //#endif
00720                 {
00721                         // goal and tool frames match.  Report success.
00722                         semaphore.Unlock();
00723                         return PASS;
00724                 }
00725 
00726                 semaphore.Unlock();
00727                 semaphore.Lock();
00728 
00729         }
00730 
00731         // If escaped from While LOOP, then timer has expired.
00732 
00733         semaphore.Unlock();
00734         return TIMER_EXPIRED;
00735 
00736 }
00737 
00738 SuccessResultType IK_ACA::Search1( const node& landmark )
00739 {
00740         // Establish the semaphore
00741         Semaphore semaphore( guid );
00742         if( this->m_UseSemaphores == true )
00743         {
00744                 semaphore.Lock();
00745         }
00746 
00747         // Clear the current search path and start fresh with the land mark.
00748         searchPath.clear();
00749 
00750         searchPath.append( G.inf(landmark) );
00751 
00752         //get configuration of Searchlandmark
00753         Configuration gh=searchPath.back();
00754 
00755         Matrix4x4 toolFrame = GetToolFrame( gh );               
00756         // check if tool frame now matches goal.
00757         double distToGoal = FrameDistance(goalFrame, toolFrame);
00758         if ( distToGoal < DEFAULT_TOL )
00759         //if ( toolFrame.Compare( goalFrame , DEFAULT_TOL ) )
00760         {
00761                 // goal and tool frames match.  Report success.
00762                 semaphore.Unlock();
00763                 return PASS;
00764         }
00765 
00766     while ( !HasTimeLimitExpired() )
00767         {
00768                 Configuration q0 = searchPath.back();
00769                 Configuration q1 = GetNextConfig( q0 );
00770 
00771                 for (int i = 0; i<q0.DOF(); i++)
00772                 {
00773                         if ( q1[i] < collisionDetector->JointMin(i) )
00774                                 q1[i] = collisionDetector->JointMin(i);
00775                         else if ( q1[i] > collisionDetector->JointMax(i) )
00776                                 q1[i] = collisionDetector->JointMax(i);
00777                 }
00778 
00779                 // check if solution has been found
00780                 if ( q1.Compare( q0 , DEFAULT_TOL1*DEFAULT_TOL1 ) )
00781                 {
00782                         // check if local min is the best so far
00783                         double dist_sq = FrameDistance( goalFrame, toolFrame );
00784                         if ( dist_sq < bestDistance_sq )
00785                         {
00786                                 // this config is closer than previous best, record it.
00787                                 bestDistance_sq = dist_sq;
00788                                 bestLandmark = landmark;
00789                                 bestPath = searchPath;
00790                         }
00791 
00792                         // report failure so we can start again.
00793                         semaphore.Unlock();
00794                         return FAIL;
00795                 }
00796                 
00797                 // get the latest tool frame
00798                 toolFrame = GetToolFrame( q1 );         
00799                 // check if tool frame now matches goal.
00800                 distToGoal = FrameDistance(goalFrame, toolFrame);
00801                 if ( distToGoal < DEFAULT_TOL )
00802                 //if ( toolFrame.Compare( goalFrame , DEFAULT_TOL ) )
00803                 {
00804                         // goal and tool frames match.  Report success.
00805             searchPath.append( q1 );
00806                         semaphore.Unlock();
00807                         return PASS;
00808                 }               
00809 
00810                 if (IsInterfering(q1))
00811                 {
00812                         semaphore.Unlock();
00813                         return FAIL;
00814                 }
00815 
00816                 // add new config to search path
00817                 searchPath.append( q1 );
00818 
00819                 semaphore.Unlock();
00820                 semaphore.Lock();
00821         }
00822 
00823         // If escaped from While LOOP, then timer has expired.
00824 
00825         semaphore.Unlock();
00826         return TIMER_EXPIRED;
00827 }
00828 
00829 VectorN IK_ACA::ComputeEndEffDiff(Matrix4x4 &frStart, Matrix4x4 &frEnd)
00830 {
00831         VectorN returnMe;
00832         returnMe.SetLength(6);
00833 
00834         int index = 0;
00835         returnMe[index++] = frEnd(0, 3) - frStart(0, 3);
00836         returnMe[index++] = frEnd(1, 3) - frStart(1, 3);
00837         returnMe[index++] = frEnd(2, 3) - frStart(2, 3);
00838 
00839         //Frame rotated = frStart.Inverse() * frEnd;
00840         Matrix4x4 rotated = frEnd * frStart.Inverse();
00841         double temp = rotated.values[0][0] + rotated.values[1][1] + rotated.values[2][2] - 1;
00842         assert(fabs(temp) <= (2+1e-5));
00843         if (temp>2.)
00844                 temp = 2.0;
00845         else if (temp<-2.)
00846                 temp = -2.0;
00847         double angle = acos(temp/2);
00848         Vector4 axis;
00849         axis[0] = rotated.values[2][1] - rotated.values[1][2];
00850         axis[1] = rotated.values[0][2] - rotated.values[2][0];
00851         axis[2] = rotated.values[1][0] - rotated.values[0][1];
00852 
00853         if (sin(angle) != 0)
00854                 axis /= (2*sin(angle));
00855 
00856         axis *= angle;
00857 
00858         returnMe[index++] = axis[0];
00859         returnMe[index++] = axis[1];
00860         returnMe[index++] = axis[2];
00861 
00862         return returnMe;        
00863 }
00864 
00865 Configuration IK_ACA::GetNextConfig( Configuration& q0 )
00866 {
00867         Matrix4x4 current_tool_frame=GetToolFrame(q0);
00868         VectorN Start_Goal_Diff=ComputeEndEffDiff(current_tool_frame, goalFrame);
00869         if (Start_Goal_Diff.Magnitude() > SAMPLING_TIME)
00870         {
00871                 Start_Goal_Diff.Normalize();
00872                 Start_Goal_Diff*=SAMPLING_TIME;
00873         }
00874         Frame identity;
00875         jacobian->SetConfiguration(q0);
00876         jacobian->SetInterestPoint(q0.DOF()-1, identity, true, true);
00877         VectorN jointDiff;
00878         jacobian->GetJointVelocity(jointDiff, Start_Goal_Diff);
00879         //LogVector("ik-aca.log", jointDiff, "jointDiff:");
00880         Configuration q1=q0+jointDiff*Rad2Deg(1);
00881         //LogVector("ik-aca.log", q1, "NextConfiguration:");
00882         return q1;
00883 }
00884 
00885 //=============================================================================
00886 // SetCollisionDetector
00887 //
00888 // Purpose: Assigns the collision detector.
00889 //
00890 //=============================================================================
00891 void IK_ACA::SetCollisionDetector (CollisionDetectorBase* collisionDetector)
00892 {
00893         //assign the goal frame
00894         CD_BasicStyle* basicStyle = dynamic_cast< CD_BasicStyle* >(  collisionDetector );
00895         assert( basicStyle != NULL );
00896         if( basicStyle != NULL )
00897         {
00898                 R_OpenChain *   robot; 
00899                 robot = dynamic_cast<R_OpenChain*>(basicStyle->GetRobot(0));
00900                 jacobian = new CJacobian(*robot);
00901                 //FrameManager* fm = basicStyle->GetFrameManager();
00902                 //int newFrame = fm->AddFrame();
00903                 PL_GraphBase::SetCollisionDetector( basicStyle );
00904         }
00905 }
00906 
00907 //=============================================================================
00908 // FindJointAdjust
00909 //
00910 // Purpose: Applies the cost minimizing function to the given joint
00911 //                      to find adjustment required to minimize the distance between
00912 //                      goal and tool frames.
00913 //
00914 // Note:  This function does not perform any collision or joint limit checking.
00915 //
00916 //=============================================================================
00917 double IK_ACA::FindJointAdjust( const unsigned int& jointNum, const Matrix4x4& toolFrame ) const
00918 {
00919 
00920         // get pointer to frame manager
00921         FrameManager* frameManager = collisionDetector->GetFrameManager();
00922 
00923         // get link frame
00924         Matrix4x4 linkFrame = frameManager->GetWorldFrame( collisionDetector->JointFrameNum( jointNum ) );
00925 
00926         // create vectors from link frame to tips of unit axes vectors of goal frame
00927         Matrix4x4 goalWRTlinkFrame = FrameManager::GetTransformRelative( goalFrame, linkFrame );
00928 #ifdef _USE_ORIENTATION_
00929         Vector4 Pgx = goalWRTlinkFrame * PX;
00930         Vector4 Pgy = goalWRTlinkFrame * PY;
00931         Vector4 Pgz = goalWRTlinkFrame * PZ;
00932 #else
00933         Vector4 goalVec;
00934         goalVec[0] = goalWRTlinkFrame(0, 3);
00935         goalVec[1] = goalWRTlinkFrame(1, 3);
00936         goalVec[2] = goalWRTlinkFrame(2, 3);
00937 #endif
00938 
00939         // create vectors from link frame to tips of unit axes vectors of tool frame
00940         Matrix4x4 toolWRTlinkFrame = FrameManager::GetTransformRelative( toolFrame, linkFrame );
00941 #ifdef _USE_ORIENTATION_
00942         Vector4 Ptx = toolWRTlinkFrame * PX;
00943         Vector4 Pty = toolWRTlinkFrame * PY;
00944         Vector4 Ptz = toolWRTlinkFrame * PZ;
00945 #else
00946         Vector4 toolVec;
00947         toolVec[0] = toolWRTlinkFrame(0, 3);
00948         toolVec[1] = toolWRTlinkFrame(1, 3);
00949         toolVec[2] = toolWRTlinkFrame(2, 3);
00950 #endif
00951 
00952         // variable to store joint adjustment.
00953         double adjustment;
00954         
00955         // Find joint adjustment to minimize the distance metric
00956         DH_Parameter jointType = collisionDetector->JointType( jointNum );
00957         switch ( jointType )
00958         {
00959                 case DH_THETA :
00960                         {
00961                                 // Using a rotation about Z, find minimum.  See thesis for details of this equation.
00962                                 // MAPLE Output:  
00963                                 //    y[gz]*y[tz]+x[gz]*x[tz]+x[gy]*x[ty]+y[gy]*y[ty]+x[tx]*x[gx]+y[tx]*y[gx] = a
00964                                 //    y[gz]*x[tz]-x[gz]*y[tz]-x[gy]*y[ty]+y[gy]*x[ty]+x[tx]*y[gx]-y[tx]*x[gx] = b
00965 #ifdef _USE_ORIENTATION_
00966                                 double a = Pgz[1]*Ptz[1] + Pgz[0]*Ptz[0] + Pgy[0]*Pty[0] + Pgy[1]*Pty[1] + Pgx[0]*Ptx[0] + Pgx[1]*Ptx[1];
00967                                 double b = Pgz[1]*Ptz[0] - Pgz[0]*Ptz[1] - Pgy[0]*Pty[1] + Pgy[1]*Pty[0] + Ptx[0]*Pgx[1] - Ptx[1]*Pgx[0];
00968 #else
00969                                 double a = goalVec[0]*toolVec[0] + goalVec[1]*toolVec[1];
00970                                 double b = -goalVec[0]*toolVec[1] + toolVec[0]*goalVec[1];
00971 #endif                          
00972                                 double theta1 = atan2( b , a );
00973                                 double theta2;
00974                                 if ( theta1 > 0 )
00975                                 {
00976                                         theta2 = theta1 - M_PI;
00977                                 }
00978                                 else
00979                                 {
00980                                         theta2 = theta1 + M_PI;
00981                                 }
00982         
00983                                 // differential equation gave two answers, find the one that minimizes the cost function
00984                                 double val1 = -a*cos(theta1) - b*sin(theta1);
00985                                 double val2 = -a*cos(theta2) - b*sin(theta2);
00986                                 if ( val1 < val2 )
00987                                 {
00988                                         adjustment = Rad2Deg( theta1 );
00989                                 }
00990                                 else
00991                                 {
00992                                         adjustment = Rad2Deg( theta2 );
00993                                 }
00994                         }
00995                         break;
00996                 case DH_ALPHA :
00997                         {
00998                                 // Using a rotation about X, find minimum.  See thesis for details of this equation.
00999                                 // MAPLE Output:  
01000                                 //    z[gy]*y[ty]-y[gy]*z[ty]-z[tx]*y[gx]+y[tx]*z[gx]-y[gz]*z[tz]+z[gz]*y[tz] = b
01001                                 //    y[gz]*y[tz]+z[gz]*z[tz]+y[gy]*y[ty]+z[gy]*z[ty]+y[tx]*y[gx]+z[tx]*z[gx] = a
01002 #ifdef _USE_ORIENTATION_
01003                                 double b = Pgy[2]*Pty[1] - Pgy[1]*Pty[2] - Ptx[2]*Pgx[1] + Ptx[1]*Pgx[2] - Pgz[1]*Ptz[2] + Pgz[2]*Ptz[1];
01004                                 double a = Pgz[1]*Ptz[1] + Pgz[2]*Ptz[2] + Pgy[1]*Pty[1] + Pgy[2]*Pty[2] + Pgx[1]*Ptx[1] + Pgx[2]*Ptx[2];
01005 #else
01006                                 assert(false); //haven't done yet;
01007                                 double b = 1;
01008                                 double a = 1;
01009 #endif
01010                                         
01011                                 double alpha1 = atan2( b , a );
01012                                 double alpha2;
01013                                 if ( alpha1 > 0 )
01014                                 {
01015                                         alpha2 = alpha1 - M_PI;
01016                                 }
01017                                 else
01018                                 {
01019                                         alpha2 = alpha1 + M_PI;
01020                                 }
01021         
01022                                 // differential equation gave two answers, find the one that minimizes the cost function
01023                                 double val1 = -a*cos(alpha1) - b*sin(alpha1);
01024                                 double val2 = -a*cos(alpha2) - b*sin(alpha2);
01025                                 if ( val1 < val2 )
01026                                 {
01027                                         adjustment = Rad2Deg( alpha1 );
01028                                 }
01029                                 else
01030                                 {
01031                                         adjustment = Rad2Deg( alpha2 );
01032                                 }
01033                         }
01034                         break;
01035                 case DH_D :
01036                         {
01037                                 // Using prismatic along Z, find minimum.  See thesis for details of this equation.
01038                                 // MAPLE Output:
01039                                 //        1/3*z[gz]+1/3*z[gy]-1/3*z[tx]+1/3*z[gx]-1/3*z[ty]-1/3*z[tz]
01040 #ifdef _USE_ORIENTATION_
01041                                 adjustment = ( Pgz[2] + Pgy[2] - Ptx[2] + Pgx[2] - Pty[2] - Ptz[2] ) / 3;
01042 #else
01043                                 adjustment = 0;
01044 #endif
01045                         }
01046                         break;
01047                 case DH_A :
01048                         {
01049                                 // Using prismatic along Z, find minimum.  See thesis for details of this equation.
01050                                 // MAPLE Output:
01051                                 //        1/3*x[gz]+1/3*x[gy]-1/3*x[tx]+1/3*x[gx]-1/3*x[ty]-1/3*x[tz]
01052 #ifdef _USE_ORIENTATION_
01053                                 adjustment = ( Pgz[0] + Pgy[0] - Ptx[0] + Pgx[0] - Pty[0] - Ptz[0] ) / 3;
01054 #else
01055                                 adjustment = 0;
01056 #endif
01057                         }
01058                         break;
01059                 default :
01060                         adjustment = 0;
01061         }
01062 
01063         // return the joint adjustment to minimize distance between goal and tool frame.
01064         return adjustment;
01065 
01066 }
01067 
01068 //=============================================================================
01069 // MinimizeDistance
01070 //
01071 // Purpose: Applies the cost minimizing function to the given configuration
01072 //                      to find a valid configuration that minimizes the distance metric
01073 //
01074 //=============================================================================
01075 Configuration IK_ACA::MinimizeDistance( const Configuration& config , list<Configuration>& minPath )
01076 {
01077 
01078         Configuration minConfig = config;
01079         minPath.clear();
01080 
01081         // Iteratively apply the cost minimizing function to each joint sequentially.
01082         int dof = collisionDetector->DOF();
01083         for ( int i = 0; i < dof; i++ )
01084         {
01085                 // find the current tool frame for given config
01086                 Matrix4x4 toolFrame = GetToolFrame( minConfig );
01087 
01088                 // adjust the joint to minimize distance for that joint 
01089                 double jointAdjust = minConfig[i] + FindJointAdjust( i, toolFrame );
01090 
01091                 // ensure joint does not exceeed the limits
01092                 double jmax = collisionDetector->JointMax( i );
01093                 double jmin = collisionDetector->JointMin( i );
01094                 if ( collisionDetector->JointWraps( i ) )
01095                 {
01096                         if ( jointAdjust > jmax )
01097                         {
01098                                 jointAdjust -= ( jmax - jmin );
01099                         }
01100                         else if ( jointAdjust < jmin )
01101                         {
01102                                 jointAdjust += ( jmax - jmin );
01103                         }
01104                 }
01105                 else
01106                 {
01107                         if ( jointAdjust > jmax )
01108                         {
01109                                 jointAdjust = jmax;
01110                         }
01111                         if ( jointAdjust < jmin )
01112                         {
01113                                 jointAdjust = jmin;
01114                         }
01115                 }
01116 
01117                 // create new configuration with joint adjustment
01118                 Configuration newConfig = minConfig;
01119                 newConfig[ i ] = jointAdjust;
01120 
01121                 // Perform collision checking to ensure path is clear
01122                 if ( IsInterfering( minConfig, newConfig ) )
01123                 {
01124                         // Set the new minConfig for next iteration based on the last valid point
01125                         minConfig = collisionDetector->GetLastValid();  
01126                 }
01127                 else
01128                 {
01129                         // set the new minConfig for next iteration based on collision free adjustment
01130                         minConfig[ i ] = jointAdjust;
01131                 }
01132 
01133                 minPath.append( minConfig );
01134 
01135         }
01136 
01137         return minConfig;
01138                 
01139 }
01140 
01141 
01142 //=============================================================================
01143 // FrameDistance
01144 //
01145 // Purpose: Computes the squared distance between two frames based on the distance metric
01146 //                  defined by Ahuactizin and Gupta (Aug 1999).
01147 //
01148 // NOTE:    This is a computationally expensive function because of all the matrix
01149 //                      and vector multiplication
01150 //=============================================================================
01151 double IK_ACA::FrameDistance ( const Matrix4x4& frameA, const Matrix4x4& frameB ) const
01152 {
01153 #ifdef _USE_ORIENTATION_
01154         // Generate vectors from base frame to each of the unit vector of the given frames.
01155         Vector4 Pax = frameA * PX;
01156         Vector4 Pay = frameA * PY;
01157         Vector4 Paz = frameA * PZ;
01158 
01159         Vector4 Pbx = frameB * PX;
01160         Vector4 Pby = frameB * PY;
01161         Vector4 Pbz = frameB * PZ;
01162 
01163         // Generate difference vectors that connect the corresponding unit vectors of the given frames
01164         Vector4 dx = Pax - Pbx;
01165         Vector4 dy = Pay - Pby;
01166         Vector4 dz = Paz - Pbz;
01167 
01168         // Calculate the value of the distance metric (square the magitude of each difference vectors and sum.
01169         double distance_sq = dx.MagSquared() + dy.MagSquared() + dz.MagSquared();
01170 #else
01171         Vector4 offset1, offset2;
01172         offset1[0] = frameA(0, 3);
01173         offset1[1] = frameA(1, 3);
01174         offset1[2] = frameA(2, 3);
01175 
01176         offset2[0] = frameB(0, 3);
01177         offset2[1] = frameB(1, 3);
01178         offset2[2] = frameB(2, 3);
01179 
01180         offset1 -= offset2;
01181 
01182         double distance_sq = offset1.MagSquared();
01183 #endif
01184 
01185         //return the squared distance.
01186         return distance_sq;
01187 
01188 }
01189           
01190 //=============================================================================
01191 // GetEmbryosPerLandmark
01192 //
01193 // Purpose: Returns the number of embryos associated with each landmark
01194 //=============================================================================
01195 int  IK_ACA::GetEmbryosPerLandmark() const
01196 {
01197         return embryosPerLandmark;
01198 }
01199 
01200 //=============================================================================
01201 // SetEmbryosPerLandmark
01202 //
01203 // Purpose: Adjusts the number of embryos associated with each landmark and
01204 //                      adds or deletes embryos as required.
01205 //
01206 // Note:    This function will create new node_maps and copy the contents of the
01207 //                      existing ones before deleting them.
01208 //
01209 // Note:        THIS FUNCTION SHOULD BE THE ONLY WAY THE EMBRYO COUNT IS UPDATED!
01210 //=============================================================================
01211 void IK_ACA::SetEmbryosPerLandmark( const int& num_of_embryos )
01212 {
01213         if ( num_of_embryos == embryosPerLandmark )
01214         {
01215                 // no change...return early.
01216                 return;
01217         }
01218 
01219         // set pointer to existing node maps
01220         node_map<Configuration>* old_embryo = embryo;
01221         assert( old_embryo != NULL );
01222 
01223         // update embryo counters
01224         int old_embryosPerLandmark = embryosPerLandmark;
01225         if ( num_of_embryos < 1 )
01226         { 
01227                 embryosPerLandmark = 1;
01228         }
01229         else
01230         {
01231                 embryosPerLandmark = num_of_embryos;
01232         }
01233 
01234 
01235         // create new node map structures for embryos and initialize
01236         embryo = new node_map<Configuration>[embryosPerLandmark];
01237         assert( embryo != NULL );
01238         for ( int i = 0; i < embryosPerLandmark; i++ )
01239         {
01240                 embryo[i].init(G);
01241         }
01242 
01243         // copy existing embyros, adding new ones when required
01244         node n1;
01245         forall_nodes( n1, G )
01246         {
01247                 for( int i = 0; i < embryosPerLandmark; i++ )
01248                 {
01249                         if ( i < old_embryosPerLandmark )
01250                         {
01251                                 // copy embryo from existing node map
01252                                 embryo[i][n1] = old_embryo[i][n1];
01253                         }
01254                         else
01255                         {
01256                                 // a previous embryo does not exist, add a new one.
01257                                 CreateEmbryo( n1, i );
01258                         }
01259                 }
01260         }
01261 
01262         // delete the old embryos
01263         delete [] old_embryo;
01264 
01265 }
01266 
01267 //=============================================================================
01268 // InitNewSearch
01269 //
01270 // Purpose: Initiates parameters to indicate if a new search has been requested.
01271 //=============================================================================
01272 void IK_ACA::InitNewSearch()
01273 {
01274         // new search, start with the first node in the tree, the start node.
01275         searchLandmark = startNode;
01276 
01277         // Since object of planner is to find a goal config, tempoary assign the start config as the goal config
01278         // so it is at least defined.
01279         SetGoalConfig( GetStartConfig() );
01280 
01281         // Reset the best parameters
01282         InitBestParams();
01283 
01284 }
01285 
01286 //=============================================================================
01287 // InitBestParams
01288 //
01289 // Purpose: Initiates parameters used to indicate the best config and path so far
01290 //=============================================================================
01291 void IK_ACA::InitBestParams()
01292 {
01293         bestLandmark = startNode;
01294         bestPath.clear();
01295 
01296         if ( collisionDetector != NULL )
01297         {
01298                 bestDistance_sq = FrameDistance( goalFrame, GetToolFrame( GetGoalConfig() ) );
01299         }
01300         else
01301         {
01302                 bestDistance_sq = INFINITY;
01303         }
01304 }
01305 
01306 //=============================================================================
01307 // ComputePath
01308 //
01309 // Purpose: Computes the final path from the tree and search path to the actual 
01310 //                      or best goal config
01311 //=============================================================================
01312 SuccessResultType IK_ACA::ComputePath ( const node& landmark, const list<Configuration>& myPath )
01313 {
01314         
01315         // Trace path from last landmark used to start config.
01316         ClearGraphPath();
01317         node n0 = landmark;
01318         graphPath.push( n0 );
01319         while ( n0 != startNode )
01320         {
01321                 n0 = G.target( G.first_adj_edge( n0 ) );
01322                 graphPath.push( n0 );
01323         }
01324                 
01325         // Translate the graph path to the system path
01326         SuccessResultType success = TranslatePath();
01327 
01328         // Append the myPath to the system path
01329         list_item last = myPath.last();
01330         list_item index = myPath.first();
01331         while ( index != last )
01332         {
01333                 index = myPath.succ( index );
01334                 path.AppendPoint( myPath.inf(index) );
01335         }
01336 
01337         // Assign the solved (best) goal configuration
01338         AssignGoalConfig( myPath.inf( index ) );
01339 
01340         return success;
01341 
01342 }

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