【问题标题】:A star algorithm with image map (android)一种带有图像映射的星型算法(android)
【发布时间】:2014-09-27 01:13:36
【问题描述】:

我使用算法 a start 来查找带有数组节点的路径。我有这样的图像映射和节点:

红色节点是障碍物,黑色用来寻找路径。我不知道为什么这条路是弯曲的。我使用了这个库https://code.google.com/p/a-star-java/source/browse/AStar/src/aStar/?r=7,我改了函数 registerEdges.:

  private void registerEdges(ArrayList<Node> nodes) 
   {
       float currentDistX = 0;
       float currentDistY = 0;
       float distance = 0;

       for(int l = 0 ; l < nodes.size(); l++)
       {
           MINDISTN = Integer.MIN_VALUE;
           MINDISTS = Integer.MAX_VALUE;
           MINDISTE = Integer.MIN_VALUE;
           MINDISTW = Integer.MAX_VALUE;

           MINDISTNE = Integer.MAX_VALUE;
           MINDISTNW = Integer.MAX_VALUE;
           MINDISTSE = Integer.MAX_VALUE;
           MINDISTSW = Integer.MAX_VALUE;

           Node node = null;
           currentDistX = 0;
           currentDistY = 0;

           //System.out.println("current " + node.x + " " + node.y);
           for(int j = 0 ; j < map.size() ; j++)
           {
               if(l != j)
               {
                   node = map.get(l);


                   currentDistX = map.get(j).x - node.x;
                   currentDistY = map.get(j).y - node.y;

                   if(currentDistX == 0)
                   {
                       if(currentDistY < 0)
                       {
                           if(currentDistY > MINDISTN)
                           {
                               MINDISTN = currentDistY;
                               node.setNorth(map.get(j));
                               //System.out.println(currentDist + " n " + map.get(j).x + " " + map.get(j).y);
                           }
                       }
                       else if(currentDistY > 0)
                       {
                           if(currentDistY < MINDISTS)
                           {
                               //System.out.println(currentDist + " south " + map.get(j).x + " " + map.get(j).y);
                               MINDISTS = currentDistY;
                               node.setSouth(map.get(j));
                           }
                       }      
                   }           

                   if(currentDistY == 0)
                   {
                       if(currentDistX < 0)
                       {

                           if(currentDistX > MINDISTE)
                           {
                               MINDISTE = currentDistX;
                               node.setEast(map.get(j));

                               //System.out.println(currentDist + " e " + map.get(j).x + " " + map.get(j).y);
                           }
                       }
                       else if(currentDistX > 0)
                       {
                           //System.out.print("m " + MINDISTRIGHT);
                           if(currentDistX < MINDISTW)
                           {
                               MINDISTW = currentDistX;
                               node.setWest(map.get(j));
                               //System.out.println(currentDist + " w " + map.get(j).x + " " + map.get(j).y);
                           }
                       }
                   }

                   if(currentDistY != 0 && currentDistX != 0)
                   {

                       if(currentDistX > 0 && currentDistY > 0)
                       {
                           distance = node.calculateDistanceBetweenNods(map.get(j));

                           if(distance < MINDISTNE)
                           {
                               MINDISTNE = distance;
                               node.setNorthEast(map.get(j));

                               //System.out.println(currentDist + " e " + map.get(j).x + " " + map.get(j).y);
                           }
                       }
                       else if(currentDistX < 0 && currentDistY > 0)
                       {

                           distance = node.calculateDistanceBetweenNods(map.get(j));

                           if(distance < MINDISTNW)
                           {
                               MINDISTNW = distance;
                               node.setNorthWest(map.get(j));

                               //System.out.println(currentDist + " e " + map.get(j).x + " " + map.get(j).y);
                           }
                       }
                       else if(currentDistX <= 0 && currentDistY <= 0)
                       {

                           distance = node.calculateDistanceBetweenNods(map.get(j));

                           if(distance < MINDISTSW)
                           {
                               MINDISTSW = distance;
                               node.setSouthWest(map.get(j));

                               //System.out.println(currentDist + " e " + map.get(j).x + " " + map.get(j).y);
                           }
                       }
                       else if(currentDistX > 0 && currentDistY < 0)
                       {

                           distance = node.calculateDistanceBetweenNods(map.get(j));

                           if(distance < MINDISTSE)
                           {
                               MINDISTSE = distance;
                               node.setSouthEast(map.get(j));

                               //System.out.println(currentDist + " e " + map.get(j).x + " " + map.get(j).y);
                           }
                       }
                   }
               }
           }
    }

此函数查找 North,South,West,East,N-East... 邻居节点。
估计路径:

public float getEstimatedDistanceToGoal(float startX, float startY, float goalX, float goalY) {         
            float dx = goalX - startX;
            float dy = goalY - startY;

            //float result = (float) (Math.sqrt((dx*dx)+(dy*dy)));

            //Optimization! Changed to distance^2 distance: (but looks more "ugly")

            float result = (float) (dx*dx)+(dy*dy);


            return (float) Math.sqrt(result);
    }

当前节点与邻居节点的连接错误。
示例:

一些节点有单向连接(上图)。
节点 2 有邻居节点 1,节点 1 没有邻居节点 2。

【问题讨论】:

  • 我不明白它看起来工作正常。你有什么问题?
  • 如何无障碍搜索近邻?

标签: java algorithm path-finding a-star


【解决方案1】:
  1. 如果您有足够的内存用于地图,您仍然可以使用 A* 地图版本

    here 这样可以避免图形混淆。找到更好的方法(不限于图形节点),但速度较慢且需要更多内存。

  2. 无论如何,您的问题看起来像是错误地关联到节点的成本

    看起来成本不是由物理距离定义的,而是由图中的节点距离定义的,所以两个节点总是比一个对角线更昂贵,无论它们实际上有多远。

    这意味着它会找到具有最小节点数而不是最小距离的路径,但我不使用图 A*,所以请记住这一点。如果您可以检查node.calculateDistanceBetweenNods() 功能或将节点设置为无缝网格(添加空节点)以纠正此问题。但是没有使用该库的经验,我只能推测...

  3. 一些见解(但我对 JAVA 不熟悉...)

    所以乍一看,您使用float 表示当前距离,使用int 表示与它们进行比较的常量。此外,所有if不处理浮点值!!! 例如:

    if(currentDistX == 0)
    

    应该是这样的:

    if(fabs(currentDistX)<=1e-6)
    

    最后一件事我不知道 JAVA 是否对 &lt;=&amp;&amp; 具有相同的优先级,但我会觉得更安全

    if((currentDistX<=0.0)&&(currentDistY<=0.0))
    

    正如我之前在许多编译器中多次烧毁的那样。

【讨论】:

  • 您好,感谢您的回复。函数 EstimateDistanceToGoal 和 calculateDistanceBetweenNods 正文:float dx = goalX - startX;浮动 dy = 目标 - 开始;浮动结果 = (float) (dxdx)+(dydy);
【解决方案2】:

我发现了一个错误。但是,不一定只有一个:

               if(currentDistY == 0)
               {
                   if(currentDistX < 0) <===== here, change to currentDistX > 0
                   {

                       if(currentDistX > MINDISTE)
                       {
                           MINDISTE = currentDistX;
                           node.setEast(map.get(j));

                           //System.out.println(currentDist + " e " + map.get(j).x + " " + map.get(j).y);
                       }
                   }
                   else if(currentDistX > 0) <======= here, change to currentDistX < 0
                   {
                       //System.out.print("m " + MINDISTRIGHT);
                       if(currentDistX < MINDISTW)
                       {
                           MINDISTW = currentDistX;
                           node.setWest(map.get(j));
                           //System.out.println(currentDist + " w " + map.get(j).x + " " + map.get(j).y);
                       }
                   }
               } 

你可以重新考虑一下。你会发现的。

【讨论】:

  • 您好,感谢您的回复。我的节点形成一个图,函数 registerEdges 只搜索 8 个邻居。有时节点与其他节点没有连接。方法 registerEdges 应该搜索当前节点的所有连接并且搜索​​路径应该避开障碍物。
【解决方案3】:

您在答案中粘贴的代码对于二维路径搜索来说似乎有点复杂。

如果我理解你的话,你打算在 8 连通网格中搜索图像中的最短路径,并且你正在尝试使用 A* 来解决问题。我建议您使用一个搜索库,它可以更清晰地组织搜索算法的不同组件。

在基础上,如果你有 A* 的实现,你只需要定义:

  • 成本函数(根据您的问题描述,它可能是点之间的欧几里德距离)。
  • 一个转换函数(给定一个Point 检索您的 8 个邻居,过滤那些由于地图图像中的障碍物而无法访问的邻居)。
  • 启发式函数,您已在 getEstimatedDistanceToGoal 中实现。

你可以看看Hipster library,它除了结构更清晰之外,还有一个好处是可以动态地生成图的节点。这样可以节省大量内存,因为您生成的大多数节点先验不会在搜索过程中使用。

Here 您可以找到使用迷宫进行二维搜索的代码示例。您唯一需要使示例适应您的情况是实现TransitionFunction 以使用您的地图图像。该示例使用以下代码生成给定当前节点的邻居节点(函数Maze2D.validLocationsFrom(Point)):

public Collection<Point> validLocationsFrom(Point loc) {
   Collection<Point> validMoves = new HashSet<Point>();
   // Check for all valid movements
   for (int row = -1; row <= 1; row++) {
      for (int column = -1; column <= 1; column++) {
         try {
            //
            //TODO: Implement isFree(Point) to check in your map image
            //if a node is occupied or not.
            //
            if (isFree(new Point(loc.x + column, loc.y + row))) {
               validMoves.add(new Point(loc.x + column, loc.y + row));
            }
         } catch (ArrayIndexOutOfBoundsException ex) {
         // Invalid move!
         }
      }
   }
   validMoves.remove(loc);
   return validMoves;
}

在示例中,函数isFree(Point) 查询迷宫以了解节点是否被占用。你只需要填写这个函数来查询你的地图图片而不是迷宫,就是这样!

希望我的回答对你有帮助,

【讨论】:

  • 您好,感谢您的回复。你的回答会帮助我。现在我创建了一个具有以下结构的 xml 文件: ... ... 在这个文件中我描述了邻居对于每个节点。在下一步中,将此 xml 文件解析为 ArrayList 映射(每个节点都有 AraryList 和邻居)。 A star 使用 Array map 搜索路径。你知道我的意思吗?
  • 嗨@michael,我想我了解你的基本想法。如果您最终决定为您的项目使用该库,您可以按如下方式实现TransitionFunction&lt;Point&gt;: 1) 在构造函数中,解析XML 文件并将信息存储在Map&lt;Point, Iterable&lt;Point&gt;&gt; 中。 2) 方法TransitionFunction&lt;Point&gt;.successorsOf(Point),只会从你在1)中生成的地图中获取后继者的信息。它应该非常有效地工作。
猜你喜欢
  • 2017-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-28
  • 2016-10-08
  • 1970-01-01
  • 1970-01-01
  • 2021-04-11
相关资源
最近更新 更多