planners/fortest/PL_ForTest.cpp

Go to the documentation of this file.
00001 #include "synchronization/semaphore.h"
00002 #include "Planners/fortest/PL_ForTest.h"
00003 #include "planners/ik_mpep/SMGraph.h"
00004 #include "math/matrixmxn.h"
00005 #include "math/vector4.h"
00006 #include <assert.h>
00007 #include <gl\gl.h>
00008 
00009 #define DEF_STEP_AHEAD          2
00010 #define MAX_SMG_EXTEND_RETRY    10
00011 #define DEF_SMG_STEPSIZE        5
00012 #define DEF_ERROR_TOLERANCE     0.01
00013 
00014 PL_ForTest::PL_ForTest()
00015 {
00016         m_pJacobian = NULL;
00017         m_nStepAhead = DEF_STEP_AHEAD;
00018         m_bUseJacobianSMGExploration = false;
00019         m_bUseBacktracking = true;
00020         m_pLocalPlanner = new Jacobian_TrajPlanner;
00021         m_nSMGStepSize = DEF_SMG_STEPSIZE;
00022         m_bUseObstacleAvoidLP = true;
00023         m_nSMGNodes = m_nSMGraphs = 0;
00024         smgNodeNum = 50;
00025 }
00026 
00027 PL_ForTest::~PL_ForTest()
00028 {
00029         if (m_pJacobian != NULL)
00030                 delete m_pJacobian;
00031         if (m_pLocalPlanner != NULL)
00032         {
00033                 delete m_pLocalPlanner;
00034         }
00035 }
00036 
00037 bool PL_ForTest::DrawExplicit () const
00038 {
00039         return PL_MPEP::DrawExplicit();
00040 }
00041 
00042 void PL_ForTest::SetCollisionDetector(CD_BasicStyle* collisionDetector)
00043 {
00044         PL_MPEP::SetCollisionDetector(collisionDetector);
00045         m_pLocalPlanner->SetCollisionDetector(collisionDetector);
00046 
00047         collisionDetector->DeactivateFrames(1, collisionDetector->DOF());
00048         this->collisionDetector = collisionDetector;
00049         m_nDof = collisionDetector->DOF();
00050         m_pRobot = dynamic_cast<R_OpenChain*>(collisionDetector->GetRobot(0));
00051         m_nToolFrame = m_pRobot->GetToolFrame(0);
00052         m_frEndEffector = Matrix4x4::Identity();
00053         if (m_nToolFrame != -1)
00054         {
00055                 FrameManager* frameManager = collisionDetector->GetFrameManager();
00056                 m_frEndEffector = *(frameManager->GetFrameRef(m_nToolFrame));
00057         }
00058         if (m_pJacobian != NULL)
00059         {
00060                 delete m_pJacobian;
00061                 m_pJacobian = new CJacobian(*m_pRobot);
00062         }
00063 }
00064 
00065 //does all the planning
00066 bool PL_ForTest::Plan ()
00067 {
00068         //Set up the trajectory, for test purpose
00069         //SetTrajectory();
00070         
00071         //MessageBox(NULL, "This planner is for test purpose!", "Test Planner", MB_OK);
00072         if (m_pJacobian == NULL)
00073                 m_pJacobian = new CJacobian(*m_pRobot);
00074 
00075         Configuration startConfig = GetStartConfig();
00076         m_pJacobian->SetConfiguration(startConfig);
00077         m_pJacobian->SetInterestPoint(m_nDof-1, m_frEndEffector, true, false);
00078 
00079         //Set seed of random, it's supposed be done by upper layer, actually
00080         srand( (unsigned)time( NULL ) );
00081 
00082         path.Clear();
00083 
00084         int result=ERROR_OK;
00085 
00086         //Always use Start Configuration
00087         usingStartConfig = true;
00088         usingGoalConfig = false;
00089         if (collisionDetector->IsInterfering(startConfig))
00090         {
00091                 return false;
00092         }
00093 
00094         StartTimer();
00095 
00096         if ((result=InitializeTree())!=ERROR_OK)
00097         {
00098                 return false;
00099         }
00100 
00101         int nStepAhead = m_nStepAhead;
00102         if (m_nStepAhead >= poses.size())
00103                 nStepAhead = poses.size()-1;
00104 
00105         PA_Points foundPath;
00106         PA_Points bufferPath;
00107         Configuration start = startConfig;
00108         int nStartIndex = 0;
00109         int nEndIndex = nStartIndex + nStepAhead;
00110         int nCurrentIndex = 0;
00111         vertex extendedVert = vertices[0];
00112 
00113         while (nEndIndex < poses.size())
00114         {
00115                 bool bFound;
00116                 if (m_bUseObstacleAvoidLP)
00117                         bFound = FindLocalPath2(start, nStartIndex, nEndIndex, foundPath);
00118                 else
00119                         bFound = FindLocalPath(start, nStartIndex, nEndIndex, foundPath);
00120                 if (bFound)
00121                 {
00122                         for (int i=0; i<foundPath.Size(); i++)
00123                                 bufferPath.AppendPoint(foundPath[i]);
00124 
00125                         Pose_Node newNode;
00126                         newNode.conf = bufferPath[0];
00127                         bufferPath.DeleteFirstPoint();
00128                         newNode.poses = nCurrentIndex + 1;
00129                         newNode.graph = NULL;
00130                         extendedVert = ConnectNode(tree, vertices, extendedVert, newNode); //extendedVert is the parent
00131                         nStartIndex = nEndIndex;
00132                         nEndIndex++;
00133                         nCurrentIndex++;
00134                         start = foundPath[foundPath.Size()-1];
00135                         foundPath.Clear();
00136                         //Log("PlannerForTest.log", "Append configuration for pose: %d", nCurrentIndex);
00137                 }
00138                 else
00139                 {
00140                         nStartIndex = nCurrentIndex;
00141                         nEndIndex = nStartIndex + nStepAhead;
00142                         bufferPath.Clear();
00143 
00144                         //Log("PlannerForTest.log", "Exploring SMG for pose: %d", nCurrentIndex);
00145                         //Propagate an SMG here.
00146                         do {
00147                                 result = Establish_Self_Motion_Graph(tree, extendedVert);
00148                         if (HasTimeLimitExpired())
00149                                         break;
00150                         } while ((result!=ERROR_OK) && (result!=ERROR_SMGRAPH_FULL));
00151 
00152                         if (result==ERROR_OK)
00153                         {
00154                                 Pose_Node *node=(Pose_Node *)tree.vertex_inf(extendedVert);
00155                                 start = node->conf;
00156                         }
00157                 }
00158 
00159                 while (result==ERROR_SMGRAPH_FULL)
00160                 {
00161                         vertex backtrackVertex;
00162                         backtrackVertex = tree.parent(extendedVert);
00163                         
00164                         //Remove All node vertices current vertex to the backtracking vertex
00165                         do
00166                         {
00167                                 vertex prevVertex = tree.parent(extendedVert);
00168                                 RemoveNode(extendedVert);
00169                                 extendedVert = prevVertex;
00170                         } while(extendedVert != backtrackVertex );
00171                         
00172                         Pose_Node *node=(Pose_Node *)tree.vertex_inf(extendedVert);
00173                         nCurrentIndex = node->poses;
00174                         nStartIndex = nCurrentIndex;
00175                         nEndIndex = nStartIndex + nStepAhead;
00176 
00177                         //Log("PlannerForTest.log", "Back track to pose: %d", nCurrentIndex);
00178                         do {
00179                                 result = Establish_Self_Motion_Graph(tree, extendedVert);
00180                                 if (HasTimeLimitExpired())
00181                                         break;
00182                         } while ((result!=ERROR_OK) && (result!=ERROR_SMGRAPH_FULL));
00183 
00184                         if (result==ERROR_OK)
00185                         {
00186                                 Pose_Node *node=(Pose_Node *)tree.vertex_inf(extendedVert);
00187                                 start = node->conf;
00188                         }
00189                 }
00190 
00191                 if (HasTimeLimitExpired())
00192                 {
00193                         result = ERROR_PLANNING_TIMEOUT;
00194                         break;
00195                 }
00196         }
00197 
00198         if (result == ERROR_OK)
00199         {
00200                 for (int i=0; i<bufferPath.Size(); i++)
00201                 {
00202                         Pose_Node newNode;
00203                         newNode.conf = bufferPath[i];
00204                         newNode.poses = nCurrentIndex + 1;
00205                         nCurrentIndex ++;
00206                         newNode.graph = NULL;
00207                         extendedVert = ConnectNode(tree, vertices, extendedVert, newNode); //extendedVert is the parent         
00208                 }
00209         }
00210         bufferPath.Clear();
00211 
00212         //Return the path anyway.
00213         goalPoseVertex = extendedVert;
00214         RetrievePathFromTree();
00215 
00216         LogStatistics();
00217         if (result == ERROR_OK)
00218                 return true;
00219         else
00220                 return false;
00221 }
00222 
00223 
00224 int PL_ForTest::Establish_Self_Motion_Graph(dynamic_trees &tr, vertex extended)
00225 {
00226         int result;
00227         Pose_Node *node = (Pose_Node *)tr.vertex_inf(extended);
00228         if (node->graph==NULL)
00229         {
00230                 //numSMGraph++;
00231                 //numFinalSMGraph++;
00232 
00233                 node->graph = new SMGraph(node->conf);
00234                 m_nSMGraphs ++;
00235         }
00236 
00237         //The condition (node->poses > 0) is used such that not backtracking is allowed
00238         //    at the starting pose.
00239         if ((m_bUseBacktracking) && (node->graph->Node_Num()>smgNodeNum) && (node->poses > 0))
00240         {
00241                 result = ERROR_SMGRAPH_FULL;
00242         }
00243         else//if (node->graph->Node_Num()<smgNodeNum)
00244         {
00245                 Configuration *nextConf;
00246                 if (m_bUseJacobianSMGExploration)
00247                         result = Extend_Node_Self_Motion_Graph_Jacobian(extended, &nextConf);
00248                 else
00249                         result = Extend_Node_Self_Motion_Graph(extended, &nextConf);
00250                 if (result==ERROR_OK)
00251                 {
00252                         //numSMGNode++;
00253                         //numFinalSMGNode++;
00254                         node->conf = *nextConf;
00255                         m_nSMGNodes ++;
00256                 }
00257         }
00258 
00259         return result;
00260 }
00261 
00262 
00263 int PL_ForTest::Extend_Node_Self_Motion_Graph(vertex g_vertex, Configuration **nextConf)
00264 {
00265         void* nodeInGraph=NULL;
00266         Pose_Node *node = (Pose_Node*) tree.vertex_inf(g_vertex);
00267         SMGraph *g = node->graph;
00268         (*nextConf)=NULL;
00269 
00270         //The method use to explore the S-M-G is RRT like exploration method
00271         //  1. Put a random configuration, as a random direction
00272         //  2. Get the closest configuration "q" in this graph
00273         //  3. Make one step further from "q" in this direction, with fixed length
00274         Configuration randConf, activeConf, newConf;
00275         Configuration *nearConf;
00276         bool bFind = false;
00277 
00278         //for (int k=0; k<MAX_SMG_EXTEND_RETRY; k++)
00279         //{
00280         for (int i=0; i<randomRetry; i++)
00281         {
00282                 GetRandomConfiguration(randConf);
00283 
00284                 //The v here, is actually the node in self-motion graph
00285                 nodeInGraph = GetNearestNodeInGraph(g, &randConf);
00286                 nearConf = g->GetConfiguration(nodeInGraph);
00287 
00288                 if (!GetConfigurationByDirection(activeConf, *(nearConf), randConf))
00289                         continue;
00290 
00291                 //I am thinking whether we should change the tolerance to make generating
00292                 //   feasible configurations easier.
00293                 if (!redundant.GetConfigurationByActive(newConf, activeConf, *nearConf,
00294                                                                                                 poses[node->poses], distTolerance))
00295                 //if (!redundant.GetConfigurationByActive(newConf, activeConf, *nearConf,
00296                 //                                        poses[node->poses], activeConf.DOF()*distTolerance))
00297                         continue;
00298 
00299                 if (collisionDetector->IsInterfering(newConf))
00300                         continue;
00301 
00302                 if (collisionDetector->IsInterferingLinear(newConf, *nearConf))
00303                         continue;
00304 
00305                 bFind = true;
00306                 break;
00307         }
00308         
00309         if (!bFind)
00310                 return ERROR_GET_COLLISION_FREE_FAILURE;
00311 
00312         nodeInGraph = g->AddConnection(nodeInGraph, newConf);
00313         (*nextConf) = g->GetConfiguration(nodeInGraph);
00314         return ERROR_OK;
00315 }
00316 
00317 bool PL_ForTest::IsJointWithinLimits(Configuration& config)
00318 {
00319         bool bResult = true;
00320         for (int i = 0; i<m_nDof; i++)
00321         {
00322                 if ( config[i] < collisionDetector->JointMin(i) )
00323                 {
00324                         bResult = false;
00325                 }
00326                 else if ( config[i] > collisionDetector->JointMax(i) )
00327                 {
00328                         bResult = false;
00329                 }
00330         }
00331         return bResult;
00332 }
00333 
00334 int PL_ForTest::Extend_Node_Self_Motion_Graph_Jacobian(vertex g_vertex, Configuration **nextConf)
00335 {
00336         void* nodeInGraph=NULL;
00337         Pose_Node *node = (Pose_Node*) tree.vertex_inf(g_vertex);
00338         SMGraph *g = node->graph;
00339         (*nextConf)=NULL;
00340 
00341         //The method use to explore the S-M-G is RRT like exploration method
00342         //  1. Put a random configuration, as a random direction
00343         //  2. Get the closest configuration "q" in this graph
00344         //  3. Make one step further from "q" in this direction, with fixed length
00345         Configuration randConf, activeConf, newConf;
00346         Configuration *nearConf;
00347         bool bFind = false;
00348 
00349         Matrixmxn mJEnd, mJEndInv;
00350         Matrixmxn mTemp(m_nDof, m_nDof); 
00351         Matrixmxn matrixIdentity(m_nDof, m_nDof);
00352         //int logK = 0;
00353         //for (int k=0; k<MAX_SMG_EXTEND_RETRY; k++)
00354         //{
00355         for (int i=0; i<randomRetry; i++)
00356         {
00357                 //logK++;
00358                 GetRandomConfiguration(randConf);
00359 
00360                 //The v here, is actually the node in self-motion graph
00361                 nodeInGraph = GetNearestNodeInGraph(g, &randConf);
00362                 nearConf = g->GetConfiguration(nodeInGraph);
00363                 Configuration dirVel = randConf - (*nearConf);
00364 
00365                 mJEnd = *(m_pJacobian->GetMatrix());
00366                 mJEnd.Inverse(mJEndInv);
00367                 mTemp = matrixIdentity;
00368                 mTemp -= mJEndInv * mJEnd;
00369                 dirVel = mTemp * dirVel;
00370                 dirVel *= (m_nSMGStepSize/ dirVel.Magnitude());
00371                 newConf = *nearConf + dirVel;
00372                 if (!IsJointWithinLimits(newConf))
00373                         continue;
00374                 if (collisionDetector->IsInterfering(newConf))
00375                         continue;
00376 
00377                 AdjustConfiguration(newConf, node->poses);
00378                 if (collisionDetector->IsInterferingLinear(newConf, *nearConf))
00379                         continue;
00380 
00381                 bFind = true;
00382                 break;
00383         }
00384         
00385         //}
00386         if (!bFind)
00387         {
00388                 //Log("PlannerForTest.log", "Failed to extend SMG after : %d  retries", logK);
00389                 return ERROR_GET_COLLISION_FREE_FAILURE;
00390         }
00391 
00392         //Log("PlannerForTest.log", "Succeeded to extend SMG after : %d  retries", logK);
00393         nodeInGraph = g->AddConnection(nodeInGraph, newConf);
00394         (*nextConf) = g->GetConfiguration(nodeInGraph);
00395 
00396 
00397         //Testing for validity, need to be removed later
00398         Frame currentFrame = GetToolFrame(**nextConf);
00399         Frame desiredFrame = poses[node->poses];
00400         Vector4 vec1 = currentFrame.GetTranslationVector();
00401         Vector4 vec2 = desiredFrame.GetTranslationVector();
00402         vec2 -= vec1;
00403         double dDistance = vec2.Magnitude();
00404         //Log("PlannerForTest.log", "The distance to pose: %d, is %f", node->poses, dDistance);
00405 
00406         return ERROR_OK;
00407 }
00408 
00409 bool PL_ForTest::AdjustConfiguration(Configuration &config, int nPose)
00410 {
00411         Frame desiredFrame = poses[nPose];
00412         Vector4 desiredPos = desiredFrame.GetTranslationVector();
00413 
00414         //LogMessage("reconfig.log", "Start From Here................");
00415         //LogMatrix("reconfig.log", desiredFrame, "Desired Frame");
00416 
00417         int logRetry=0;
00418         while (true)
00419         {
00420                 Frame currentFrame = GetToolFrame(config);
00421                 Vector4 currentPos = currentFrame.GetTranslationVector();
00422 
00423                 //LogConfiguration("reconfig.log", config);
00424                 //LogMatrix("reconfig.log", currentFrame, "Current Frame");
00425                 
00426                 Vector4 offset = desiredPos - currentPos;
00427                 double dDistance = offset.Magnitude();
00428                 if (dDistance < DEF_ERROR_TOLERANCE)
00429                         break;
00430 
00431                 logRetry++;
00432 
00433                 Matrixmxn mJEnd, mJEndInv;
00434                 m_pJacobian->SetConfiguration(config);
00435                 m_pJacobian->SetInterestPoint(m_nDof-1, m_frEndEffector, true, false);
00436                 mJEnd = *(m_pJacobian->GetMatrix());
00437                 mJEnd.Inverse(mJEndInv);
00438                 //LogMatrix("reconfig.log", mJEnd, "Jacobian");
00439                 //LogMatrix("reconfig.log", mJEndInv, "Jacobian Inverse");
00440 
00441                 VectorN endEffOffset(offset[0], offset[1], offset[2]);
00442                 Configuration jointOffset;
00443                 jointOffset = mJEndInv * endEffOffset *  Rad2Deg(1);
00444                 config += jointOffset;
00445         }
00446         //Log("reconfig.log", "It take: %d  iterations to do adjustment", logRetry);
00447         return true;
00448 }
00449 
00450 VectorN PL_ForTest::ComputeDeltaEndEff(Frame &fromPose, Frame &toPose)
00451 {
00452         VectorN returnMe;
00453 
00454         //=======Here, no orientation is considered!!!!!
00455         returnMe.SetLength(3);
00456 
00457         int index = 0;
00458         returnMe[index++] = toPose(0, 3) - fromPose(0, 3);
00459         returnMe[index++] = toPose(1, 3) - fromPose(1, 3);
00460         returnMe[index++] = toPose(2, 3) - fromPose(2, 3);
00461 
00462         return returnMe;        
00463 }
00464 
00465 
00466 //Note:
00467 //  1. CALL m_pJacobian->SetInterestPoint(), before calling this function.
00468 //  2. The start configuration is not store in the localpath.
00469 //  3. This function is made to be called frequently.
00470 bool PL_ForTest::FindLocalPath(Configuration &start, int nStart, int nEnd, PA_Points &localPath)
00471 {
00472         Matrixmxn mJEnd, mJEndInv;
00473         bool bValid = true;
00474         VectorN deltaEndEff;
00475         Configuration deltaConf;
00476         Configuration nextConf = start;
00477 
00478         for(int i=nStart; i<nEnd; i++)
00479         {
00480                 m_pJacobian->SetConfiguration(nextConf);
00481                 m_pJacobian->SetInterestPoint(m_nDof-1, m_frEndEffector, true, false);
00482                 mJEnd = *(m_pJacobian->GetMatrix());
00483                 mJEnd.Inverse(mJEndInv);
00484                 //To avoid drifting...
00485                 Frame currentPose = GetToolFrame(nextConf);
00486                 //deltaEndEff = ComputeDeltaEndEff(poses[i], poses[i+1]);
00487                 deltaEndEff = ComputeDeltaEndEff(currentPose, poses[i+1]);
00488                 deltaConf = mJEndInv * deltaEndEff;
00489                 deltaConf *= Rad2Deg(1);
00490 
00491                 //LogVector("PlannerForTest.log", deltaEndEff, "End-effector increment:");
00492                 //LogMessage("PlannerForTest.log", "Joint increment:");
00493                 //LogConfiguration("PlannerForTest.log", deltaConf);
00494 
00495                 Configuration newConf;
00496                 newConf = nextConf + deltaConf;
00497                 if (!IsJointWithinLimits(newConf))
00498                 {
00499                         localPath.Clear();
00500                         bValid = false;
00501                         break;
00502                 }
00503                 AdjustConfiguration(newConf, i+1);
00504                 if (collisionDetector->IsInterferingLinear(newConf, nextConf))
00505                 {
00506                         localPath.Clear();
00507                         bValid = false;
00508                         break;
00509                 }
00510                 else
00511                 {
00512                         nextConf = newConf;
00513                         localPath.AppendPoint(nextConf);
00514                 }
00515         }
00516 
00517         return bValid;
00518 }
00519 
00520 
00521 bool PL_ForTest::FindLocalPath2(Configuration &start, int nStart, int nEnd, PA_Points &localPath)
00522 {
00523         std::vector<Frame> piece;
00524         for (int i=nStart; i<=nEnd; i++)
00525                 piece.push_back(poses[i]);
00526 
00527         m_pLocalPlanner->SetStartConfig(start);
00528         m_pLocalPlanner->SetTrajectory(piece);
00529         m_pLocalPlanner->SetUsingOrientation(false);
00530         m_pLocalPlanner->SetUseGoalConfig(false);
00531         if (m_pLocalPlanner->Plan())
00532         {
00533                 PA_Points *foundPath = (PA_Points *)m_pLocalPlanner->GetPath();
00534                 for (int k=1; k<foundPath->Size(); k++)
00535                         localPath.AppendPoint((*foundPath)[k]);
00536                 return true;
00537         }
00538         return false;
00539 }
00540 
00541 void PL_ForTest::RemoveNode(vertex failVert)
00542 {
00543         //Here, assume failVertex is a leaf node in the tree.
00544         assert(failVert != NULL);
00545 
00546         Semaphore semaphore( guid );
00547         semaphore.Lock();
00548 
00549         tree.cut(failVert);
00550         Pose_Node *node=(Pose_Node *)tree.vertex_inf(failVert);
00551         if (node->graph != NULL)
00552         {
00553                 node->graph->Clear();
00554                 delete node->graph;
00555                 node->graph = NULL;
00556         }
00557 
00558         semaphore.Unlock();
00559 }
00560 
00561 void PL_ForTest::ResetStatistics()
00562 {
00563         m_nSMGNodes = 0;
00564         m_nSMGraphs = 0;
00565 }
00566 
00567 void PL_ForTest::LogStatistics()
00568 {
00569         int nNodes = vertices.size();
00570         int nPathLen = path.Size();
00571         Log("ForTest.log", "SMGNodes: %d, SMGraphs: %d, TreeNodes: %d, PathLen: %d", 
00572                         m_nSMGNodes, m_nSMGraphs, nNodes, nPathLen);
00573 }

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