高效算法,B*寻路算法,python版,思维优化(1)

上一篇文章只发布了很粗糙的代码,属于能跑就行,确实难看懂。

这一篇继续说一下爬墙思维,,B*寻路算法就是贪婪思维 +攀爬思维,

但是比较难判定怎么算爬过的障碍,所以这里改为  贪婪思维 +穿透障碍,(空心障碍的话这不坑爹吗)

开始研究B*寻路算法时,真是时 不知道怎么取解决爬墙,,,

从格子3 开始分路,开始考虑撞墙,换方向,又得判定是否已经翻过了障碍,起初我觉得可以用距离来判断翻过了障碍,因为对于B*算法来说,情况是这样的。

这里距离=该点到起点的距离+到终点的距离,这里有点像椭圆离的两个固定坐标,就是起点和终点,直接连线那么距离最短,遇到障碍后距离局部变大,爬过障碍后又变小。但是对于上图的包围型障碍来说,通过距离的起伏判定是失效的

也许有其他的解决方法,但是这里我转变的一下,就是如果我穿透障碍,从格子3 到格子4.。

那么就算爬过的障碍,这样就不用取判定怎么算爬过了障碍。只需要关心怎么沿着障碍,走到穿透后的点就行了

接下来就是怎么走了,怎么走好像也有点难。

但是这里我们发现

 既然要沿着障碍边缘走,那么我们的就障碍边缘所有可以走的点找出来,那么这这些点连在一起,就是包围了障碍的圈。

判定方法,

1.从o(欧)点开始,遍历周围8个点,。。做完事后加到关闭列表

如果有一个点=0,那么就是该点O就是边缘点,把=0的点加入 障碍包围圈 path里,

如果=1,那么这个点是障碍点,是不是可以加到开启列表,

就看他的邻居有没有=0的点,如果有,说明该点是障碍边缘的点。加到开启列表,如果没有那么这个点是障碍内部的点,不需要探索(这里可以从前后左右四个方向开始,再从其他四个方向遍历)

2 从开启列表取一个点,继续 1 步骤

下面代码  0 代表可以走,1代表障碍


# 通过一个障碍内的点,得到障碍周围一圈的可探索点,,如果是环形空心障碍,这不设坑爹吗,穿透后的目标点都到不了
def obstacle_around_openSet(self, obstacle_point=(2,5)):
    # 边缘可走点集合
    path=[]
    # 开启的表
    obstacle_openSet = [obstacle_point, ]
    # 关闭的表
    obstacle_closeSet = []
    while obstacle_openSet != []:
        # 切换到关闭列表  .pop默认删除最后一个(这里后面会有点新发现的)
        cur = obstacle_openSet.pop()
        obstacle_closeSet.append(cur)


        # 对当前格相邻的8格中的每一个
        neighbors = self.get_neighbors(cur[0], cur[1])
        for neighbor in neighbors:
            #    =0即边缘可以走的点                               看看是否加过了                                   # 不能往回走 self.closeSet是全局关闭表(走过的表,用来回溯路劲,所以是带坐标的字典)
            if map_be_search[neighbor[0]][neighbor[1]] == 0 and neighbor not in obstacle_openSet and neighbor not in [p["point"] for p in self.closeSet]:
                path.append(neighbor)


            #   =1 这是相邻障碍点,  就是障碍内的点  且在边界内   =1的点可能是边界点,所以联合判定
            if map_be_search[neighbor[0]][neighbor[1]] == 1 and border_x_min < neighbor[0] < border_x_max and border_y_min < neighbor[1] < border_y_max:
                # 已经在 "关闭列表"(探索过) 中 不做处理
                if neighbor in obstacle_closeSet:
                    continue

                # 它不在 开启列表中,这个障碍点可能可以探索,但是如果是内部的点,而障碍不是边缘的点,就不能加到开启列表
                if neighbor not in obstacle_openSet:
                    # 遍历 该邻居   相邻的8格中的每一个
                    neighbors_list = self.get_neighbors(neighbor[0], neighbor[1])
                    for neighbor_neighbor in neighbors_list:
                        # 如果该邻居周围的格子里有一个 0, 说明它在障碍边缘, 则加入 并且打断
                        if map_be_search[neighbor_neighbor[0]][neighbor_neighbor[1]] == 0 :
                            obstacle_openSet.append(neighbor)
                            break

 得到障碍包围圈path  后,我们就沿着path 爬就行了。

1.我们新建一个openSe和 closeSet 开启的表和关闭的表,把格子3放进去,

2.从开放的表 取出格子3  作为当前点(也就是起点,每次从开启表中拿点都是重头再来),并放进关闭的表。

3.遍历一下格子3的8个邻居(这里的话还是优先遍历前后左右的四个点,可以减少遍历次数)

发现只有 *1和1* 两个点#(1个也行,都没有就是说三面都是障碍,要往回走了,那么在在上面计算path时,走过的点(只要是障碍边缘可走的点)也得加入path,不过这也有点坑爹的感觉)#

只有这两个点  在 障碍包围圈path里面,所以选择一个作为下一个点,更新下一个点的信息,另一个点加入开启的表。

4.把下一个点更新为当前点。并加到关闭的表。继续遍历邻居。

 

这里先向上爬,取出*1格子,把1*放进开启的表,

遍历周围八个点,只有*2(距离*1的距离是1)和*3 (距离*1的距离是1.4)。

但是这里我们需要确定下一个点,也就是*2,根据距离=1可以确定,把*3放进开启的表。所以更新该点为当前点,

继续遍历 *2,发现只有*3就是下一个点,记录一下点信息,把*3更新为当前点(*3马上就进入关闭的表。那么开启表的那个*3,取出来作为起点也没有用了)

继续遍历 *3,发现只有4*就是下一个点,记录一下点信息,把*34更新为当前点............继续就行了,

如果前面没有点可以走了,那么就是往上走是死路,下一个点的信息为空,判定一下,后从开启的表拿点出来作为起点重新走,也就是只有为唯一一个1* 可以作为新的起点。开启的表中其他的都已经走过了。

如果下一个点信息为穿透障碍后的点,说明该路路径可以走,但是我们还需要对另一条路走一遍,看看谁最短

也就是我先把格子3 关闭点,新建两个不同的开启表和关闭表,把*1和1* 分别放到两个不同的开启的表中,也就是只可以计算出两条路径。

这样我们就可以解决绕过障碍的难点了,,只要跑到对面那个点就可以算绕过障碍 了

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
A*寻路算法是一种常用的路径搜索算法,通过对搜索空间中的节点进行评估和排序,可以找到最优路径。它结合了启发式搜索和贪婪搜索的思想,具有高效性和准确性。 算法的核心思想是通过使用一个启发函数,对每个节点进行估价,以选择最有希望的节点进行搜索。启发函数一般使用曼哈顿距离或欧几里得距离来评估节点与目标节点的距离。同时,A*算法还维护了一个开放列表和一个关闭列表,用于保存已搜索和待搜索的节点。 首先,将起点节点加入到开放列表中,并初始化各个节点的启发函数值和代价值。然后,从开放列表中选取具有最小代价值的节点,进行扩展。扩展过程中,评估每个相邻节点的代价值,并更新节点的父节点和代价值。将扩展完成的节点加入到关闭列表中。 重复上述步骤,直到找到目标节点或者开放列表为空。如果找到目标节点,可以通过回溯从目标节点到起点节点,得到最优路径。如果开放列表为空,则表示无法找到路径。 以下是使用Python实现A*寻路算法的基本步骤: 1. 定义节点类,包括节点坐标、启发函数值、代价值等属性,并实现比较运算符以便排序。 2. 初始化起点节点和目标节点,并将起点节点加入到开放列表中。 3. 进入循环,遍历开放列表中的节点。 4. 从开放列表中选取代价值最小的节点,并将其从开放列表中移除,加入到关闭列表中。 5. 对选中的节点进行扩展,生成所有相邻节点,并计算它们的代价值和启发函数值。 6. 遍历所有相邻节点,并更新它们的父节点和代价值。 7. 检查相邻节点是否在开放列表或关闭列表中,若不在,则加入开放列表。 8. 重复步骤3到7,直到找到目标节点或开放列表为空。 9. 如果找到目标节点,可以通过回溯从目标节点到起点节点,得到最优路径。 10. 如果开放列表为空,则表示无法找到路径。 总之,A*寻路算法是一种高效而准确的路径搜索算法,通过合理的启发函数和排序策略,可以找到最优路径,并且在实践中常被广泛应用。使用Python实现该算法时,需要定义节点类、初始化起点和目标节点、维护开放列表和关闭列表,并进行节点的评估和更新。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值