planners/atace/PL_RGD_Constraint.cpp

Go to the documentation of this file.
00001 
00002 #include "math/vector4.h"
00003 #include "math/matrixmxn.h"
00004 #include "synchronization/semaphore.h"
00005 #include "robots/R_OpenChain.h"
00006 #include "CollisionDetectors/CD_Swiftpp.h"
00007 #include <assert.h>
00008 #include "planners/inversekin/Redundant.h"
00009 #include "planners/ik_mpep/IK_Jacobian.h"
00010 #include "planners/closedchain/PL_PRM_Closedchain.h"
00011 #include "PL_RGD_Constraint.h"
00012 #include <gl/gl.h>
00013 #include <opengl/gl_sphere.h>
00014 #include <opengl/gl_group.h>
00015 
00016 #define MAX_ITERATION        30
00017 #define MAX_RETRY            30
00018 #define MAX_RETRY2           30
00019 #define DEF_NEIGHBOR         (2)
00020 #define DEF_DIST_TOLERANCE   (3)
00021 #define DEF_ERR_TOLERANCE    (1e-1)
00022 
00023 //For sphere constraint
00024 #define RGD_SPHERE_CX           15
00025 #define RGD_SPHERE_CY           0  
00026 #define RGD_SPHERE_CZ           5
00027 #define RGD_SPHERE_RADIUS       12
00028 #define SHPERE_ORIENTATION
00029 
00030 double (PL_RGD_PRM::*costFunc)(const Configuration &p1, const Frame &pose) const = &PL_RGD_PRM::Error1;
00031 
00032 PL_RGD_PRM::PL_RGD_PRM()
00033 {
00034         edgePath.init(G);
00035         edgeFrag = new Fragment;
00036         //int dof = collisionDetector->DOF();
00037         //distTolerance = DEF_NEIGHBOR * dof;
00038         planner = new LocalPlannerClosed;
00039         pCollisionDetector = NULL;
00040         useJacobian = false;
00041         useGoalPose = false;
00042         typeOfConstraint = CONSTRAINT_COLSURE;
00043 }       
00044 
00045 PL_RGD_PRM::~PL_RGD_PRM()
00046 {
00047         if(pCollisionDetector)
00048         {
00049                 delete pCollisionDetector;
00050         }
00051         delete planner;
00052 
00053         edgeFrag->clear();
00054         delete edgeFrag;
00055 }
00056 
00057 void PL_RGD_PRM::SetCollisionDetector(CD_BasicStyle* collisionDetector)
00058 {
00059         // Call Parent's Collision Detector and assign the collision detector
00060         PL_PRM::SetCollisionDetector( collisionDetector );
00061 
00062         if (pCollisionDetector != NULL)
00063                 delete pCollisionDetector;
00064 
00065         pCollisionDetector = new CD_Swiftpp( *(collisionDetector->GetUniverse()) );
00066         planner->SetCollisionDetector(pCollisionDetector);
00067         pCollisionDetector->DeactivateFrames(1, pCollisionDetector->DOF());
00068 }
00069 
00070 bool PL_RGD_PRM::Plan ()
00071 {
00072         srand( (unsigned)time( NULL ) );
00073 
00074         StartTimer();
00075         if (typeOfConstraint == CONSTRAINT_PLANAR)
00076         {
00077                 UpdatePlanarConstraint();
00078         }
00079         else if (typeOfConstraint == CONSTRAINT_ORIENTATION)
00080         {
00081                 UpdateOrientConstraint();
00082         }
00083         else if (typeOfConstraint == CONSTRAINT_SPHERE)
00084         {
00085                 UpdateShpereConstraint();
00086         }
00087 
00088         if (useJacobian)
00089         {
00090                 planner->SetTimeLimitInSeconds(100);
00091                 Configuration q1 = GetStartConfig();
00092                 Configuration q2 = GetGoalConfig();
00093                 planner->SetStartConfig(q1);
00094                 planner->SetGoalConfig(q2);
00095 
00096                 double dObstacleTol = 0.01;
00097                 double dHomogain = 2.0;
00098                 double dPathTol = 0.5;
00099                 int nObstacleNum = 2;
00100 
00101                 planner->SetObstacleTolerance(dObstacleTol);
00102                 planner->SetNumObstaclePt(nObstacleNum);
00103                 planner->SetHomogeneousGain(dHomogain);
00104                 planner->SetPathTolerence(dPathTol);
00105                 planner->SetOrientation(false);
00106                 planner->SetPosition(true);
00107 
00108                 //if (planner->Plan())
00109                 bool result = planner->Plan();
00110 
00111                 PA_Points *plannerPath = (PA_Points *)planner->GetPath();
00112                 path = *plannerPath;
00113 
00114                 //To take a look at where planner fail to go on,
00115                 //the path will be returned no matter the planing is success or not.
00116                 return result;
00117         }
00118         else if (useGoalPose)
00119         {
00120                 Configuration conf;
00121                 Frame goalPose = GetToolFrame( GetGoalConfig() );
00122                 bool Result = false;
00123                 double oldTimeLimit = GetTimeLimitInSeconds();
00124                 double timeLimit = 100;
00125                 
00126                 while (Result == false)
00127                 {
00128                         Result = GenerateRandomConfigForPose(conf, goalPose);
00129                         if (Result)
00130                         {
00131                                 timeLimit = GetTimeElapsedInSeconds() + 20;
00132                                 oldTimeLimit = GetTimeLimitInSeconds();
00133                                 if (timeLimit > oldTimeLimit)
00134                                         timeLimit = oldTimeLimit;
00135                                 SetTimeLimitInSeconds( timeLimit );
00136                                 PL_PRM::SetGoalConfig(conf);
00137                                 Result = Plan_As_Usual();
00138                                 if (GetTimeLimitInSeconds() != timeLimit)
00139                                         break;
00140                                 else
00141                                         SetTimeLimitInSeconds( oldTimeLimit );
00142                         }
00143                         if (Result)
00144                                 return true;
00145                         if ( HasTimeLimitExpired() )
00146                         {
00147                                 return false;
00148                         }
00149                 }
00150                 return false;
00151                 //return Plan_As_Usual();
00152                 //return PL_PRM::Plan();
00153         }
00154         else
00155         {
00156                 return Plan_As_Usual();
00157         }
00158 
00159 /*
00160         Configuration q_last = q1;
00161         Configuration q_end = q2;
00162         path.AppendPoint(q1);
00163         int MAX_I = MAX_ITERATION * MAX_RETRY * MAX_RETRY2;
00164         int MAX_J = MAX_RETRY;
00165         int MAX_K = MAX_RETRY2;
00166         double distToLast = sqrt(Distance(q_last, q2));
00167         while ((i<MAX_I) && (j<MAX_J) && (k<MAX_K) && (distToLast>DEF_DIST_TOLERANCE))
00168         {
00169                 i++;  j++;
00170                 Configuration q_mid = PL_PRM::GenerateRandomConfig(q_last, DEF_NEIGHBOR*0.2);
00171                 if (MakeItSatisfied(q_mid))  //if (Error(q_mid)<DEF_ERR_TOLERANCE)
00172                 {
00173                         j = 0; k++;
00174                         if (Distance(q_mid, q_end) < Distance(q_last, q_end))
00175                         {
00176                                 k = 0;
00177                                 path.AppendPoint(q_mid);
00178                                 q_last = q_mid;
00179                                 distToLast = sqrt(Distance(q_last, q2));
00180                         }
00181                 }
00182         }
00183 
00184         if (sqrt(Distance(q_last, q_end))<DEF_DIST_TOLERANCE)
00185         {
00186                 path.AppendPoint(q2);
00187                 return true;
00188         }
00189         else
00190         {
00191                 return false;
00192         }
00193 */
00194 //      return PL_PRM::Plan();
00195 }
00196 
00197 //****************************************************************************
00198 //             Function to Get Tool Frame: End-effector Frame.
00199 //****************************************************************************
00200 Frame PL_RGD_PRM::GetToolFrame( const Configuration& config ) const
00201 {
00202         Frame toolFrame = Matrix4x4();
00203         if ( collisionDetector != NULL )
00204         {
00205                 FrameManager* frameManager = collisionDetector->GetFrameManager();
00206                 collisionDetector->SetConfiguration( config );
00207                 R_OpenChain * robot = (R_OpenChain *)collisionDetector->GetRobot(0);
00208                 int toolFrameID = robot->GetToolFrame(0);
00209                 if (toolFrameID == -1)
00210                 {
00211                         toolFrameID = collisionDetector->JointFrameNum(collisionDetector->DOF()-1);
00212                         toolFrame = frameManager->GetWorldFrame( toolFrameID );
00213                 }
00214                 else
00215                 {
00216                         toolFrame = *(frameManager->GetFrameRef(toolFrameID));
00217                         toolFrame = frameManager->GetTransformRelative(collisionDetector->DOF(), 0) * toolFrame;
00218                 }
00219         }
00220         return toolFrame;
00221 }
00222 
00223 bool PL_RGD_PRM::Plan_As_Usual ()
00224 {
00225         PRM_StateMachineType currentState = lastPlanningState;
00226 
00227         // Nodes may have been added since last plan.  Allow planner to check roadmap again
00228         // IMPROVE:  Is this still needed?
00229         if ( lastPlanningState == PRM_FAILURE )
00230         {
00231                 currentState = PRM_START;
00232         }
00233 
00234         // Start the timer
00235         //StartTimer();
00236 
00237         // Establish the semaphore
00238         Semaphore semaphore( guid );
00239         if( this->m_UseSemaphores == true )
00240         {
00241                 semaphore.Lock();
00242         }
00243         
00244 
00245         // Some quick checks to determine if we really need to plan
00246         if ( (currentState != PRM_DONE ) && (currentState != PRM_FAILURE) ) 
00247         {
00248                 if ( startNode == goalNode )
00249                 {
00250                         // start and goal are the same.  Do not plan.
00251                         currentState = PRM_DONE;
00252 
00253                         // Assign a small path.
00254                         path.Clear();
00255                         path.AppendPoint( GetStartConfig() );
00256                 }
00257                 else if ( (PL_PRM::IsInterfering(startNode)) || (PL_PRM::IsInterfering(goalNode)) )
00258                 {
00259                         // either the start or goal are already interfering.  Plan will
00260                         // automatically fail.
00261                         currentState = PRM_FAILURE;
00262                 }
00263         }
00264         if( this->m_UseSemaphores == true )
00265         {
00266                 semaphore.Unlock();
00267         }
00268 
00269         // Ensure the diagonal length is correct
00270         diagonal_squared = GetCspaceRange();
00271         
00272         // State Machine
00273         while (( currentState != PRM_DONE ) && ( currentState != PRM_FAILURE )) 
00274                 // NOTE:  The PRM_FAILURE state should eventually be removed!
00275         {
00276                 SuccessResultType success;
00277 
00278                 if( this->m_UseSemaphores == true )
00279                 {
00280                         semaphore.Lock();
00281                 }
00282                 // Determine the State function to call for this iteration
00283                 switch ( currentState )
00284                 {
00285                         case PRM_BUILD_INIT_ROADMAP :
00286                                 success = BuildInitRoadMap();
00287                                 break;
00288                         case PRM_FIND_PATH :
00289                                 success = FindPath();
00290                                 break;
00291                         case PRM_VERIFY_PATH :
00292                                 success = VerifyPath();
00293                                 break;
00294                         case PRM_TRANSLATE_PATH :
00295                                 success = TranslatePath();
00296                                 break;
00297                         case PRM_ENHANCE_ROADMAP :
00298                                 success = EnhanceRoadMap();
00299                                 break;
00300                         default :
00301                                 // No state functions are associated with this state.
00302                                 // Do nothing except prepare for next iteration.
00303                                 success = PASS;
00304                 }  // end SWITCH
00305 
00306 
00307                 // Check if timer has expired and one of the state functions had returned early.
00308                 if ( success == TIMER_EXPIRED )
00309                 {
00310                         // Escape the state machine.
00311                         break;
00312                 }
00313 
00314                 // Determine the State Function to call for the next iteration
00315                 switch ( currentState )
00316                 {
00317                         case PRM_START :
00318                                 // Start by building the initial roadmap.
00319                                 currentState = PRM_BUILD_INIT_ROADMAP;  
00320                                 break;
00321                         case PRM_BUILD_INIT_ROADMAP :
00322                                 // Search current road map for a short path.
00323                                 currentState = PRM_FIND_PATH;                   
00324                                 break;
00325                         case PRM_FIND_PATH :
00326                                 if ( success == PASS )
00327                                 {
00328                                         // A path has been found, verify it has no collision.
00329                                         currentState = PRM_VERIFY_PATH;
00330                                 }
00331                                 else
00332                                 {
00333                                         // No path was found.  Enhance some of the trouble areas.
00334                                         currentState = PRM_ENHANCE_ROADMAP;
00335                                         //currentState = PRM_FAILURE;           // NOTE:  Once EnhanceRoadmap is working,
00336                                                                                                         //                the PRM_FAILURE state should be removed.
00337                                 }
00338                                 break;
00339                         case PRM_VERIFY_PATH :
00340                                 if ( success == PASS )
00341                                 {
00342                                         // Path represented by valid nodes is successful. Translate it so the
00343                                         // main program can implement it.
00344                                         currentState = PRM_TRANSLATE_PATH;
00345                                 }
00346                                 else
00347                                 {
00348                                         // Path was not collision free.  Need to find a new path now that the troublesome
00349                                         // nodes/edges have been removed.
00350                                         currentState = PRM_FIND_PATH;
00351                                 }
00352                                 break;
00353                         case PRM_TRANSLATE_PATH :
00354                                 // We are done.  Escape state machine and report success.
00355                                 currentState = PRM_DONE;
00356                                 break;
00357                         case PRM_ENHANCE_ROADMAP :
00358                                 // Try finding a path again with the new nodes and edges added.
00359                                 currentState = PRM_FIND_PATH;
00360                                 break;
00361                         default :
00362                                 // an unexpected or invalid state has occurred.  Crash the program!
00363                                 ASSERT( FALSE );
00364                 } // end SWITCH.
00365 
00366                 // Release semaphore temporary.
00367                 if( this->m_UseSemaphores == true )
00368                 {
00369                         semaphore.Unlock();
00370                 }
00371         }  // END State Machine
00372 
00373 
00374         // save the current state of the machine for the next time the planner is called.
00375         lastPlanningState = currentState;
00376 
00377         // Report the success of the planner.
00378         if ( currentState == PRM_DONE )
00379         {
00380                 // planner has completed.  A path has been found and saved.
00381                         
00382                 // Release semaphore permanetly.
00383                 if( this->m_UseSemaphores == true )
00384                 {
00385                         semaphore.Unlock();
00386                 }
00387 
00388                 return true;
00389         }
00390         else
00391         {
00392                 // planner has not completed and has terminated early
00393                 graphPath.clear();
00394 
00395                 // Assign a small path.
00396                 path.Clear();
00397                 path.AppendPoint( GetStartConfig() );
00398 
00399                 // Release semaphore permanetly.
00400                 if( this->m_UseSemaphores == true )
00401                 {
00402                         semaphore.Unlock();
00403                 }
00404 
00405                 return false;
00406         }
00407 }  // END Plan
00408 
00409 bool PL_RGD_PRM::GetSatisfactoryConfiguration(Configuration &conf, Frame &pose)
00410 {
00411         int i,j;
00412         Configuration q;
00413         q = conf;
00414         i = 0; j = 0;
00415         int MAX_I = MAX_ITERATION * MAX_RETRY;
00416         int MAX_J = MAX_RETRY*2;
00417         double err_q = (this->*costFunc)(q, pose);
00418         while ((i<MAX_I) && (j<MAX_J) && (err_q>DEF_ERR_TOLERANCE))
00419         {
00420                 i++;   j++;
00421                 double deviation = DEF_NEIGHBOR;
00422                 if (err_q < 1)
00423                         deviation *= err_q;
00424                 Configuration q_next = PL_PRM::GenerateRandomConfig(q, deviation);
00425                 if ((this->*costFunc)(q_next, pose) < err_q)
00426                 {
00427                         j = 0; 
00428                         q = q_next;
00429                         err_q = (this->*costFunc)(q, pose);
00430                 }
00431                 if ( HasTimeLimitExpired() )
00432                 {
00433                         return false;
00434                 }
00435         }
00436 
00437         char msg[200];
00438         sprintf(msg, "I=%d, J=%d \t %f", i, j, err_q);
00439         //LogMessage("_generateConf.log", msg);
00440         conf = q;
00441         return (err_q <= DEF_ERR_TOLERANCE);
00442 }
00443 
00444 bool PL_RGD_PRM::GetSatisfiedConfiguration(Configuration &conf)
00445 {
00446         UpdatePlanarConstraint();
00447         UpdateOrientConstraint();
00448         UpdateShpereConstraint();
00449 
00450         int i,j;
00451         Configuration q;
00452         q = conf;
00453         i = 0; j = 0;
00454         int MAX_I = MAX_ITERATION * MAX_RETRY;
00455         int MAX_J = MAX_RETRY;
00456         double err_q = Error(q);
00457         while ((i<MAX_I) && (j<MAX_J) && (err_q>DEF_ERR_TOLERANCE))
00458         {
00459                 i++;   j++;
00460                 double deviation = DEF_NEIGHBOR;
00461                 if (err_q < 1)
00462                         deviation *= err_q;
00463                 Configuration q_next = PL_PRM::GenerateRandomConfig(q, deviation);
00464                 if (Error(q_next) < err_q)
00465                 {
00466                         j = 0; 
00467                         q = q_next;
00468                         err_q = Error(q);
00469                 }
00470         }
00471 
00472         conf = q;
00473         return (err_q <= DEF_ERR_TOLERANCE);
00474 }
00475 
00476 bool PL_RGD_PRM::GenerateRandomConfigForPose (Configuration &conf, Frame &endEffPose)
00477 {
00478         conf = PL_PRM::GenerateRandomConfig();
00479         costFunc = &PL_RGD_PRM::Error1;
00480 
00481         bool Result = GetSatisfactoryConfiguration(conf, endEffPose);
00482         if (Result)
00483         {
00484                 Result = !IsInterfering(conf);
00485         }
00486         return Result;
00487 }
00488 
00489 Configuration PL_RGD_PRM::GenerateRandomConfig ()
00490 {
00491         Configuration conf;
00492         Frame endEffPose;
00493         conf = PL_PRM::GenerateRandomConfig();
00494         if (typeOfConstraint == CONSTRAINT_PLANAR)
00495         {
00496                 endEffPose = planeDesired;
00497                 costFunc = &PL_RGD_PRM::Error3;
00498         }
00499         else if (typeOfConstraint == CONSTRAINT_ORIENTATION)
00500         {
00501                 endEffPose = orientDesired;
00502                 costFunc = &PL_RGD_PRM::Error4;
00503         }
00504         else if (typeOfConstraint == CONSTRAINT_SPHERE)
00505         {
00506                 costFunc = &PL_RGD_PRM::Error5;
00507         }
00508         else if (typeOfConstraint == CONSTRAINT_OTHER)
00509         {
00510         //At current moment, I use it for orientation constraint.
00511                 endEffPose = orientDesired; 
00512                 costFunc = &PL_RGD_PRM::Error6;
00513         }
00514         else
00515         {
00516                 costFunc = &PL_RGD_PRM::Error2;
00517         }
00518 
00519         GetSatisfactoryConfiguration(conf, endEffPose);
00520         //MakeItSatisfied(conf);
00521         return conf;
00522 }
00523 
00524 Configuration PL_RGD_PRM::GenerateRandomConfig ( const Configuration& seed, const double& std_dev )
00525 {
00526         Configuration conf;
00527         Frame endEffPose;
00528         conf = PL_PRM::GenerateRandomConfig(seed, std_dev);
00529         if (typeOfConstraint == CONSTRAINT_PLANAR)
00530         {
00531                 endEffPose = planeDesired;
00532                 costFunc = &PL_RGD_PRM::Error3;
00533         }
00534         else if (typeOfConstraint == CONSTRAINT_ORIENTATION)
00535         {
00536                 endEffPose = orientDesired;
00537                 costFunc = &PL_RGD_PRM::Error4;
00538         }
00539         else if (typeOfConstraint == CONSTRAINT_SPHERE)
00540         {
00541                 costFunc = &PL_RGD_PRM::Error5;
00542         }
00543         else
00544         {
00545                 costFunc = &PL_RGD_PRM::Error2;
00546         }
00547 
00548         GetSatisfactoryConfiguration(conf, endEffPose);
00549         return conf;
00550 }
00551 
00552 void PL_RGD_PRM::ConnectEdgesFull( const node& newnode, const double& radius_squared )
00553 {
00554         // verify connectIDp is valid.
00555         assert( connectIDp != NULL );
00556 
00557         // Save calculation time by determining configuration of the node once intstead of in each iteration
00558         Configuration nodeconfig = G.inf(newnode);
00559 
00560         node n1;
00561 
00562         // create a list of neighbour nodes to connect to within the given radius.
00563         node_pq<double> neighbours(G);
00564         forall_nodes( n1, G)
00565         {
00566                 if ( newnode != n1)
00567                 {
00568                         double edgelength_squared = Distance( nodeconfig, G.inf(n1) );  // returns the squared distance
00569                         // Check if the two nodes are within radius
00570                         if (  edgelength_squared <= radius_squared )  // can compare squares since a^2<b^2 if |a|<|b|
00571                         {
00572                                 // node is within radius, add it as a neighbour with its distance as its priority.
00573                                 neighbours.insert( n1, edgelength_squared );
00574                         }
00575                 }
00576         }
00577 
00578         // New node is currently not connected to anyone, assign it the NIL_ID.
00579         (*connectIDp)[newnode] = NIL_ID;
00580 
00581         // Create a running list of graph connected components new node is attached to.
00582         list<int> connectIDs;
00583 
00584         // While the list of neighbour is not empty, connect the node to the closests nodes, not already graph
00585         // connected to.
00586         while ( !neighbours.empty() )
00587         {
00588                 // get closest neighbour and remove it from the list
00589                 node neighbour = neighbours.find_min();
00590                 double dist_sq = neighbours.inf( neighbour );
00591                 neighbours.del( neighbour );
00592 
00593                 // connect the neighbour to the new node if it is not already graph connected.
00594                 // A node is graph connected if its current connectID is in the running list of
00595                 // connected graph components or has the same connectID as the new node.
00596                 if ( ((*connectIDp)[neighbour] == NIL_ID) ||
00597                          ( ((*connectIDp)[neighbour] != (*connectIDp)[newnode]) &&
00598                            ( !NodeInConnectionList(neighbour, connectIDs) ) )
00599                    )
00600                 {
00601                         edgeFrag->clear();
00602                         // nodes are not aleady connected.  Connect them now if there is a collision free path.
00603                         if ( !IsInterfering( nodeconfig, G.inf(neighbour) ) )
00604                         {
00605                                 double edgelength = sqrt( dist_sq );
00606                                 edge newedge = G.new_edge( newnode, neighbour, edgelength );
00607                                 edgeChecked[newedge] = TRUE;
00608                                 edgePath[newedge] = *edgeFrag;
00609 
00610                                 //LogMessage("closedchain.log", "Configurations checked in fragment");
00611                                 //for (int testj=0; testj<edgePath[newedge].size(); testj++)
00612                                 //{
00613                                 //      Fragment& E= edgePath[newedge];
00614                                 //      list_item itt = E.get_item(testj);
00615                                 //      Configuration conf = (E[itt]);
00616                                 //      LogVector("closedchain.log", conf, "Conf: ");
00617                                 //}
00618 
00619                                 // update the connectionIDs to show these two nodes are now graph connected.
00620                                 if ( (*connectIDp)[neighbour] != NIL_ID )
00621                                 // neighbour node has been previously connected to a graph component.
00622                                 {
00623                                         if ( (*connectIDp)[newnode] == NIL_ID )
00624                                         {
00625                                                 // node has not been previously connected, assign it the connect ID of its new neighbour.
00626                                                 (*connectIDp)[newnode] = (*connectIDp)[neighbour];
00627                                         }
00628                                         else if ( (*connectIDp)[neighbour] < (*connectIDp)[newnode] )
00629                                         {
00630                                                 // the neighbour node has the smaller ID.  Select this as the new ID for the two
00631                                                 // newly connected graph components (one from the new neighbour, one from the new node).
00632 
00633                                                 // save the old connectionID into the running list to be updated later.
00634                                                 connectIDs.push( (*connectIDp)[newnode] );
00635 
00636                                                 // assign the lower connection ID to the new node.
00637                                                 (*connectIDp)[newnode] = (*connectIDp)[neighbour];
00638                                         }
00639                                         else
00640                                         {
00641                                                 // the new node has the smaller ID.  Select this as the new ID for the two components.
00642 
00643                                                 // save the old connectionID into the running list to be updated later.
00644                                                 connectIDs.push( (*connectIDp)[neighbour] );
00645 
00646                                                 // assign the lower connection ID to the neighbour.
00647                                                 (*connectIDp)[neighbour] = (*connectIDp)[newnode];
00648                                         }
00649                                 }  // end if neighbour != NIL_ID
00650                                 else
00651                                 // neighbour has not been previously connected.
00652                                 {
00653                                         if ( (*connectIDp)[newnode] != NIL_ID )
00654                                         {
00655                                                 // new node has been previously connected, assign the neighbour its ID.
00656                                                 (*connectIDp)[neighbour] = (*connectIDp)[newnode];
00657                                         }
00658                                         else
00659                                         {
00660                                                 // both nodes have not been previously connected.  Create a new graph connected
00661                                                 // component by assigning these two nodes the baseConnectID.
00662                                                 (*connectIDp)[newnode] = baseConnectID;
00663                                                 (*connectIDp)[neighbour] = baseConnectID;
00664 
00665                                                 // Update the base connect ID to ensure a new unique ID is available for next new node.
00666                                                 baseConnectID++;
00667                                         }
00668                                 }  // end update connectIDs.
00669 
00670                         } // end if interfering
00671                         else
00672                         {
00673                                 edgeFrag->clear();
00674                                 // nodes have a collision path.  Use the midpoint between these two nodes as a seed for enhancing.
00675                                 // Add the midpoint of this potential edge as a seed, if requested
00676                                 if ( useMidPts )
00677                                 {
00678                                         Configuration midpt = GetMidPoint( nodeconfig, G.inf(neighbour) );
00679                                         config_seeds.append( midpt );
00680                                 }
00681                         }  // end if interfering else.
00682 
00683                 }       // end if not already graph connected.
00684 
00685         } // end while !neighbours.empty().
00686 
00687         // Search the entire graph, if required, updating connectIDs to reflect how new node has graph connected
00688         // different components of the graph.
00689         if ( ((*connectIDp)[newnode] != NIL_ID) && ( !connectIDs.empty() ) )
00690         {
00691                 // new node is connected to more than one graph connected component.  Update the connect IDs of
00692                 // affected nodes.
00693                 int newID = (*connectIDp)[newnode];
00694 
00695                 forall_nodes( n1, G )
00696                 {
00697                         if ( ((*connectIDp)[n1] != newID ) && (NodeInConnectionList( n1, connectIDs )) )
00698                         {
00699                                 (*connectIDp)[n1] = newID;
00700                         }
00701                 }
00702         }  // end update connectIDs of entire graph
00703 
00704         return;
00705 }
00706 
00707 bool PL_RGD_PRM::MakeItSatisfied(Configuration &conf)
00708 {
00709         int i,j;
00710         Configuration q;
00711         q = conf;
00712         i = 0; j = 0;
00713         int MAX_I = MAX_ITERATION * MAX_RETRY;
00714         int MAX_J = MAX_RETRY;
00715         double err_q = Error(q);
00716         while ((i<MAX_I) && (j<MAX_J) && (err_q>DEF_ERR_TOLERANCE))
00717         {
00718                 i++;   j++;
00719                 double deviation = DEF_NEIGHBOR;
00720                 if (err_q < 1)
00721                         deviation *= err_q;
00722                 Configuration q_next = PL_PRM::GenerateRandomConfig(q, deviation);
00723                 if (Error(q_next) < err_q)
00724                 {
00725                         j = 0; 
00726                         q = q_next;
00727                         err_q = Error(q);
00728                 }
00729                 if ( HasTimeLimitExpired() )
00730                 {
00731                         return false;
00732                 }
00733         }
00734 
00735         conf = q;
00736         return (err_q <= DEF_ERR_TOLERANCE);
00737 }
00738 
00739 bool PL_RGD_PRM::IsSatisfied(const Configuration &conf) const
00740 {
00741         return (Error(conf) <= DEF_ERR_TOLERANCE);
00742 }
00743 
00744 bool PL_RGD_PRM::IsInterfering ( const Configuration& q1, const Configuration& q2 )
00745 {
00746         int i, j, k;
00747         i = 0;  j = 0;  k = 0;
00748         Configuration q_last = q1;
00749         //Configuration q_end = q2;
00750         edgeFrag->append(q1);
00751         int MAX_I = MAX_ITERATION * MAX_RETRY * MAX_RETRY2;
00752         int MAX_J = MAX_RETRY;
00753         int MAX_K = MAX_RETRY2;
00754         double distToLast = sqrt(Distance(q_last, q2));
00755         bool result = false;
00756         while ((i<MAX_I) && (j<MAX_J) && (k<MAX_K) && (distToLast>DEF_DIST_TOLERANCE))
00757         {
00758                 i++;  j++;
00759                 //Configuration q_mid = PL_PRM::GenerateRandomConfig(q_last, DEF_NEIGHBOR*0.2);
00760                 Configuration q_mid = q_last*(1-(DEF_DIST_TOLERANCE/distToLast)) + q2*(DEF_DIST_TOLERANCE/distToLast);
00761                 if (MakeItSatisfied(q_mid))  //if (Error(q_mid)<DEF_ERR_TOLERANCE)
00762                 {
00763                         j = 0; k++;
00764                         if (PL_PRM::IsInterfering(q_mid))
00765                         {
00766                                 result = true;
00767                                 break;
00768                         }
00769                         if (Distance(q_mid, q2) < distToLast*distToLast)
00770                         {
00771                                 k = 0;
00772                                 edgeFrag->append(q_mid);
00773                                 q_last = q_mid;
00774                                 distToLast = sqrt(Distance(q_last, q2));
00775                         }
00776                 }
00777                 if ( HasTimeLimitExpired() )
00778                 {
00779                         result = true;
00780                         break;
00781                 }
00782         }
00783 
00784         //LogMessage("closedchain.log", "Configurations added into fragment");
00785         //for (int testj=0; testj<edgeFrag->size(); testj++)
00786         //{
00787         //      list_item itt = edgeFrag->get_item(testj);
00788         //      Configuration conf = edgeFrag->contents(itt);
00789         //      LogVector("closedchain.log", conf, "Conf: ");
00790         //}
00791 
00792         if ((!result) && (distToLast<=DEF_DIST_TOLERANCE))
00793         {
00794                 edgeFrag->append(q2);
00795                 return false;
00796         }
00797         else
00798         {
00799                 edgeFrag->clear();
00800                 return true;
00801         }
00802 }
00803 
00804 bool PL_RGD_PRM::IsInterfering ( const Configuration& c1 )
00805 {
00806         if (!IsSatisfied(c1)) 
00807                 return true;
00808         if (PL_PRM::IsInterfering(c1))
00809                 return true;
00810         return false;
00811 }
00812 
00813 
00814 void PL_RGD_PRM::UpdatePlanarConstraint() 
00815 {
00816         planeDesired = GetToolFrame( GetStartConfig() );
00817 }
00818 
00819 void PL_RGD_PRM::UpdateOrientConstraint()
00820 {
00821         //Make it same as the start configuration.
00822         //orientDesired = GetToolFrame( GetStartConfig() );
00823         
00824         //Make it upward
00825         if (typeOfConstraint == CONSTRAINT_OTHER)
00826         {
00827                 orientDesired = Matrix4x4::Identity();
00828                 orientDesired.Rotate2(Vector4(0, 1, 0), 90);//For Rightward
00829         }
00830         else
00831         {
00832                 orientDesired = Matrix4x4::Identity();
00833                 orientDesired.Rotate2(Vector4(1, 0, 0), 90);//For Upward
00834                 //orientDesired.Rotate2(Vector4(0, 1, 0), 90);//For Rightward
00835 
00836                 //Or, you can choose desired Z-axis fixed to wherever you want.
00837                 //orientDesired.Rotate(Vector4(0, 0, 1), 90);
00838                 //orientDesired.Rotate(Vector4(1, 0, 0), 90);
00839     }
00840 }
00841 
00842 void PL_RGD_PRM::UpdateShpereConstraint() 
00843 {
00844         return;
00845 }
00846 
00847 //Distance between a configuration to a pose, and it is used to generate goal configurations
00848 double PL_RGD_PRM::Error1(const Configuration &p1, const Frame &pose) const
00849 {
00850         double distance;
00851 
00852         Frame toolFrame = GetToolFrame( p1 );
00853 
00854         if (typeOfConstraint == CONSTRAINT_ORIENTATION)
00855         {
00856                 Vector4 offset = pose.GetTranslationVector() - toolFrame.GetTranslationVector();
00857                 distance = offset.Magnitude();
00858 
00859                 //=== Basically, this is the metrics used in IK-ACA;
00860                 //Vector4 PX(1, 0, 0);
00861                 //Vector4 PY(0, 1, 0);
00862                 Vector4 PZ(0, 0, 1);
00863 
00864                 // Generate vectors from base frame to each of the unit vector of the given frames.
00865                 //Vector4 Pax = toolFrame * PX;
00866                 //Vector4 Pay = toolFrame * PY;
00867                 Vector4 Paz = toolFrame * PZ;
00868 
00869                 //Vector4 Pbx = pose * PX;
00870                 //Vector4 Pby = pose * PY;
00871                 Vector4 Pbz = pose * PZ;
00872 
00873                 // Generate difference vectors that connect the corresponding unit vectors of the given frames
00874                 //Vector4 dx = Pax - Pbx;
00875                 //Vector4 dy = Pay - Pby;
00876                 Vector4 dz = Paz - Pbz;
00877 
00878                 // Calculate the value of the distance metric (square the magitude of each difference vectors and sum.
00879                 //double distance_sq = dx.MagSquared() + dy.MagSquared() + dz.MagSquared();
00880                 //distance = sqrt(distance_sq);
00881                 distance += dz.Magnitude(); //need to make sure the origin of tool frame concide.
00882         }       
00883         else if (typeOfConstraint == CONSTRAINT_SPHERE)
00884         {
00885                 Vector4 offset = pose.GetTranslationVector() - toolFrame.GetTranslationVector();
00886                 distance = offset.Magnitude();
00887 
00888                 Vector4 center(RGD_SPHERE_CX, RGD_SPHERE_CY, RGD_SPHERE_CZ);
00889                 //Get desired Z-axis
00890                 Vector4 pos1 = pose.GetTranslationVector();
00891                 Vector4 desiredZ = center;
00892                 desiredZ -= pos1;
00893                 desiredZ.Normalize();
00894                 //desiredZ *= -(RGD_SPHERE_CX - 1);
00895                 //desiredZ += center;
00896                 //Get current Z-axis
00897                 Vector4 pos2 = toolFrame.GetTranslationVector();
00898                 Vector4 currentZ;
00899                 currentZ[0] = toolFrame(0, 2);
00900                 currentZ[1] = toolFrame(1, 2);
00901                 currentZ[2] = toolFrame(2, 2);
00902                 //currentZ += pos2;
00903                 
00904                 desiredZ -= currentZ;
00905                 distance += desiredZ.Magnitude();
00906         }
00907         else
00908         {
00909                 Vector4 offset = pose.GetTranslationVector() - toolFrame.GetTranslationVector();
00910                 distance = offset.Magnitude();
00911         }
00912 
00913         return distance;
00914 }
00915 
00916 //Distance between a configuration to a closure constraint
00917 double PL_RGD_PRM::Error2(const Configuration &p1, const Frame &pose) const
00918 {
00919         //This can only be use for OUR planar robot.
00920         //The reason to set the offset[2] to be 0 is because the thickness of the
00921         Frame toolFrame = GetToolFrame( p1 );
00922         Vector4 offset = toolFrame.GetTranslationVector();
00923         offset[2] = 0;
00924         return offset.Magnitude();
00925 }
00926 
00927 //Distance between a configuration to a plane
00928 double PL_RGD_PRM::Error3(const Configuration &p1, const Frame &pose) const
00929 {
00930         //Simplify the code by assuming the plane is parrallel to X-Z plane
00931         Frame toolFrame = GetToolFrame( p1 );
00932         return fabs(toolFrame(1, 3)-pose(1, 3));
00933 }
00934 
00935 //Distance between a configuration to a desired orientation
00936 //To change the constraint, please modify the function "UpdateOrientConstraint"
00937 double PL_RGD_PRM::Error4(const Configuration &p1, const Frame &pose) const
00938 {
00939         //=== Take the rotation angle between current Z-axis
00940         //===    and desired Z-axis as the distance.
00941         //===    I set the unit to degree for better precision
00942         Frame toolFrame = GetToolFrame( p1 );
00943         Vector4 desiredZ, currentZ;
00944         desiredZ = orientDesired*Vector4(0, 0, 1);  
00945         currentZ[0] = toolFrame(0, 2);  
00946         currentZ[1] = toolFrame(1, 2);
00947         currentZ[2] = toolFrame(2, 2);  //X axis;
00948         double anglecos = currentZ.Dot(desiredZ);
00949         if (anglecos > 1)
00950                 anglecos = 1;
00951         else if (anglecos < -1)
00952                 anglecos = -1;
00953         //return sqrt(1.-anglecos*anglecos); //when theta is small; sin(theta)=theta;
00954     return fabs(acos(anglecos));
00955     //return Rad2Deg(acos(anglecos));
00956         
00957         //=== There another ways to do this: 
00958         //===     Compare RPY-angle, which doesn't work well in
00959         //====        cases where Z-axis is required to be awry.
00960         //double yaw1, pitch1, roll1;
00961         //double yaw2, pitch2, roll2;
00962         //GetRotAngles(toolFrame, roll1, pitch1, yaw1);
00963         //GetRotAngles(pose, roll2, pitch2, yaw2);
00964         //return ((roll1-roll2)*(roll1-roll2) + (yaw1-yaw2)*(yaw1-yaw2); //Upward
00965         //return ((roll1-roll2)*(roll1-roll2) + (pitch1-pitch2)*(pitch1-pitch2)); //Rightward
00966 }
00967 
00968 //For a sphere constraint, with the end-effector pointing toward the shpere center.
00969 double PL_RGD_PRM::Error5(const Configuration &p1, const Frame &pose) const
00970 {
00971         Vector4 center(RGD_SPHERE_CX, RGD_SPHERE_CY, RGD_SPHERE_CZ);
00972         //Vector4 pos1 = pose.GetTranslationVector(); //pose is not used here
00973     Frame toolFrame = GetToolFrame(p1); 
00974         Vector4 pos1 = toolFrame.GetTranslationVector();
00975 
00976 #ifdef SHPERE_ORIENTATION //sphere constraint with constraint
00977         Vector4 desiredZ = center;
00978         desiredZ -= pos1;       //Get desired Z-axis
00979         desiredZ.Normalize();
00980         desiredZ *= -(RGD_SPHERE_RADIUS-1);
00981         desiredZ += center;
00982         //Get current Z-axis
00983         Vector4 pos2 = toolFrame.GetTranslationVector();
00984         Vector4 currentZ;
00985         currentZ[0] = toolFrame(0, 2);
00986         currentZ[1] = toolFrame(1, 2);
00987         currentZ[2] = toolFrame(2, 2);
00988         currentZ += pos2;
00989 
00990         desiredZ -= currentZ;
00991         return desiredZ.Magnitude();
00992 
00993 #else //Without orientation
00994         pos1 -= center;
00995         return sqrt((pos1.Magnitude() - radius)*(pos1.Magnitude() - radius));
00996 #endif
00997 }
00998 
00999 double PL_RGD_PRM::Error6(const Configuration &p1, const Frame &pose) const
01000 {
01001         //Pending for future.
01002         return Error4(p1, pose);
01003 }
01004 
01005 double PL_RGD_PRM::Error(const Configuration &p1) const
01006 {
01007         Frame toolFrame = GetToolFrame( p1 );
01008 
01009         if (typeOfConstraint == CONSTRAINT_PLANAR)
01010         {
01011                 return Error3(p1, planeDesired); //Planar constraint
01012         }
01013         else if (typeOfConstraint == CONSTRAINT_ORIENTATION)
01014         {
01015                 return Error4(p1, orientDesired); //Orientation constraint.
01016         }
01017         else if (typeOfConstraint == CONSTRAINT_SPHERE)
01018         {
01019                 return Error5(p1, toolFrame); //Sphere constraint
01020         }
01021         else if (typeOfConstraint == CONSTRAINT_OTHER)
01022         {
01023                 return Error6(p1, toolFrame); //Constraint for testing
01024         }
01025         else
01026         {
01027                 return Error2(p1, toolFrame); //Closure constraint
01028         }
01029 }
01030 
01031 void PL_RGD_PRM::GetRotAngles( const Matrix4x4& frame, double& roll, double& pitch, double& yaw ) const
01032 {
01033         // Declare the fixed angle variables.
01034         double alpha, beta, gamma;
01035         
01036         // Calculate beta and cache the cosine.
01037         beta = atan2( -frame(2,0) , sqrt( Sqr(frame(0,0)) + Sqr(frame(1,0)) ) );
01038         double cB = cos ( beta );
01039 
01040         // Calculate the other two rotations
01041         if ( cB == 0.0 )
01042         { 
01043                 alpha = 0;
01044                 if ( beta > 0 ) // if beta == PI/2
01045                 {
01046                         gamma = atan2( frame(0,1) , frame(1,1) );
01047                 }
01048                 else
01049                 {
01050                         gamma = -atan2( frame(0,1), frame(1,1) );
01051                 }
01052         }
01053         else
01054         {
01055                 alpha = atan2( frame(1,0) / cB , frame(0,0) / cB );
01056                 gamma = atan2( frame(2,1) / cB , frame(2,2) / cB );
01057         }
01058 
01059         // Convert angles to degrees and assign to appropriate parameters
01060         // NOTE:  These angles must correspond to same angles used in SetGoalFrame
01061         yaw   = Rad2Deg( alpha );
01062         pitch = Rad2Deg( beta );
01063         roll  = Rad2Deg( gamma );
01064 }
01065 
01066 SuccessResultType PL_RGD_PRM::TranslatePath()
01067 {
01068         // Clear any current path.
01069         path.Clear();
01070 
01071         // Check if a graph path is available.
01072         if ( graphPath.empty() )
01073         {
01074                 // Path is empty.  Set start as the beginning of the path, and return.
01075                 path.AppendPoint( GetStartConfig() );
01076 
01077                 // no path exists.
01078                 return FAIL;
01079         }
01080 
01081         // If still in the function, there is a graphPath.
01082         // Go through all nodes stored in graphPath and assign the configuration they correspond to the
01083         // actual path.
01084         node n1;
01085         node n2;
01086         forall( n1, graphPath )
01087         {
01088                 Configuration conf = G.inf(n1);
01089                 path.AppendPoint( conf );
01090                 n2 = graphPath.succ(n1);
01091                 if (n2 == NULL)
01092                         continue;
01093 
01094                 edge e;
01095                 forall_inout_edges(e, n1)
01096                 //edge e = G.first_in_edge(n1);
01097                 //while(e)
01098                 {
01099                         if (G.opposite(n1, e) == n2)
01100                         {
01101                                 int nStep = 0;
01102                                 int dir = -1;
01103                                 Fragment& frag = edgePath[e];
01104                                 int nFirst = frag.size();
01105                                 if (conf == frag[frag[0]])
01106                                 {
01107                                         nFirst = 0;
01108                                         dir = 1;
01109                                 }
01110                                 for (int i=1; i<(frag.size()-1); i++)
01111                                 {
01112                                         nStep += dir;
01113                                         list_item it = frag[nFirst+nStep];
01114                                         conf = frag[it];
01115                                         //->get_item(i);//((*frag)[nFirst+dir]);
01116                                         path.AppendPoint( conf );
01117                                 }
01118                                 break;
01119                         }
01120                 }
01121         }
01122 
01123         // Path has been translated and is ready to be animated.
01124         return PASS;
01125 }
01126 
01127 //===========================================================================================
01128 
01129 typedef struct
01130 {
01131         Configuration conf;
01132         PA_Points edge;
01133 } VertexInfoInTree;
01134 
01135 #define ERR_FAIL            0xff
01136 #define ERR_SUCCESS         0x00
01137 #define ERR_TIMEOUT         0x10
01138 #define ERR_ILLPARAMETER    0x20
01139 
01140 
01141 PL_RGD_RRT::PL_RGD_RRT()
01142 {
01143         m_rootVert = NULL;
01144         m_goalVert = NULL;
01145 }
01146 
01147 PL_RGD_RRT::~PL_RGD_RRT()
01148 {
01149         if ( m_rootVert != NULL )
01150                 ClearTree();
01151 }
01152 
01153 bool PL_RGD_RRT::DrawExplicit () const
01154 {
01155         double Xcor, Ycor, Zcor;        // temp coordinate variables
01156 
01157         Semaphore semaphore( guid );
01158         semaphore.Lock();
01159 
01160         // Setup GL Environment
01161         glClearColor( 0.0f, 0.0f, 0.2f, 1.0f );
01162         glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
01163         BOOL lightingState = glIsEnabled( GL_LIGHTING );
01164         glDisable( GL_LIGHTING );
01165         glShadeModel( GL_SMOOTH );
01166         glPointSize(5.0f);      // Set size of points associated with the nodes.
01167 
01168         if (m_vertices.size() )
01169         {
01170                 int i;
01171 
01172                 //const dynamic_trees *ptrTree = &tree;
01173                 glBegin(GL_POINTS);
01174                 for(i = 0; i<m_vertices.size(); i++)
01175                 {
01176                         vertex vert;
01177                         VertexInfoInTree *info;
01178                         vert = m_vertices[i];
01179                         info = (VertexInfoInTree *)((dynamic_trees &)m_trajTree).vertex_inf(vert);
01180 
01181                         Configuration conf = info->conf;
01182                         Xcor = conf[0];
01183                         Ycor = conf[1];
01184                         Zcor = conf[2];
01185 
01186                         if ((i==0) || (i==(m_vertices.size()-1)))
01187                                 glColor3f(0.0f,0.0f,1.0f);    //Set the start and end to be blue
01188                         else
01189                                 glColor3f(1.0f,1.0f,0.0f);              // set colour to yellow
01190                         glVertex3f( (float)Xcor, (float)Ycor, (float)Zcor );
01191                 }
01192                 glEnd();
01193 
01194                 glBegin(GL_LINES);
01195                 for(i = 1; i<m_vertices.size(); i++)
01196                 {
01197                         vertex vert, parentVert;
01198                         VertexInfoInTree *info, *parentInfo;
01199 
01200                         vert = m_vertices[i];
01201                         parentVert = ((dynamic_trees &)m_trajTree).parent(vert);
01202                         info = (VertexInfoInTree *)((dynamic_trees &)m_trajTree).vertex_inf(vert);
01203                         parentInfo = (VertexInfoInTree *)((dynamic_trees &)m_trajTree).vertex_inf(parentVert);
01204 
01205                         Configuration conf = info->conf;
01206                         Configuration parentConf = parentInfo->conf;
01207 
01208                         Xcor = conf[0];
01209                         Ycor = conf[1];
01210                         Zcor = conf[2];
01211                         glColor3f(1.0f,0.5f,0.0f);      // set colour to orange
01212                         glVertex3f( (float)Xcor, (float)Ycor, (float)Zcor );    // add source vertex for edge line
01213 
01214                         Xcor = parentConf[0];
01215                         Ycor = parentConf[1];
01216                         Zcor = parentConf[2];
01217                         glColor3f(1.0f,0.0f,0.0f);      // set colour to red
01218                         glVertex3f( (float)Xcor, (float)Ycor, (float)Zcor );    // add target vertex for edge line
01219                 }
01220                 glEnd();
01221         }
01222 
01223         // Clean up Environment
01224         if( lightingState != FALSE )
01225         {
01226                 glEnable( GL_LIGHTING );
01227         }
01228 
01229         semaphore.Unlock();
01230 
01231         //Sleep( 50 );
01232 
01233         return true;
01234 }
01235 
01236 bool PL_RGD_RRT::Plan ()
01237 {
01238         srand( (unsigned)time( NULL ) );
01239 
01240         path.Clear();
01241 
01242         // Start the timer
01243         StartTimer();
01244 
01245         Configuration startConf = GetStartConfig();
01246         CreateTree(startConf);
01247 
01248         int result = ERR_FAIL;
01249         bool pathFound = false;
01250         m_goalVert = NULL;
01251         
01252         int repeatNum = 0;
01253         while ((!pathFound) && (result != ERR_TIMEOUT))
01254         {
01255                 PA_Points localPath;
01256                 Configuration randConf = PL_RGD_PRM::GenerateRandomConfig();
01257                 vertex fromVert = FindClosestInTree(randConf);
01258                 Configuration fromConf = GetConfigurationFromTree(fromVert);
01259                 Configuration toConf;
01260 
01261                 result = Extend(fromConf, toConf, randConf, localPath);
01262                 if (result == ERR_SUCCESS)
01263                 {
01264                         fromVert = AddNodeInTree(fromVert, toConf, localPath);
01265                         //if (ConnectToGoal(fromVert) == ERR_SUCCESS)
01266                         if (ConnectToGoal() == ERR_SUCCESS)
01267                         {
01268                                 pathFound = true;
01269                         }
01270                 }
01271 
01272                 //semaphore.Unlock();
01273                 //semaphore.Lock();
01274 
01275                 if ( HasTimeLimitExpired() )
01276                 {
01277                         break;
01278                 }
01279 
01280         } //End of While(...)
01281 
01282         //semaphore.Unlock();
01283         if (pathFound)
01284         {
01285                 assert(m_goalVert != NULL);
01286                 RetrievePath(m_goalVert);
01287                 return true;
01288         }
01289         
01290         return false;
01291 }
01292 
01293 #define LEN_STEP_SIZE   10
01294 #define MAX_CONF_RETRY  10
01295 int PL_RGD_RRT::Extend(Configuration &fromConf, Configuration &toConf, Configuration dirConf, PA_Points &localPath)
01296 {
01297         std::vector<Frame> edgeTraj;
01298         localPath.Clear();
01299 
01300         double pathLen = 0;
01301         bool trajExtracted = true;
01302 
01303         //Extracted a end-effector path as an edge in physical space.
01304         double dist = Distance(fromConf, dirConf);
01305         if (dist > LEN_STEP_SIZE)
01306                 toConf = fromConf * (1-LEN_STEP_SIZE/dist) + dirConf * (LEN_STEP_SIZE/dist);
01307         else
01308                 toConf = dirConf;
01309 
01310         bool result = false;
01311         int retry = 0;
01312         while ( (!result) && (retry < MAX_CONF_RETRY) )
01313         {
01314                 result = GetSatisfiedConfiguration( toConf );
01315                 retry ++;
01316         }       
01317 
01318         if (!result)
01319         {
01320                 return ERR_FAIL;
01321         }
01322         if ( IsInterfering(fromConf, toConf) == false)
01323         {
01324                 for (int i=0; i<edgeFrag->size(); i++)
01325                 {
01326                         list_item itt = edgeFrag->get_item(i);
01327                         Configuration conf = edgeFrag->contents(itt);
01328                         localPath.AppendPoint(conf);
01329                 }
01330                 edgeFrag->clear();
01331                 //localPath = *edgeFrag;
01332                 return ERR_SUCCESS;
01333         }
01334 
01335         return ERR_FAIL;
01336 }
01337 
01338 //int PL_RGD_RRT::ConnectToGoal(vertex fromVert)
01339 int PL_RGD_RRT::ConnectToGoal()
01340 {
01341         Configuration goalConf = GetGoalConfig();
01342         Frame goalPose = GetToolFrame(goalConf);
01343         bool result = true;
01344         if (useGoalPose)
01345         {
01346                 result = false;
01347                 int retry = 0;
01348                 while ( (!result) && (retry++<MAX_CONF_RETRY) && (!HasTimeLimitExpired()))
01349                 {
01350                         result = GenerateRandomConfigForPose(goalConf, goalPose);
01351                 }
01352         }
01353 
01354         vertex fromVert = NULL;
01355         if (result)
01356         {
01357                 fromVert = FindClosestInTree(goalConf);
01358         }
01359         if (fromVert == NULL)
01360         {
01361                 result = false;
01362         }
01363 
01364         if (result) 
01365         {
01366                 Configuration fromConf = GetConfigurationFromTree(fromVert);
01367                 if (!IsInterfering(fromConf, goalConf))
01368                 {
01369                         PA_Points localPath;
01370                         for (int i=0; i<edgeFrag->size(); i++)
01371                         {
01372                                 list_item itt = edgeFrag->get_item(i);
01373                                 Configuration conf = edgeFrag->contents(itt);
01374                                 localPath.AppendPoint( conf );
01375                         }
01376                         edgeFrag->clear();
01377                         m_goalVert = AddNodeInTree(fromVert, goalConf, localPath);
01378                         return ERR_SUCCESS;
01379                 }
01380         }
01381         return ERR_FAIL;
01382 }
01383 
01384 bool PL_RGD_RRT::CreateTree(Configuration &conf)
01385 {
01386         if (m_rootVert != NULL)
01387         {
01388                 ClearTree();
01389         }
01390 
01391         VertexInfoInTree *newNode = new VertexInfoInTree;
01392         newNode->conf = conf;
01393 
01394         Semaphore semaphore( guid );
01395         semaphore.Lock();
01396         m_rootVert = m_trajTree.make(newNode);
01397         m_vertices.push_back(m_rootVert);
01398         semaphore.Unlock();
01399 
01400         return true;
01401 }
01402 
01403 void PL_RGD_RRT::ClearTree()
01404 {
01405         Semaphore semaphore( guid );
01406         semaphore.Lock();
01407         for (int i=0; i<m_vertices.size(); i++)
01408         {
01409                 VertexInfoInTree *info;
01410                 info = (VertexInfoInTree *)m_trajTree.vertex_inf(m_vertices[i]);
01411                 delete info;
01412         }
01413 
01414         m_trajTree.clear();
01415         m_vertices.clear();
01416         m_rootVert = NULL;
01417         semaphore.Unlock();
01418 }
01419 
01420 vertex PL_RGD_RRT::AddNodeInTree(vertex parentVertex, Configuration &childConf, PA_Points &localPath)
01421 {
01422         VertexInfoInTree *newNode = new VertexInfoInTree;
01423         newNode->conf = childConf;
01424         CopyPath(newNode->edge, localPath);
01425 
01426         Semaphore semaphore( guid );
01427         semaphore.Lock();
01428         vertex newVert = m_trajTree.make(newNode);
01429         m_vertices.push_back(newVert);
01430         m_trajTree.link(newVert, parentVertex, 1);
01431         semaphore.Unlock();
01432 
01433         return newVert;
01434 }
01435 
01436 vertex PL_RGD_RRT::FindClosestInTree(Configuration &conf)
01437 {
01438         if (m_vertices.size() == 0)
01439                 return NULL;
01440 
01441         VertexInfoInTree *info;
01442         double minDist, currDist;
01443         int minIndex=0;
01444 
01445         info = (VertexInfoInTree *)m_trajTree.vertex_inf(m_vertices[0]);
01446         minDist = Distance(info->conf, conf);
01447         minIndex = 0;
01448 
01449         for (int i=1; i<m_vertices.size(); i++)
01450         {
01451                 info = (VertexInfoInTree *)m_trajTree.vertex_inf(m_vertices[i]);
01452                 currDist = Distance(info->conf, conf);
01453                 if (currDist < minDist)
01454                 {
01455                         minDist = currDist;
01456                         minIndex = i;
01457                 }
01458         }
01459 
01460         return m_vertices[minIndex];
01461 }
01462 
01463 Configuration& PL_RGD_RRT::GetConfigurationFromTree(vertex vert)
01464 {
01465         VertexInfoInTree *info;
01466         info = (VertexInfoInTree *)m_trajTree.vertex_inf(vert);
01467         return info->conf;
01468 }
01469 
01470 double PL_RGD_RRT::Distance(const Configuration &conf1, const Configuration &conf2)
01471 {
01472         double dist = 0;
01473         VectorN jointDiff = collisionDetector->JointDisplacement(conf1, conf2);
01474         for(int i = 0; i < jointDiff.Length(); i++)
01475         {
01476                 dist += (jointDiff[i])*(jointDiff[i]);
01477         }
01478         return sqrt(dist);
01479 }
01480 
01481 PA_Points& PL_RGD_RRT::GetPathFromTree(vertex vert)
01482 {
01483         VertexInfoInTree *info;
01484         info = (VertexInfoInTree *)m_trajTree.vertex_inf(vert);
01485         return info->edge;
01486 }
01487 
01488 void PL_RGD_RRT::RetrievePath(vertex &goalVert)
01489 {
01490         vertex currVert = goalVert;
01491         while (currVert != NULL)
01492         {
01493                 InsertPath(path, GetPathFromTree(currVert));
01494                 currVert = m_trajTree.parent(currVert);
01495         }//end of while
01496 }
01497 
01498 void PL_RGD_RRT::AppendPath(PA_Points &collect, PA_Points &local)
01499 {
01500         for (int i=0; i<local.Size(); i++)
01501         {
01502                 collect.AppendPoint(local[i]);
01503         }
01504 }
01505 
01506 void PL_RGD_RRT::AppendPath(PA_Points &collect, PA_Points *local)
01507 {
01508         for (int i=0; i<local->Size(); i++)
01509         {
01510                 collect.AppendPoint(local->GetPoint(i));
01511         }
01512 }
01513 
01514 void PL_RGD_RRT::InsertPath(PA_Points &target, PA_Points &source)
01515 {
01516         int nLen = source.Size()-1;
01517         if ( target.Size() != 0 )
01518         {
01519                 nLen = nLen - 1;
01520         }
01521         for( int i = nLen; i >= 0; i-- )
01522         {
01523                 target.AppendPointToBeginning( source[ i ] ) ;
01524         }
01525 }
01526 
01528 PL_RGD_Constraint::PL_RGD_Constraint()
01529 {
01530         m_strategy = STRATEGY_RRT;
01531 }
01532 
01533 void PL_RGD_Constraint::SetStrategy(int strategy)
01534 {
01535         if (m_strategy != strategy)
01536         {
01537                 path.Clear();
01538                 if (m_strategy == STRATEGY_RRT)
01539                 {
01540                         this->ClearTree();
01541                 }
01542                 else
01543                 {
01544                         this->ClearGraph();
01545                 }
01546         }
01547         m_strategy = strategy;
01548 }
01549 
01550 int PL_RGD_Constraint::GetStrategy()
01551 {
01552         return m_strategy;
01553 }
01554 
01555 bool PL_RGD_Constraint::DrawExplicit () const
01556 {
01557         if (m_strategy == STRATEGY_RRT)
01558                 return PL_RGD_RRT::DrawExplicit();
01559         else
01560                 return PL_RGD_PRM::DrawExplicit();
01561 }
01562 
01563 bool PL_RGD_Constraint::Plan ()
01564 {
01565         if (m_strategy == STRATEGY_RRT)
01566                 return PL_RGD_RRT::Plan();
01567         else
01568                 return PL_RGD_PRM::Plan();
01569 }
01570 

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