planners/atace/PL_ATACE.cpp

Go to the documentation of this file.
00001 
00002 //
00003 //Contents: Class PL_ATACE
00004 // 
00005 //PL_ATACE: Alternate Physical-space And C-space Exploration
00006 //      is a path planning algorithm for PPGEEC, Path Planning problem
00007 //      with General End-Effector Constraints.
00008 //
00009 //This is the topic of Zhenwang Yao's Master thesis, for more information
00010 //please refer to that. The basic idea of APACE is: Instead of finding a path
00011 //in C-space directly, APACE explore the physical space(or, the task space) 
00012 //first for feasible end-effector poses and paths; then track these paths in 
00013 //C-space with trajectory tracking planners.
00014 //
00015 //Revision History:
00016 //       Date     Author    Description
00017 //      ---------------------------------------------------------
00018 //     Jun-2004:  Z.Yao     First version implemented: PL_JPRM
00019 //     Oct-2004:  Z.Yao     Lazy version implemented
00020 //                          Rename the planner to PL_ATACE.
00021 //     Nov-2004:  Z.Yao     Comments added
00022 //  
00023 //Notes:
00024 //There are serveral things may affect the performance:
00025 //   1. m_stepSize/m_timeInterval: extension step size and sampling time;
00026 //   2. m_localPlanner: local planner, any of trajectory tracking planners;
00027 //   3. m_metrics: which metrics used
00028 //   4. m_useLazy: whether Lazy strategy or not
00029 //   5. "fake.wrl": In current version[Nov-2004], the anticipatory collision detector,
00030 //      which detects collision along the end-effector path, loads "fake.wrl" as 
00031 //      the artificial end-effector. Its size and shape may affect the performance A-LOT.
00032 //
00034 
00035 #include <synchronization/semaphore.h>
00036 #include <assert.h>
00037 #include "math/Vector4.h"
00038 #include "opengl/glos.h"
00039 #include <gl/gl.h>
00040 #include "LocalPlanner.h"
00041 #include "PL_ATACE.h"
00042 #include "CollisionDetectors/CD_Vcollide.h"
00043 #include "Universe/universe.h"
00044 #include <opengl/gl_sphere.h>
00045 #include <opengl/gl_group.h>
00046 #include <geometry/vrml_20_reader.h>
00047 #include <serializable/MPK_Dir.h>
00048 
00049 #define NUM_MAX_ITERATION   10
00050 #define LEN_ENDEFF_SIZE     0.5
00051 #define LEN_RESOLUTION      (0.1)
00052 #define LEN_TOL_ERROR       (1e-5)
00053 #define LEN_ERROR_RADIUS    0.005
00054 
00055 #if 1
00056         #include "math\Matrixmxn.h"
00057         #define LogMatrix(a, b, c) 
00058         #define LogVector(a, b, c)
00059         #define LogMessage(a, b)
00060 #endif
00061 //****************************************************************************
00062 //              Construction and Deconstruction Functions
00063 //****************************************************************************
00064 PL_ATACE::PL_ATACE()
00065 {
00066         m_robot = NULL;
00067         m_toolFrame = -1;
00068         m_rootVert = NULL;
00069         m_trajCollisionDetector = NULL;
00070         m_trajUniverse = NULL;
00071 
00072         IsPoseSatified = NULL;
00073         AdjustPoseToSatisfy = NULL;
00074         GetVelocity = NULL;
00075         GetDirectedVelocity = NULL;
00076 
00077         m_isGoalConfSet = m_isGoalPoseSet = false;
00078         m_isStartConfSet = m_isStartPoseSet = false;
00079         
00080         //The following parameters could be set by users
00081         m_useLazy = false;
00082         m_useGoalConf = m_useGoalPose = false;
00083         m_useStartConf = m_useStartPose = false;
00084         m_useOrientation = false;
00085         m_useOrientationAlways = false;
00086         m_drawCSpace = false;
00087         m_metrics = FLAG_P_METRICS;
00088         m_stepSize = 1;                 //This will be changed in SetCollisionDetector()
00089         m_timeInterval = 0.2;   //This will be changed in SetCollisionDetector()
00090         m_nLocalPlanner = LOCAL_JACOBIAN;
00091 
00092         m_localPlanner = new Jacobian_TrajPlanner;//RRT_TrajPlanner;//TrajPlanner;
00093 }
00094 
00095 PL_ATACE::~PL_ATACE()
00096 {
00097         if (m_rootVert != NULL)
00098         {
00099                 ClearTree();
00100         }
00101 
00102         if (m_localPlanner != NULL)
00103         {
00104                 delete m_localPlanner;
00105         }
00106 
00107         DeleteTrajectoryCD();
00108 }
00109 
00110 bool PL_ATACE::Plan()
00111 {
00112         srand( (unsigned)time( NULL ) );
00113         path.Clear();
00114         StartTimer();  // Start the timer
00115 
00116         Node rootNode;
00117         rootNode.pose = m_startPose;
00118         rootNode.conf = GetStartConfig();
00119         CreateTree(rootNode);
00120 
00121         m_goalVert = NULL;
00122         int result = ERR_FAIL;
00123         bool pathFound = false;
00124         int repeatNum = 0;
00125         Vertex fromVert = m_rootVert;
00126         while ((!pathFound) && (result != ERR_TIMEOUT))
00127         {
00128                 //Try to greedily extend from latest node to the goal
00129                 if (fromVert != NULL)
00130                 {
00131                         Pose extendToGoal = GetPoseFromTree(fromVert);
00132                         if (!IsInterfering(extendToGoal, m_goalPose))
00133                         {
00134                                 result = ExtendToGoal(fromVert, m_goalPose, m_goalVert);
00135                         }
00136                         if (m_goalVert != NULL)
00137                         {
00138                                 pathFound = true;
00139                                 break;
00140                         }
00141                 }
00142 
00143                 Node dirNode;
00144                 Node toNode;
00145                 Node fromNode;
00146                 Path localPath;
00147                 EEPath endeffPath;
00148 
00149                 //Pick up a node that is closest to a randomly-chosen landmark duo
00150                 GenerateRandomNode(dirNode);
00151                 fromVert = FindClosestInTree(dirNode);
00152                 fromNode.conf = GetConfigurationFromTree(fromVert);
00153                 fromNode.pose = GetPoseFromTree(fromVert);
00154 
00155                 endeffPath.clear();
00156                 localPath.Clear();
00157                 //Extend the tree in direction of dirNode
00158                 result = ExtendWithConstraint(fromNode, dirNode.pose, toNode, localPath, endeffPath, false);
00159                 if (result == ERR_SUCCESS) 
00160                 {
00161                         fromVert = AddNodeInTree(fromVert, toNode, dirNode.pose, localPath, endeffPath);
00162                 }
00163                 else
00164                 {
00165                         fromVert = NULL;
00166                 }
00167                 endeffPath.clear();
00168                 localPath.Clear();
00169 
00170                 if ( HasTimeLimitExpired() )
00171                 {
00172                         break;
00173                 }
00174         } //End of While(...)
00175 
00176         if (pathFound)
00177         {
00178                 assert(m_goalVert != NULL);
00179                 RetrievePath(m_goalVert);
00180                 return true;
00181         }
00182         
00183         return false;
00184 }
00185 
00186 //------------------------------------------------------------------
00187 //ExtendWithConstraint(...)
00188 //
00189 //This function is used to extend the random tree in a given direction.
00190 //
00191 //Input Parameter:
00192 //      fromNode : (config., pose) of the node from which to extend the tree
00193 //      dirPose  : (config., pose) of the direction
00194 //      greedy   : use greedy extension or not.
00195 //
00196 //Ouput Parameter:
00197 //      toNode   : (config., pose) of the extened node
00198 //      edgeTraj : the end-effector path in physical space
00199 //      edgePath : the path in C-space to track $edgeTraj$
00200 //
00201 //Return Value:
00202 //      ERR_SUCCESS, if success; 
00203 //      ERR_FAIL   , otherwise;
00204 //
00205 //Notes:
00206 //   1. The caller is responsible for connecting the extended node into the radnom tree.
00207 //   2. edgeTraj/edgePath is allocated by the caller. If extension succeeds, 
00208 //      edgeTraj/edgePath will be emptied by the caller, after the node is connected
00209 //      to the tree; if extension fails, then edgeTraj/edgePath return as empty queues.
00210 //
00211 //------------------------------------------------------------------
00212 int PL_ATACE::ExtendWithConstraint(Node &fromNode, Pose &dirPose, Node &toNode, Path &edgePath, EEPath &edgeTraj, bool greedy)
00213 {
00214         Pose startPose = fromNode.pose;
00215 
00216         double pathLen = 0;
00217         bool trajExtracted = true;
00218 
00219         //Extracted a end-effector path as an edge in physical space.
00220         edgeTraj.push_back(startPose);
00221         //Note: m_stepSize>0, extraction ends when pathLen exceeds m_stepSize;
00222         //      m_stepSize<0, extraction ends only when the goal is achieved.
00223         while((m_stepSize<0) || (pathLen < m_stepSize) ) 
00224         {
00225                 Pose toPose;
00226                 GetNextPose(startPose, dirPose, toPose, greedy);
00227                 double dist = Distance(startPose, toPose);
00228                 if (dist < m_timeInterval*(1e-5))
00229                 {
00230                         if (pathLen < 1.e-10)
00231                         {
00232                                 trajExtracted = false;
00233                         }
00234                         break;
00235                 }
00236                 if (!IsInterfering(startPose, toPose))
00237                 {
00238                         pathLen += dist;
00239                         edgeTraj.push_back(toPose);
00240                         startPose = toPose;
00241                 }
00242                 else
00243                 {
00244                         trajExtracted = false;
00245                         break;
00246                 }
00247                 if ( HasTimeLimitExpired() )
00248                 {
00249                         trajExtracted = false;
00250                         break;
00251                 }
00252         } //END OF WHILE
00253 
00254         bool pathExtracted = true;
00255         if (trajExtracted)
00256         {
00257                 if (m_useLazy)   //using LAZY strategy, trach the path later
00258                 {
00259                         int lastIndex = edgeTraj.size()-1;
00260                         toNode.pose = edgeTraj[lastIndex];
00261                 }
00262                 else //Not using LAZY strategy, have to track the E.E. path right away.
00263                 {
00264                         m_localPlanner->SetStartConfig(fromNode.conf);
00265                         m_localPlanner->SetTrajectory(edgeTraj);
00266                         m_localPlanner->SetUsingOrientation((greedy && m_useOrientation) || (m_useOrientation && m_useOrientationAlways));
00267                         m_localPlanner->SetUseGoalConfig(false);
00268                         if (m_useGoalConf && greedy)
00269                         {
00270                                 m_localPlanner->SetGoalConfig(GetGoalConfig());
00271                                 m_localPlanner->SetUseGoalConfig(true);
00272                         }
00273                         if (m_localPlanner->Plan())
00274                         {
00275                                 PA_Points *localPath;
00276                                 localPath = (PA_Points *)m_localPlanner->GetPath();
00277                                 AppendPath(edgePath, localPath);
00278                                 int lastIndex = edgePath.Size() - 1;
00279                                 toNode.conf = edgePath.GetPoint(lastIndex);
00280                                 toNode.pose = GetToolFrame(toNode.conf);
00281                         }
00282                         else
00283                         {
00284                                 pathExtracted = false;
00285                 //if (greedy)
00286                 {
00287                     Matrixmxn logMatrix;
00288                     int lastIndex = edgeTraj.size()-1;
00289                     logMatrix = edgeTraj[0];
00290                     char szMessage[100];
00291                     sprintf(szMessage, "The length of the path: %d", lastIndex+1);
00292                     LogMessage("greedy.log", szMessage);
00293                     LogMatrix("greedy.log", logMatrix, "First");
00294                     logMatrix = edgeTraj[1];
00295                     LogMatrix("greedy.log", logMatrix, "Second");
00296                     logMatrix = edgeTraj[lastIndex-1];
00297                     LogMatrix("greedy.log", logMatrix, "Second Last");
00298                     logMatrix = edgeTraj[lastIndex];
00299                     LogMatrix("greedy.log", logMatrix, "Last");
00300                 }
00301                         }
00302                 }
00303         }
00304 
00305         if ((trajExtracted == false) || (pathExtracted == false))
00306         {
00307                 return ERR_FAIL;
00308         }
00309 
00310         return ERR_SUCCESS;
00311 }
00312 
00313 //------------------------------------------------------------------
00314 //LazyTrackEEPath
00315 //
00316 //This function is used to track an entire end-effector path in the physical space.
00317 //
00318 //Input Parameter: N/A.
00319 //Ouput Parameter: N/A.
00320 //
00321 //Return Value:
00322 //      ERR_SUCCESS, if success; 
00323 //      ERR_FAIL   , otherwise;
00324 //
00325 //Notes:
00326 //   1. The caller is responsible for connecting the extended node into the radnom tree.
00327 //   2. edgeTraj/edgePath is allocated by the caller. If extension succeeds, 
00328 //      edgeTraj/edgePath will be emptied by the caller, after the node is connected
00329 //      to the tree; if extension fails, then edgeTraj/edgePath return as empty queues.
00330 //   3. The prerequisite of calling this function is (m_goalVert!=NULL), which means
00331 //      a candidate end-effector path joint the start and the goal has been found.
00332 //
00333 //------------------------------------------------------------------
00334 int PL_ATACE::LazyTrackEEPath()
00335 {
00336         assert( m_goalVert!= NULL);
00337         bool pathExtracted = true;
00338         bool greedy = false;
00339         int failureIndex = 0;
00340         std::vector<vertex> trajectory;
00341         Vertex currVert = m_goalVert;
00342         //The following while-loop extract the end-effector path into a queue:
00343         //      starting from the goal-pose, ending at the strat-pose
00344         while (currVert != NULL)
00345         {
00346                 trajectory.push_back(currVert);
00347                 currVert = m_trajTree.parent(currVert);
00348         }//end of while
00349 
00350         int nNumOfVert = trajectory.size();
00351         for (int i=nNumOfVert-1; i>=1; i--)
00352         {
00353                 Vertex trackingVert = trajectory[i-1];
00354                 Vertex parent = trajectory[i];
00355 
00356                 VertexInfo *info;
00357                 info = (VertexInfo *)m_trajTree.vertex_inf(trackingVert);
00358 
00359                 if (info->collisionChecked)
00360                         continue;
00361 
00362                 if  (i==1)   //Deal with the last one, greedy to the goal
00363                         greedy = true;
00364 
00365                 Configuration conf = GetConfigurationFromTree(parent);
00366                 m_localPlanner->SetStartConfig(conf);
00367                 m_localPlanner->SetTrajectory(info->eeEdge);
00368                 m_localPlanner->SetUsingOrientation((greedy && m_useOrientation) || (m_useOrientation && m_useOrientationAlways));
00369                 m_localPlanner->SetUseGoalConfig(false);
00370 
00371                 if (m_useGoalConf && greedy)
00372                 {
00373                         m_localPlanner->SetGoalConfig(GetGoalConfig());
00374                         m_localPlanner->SetUseGoalConfig(true);
00375                 }
00376 
00377                 if (m_localPlanner->Plan())
00378                 {
00379                         PA_Points *localPath;
00380                         localPath = (PA_Points *)m_localPlanner->GetPath();
00381                         int lastIndex = localPath->Size() - 1;
00382                         info->conf = localPath->GetPoint(lastIndex);
00383 
00384                         if ( m_useGoalConf && greedy )
00385                         {
00386                                 Configuration goalConf = GetGoalConfig();
00387                                 if ( collisionDetector->IsInterferingLinear(info->conf, goalConf) == false )
00388                                 {
00389                                         pathExtracted = false;
00390                                         failureIndex = i;
00391                                         break;
00392                                 }
00393                                 else
00394                                 {
00395                                         InterpolatePath(*localPath, info->conf, goalConf);
00396                                 }
00397                         }
00398 
00399                         info->edge.Clear();
00400                         AppendPath(info->edge, localPath);
00401                         info->pose = GetToolFrame(info->conf);   //Maybe I should check whether this configuration get to the right pose
00402                         info->collisionChecked = true;
00403                         //lastIndex = edgeTraj.size()-1;
00404                         //toNode.pose = edgeTraj[lastIndex];
00405                 }
00406                 else
00407                 {
00408                         pathExtracted = false;
00409                         failureIndex = i;
00410                         break;
00411                 }
00412         }
00413 
00414         if (pathExtracted==false)
00415         {
00416                 TrimTreeFrom( trajectory[failureIndex-1] );
00417                 m_goalVert = NULL;
00418                 return ERR_FAIL;
00419         }
00420 
00421         return ERR_SUCCESS;
00422 }
00423 
00424 //------------------------------------------------------------------
00425 //ExtendToGoal
00426 //
00427 //This function is used to track an entire end-effector path in the physical space.
00428 //
00429 //Input Parameter:
00430 //      fromVert: The newly-extended node in the random tree
00431 //      dirPose : The expected extending direction
00432 // 
00433 //Ouput Parameter:
00434 //      endVert : A new node will be added into the tree, endVert is the pointer
00435 //
00436 //Return Value:
00437 //      ERR_SUCCESS, if success; 
00438 //      ERR_FAIL   , otherwise;
00439 //
00440 //Notes:
00441 //   1. In this function, ExtendWithConstraint() will be called with $greedy$ strategy, 
00442 //      which means the extension ends only after getting to the $dirPose$. 
00443 //   2. It also deals with both CONFIG-TO-POSE and CONFIG-TO-CONFIG problem.
00444 //   3. CONFIG-TO-CONFIG problem: in this type of problem, we simple treat it as
00445 //      a CONFIG-TO-POSE problem. Only when the last step, ExtendToGoal, we bring
00446 //      the goal configuration into consideration.
00447 //      a. With constraints. It needs to be done by the local planner.
00448 //      b. Without constraints. It can be handled by a simple linear configurations connection. 
00449 //      -. In current implmentation [Nov-12-2004], we simply ignore the (a) part, due to the 
00450 //         limitation of our current local planners. So basicaly, we just deal with the basic
00451 //         motion planning problem in (b) part.
00452 //
00453 //------------------------------------------------------------------
00454 int PL_ATACE::ExtendToGoal(Vertex &fromVert, Pose &dirPose, Vertex &endVert)
00455 {
00456         Vertex currVert;
00457         Node currNode;
00458 
00459         endVert = NULL;
00460         currVert = fromVert;
00461         currNode.pose = GetPoseFromTree(fromVert);
00462         currNode.conf = GetConfigurationFromTree(fromVert);
00463 
00464         Node toNode;
00465         Path localPath;
00466         EEPath endeffPath;
00467         double oldStepSize;
00468         int result = ERR_SUCCESS;
00469 
00470         oldStepSize = m_stepSize;
00471         m_stepSize = -1.0; //Trigger the greedy extension at ExtendWithConstraint()
00472 
00473         localPath.Clear();
00474         result = ExtendWithConstraint(currNode, dirPose, toNode, localPath, endeffPath, true);
00475         if ( (result == ERR_SUCCESS ) && (m_useGoalConf) && (!m_useLazy))
00476         {
00477                 //Deal with the basic motion planning problem
00478                 Configuration goalConf = GetGoalConfig();
00479                 if ( collisionDetector->IsInterferingLinear(currNode.conf, goalConf) == false )
00480                 {
00481                         result = ERR_FAIL;
00482                 }
00483                 else
00484                 {
00485                         InterpolatePath(localPath, toNode.conf, goalConf);
00486                 }
00487         }
00488         if (result == ERR_SUCCESS)
00489         {
00490                 Vertex newVert = AddNodeInTree(currVert, toNode, dirPose, localPath, endeffPath);
00491                 localPath.Clear();
00492                 endeffPath.clear();
00493                 endVert = newVert;
00494         }
00495 
00496         if ((m_useLazy) && (result==ERR_SUCCESS))
00497         {
00498                 result = LazyTrackEEPath();
00499         }
00500 
00501         m_stepSize = oldStepSize;
00502 
00503         return result;
00504 }
00505 
00506 //****************************************************************************
00507 //              Functions for metrics
00508 //****************************************************************************
00509 //Using physical-space metric.
00510 double PL_ATACE::Distance(const Pose &pos1, const Pose &pos2)
00511 {
00512         Vector4 diff = pos1.GetTranslationVector() - pos2.GetTranslationVector();
00513         double dist = (diff[0]*diff[0])+(diff[1]*diff[1])+(diff[2]*diff[2]);
00514         return sqrt(dist);
00515 }
00516 
00517 //Using C-space metric
00518 double PL_ATACE::Distance(const Configuration &conf1, const Configuration &conf2)
00519 {
00520         double dist = 0;
00521         VectorN jointDiff = collisionDetector->JointDisplacement(conf1, conf2);
00522         for(int i = 0; i < jointDiff.Length(); i++)
00523         {
00524                 dist += (jointDiff[i])*(jointDiff[i]);
00525         }
00526         return sqrt(dist);
00527 }
00528 
00529 //****************************************************************************
00530 //              All functions related to Trajectory Tree
00531 //****************************************************************************
00532 //Create a random tree
00533 bool PL_ATACE::CreateTree(Node &rootNode)
00534 {
00535         if (m_rootVert != NULL)
00536         {
00537                 ClearTree();
00538         }
00539 
00540         VertexInfo *newNode = new VertexInfo;
00541         newNode->flag = FLAG_NEW;
00542         newNode->pose = rootNode.pose;
00543         newNode->conf = rootNode.conf;
00544 
00545         Semaphore semaphore( guid );
00546         semaphore.Lock();
00547         m_rootVert = m_trajTree.make(newNode);
00548         m_vertices.push_back(m_rootVert);
00549         semaphore.Unlock();
00550 
00551         return true;
00552 }
00553 
00554 //Destroy a random tree
00555 void PL_ATACE::ClearTree()
00556 {
00557         Semaphore semaphore( guid );
00558         semaphore.Lock();
00559         for (int i=0; i<m_vertices.size(); i++)
00560         {
00561                 VertexInfo *info;
00562                 info = (VertexInfo *)m_trajTree.vertex_inf(m_vertices[i]);
00563                 if (info->flag != FLAG_OBSOLETE)
00564                 {
00565                         info->edge.Clear();
00566                         info->eeEdge.clear();
00567                 }
00568                 delete info;
00569         }
00570 
00571         m_trajTree.clear();
00572         m_vertices.clear();
00573         m_rootVert = NULL;
00574         semaphore.Unlock();
00575 }
00576 
00577 //------------------------------------------------------------------
00578 //TrimTreeFrom
00579 //
00580 //This function is used to delete a whole branch of the random tree.
00581 //
00582 //Input Parameter:
00583 //      failVert: The branch to be deleted
00584 // 
00585 //Ouput Parameter: 
00586 //      N/A.
00587 //
00588 //Return Value:
00589 //      N/A.
00590 //
00591 //Notes: 
00592 //This function will be used in Lazy mode of APACE. We explore the end-effector paths
00593 //first in the task space and save it as edges in the tree. When we fail to track some of
00594 //the edge, we need to delete the entire tree branch after this point. For example, 
00595 //after exploratin in the task space, we get the following tree:
00596 //        ---N1---N2---N3---N4
00597 //                |     |
00598 //                N6   N5
00599 //                      |
00600 //                     N7
00601 //when we fail to track edge(N1,N2), then the branch after N1 should be deleted.
00602 //This can be done by calling TrimTreeFrom($N2$)
00603 //
00604 //We use LEDA dynamic_tree to store our random tree, It would be expensive to physically 
00605 //delete the nodes/vertices. So what we did is to delete the corresponding edges and disable the node.
00606 // 
00607 //------------------------------------------------------------------
00608 void PL_ATACE::TrimTreeFrom(Vertex failVert)
00609 {
00610         assert(failVert != NULL);
00611 
00612         Semaphore semaphore( guid );
00613         semaphore.Lock();
00614         Vertex currVert = m_goalVert;
00615 
00616         std::vector<Vertex> deletingVert;
00617         deletingVert.push_back(failVert);
00618 
00619         int testStartFrom = 0;
00620         int currentSize;
00621         bool bFound = true;
00622         while (bFound == true)
00623         {
00624                 bFound = false;
00625                 currentSize = deletingVert.size();
00626                 for (int i=0; i<m_vertices.size(); i++)
00627                 {
00628                         Vertex testingVert = m_vertices[i];
00629                         Vertex testingParent = m_trajTree.parent(testingVert);
00630 
00631                         for (int j=testStartFrom; j<currentSize; j++)
00632                         {
00633                                 if (testingParent == deletingVert[j])
00634                                 {
00635                                         deletingVert.push_back(testingVert);
00636                                         bFound = true;
00637                                 }
00638                         }
00639                 }
00640                 testStartFrom = currentSize;
00641         }
00642         //After the above while-loop, taking the example above, TrimTreeFrom(N2).
00643         //the sequence in $deletingVert$ will be: N2-N3-N6-N4-N5-N7
00644         //Maybe this is not the best way to delete a branch, aparently,
00645         //in the worst scenario, it cost $O(n^2)$, but this is the best I can come up with
00646         //using the LEDA data structure: dynamic_tree.
00647         //
00648         //Then, in the following for-loop, $deleteingVert$ will be traversed backwords,
00649         //and deleted one after another.
00650 
00651         currentSize = deletingVert.size()-1;
00652         for (int i=currentSize; i>=0; i--)
00653         {
00654                 currVert = deletingVert[i];
00655                 VertexInfo *info;
00656                 info = (VertexInfo *)m_trajTree.vertex_inf(currVert);
00657                 info->edge.Clear();
00658                 info->eeEdge.clear();
00659                 //delete info;
00660                 info->flag = FLAG_OBSOLETE;  //All vertices is store in a std:vector<vertex>, 
00661                                              //It could be expensive to delete a node in the middle,
00662                                              //So what I did is to disable the node by setting this flag.
00663                 m_trajTree.cut(currVert);
00664         }//end of for
00665         semaphore.Unlock();
00666 }
00667 
00668 
00669 Vertex PL_ATACE::AddNodeInTree(Vertex parentVertex, Node &childNode, Pose &dirPose, Path &localPath, EEPath &endeffPath)
00670 {
00671         VertexInfo *newNode = new VertexInfo;
00672         newNode->flag = FLAG_NEW;
00673         newNode->pose = childNode.pose;
00674         newNode->conf = childNode.conf;
00675         newNode->dirPose = dirPose;
00676         if (m_useLazy)
00677         {
00678                 newNode->collisionChecked = false;
00679                 CopyEEPath(newNode->eeEdge, endeffPath);
00680         }
00681         else
00682         {
00683                 newNode->collisionChecked = true;
00684                 CopyPath(newNode->edge, localPath);
00685         }
00686 
00687         Semaphore semaphore( guid );
00688         semaphore.Lock();
00689         vertex newVert = m_trajTree.make(newNode);
00690         m_vertices.push_back(newVert);
00691         m_trajTree.link(newVert, parentVertex, 1);
00692         semaphore.Unlock();
00693 
00694         return newVert;
00695 }
00696 
00697 Vertex PL_ATACE::FindClosestInTree(Pose &pose)
00698 {
00699         if (m_vertices.size() == 0)
00700                 return NULL;
00701 
00702         VertexInfo *info;
00703         double minDist, currDist;
00704         int minIndex=0;
00705 
00706         info = (VertexInfo *)m_trajTree.vertex_inf(m_vertices[0]);
00707         minDist = Distance(info->pose, pose);
00708         minIndex = 0;
00709 
00710         for (int i=1; i<m_vertices.size(); i++)
00711         {
00712                 info = (VertexInfo *)m_trajTree.vertex_inf(m_vertices[i]);
00713                 if (info->flag == FLAG_OBSOLETE)
00714                         continue;
00715                 currDist = Distance(info->pose, pose);
00716                 if (currDist < minDist)
00717                 {
00718                         minDist = currDist;
00719                         minIndex = i;
00720                 }
00721         }
00722 
00723         return m_vertices[minIndex];
00724 }
00725 
00726 Vertex PL_ATACE::FindClosestInTree(Configuration &conf)
00727 {
00728         if (m_vertices.size() == 0)
00729                 return NULL;
00730 
00731         VertexInfo *info;
00732         double minDist, currDist;
00733         int minIndex=0;
00734 
00735         info = (VertexInfo *)m_trajTree.vertex_inf(m_vertices[0]);
00736         minDist = Distance(info->conf, conf);
00737         minIndex = 0;
00738 
00739         for (int i=1; i<m_vertices.size(); i++)
00740         {
00741                 info = (VertexInfo *)m_trajTree.vertex_inf(m_vertices[i]);
00742                 if (info->flag == FLAG_OBSOLETE)
00743                         continue;
00744                 currDist = Distance(info->conf, conf);
00745                 if (currDist < minDist)
00746                 {
00747                         minDist = currDist;
00748                         minIndex = i;
00749                 }
00750         }
00751 
00752         return m_vertices[minIndex];
00753 }
00754 
00755 Vertex PL_ATACE::FindClosestInTree(Node node)
00756 {
00757         if (m_metrics == FLAG_C_METRICS)
00758                 return FindClosestInTree(node.conf);
00759         else if (m_metrics == FLAG_P_METRICS)
00760                 return FindClosestInTree(node.pose);
00761         else
00762         {
00763                 if (rand() % 2)
00764                         return FindClosestInTree(node.conf);
00765                 else
00766                         return FindClosestInTree(node.pose);
00767         }
00768 }
00769 
00770 Configuration& PL_ATACE::GetConfigurationFromTree(Vertex vert)
00771 {
00772         VertexInfo *info;
00773         info = (VertexInfo *)m_trajTree.vertex_inf(vert);
00774         return info->conf;
00775 }
00776 
00777 Pose& PL_ATACE::GetPoseFromTree(Vertex vert)
00778 {
00779         VertexInfo *info;
00780         info = (VertexInfo *)m_trajTree.vertex_inf(vert);
00781         return info->pose;
00782 }
00783 
00784 Path& PL_ATACE::GetPathFromTree(Vertex vert)
00785 {
00786         VertexInfo *info;
00787         info = (VertexInfo *)m_trajTree.vertex_inf(vert);
00788         return info->edge;
00789 }
00790 
00791 //****************************************************************************
00792 //             Functions about constraints
00793 //****************************************************************************
00794 //------------------------------------------------------------------
00795 //GetNextPose
00796 //
00797 //This function is used to get next pose when extracting an end-effector path.
00798 //
00799 //Input Parameter:
00800 //      prePose : Current end-effector pose.
00801 //      dirPose : Stepping direction.
00802 //      greedy  : Using greedy or step with a fixed size.
00803 // 
00804 //Ouput Parameter: 
00805 //      postPose: The very next end-effector pose.
00806 //
00807 //Return Value:
00808 //      N/A.
00809 //
00810 //Notes: 
00811 //   1. Some call-back functions set by users will be called here, including
00812 //      - IsPoseSatified(...)
00813 //      - AdjustPoseToSatisfy(...)
00814 //      - GetDirectedVelocity(...)
00815 //   2. GetDirectedVelocity(...) returns the feasible linear and angular velocity
00816 //      according to user constraints. For the comments about parameters of 
00817 //      GetDirectedVelocity() please refer to UI-level, dialog for planner APACE.
00818 //       
00819 //------------------------------------------------------------------
00820 void PL_ATACE::GetNextPose(Pose &prePose, Pose &dirPose, Pose &postPose, bool greedy)
00821 {
00822         VectorN velocity;
00823         Frame projection;
00824 
00825         postPose = prePose;
00826         if ( ! IsPoseSatified(postPose) )
00827         {
00828                 AdjustPoseToSatisfy(postPose);
00829                 //Need to update to position
00830         }
00831 
00832         GetDirectedVelocity(postPose, dirPose, velocity, projection, greedy, m_timeInterval);
00833 
00834         //Translation, Velocity assumed normalized already
00835         Vector4 linearVel;
00836         linearVel[0] = velocity[0];
00837         linearVel[1] = velocity[1];
00838         linearVel[2] = velocity[2];
00839     //Extension won't exceed $projection$
00840         Vector4 offset = linearVel * m_timeInterval;
00841         Vector4 offset2 = projection.GetTranslationVector() - prePose.GetTranslationVector();
00842         if (offset.Magnitude() > offset2.Magnitude())
00843                 offset = offset2;
00844         postPose.Translate(offset);
00845 
00846         //Roatation, only apply when using orientation
00847         //Rotate, this is the cases where you need to consider the orientation
00848         //Please note that although linear velocity returned by GetDirectedVelocity()
00849         //  has been normalized, angular velocity hasn't. In another world, the returned 
00850         //  angular velocity has information about axis and the total rotating angle.
00851         //  We need to compute how much angle we need to roate within $m_timeInterval$.
00852         if ((m_useOrientation && m_useOrientationAlways) || (greedy && m_useOrientation))
00853         {
00854                 //Get the equivalent axis and rotated angle
00855                 double angle;
00856                 Vector4 angularVel;
00857                 angularVel[0] = velocity[3];
00858                 angularVel[1] = velocity[4];
00859                 angularVel[2] = velocity[5];
00860                 double magnitude = angularVel.Magnitude();
00861                 if ( !IsZero(magnitude) )
00862                 {
00863                         angularVel = angularVel/magnitude;
00864                         //Now angularVel is the equivalent axis of rotation, required to be unitary.
00865                 }
00866                 else
00867                 {
00868                         angularVel[0] = angularVel[1] = 0;
00869                         angularVel[2] = 1;
00870                 }
00871                 angle = magnitude*m_timeInterval;
00872 
00873                 //double distance, ratio;
00874                 //distance = Distance(prePose, dirPose);
00875                 //if ( IsZero(distance) )
00876                 //{
00877                 //      ratio = 0;
00878                 //}
00879                 //else
00880                 //{
00881                 //      ratio = Distance(prePose, postPose)/distance;
00882                 //}
00883                 //angle = angle * ratio;
00884 
00885                 Frame rotated;
00886                 rotated.Rotate2(angularVel, Rad2Deg(angle));
00887 
00888                 offset = postPose.GetTranslationVector();
00889                 postPose = rotated * postPose;
00890                 postPose.SetTranslationVector(offset);
00891         //Matrixmxn logMatrix=postPose;
00892         //LogMatrix("adjust.log", logMatrix, "Next Pose:");
00893         }
00894 }
00895 
00896 void PL_ATACE::SetPoseChecker(ProcIsStaified proc)
00897 {
00898         IsPoseSatified = proc;
00899 }
00900 
00901 void PL_ATACE::SetPoseAdjuster(ProcAdjustToSatisfy proc)
00902 {
00903         AdjustPoseToSatisfy = proc;
00904 }
00905 
00906 void PL_ATACE::SetVelocityChecker(ProcGetVelocity proc)
00907 {
00908         GetVelocity = proc;
00909 }
00910 
00911 void PL_ATACE::SetDirectedVelocityChecker(ProcGetDirectedVelocity proc)
00912 {
00913         GetDirectedVelocity = proc;
00914 }
00915 
00916 //****************************************************************************
00917 //             Collision Detection
00918 //****************************************************************************
00919 //------------------------------------------------------------------
00920 //CreateTrajectoryCD
00921 //
00922 //This function is used to create anticipatory collision detector in APACE.
00923 //
00924 //Input Parameter:
00925 //      collisionDetector: default collisionDetector.
00926 // 
00927 //Ouput Parameter: 
00928 //      N/A.
00929 //
00930 //Return Value:
00931 //      N/A.
00932 //
00933 //Note:
00934 //      An anticipatory collision detector will be created by
00935 //      using current obstacle and replacing the robot manipulator
00936 //      with a rigid body, "fake.wrl".
00937 //
00938 //------------------------------------------------------------------
00939 void PL_ATACE::CreateTrajectoryCD(CD_BasicStyle* collisionDetector)
00940 {
00941         m_trajUniverse = new Universe;
00942         std::vector<Entity *> entities = collisionDetector->GetAllElements();
00943 
00944         //Add all obstacles into the virtual universe.
00945         for( int i = 0; i < entities.size(); i++ )
00946         {
00947                 Entity* addme = entities[ i ];
00948                 if( dynamic_cast<RobotBase*>( addme ))
00949                 {
00950                         continue;
00951                 }
00952                 if (addme->BaseFrame() == 0)
00953                 {
00954                         m_trajUniverse->AddEntity(addme);
00955                 }
00956         }
00957 
00958         //Note::::
00959         //    The geomtry of "fake.wrl", especially its size, may significant affect the performance,
00960         //Improvement expected:
00961         //    To adaptively load different rigid body for different application,
00962         //       it's better to create this body dynamically, using "GL_Mesh" or things like that....
00963         VRML_20_Reader reader;
00964         const char *workingPath = GetMPKWorkingDirectory();
00965         reader.SetRootPath(workingPath);
00966         reader.SetFilename( "vrml models\\fake.wrl" );
00967         reader.Read();
00968         const ObjectBase* theObject = reader.GetTheObject();
00969         assert( theObject != NULL );
00970         if( theObject != NULL )
00971         {
00972                 ObjectBase* fakeEnd = dynamic_cast< ObjectBase* >( theObject->Clone() );
00973                 assert( fakeEnd != NULL );
00974                 fakeEnd->SetBaseFrame( 1 );
00975                 m_trajUniverse->AddEntity( fakeEnd );
00976                 delete fakeEnd;
00977         }
00978 
00979         if( dynamic_cast<CD_Vcollide*>(collisionDetector) )
00980         {
00981                 CD_Vcollide *detector = new CD_Vcollide(*m_trajUniverse);
00982                 detector->PermActivateFrames(1, 0);
00983                 detector->ActivateFrames(1, 0);
00984                 m_trajCollisionDetector = detector;
00985         }
00986         else
00987         {
00988                 assert(false);
00989         }
00990 }
00991 
00992 void PL_ATACE::DeleteTrajectoryCD()
00993 {
00994         if (m_trajCollisionDetector)
00995                 delete m_trajCollisionDetector;
00996         if (m_trajUniverse)
00997                 delete m_trajUniverse;
00998 }
00999 
01000 //------------------------------------------------------------------
01001 //IsInterfering
01002 //
01003 //This function is used to check collision between two end-effector poses.
01004 //
01005 //Input Parameter:
01006 //      pose1, pose2: Two end-effector poses.
01007 // 
01008 //Ouput Parameter: 
01009 //      N/A.
01010 //
01011 //Return Value:
01012 //      TRUE,  colliding in between.
01013 //      FALSE, collision free along the path.
01014 //
01015 //------------------------------------------------------------------
01016 bool PL_ATACE::IsInterfering (const Pose& pose1, const Pose &pose2)
01017 {
01018         double length = Distance(pose1, pose2);
01019         int sampleNum = (int)(length/LEN_RESOLUTION) + 1;
01020         Vector4 pos1 = pose1.GetTranslationVector();
01021         Vector4 pos2 = pose2.GetTranslationVector();
01022         for (int i=0; i<sampleNum; i++)
01023         {
01024                 Pose tran;
01025                 Vector4 pos;
01026                 pos = pos1*(double(sampleNum-i)/double(sampleNum)) + pos2*(double(i)/double(sampleNum));
01027                 tran.SetTranslationVector(pos);
01028                 if (((CD_Vcollide *)m_trajCollisionDetector)->IsInterfering(tran))
01029                         return true;
01030         }
01031         
01032         return false;
01033 }
01034 
01035 //****************************************************************************
01036 //             Function to Get Tool Frame: End-effector Frame.
01037 //****************************************************************************
01038 Frame PL_ATACE::GetToolFrame( const Configuration& config ) const
01039 {
01040         Frame toolFrame = Matrix4x4();
01041 
01042         if ( collisionDetector != NULL )
01043         {
01044                 FrameManager* frameManager = collisionDetector->GetFrameManager();
01045                 collisionDetector->SetConfiguration( config );
01046                 //toolFrame = frameManager->GetWorldFrame( m_toolFrame );
01047                 if (m_toolFrame != -1)
01048                         toolFrame = *(frameManager->GetFrameRef(m_toolFrame));
01049                 toolFrame = frameManager->GetTransformRelative(collisionDetector->DOF(), 0) * toolFrame;
01050         }
01051         return toolFrame;
01052 }
01053 
01054 //****************************************************************************
01055 //             Functions to generate random node/configuration.
01056 //****************************************************************************
01057 void PL_ATACE::GenerateRandomNode(Node &randNode)
01058 {
01059         randNode.conf = GenerateRandomConfig();
01060         randNode.pose = GetToolFrame(randNode.conf);
01061 }
01062 
01063 Configuration PL_ATACE::GenerateRandomConfig ()
01064 {
01065         int dof = collisionDetector->DOF() ;
01066 
01067         Configuration returnme ;
01068         returnme.SetLength( dof ) ;
01069 
01070         for( int i = 0; i < dof; i++ )
01071         {
01072                 double max = collisionDetector->JointMax( i ) ;
01073                 double min = collisionDetector->JointMin( i ) ;
01074                 double random = 2*( double( rand() ) / RAND_MAX ) - 1; //this is a random number between [-1..1]
01075                 double jointvalue = ( max - min ) * random;
01076 
01077                 // Create a uniform distribution by having the random number go over the limits have wrapping the C-space;
01078                 if ( jointvalue < min )
01079                 {
01080                         jointvalue += (max - min);
01081                 }
01082                 else if ( jointvalue > max )
01083                 {
01084                         jointvalue -= (max - min);
01085                 }
01086 
01087                 returnme[ i ] = jointvalue;
01088         }
01089 
01090         return returnme ;
01091 }
01092 
01093 //****************************************************************************
01094 //             Operation on Path in configuration space.
01095 //****************************************************************************
01096 void PL_ATACE::RetrievePath(Vertex &goalVert)
01097 {
01098         Vertex currVert = goalVert;
01099         while (currVert != NULL)
01100         {
01101                 InsertPath(path, GetPathFromTree(currVert));
01102                 currVert = m_trajTree.parent(currVert);
01103         }//end of while
01104 }
01105 
01106 void PL_ATACE::AppendPath(Path &collect, Path &local)
01107 {
01108         for (int i=0; i<local.Size(); i++)
01109         {
01110                 collect.AppendPoint(local[i]);
01111         }
01112 }
01113 
01114 void PL_ATACE::AppendPath(Path &collect, PA_Points *local)
01115 {
01116         for (int i=0; i<local->Size(); i++)
01117         {
01118                 collect.AppendPoint(local->GetPoint(i));
01119         }
01120 }
01121 
01122 void PL_ATACE::CopyPath(Path &target, Path &source)
01123 {
01124         target = source;
01125 }
01126 
01127 void PL_ATACE::CopyEEPath(EEPath &target, EEPath &source)
01128 {
01129         int nLen = source.size();
01130         if ( target.size() != 0 )
01131         {
01132                 target.clear();
01133         }
01134         for( int i = 0; i < nLen; i++ )
01135         {
01136                 target.push_back( source[ i ] ) ;
01137         }
01138 }
01139 
01140 void PL_ATACE::InsertPath(Path &target, Path &source)
01141 {
01142         int nLen = source.Size()-1;
01143         if ( target.Size() != 0 )
01144         {
01145                 nLen = nLen - 1;
01146         }
01147         for( int i = nLen; i >= 0; i-- )
01148         {
01149                 target.AppendPointToBeginning( source[ i ] ) ;
01150         }
01151 }
01152 
01153 //------------------------------------------------------------------
01154 //InterpolatePath
01155 //
01156 //This function is used to interpolate a path between two configuration.
01157 //
01158 //Input Parameter:
01159 //      start, end: Two configurations.
01160 // 
01161 //Ouput Parameter: 
01162 //      target: The interpolated path.
01163 //
01164 //Return Value:
01165 //      N/A.
01166 //
01167 //Note:
01168 //      The reason we need this function is to improve the visual effect.
01169 //      By tracking the end-effector path which is normally sampled into a 
01170 //      a sequence of poses, the joint path we get normally is a sequence of 
01171 //      configurations and consecutive configurations are pretty close. However,
01172 //      for the basic motion planning problem, we do the last step to goal configuration
01173 //      by simply connecting to the goal with a linear connection. To make the 
01174 //      path has smoothier replay in UI, we also sample this linear connection.
01175 //      This is what we do in InterpolatePath().
01176 //
01177 //------------------------------------------------------------------
01178 void PL_ATACE::InterpolatePath(Path &target, Configuration &start, Configuration &end)
01179 {
01180         double dDist = Distance(start, end);
01181         dDist = Deg2Rad(dDist);
01182         int nSample = dDist/m_timeInterval + 1;
01183         for (int i = 0; i<=nSample; i++)
01184         {
01185                 Configuration conf = end * ((double)i/nSample) + start * ((double)(nSample-i)/nSample);
01186                 target.AppendPoint(conf);
01187         }
01188 }
01189 
01190 //****************************************************************************
01191 //              Parameter Setting Functions
01192 //****************************************************************************
01193 
01194 void PL_ATACE::SetCollisionDetector (CD_BasicStyle* collisionDetector)
01195 {
01196         PL_Boolean_Output::SetCollisionDetector(collisionDetector);
01197         m_localPlanner->SetCollisionDetector(collisionDetector);
01198 
01199         if( this->collisionDetector != NULL )
01200         {
01201                 //Get the Robot information from CD.
01202                 if( dynamic_cast<R_OpenChain*>(collisionDetector->GetRobot(0))
01203                   )
01204                 {
01205                         m_robot = (R_OpenChain *)collisionDetector->GetRobot(0);
01206                         m_toolFrame = m_robot->GetToolFrame(0);
01207                 }
01208                 else
01209                 {
01210                         m_robot = NULL;
01211                         m_toolFrame = 0;
01212                 }
01213 
01214                 //Create virtual CD for trajectory.
01215                 DeleteTrajectoryCD();
01216                 CreateTrajectoryCD(collisionDetector);
01217         }
01218 
01219         //Compute m_stepSize/m_timeInterval adaptively:
01220         m_stepSize = 0;
01221         for (int i=0; i<m_robot->DOF(); i++)
01222         {
01223                 DH_Link *currLink = (DH_Link *)m_robot->GetLink(i);
01224                 Vector4 endPos = currLink->GetFrame().GetTranslationVector();
01225                 m_stepSize += endPos.Magnitude(); 
01226         }
01227         m_stepSize = (double)((int)(m_stepSize/10));
01228         m_timeInterval = m_stepSize/10;
01229 }
01230 
01231 void PL_ATACE::SetLocalPlanner(int localPlanner)
01232 {
01233         if (m_nLocalPlanner != localPlanner)
01234         {
01235                 if (m_localPlanner)
01236                         delete m_localPlanner;
01237 
01238                 if (localPlanner == LOCAL_RRT)
01239                         m_localPlanner = new RRT_TrajPlanner;
01240                 else
01241                         m_localPlanner = new Jacobian_TrajPlanner;
01242 
01243                 m_nLocalPlanner = localPlanner;
01244                 m_localPlanner->SetCollisionDetector(this->collisionDetector);
01245         }
01246 }
01247 
01248 void PL_ATACE::SetStartConfig( const Configuration& config )
01249 {
01250         PL_Boolean_Output::SetStartConfig( config );
01251         if (this->m_useStartConf)
01252         {
01253                 m_isStartConfSet = true;
01254         }
01255 }
01256 
01257 void PL_ATACE::SetGoalConfig ( const Configuration& config )
01258 {
01259         PL_Boolean_Output::SetGoalConfig( config );
01260         if (this->m_useGoalConf)
01261         {
01262                 m_isGoalConfSet = true;
01263                 m_goalPose = GetToolFrame( config );
01264         }
01265 }
01266 
01267 void PL_ATACE::SetStartPose(const Pose &start)
01268 {
01269         m_startPose = start;
01270         m_isStartPoseSet = true;
01271 }
01272 
01273 void PL_ATACE::SetGoalPose(const Pose &goal)
01274 {
01275         m_goalPose = goal;
01276         m_isGoalPoseSet = true;
01277 }
01278 
01279 //------------------------------------------------------------------
01280 //SetProblemType
01281 //
01282 //This function is used to set a planning task.
01283 //
01284 //Input Parameter:
01285 //      type: problem type.
01286 // 
01287 //Ouput Parameter: 
01288 //      N/A.
01289 //
01290 //Return Value:
01291 //      true/false.
01292 //
01293 //Note:
01294 //      It might be confusing setting a task. Setting a task includes:
01295 //      - Set the type of problem: 
01296 //          CONFIG-TO-CONFIG/CONFIG-TO-POSE/POSE-TO-CONFIG/POSE-TO-POSE;
01297 //         Actually, current version[Nov-12-2004] don't support the last two types.
01298 //      - Set the start: Set start configuration/pose
01299 //      - Set the goal: Set goal configuration/pose
01300 //
01301 //------------------------------------------------------------------
01302 void PL_ATACE::SetProblemType(unsigned int type)
01303 {
01304         m_useGoalPose = ((type & TYPE_GOAL_POSE)!=0);
01305         m_useGoalConf = ((type & TYPE_GOAL_CONF)!=0);
01306         m_useStartPose = ((type & TYPE_START_POSE)!=0);
01307         m_useStartConf = ((type & TYPE_START_CONF)!=0);
01308         
01309         assert(m_useStartConf==true);
01310 }
01311 
01312 //------------------------------------------------------------------
01313 //IsReady
01314 //
01315 //This function is used to check whether a planning task is properly set.
01316 //
01317 //Input Parameter:
01318 //      N/A.
01319 // 
01320 //Ouput Parameter: 
01321 //      N/A.
01322 //
01323 //Return Value:
01324 //      true/false.
01325 //
01326 //Note:
01327 //      Start/Goal should be set and match the type of the problem.
01328 //
01329 //------------------------------------------------------------------
01330 bool PL_ATACE::IsReady()
01331 {
01332         if (IsPoseSatified == NULL)
01333                 return false;
01334         if (AdjustPoseToSatisfy == NULL)
01335                 return false;
01336         if (GetVelocity == NULL)
01337                 return false;
01338         if (GetDirectedVelocity == NULL)
01339                 return false;   
01340         if (m_localPlanner == NULL)
01341                 return false;
01342         if ((m_isStartConfSet == false) && (m_isStartPoseSet == false))
01343                 return false;
01344         if ((m_isGoalConfSet == false) && (m_isGoalPoseSet == false))
01345                 return false;
01346 
01347         if ((m_useStartConf == false) && (m_useStartPose == false))
01348                 return false;
01349         if ((m_useGoalConf == false) && (m_useGoalPose == false))
01350                 return false;
01351 
01352         if ((m_useStartConf == true) && (m_isStartConfSet == false))
01353                 return false;
01354         if ((m_useGoalConf == true) && (m_isGoalConfSet == false))
01355                 return false;
01356         if ((m_useStartPose == true) && (m_isStartPoseSet == false))
01357                 return false;
01358         if ((m_useGoalPose == true) && (m_isGoalPoseSet == false))
01359                 return false;
01360 
01361         return true;
01362 }
01363 
01364 //****************************************************************************
01365 //              Draw the tree
01366 //****************************************************************************
01367 bool PL_ATACE::DrawExplicit () const
01368 {
01369         double Xcor, Ycor, Zcor;        // temp coordinate variables
01370 
01371         Semaphore semaphore( guid );
01372         semaphore.Lock();
01373 
01374         // Setup GL Environment
01375         glClearColor( 0.0f, 0.0f, 0.2f, 1.0f );
01376         glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
01377         BOOL lightingState = glIsEnabled( GL_LIGHTING );
01378         glDisable( GL_LIGHTING );
01379         glShadeModel( GL_SMOOTH );
01380         glPointSize(5.0f);      // Set size of points associated with the nodes.
01381 
01382         if (m_vertices.size() )
01383         {
01384                 int i;
01385 
01386                 //const dynamic_trees *ptrTree = &tree;
01387                 //Drawing NODEs
01388                 glBegin(GL_POINTS);
01389                 for(i = 0; i<m_vertices.size(); i++)
01390                 {
01391                         Vertex vert;
01392                         VertexInfo *info;
01393                         vert = m_vertices[i];
01394                         info = (VertexInfo *)((dynamic_trees &)m_trajTree).vertex_inf(vert);
01395                         if (info->flag == FLAG_OBSOLETE)
01396                                 continue;
01397 
01398                         if (!m_drawCSpace)
01399                         {
01400                                 Vector4 pos = info->pose.GetTranslationVector();
01401 
01402                                 Xcor = pos[0];
01403                                 Ycor = pos[1];
01404                                 Zcor = pos[2];
01405                         }
01406                         else
01407                         {
01408                                 Configuration conf = info->conf;
01409                                 Xcor = conf[0];
01410                                 Ycor = conf[1];
01411                                 Zcor = conf[2];
01412                         }
01413 
01414                         if ((i==0) || (i==(m_vertices.size()-1)))
01415                                 glColor3f(0.0f,0.0f,1.0f);    //Set the start and end to be blue
01416                         else
01417                                 glColor3f(1.0f,1.0f,0.0f);              // set colour to yellow
01418                         glVertex3f( (float)Xcor, (float)Ycor, (float)Zcor );
01419                 }
01420                 glEnd();
01421 
01422                 //Drawing EDGEs
01423                 glBegin(GL_LINES);
01424                 for(i = 1; i<m_vertices.size(); i++)
01425                 {
01426                         Vertex vert, parentVert;
01427                         VertexInfo *info, *parentInfo;
01428 
01429                         vert = m_vertices[i];
01430                         parentVert = ((dynamic_trees &)m_trajTree).parent(vert);
01431                         if (parentVert==NULL)
01432                                 continue;
01433 
01434                         info = (VertexInfo *)((dynamic_trees &)m_trajTree).vertex_inf(vert);
01435                         parentInfo = (VertexInfo *)((dynamic_trees &)m_trajTree).vertex_inf(parentVert);
01436 
01437                         if (!m_drawCSpace)
01438                         {
01439 
01440                                 Vector4 pos = info->pose.GetTranslationVector();
01441                                 Vector4 parentPos = parentInfo->pose.GetTranslationVector();
01442 
01443                                 Xcor = pos[0];
01444                                 Ycor = pos[1];
01445                                 Zcor = pos[2];
01446                                 glColor3f(1.0f,0.5f,0.0f);      // set colour to orange
01447                                 glVertex3f( (float)Xcor, (float)Ycor, (float)Zcor );    // add source vertex for edge line
01448 
01449                                 Xcor = parentPos[0];
01450                                 Ycor = parentPos[1];
01451                                 Zcor = parentPos[2];
01452                                 glColor3f(1.0f,0.0f,0.0f);      // set colour to red
01453                                 glVertex3f( (float)Xcor, (float)Ycor, (float)Zcor );    // add target vertex for edge line
01454 
01455                         }
01456                         else
01457                         {
01458                                 Configuration conf = info->conf;
01459                                 Configuration parentConf = parentInfo->conf;
01460 
01461                                 Xcor = conf[0];
01462                                 Ycor = conf[1];
01463                                 Zcor = conf[2];
01464                                 glColor3f(1.0f,0.5f,0.0f);      // set colour to orange
01465                                 glVertex3f( (float)Xcor, (float)Ycor, (float)Zcor );    // add source vertex for edge line
01466 
01467                                 Xcor = parentConf[0];
01468                                 Ycor = parentConf[1];
01469                                 Zcor = parentConf[2];
01470                                 glColor3f(1.0f,0.0f,0.0f);      // set colour to red
01471                                 glVertex3f( (float)Xcor, (float)Ycor, (float)Zcor );    // add target vertex for edge line
01472                         }
01473 
01474 
01475                 }
01476                 glEnd();
01477         }
01478 
01479         // Clean up Environment
01480         if( lightingState != FALSE )
01481         {
01482                 glEnable( GL_LIGHTING );
01483         }
01484 
01485         semaphore.Unlock();
01486 
01487         //Sleep( 50 );
01488 
01489         return true;
01490 }
01491 

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