从头理解JPS寻路算法

文末有新版描述

JPS(jump point search)概述

本文的思路受到博客:http://blog.sina.com.cn/s/blog_4a5c75d40102wo5l.html
和论文:http://www.doc88.com/p-6099778647749.html的启发和借鉴。
JPS(jump point search)算法实际上是对A寻路算法的一个改进,即在扩展搜索节点时,提出了更优化的策略,A在扩展节点时会把节点所有邻居都考虑进去,这样openlist中点的数量会很多,搜索效率较慢。JPS算法通过寻找跳点的方式,排除了大量不感兴趣的点,减少了openlist中搜索的点的数量,速度大大提高。

图例拆解JPS过程

自然邻居:如图所示,红色块是自然邻居。
被迫邻居:点x的8个邻居中有障碍,n不是x的自然邻居,且x的父亲节点p(x)经过x到达n的距离代价比不经过x到达的n的任意路径的距离代价小,则称n是x的被迫邻居。这其中隐含了对p(x)的描述,最完整的表述应该是,n是x在x的父亲节点是p(x)的情况下的被迫邻居。见图示。
跳点:基于点x(当前点为x),且搜索方向为d(斜向或水平或垂直),点y满足一下三个条件之一,那么y就是跳点。
a.节点y是终点,那么节点y是跳点。
b.节点y至少有一个被迫邻居,那么节点y是跳点。
c.如果d是斜向搜索,如果节点y的水平或垂直方向上有满足条件a,b的点,那么节点y是跳点。注:节点y的水平或垂直方向是斜向向量的拆解,比如向量d=(1,1),那么水平方向则是(1,0),并不会往左搜索,只会看右边,如果向量d=(-1,-1),那么水平方向是(-1,0),只会搜索左边,不看右边,其他同理。

红色块为自然邻居,黑色块为障碍物,绿色块为被迫邻居

水平(垂直)搜索:如图右边部分描述,点1和4如果经过x到达,还不如从点p(x)到达,所以不用考虑点1,4,同理继续向右搜索时,点2,5和点3,6,都是类似的情况,直到遇到黑色的障碍,没有发现感兴趣的点,x处水平方向搜索完成,垂直方向搜索类似。如图左边部分描述,在点x处向右搜索至点y时,点y有一个强迫邻居(点7),因此y是从点x处沿水平方向搜索的一个跳点,需要将y加入到openlist中。水平搜索结束。

水平(垂直)搜索

对角搜索:斜向搜索时,需要先在当前点的水平和垂直方向搜索一下,看能否找到感兴趣的点,如果找到,则将当前点加到openlist,结束斜向搜索,如果找不到,则继续斜向多走一步,继续,直到找到感兴趣的点或者斜向方向遇到障碍。

斜向搜索的两种情况

一条完整路线的搜索过程:

完整搜索路线,起点S,终点T,黄色框是在过程中加入openlist的点,红色箭头尝试搜索返回失败,绿色箭头成功返回感兴趣点。

搜索算法:

Algorithm 1 Identify Successors

Require: x:current node, s:start, g:goal
1: successor(x) <- empty
2: neighbours(x) <- prune(x, neighbours(x))
3: for all n in neighbours(x) do
4:__n <- jump(x, direction(x,n),s,g)
5:__add n to successor(x)
6:return successor(x)

Algorithm 2 Function Jump

Require: x:initial node, d:direction, s:start, g:goal
1: n <- step(x, d)
2: if n is an obstacle or is outside the grid then
3:__return null
4: if n = g then
5: return n
6: if exists n' belongs to neighbours(n) s.t. n' is forced then
7:__return n
8: if d is diagonal then
9: __for i in {1,2} do
10: ____if jump(n,di,s,g) is not null then return n
11: return jump(n,d,s,g)

A*与JPS对比

下面两张对比图,摘自上面的论文,可以看出,JPS算法实在优秀。

A*与JPS扩展节点对比
各寻路算法路径长度和搜索时间

代码

github链接

2020-5-15 重写版本

  1. 强迫邻居(被迫邻居)定义
自然邻居和强迫邻居

上图中红色块为节点x,基于前节点为P(x)的情况下的自然邻居节点。而被迫邻居则是图中绿色的方块(其对称情况未画出)。x被迫邻居包含三层隐藏含义:首先被迫邻居的位置是基于P(x)、x、阻挡块的相对关系定的,如第三个图所示,如果第三个图中,P(x)的位置在节点6的位置,那么绿色方块就不是x的被迫邻居了。其次,被迫邻居一点是考察非自然邻居的节点。最后被迫邻居一定是P(x)经过x到达才能取得最短路径的点。

注意:接下来的讨论都基于一个前提:斜向可以通过,即如上图4中,P(x)和x可以直达,x和绿色块可以直达。
有些算法或者游戏实践中,这种斜向穿过是不允许的,如P(x)->x,这好比人物穿过了墙角,在游戏内是不可以接受的,应该走P(x)->6->x。

  1. 跳点定义
    满足如下条件的点视为跳点:
    i. 节点y是起点或终点。
    ii. 节点y在当前搜索方向的前提下,有强迫邻居。
    iii. 当前搜索方向是斜向,且在y节点处,经过该斜向的水平分量或垂直分量方向移动可以找到跳点,那么当前节点y是跳点。

  2. 搜索规则
    i. 在搜索时,如果直线和斜向都能通过,先在直线方向搜索跳点,然后在斜向上搜索跳点。
    ii. n是x的邻居,若有从P(x)到n且不经过x的路径,且该路径小于等于从P(x)经过x到达n的路径的长度,那么走到x后下一个节点不会走到n。
    iii. 只有跳点才会被加入openlist里,最后找出来的最短路径也是由跳点组成。

一次完整的搜索过程

JPS搜索过程

起点S,终点T,黑色块为阻挡黄色块为跳点,红色箭头是搜索方向,但是没有找到跳点,绿色箭头表示找到跳点。横坐标A-N,纵坐标1-10。

起始位置S,将A10加入openlist里,开始算法流程。
从openlist里取出代价最小的节点(现在为S),当前节点没有方向,所以需要搜索8个方向,只有右上方B9点是跳点。因为根据跳点定义iii,斜向搜索时,需要在两个分量方向查找跳点,右方是墙壁,略过,上方B8点有强迫邻居点C7,所以B8是跳点(根据跳点定义ii),所以B9是跳点。将B9加入openlist里。A10处理完后,将其从openlist中移除,加入closelist里。

从openlist中取出B9点,该点的父亲是S,所以搜索方向为右斜上,需要在右斜上,右方,上方搜索跳点,只有B8满足要求,将B8加入openlist。处理完B9点将其移到closelist。

从openlist取出B8点,该点搜索方向为上,B8有被邻居C7点,在斜上方搜索跳点,可以看出D8是C7的被迫邻居,所以C7是跳点,B8处继续向上搜索结束。

从openlist中取出C7点。需要搜索右上,右,上三个方向。水平搜索时发现被迫邻居D8,加入openlist。右上搜索时发现跳点G3(因其在上方搜索时发现具有被迫邻居节点的G2),将G3加入openlist。C7点处理结束。

取出G3点(为啥是G3,而不是D8点呢,因为从总代价来说G3比D8更小,总代价=已经走过的距离 + 估值,估值可采用曼哈顿距离或者高斯距离),需要搜索右上,右,上三个方向。向上搜索到跳点G2。

其余点路径在图上标注,就不再重复了。

实作中的搜索流程

(1) 若current方向是直线
i. 如果current左后方不可走且左方可走,则沿current左前方和左方寻找跳点。
ii. 如果current当前方向可走,则沿current方向寻找跳点。
iii. 如果current右后方不可走且右方可走,则沿current右前方和右方寻找跳点。
(2) 若current方向是斜线
i. 如果当前方向的水平分量可走,则沿current方向的水平分量方向寻找跳点。
ii. 如果当前方向可走,沿current方向寻找跳点。
iii. 如果当前方向的垂直分量可走,则沿current方向的垂直分量方向寻找跳点。

上述算法流程是建立在斜向不可穿过阻挡基础上。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,757评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,478评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,540评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,593评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,903评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,329评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,659评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,383评论 0 195
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,055评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,337评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,864评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,227评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,820评论 3 231
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,999评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,750评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,365评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,260评论 2 258

推荐阅读更多精彩内容

  • sì 支zhī茶chá 对duì 酒jiǔ,赋fù 对duì 诗shī,燕yàn子zi 对duì 莺yīng 儿é...
    每个人的孟母堂阅读 1,073评论 0 6
  • 一年级语文上册生字表 生字表一(共400字) 啊(ā)爱(ài)安(ān)岸(àn)爸(bà)八(bā)巴(bā)...
    meychang阅读 2,627评论 0 6
  • 原文:http://www.cnblogs.com/wangnfhy/p/4956711.html 参考:http...
    top_liu阅读 1,583评论 0 52
  • 围棋是兵法,也是势的哲学,得势者得天下。势者,因利而制权。像水一样,行乎当行,止乎当止,从不刻意而为,无为而无不为...
    三清未央阅读 397评论 0 0
  • JavaScript拥有动态类型,这意味着相同的变量可用作不同的类型。 字符串 字符串是存储字符的变量,单引号双引...
    一亩水塘阅读 367评论 0 4