deque<PlanNode>* AStarSearch::search(PlanningMap* planningMap, int startX, int startZ, int goalX, int goalZ)
{
   if (!planningMap->pointInMap(startX, startZ)) {
      M_ERR("Start %d %d  is not on map!\n",startX, startZ);
      return NULL;
   }
   if (!planningMap->pointInMap(goalX, goalZ)) {
      M_ERR("Goal %d %d  is not on map!\n",goalX, goalZ);
      return NULL;
   }
 
   // Reading parameters from param daemon
   _maxDistance = Params::g_obstacleMaxDist * 1000.0;
   _minDistance = Params::g_obstacleMinDist * 1000.0;
   _skillCellExploration = Params::g_skillExploration;
   if (Params::g_greedyExploration)
      _greedyFactor = DEFAULT_GREEDY_FACTOR;
   else
      _greedyFactor = 0.0;

   if (planningMap->hasVegetation(goalX, goalZ)) {
      M_INFO1("WARNING: Goal Node %d %d has vegetation\n",goalX, goalZ);
   }

   if (!planningMap->isTraversable(goalX, goalZ, _skillCellExploration)) {
      M_ERR("WARNING: Goal Node %d %d is not traversable!\n",goalX, goalZ);
      return NULL;
   }

   const int maxUntraversableSearchDepth = 15;

   AStarNode* goalNode = NULL;

   deleteSearchSpace();

   // Create queue and closed list, only if they do not already exist from former planning calls.
   if(_closedList == NULL)
      _closedList = new set<AStarNode*, AStarNode::PtrLower>();
   if(_priorityQueue == NULL)
      _priorityQueue = new PriorityQueue();

   AStarNode* node = new AStarNode(startX, startZ, 0.0, NULL);
   _priorityQueue->addNode(heuristic(node, goalX, goalZ), node);

   int nExpansions = 0;
   while( goalNode == NULL /*&& (nExpansions < NUM_MAX_EXPANSIONS)*/) {
      if(_priorityQueue->empty()) {
         AStarNode* current = _priorityQueue->popFront();
         goalNode = current;
         if(DEBUG_ASTAR_SMALL)
            printf("AStar: Queue empty: No Path found.\n");
         break;
      }
      AStarNode* current = _priorityQueue->popFront();
      if(goalTest(current, goalX, goalZ)) {
         _closedList->insert(current);
         goalNode = current;
         break;
      }

      if(DEBUG_ASTAR && nExpansions < DEBUG_ASTAR_MAX_NUM) {
         printf("AStar: Closing: %d %d.\n", current->_x, current->_z);
      }

      if(_closedList->find(current) != _closedList->end()) {    // already have a better way to here.
         delete current;
         continue;
      }

      if(DEBUG_ASTAR && nExpansions < DEBUG_ASTAR_MAX_NUM)
         printf("AStar: EXPANDING: %d %d.\n", current->_x, current->_z);

      // close and expand current 
      _closedList->insert(current);
  
      bool currentTraverable = planningMap->isTraversable(current->_x, current->_z, _skillCellExploration);
      nExpansions++;
      for(int i = -1; i <= 1; i++) {
         if( ((current->_x + i) < 0) || ((current->_x + i) >= planningMap->sizeX()) )
            continue;
         for(int j = -1; j <= 1; j++) {
             if( ((current->_z + j) < 0) || ((current->_z + j) >= planningMap->sizeZ()) )
               continue;
            if((i == 0) && (j == 0))   // No need to look at current node
               continue;
             // Do no plan from traversable cells to untraversable cells (but allow planning from untraversable cells)
            if(currentTraverable && (!planningMap->isTraversable(current->_x + i, current->_z + j, _skillCellExploration)))  // traversable -> untraversable
               continue;
            // untraversable -> untraversable, only possible if startNode was untraversable
            if((!currentTraverable) && (!planningMap->isTraversable(current->_x + i, current->_z + j, _skillCellExploration))) {   
               if(current->_depth >= maxUntraversableSearchDepth)    // Do no expand more than maxUntraversableSearchDepth over untraversable nodes -> Forces to plan out of walls
                  continue;
            }

            double dirCost = 1.0;
            if(abs(i) + abs(j) > 1)
               dirCost -= 0.1;

            // Only prefer to plan over explored terrain if close to the robot
            double d1 = hypot(current->_x+i - startX, current->_z+j - startZ) * planningMap->resolution();
            double cellTypeCost = 1.0;

            if (!planningMap->pointInMap(current->_x+1, current->_z+j)) 
               cellTypeCost += 200.0;

            if (d1 < 5000.0 && planningMap->isUnclassified(current->_x+i, current->_z+j))
               cellTypeCost += 0.9;


            double distCost = 5.0 / MIN(5.0, planningMap->getPlanningCells()[current->_x+i][current->_z+j].getDistance()/_maxDistance);
            double cost = current->_cost + (abs(i) + abs(j)) * distCost * dirCost * cellTypeCost;
            //double cost = current->_cost + (abs(i) + abs(j)) * (1 + 10 * planningMap->getPlanningCells()[current->_x + i][current->_z + j].getCost());
            AStarNode* n = new AStarNode(current->_x + i, current->_z + j, cost, current);
            if(_closedList->find(n) != _closedList->end()) {    // Node already closed
               if(DEBUG_ASTAR && nExpansions < DEBUG_ASTAR_MAX_NUM)
                  printf("Already closed: %d %d \n", n->_x, n->_z);
               delete n;
            } else {
               double f = n->_cost + heuristic(n, goalX, goalZ);
               if(DEBUG_ASTAR && nExpansions < DEBUG_ASTAR_MAX_NUM)
                  printf("Adding in queue f(%.2f): %d %d cost:(%.2f)\n", f, n->_x, n->_z, n->_cost);
               _priorityQueue->addNode(f, n);
            }
         }
      }
   }

   /*if(nExpansions >= NUM_MAX_EXPANSIONS) {
      M_WARN("AStar: Max Expansions %d reached.\n", NUM_MAX_EXPANSIONS);
      // Do not generate partial plan here, because the action might still have an older suitable plan.
      // No need to interfere with bad plan here.
   }*/
   if(DEBUG_ASTAR_SMALL)
      printf("nExp: %d\n", nExpansions);
   
   deque<PlanNode>* path = NULL;
   if(goalNode != NULL) {
      path = createPathFromGoal(goalNode, planningMap);
   }

   if(path != NULL) {
      if(DEBUG_ASTAR_SMALL)
         printf("AStar: Path length: %d\n", (int)path->size());
   } else {
      if(DEBUG_ASTAR_SMALL)
         printf("AStar: No path found.\n");
   }

   deleteSearchSpace();

   return path;
}
Example #2
0
Node* AStarGraphSearch::runSearch()
{
    // Declare Variables
    bool  goalFound;
    Node* current;
    Node* start = feeder->getNode(initNodeID);

    g_score[initNodeID] = 0;
    h_score[initNodeID] = heuristic->evaluateHeuristic(start);
    f_score[initNodeID] = g_score[initNodeID] + h_score[initNodeID];

    addNodeToFrontier(start);

    while (numberOfNodesInFrontier > 0)
    {
        current = popFrontier(); /*---- GUI UPDATE ----*/ notifyObservers(current->getNodeID(),NODE_UPDATE);

        goalFound = goalTest(current);
        if (goalFound)
            break;

        addNodeToExploredSet(current);

        int currentID = current->getNodeID();
        std::vector <Edge*> edgeSuccessors;
        feeder->getSuccessors(current,&edgeSuccessors);
        int numberOfSuccessors = edgeSuccessors.size();
        for (int i=0; i<numberOfSuccessors; i++)
        {
            Node* neighbour = edgeSuccessors[i]->getTarget(); /*---- GUI UPDATE ----*/ notifyObservers(edgeSuccessors[i]->getEdgeID(),EDGE_UPDATE);
            if (isNodeInExploredSet(neighbour))
                continue;

            int neighbourID = neighbour->getNodeID();

            int posInOpenSet = isNodeInFrontier(neighbour);
            if (posInOpenSet == -1)
            {
                double g_neighbour   = g_score[currentID] + edgeSuccessors[i]->getCost();
                g_score[neighbourID] = g_neighbour;
                h_score[neighbourID] = heuristic->evaluateHeuristic(neighbour);
                f_score[neighbourID] = g_neighbour + h_score[neighbourID];
                neighbour->setParent(current);
                addNodeToFrontier(neighbour);
            }
            else
            {
                double newPath_g_score = g_score[currentID] + edgeSuccessors[i]->getCost();
                if (newPath_g_score < g_score[neighbourID])
                {
                    //update g,f scores and parent, h score stays the same
                    g_score[neighbourID] = newPath_g_score;
                    f_score[neighbourID] = newPath_g_score + h_score[neighbourID];
                    neighbour->setParent(current);
                    openSet.erase(openSet.begin() + posInOpenSet);
                    numberOfNodesInFrontier--;
                    addNodeToFrontier(neighbour);
                }
            }
        }
    }

    if (goalFound)
        return current;
    else
        return NULL;
}