PGRouting导航规划-AStar算法

Posted 爱是与世界平行

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PGRouting导航规划-AStar算法相关的知识,希望对你有一定的参考价值。

  • 推荐数据库DBeaver,可以直接根据几何要素查看图形,相当方便。

1 生成拓扑

要生成最佳路径,首先要生成合法的拓扑。

生成拓扑前,需要添加两个字段,用来存储线段的首尾编号

-- Add "source" and "target" column
ALTER TABLE nyc_roads ADD COLUMN "source" integer;
ALTER TABLE nyc_roads ADD COLUMN "target" integer;
  • source —— 用于保存路径起始顶点的id
  • target —— 用于保存路径终止顶点的id

调用pgr_createTopology生成拓扑,注意就是生成线段的首位编号的过程

pgr_createTopology(
'<table>',   -- 需要生成拓扑的表名
float tolerance,   --  容错值
'<geometry column>',   --  线段列名
'<gid>')  --  gid

容错值:例如线段的端不能完全吻合时,允许多少误差,单位一般为角度或公里数

官方说明:https://docs.pgrouting.org/3.1/en/pgr_createTopology.html

例子

-- Run topology function
SELECT pgr_createTopology('nyc_roads', 0.00001, 'geom', 'gid');

或者:

创建路网拓扑需要调用pgr_createTopology数:

SELECT pgr_createTopology(
	'aaa_bbb', 
	0.001,
	'geom',
	'gid',
	'source',
	'target'
); 

上面的六个参数分别表示:

  • 路网表
  • 路径之间的容差,两条路径的距离大于这个容差值,就表示它们不相交,否则就是相交。
  • 路网表中包含空间信息的列
  • 路网表的主码列
  • 保存路径起始顶点的id的列
  • 保存路径终止顶点的id的列

拓扑路径创建完成后,数据库中会自动多出一张表aaa_bbb_vertices_pgr

这张表保存了路径的起始、终止顶点数据

我们再查询路网表aaa_bbb,可以发现source列和target列都被填满了,值就是aaa_bbb_vertices_pgr这张表中对应的的id值

2 生成最佳路径

pgrouting支持的最佳路径算法很多。

官方说明:[https://docs.pgrouting.org/3.1/en/search.html?q=+shortest+path&check_keywords=yes&area=default](https://docs.pgrouting.org/3.1/en/search.html?q= shortest path&check_keywords=yes&area=default)
这里以Shortest Path A*和Shortest Path Dijkstra(狄克斯特拉)为例,介绍如何生成最佳路径

如果考虑回程成本的话,需要增加回程成本的字段,并设置为公里数。

ALTER TABLE nyc_roads ADD COLUMN reverse_cost double precision;
UPDATE nyc_roadsSET reverse_cost = length;
  • cost —— 用于保存路径正向的成本(或者代价)
  • reverse_cost —— 用于保存路径反向的成本(或者代价)
ALTER TABLE nyc_roads
ADD COLUMN cost DOUBLE PRECISION,
ADD COLUMN reverse_cost DOUBLE PRECISION;

OSM数据包含一个oneway列,它的值可能是以下三个值之一:

  • F’ —— 表示该路径是单向的,且路径方向是正向的。
  • T’ —— 表示该路径是单向的,且路径方向是反向的。
  • B’ —— 表示该路径是双向的。

现在就根据路径的方向来计算各个路径的成本。

将路径的长度作为成本,如果路径是正向的,则cost值为路径的长度,reverse_cost值为-1;如果路径是反向的,则reverse_cost值为路径的长度,cost值为-1;如果路径是双向的,则cost和reverse_cost的值都为路径的长度。

①正向路径的成本:

UPDATE aaa_bbb
SET cost = ST_Length(geom), reverse_cost = -1
WHERE oneway = 'F';

②反向路径的成本:

UPDATE aaa_bbb
SET reverse_cost = ST_Length(geom), cost = -1
WHERE oneway = 'T';

③双向路径的成本:

UPDATE aaa_bbb
SET cost = ST_Length(geom), reverse_cost = ST_Length(geom)
WHERE oneway = 'B';

2.1 Shortest Path Dijkstra算法举例

Dijkstra算法是第一个在pgRouting中实现的算法。它不需要除id、source、target和cost之外的其他属性。而且可以明确指定将图视为有向的无向的

pgr_dijkstra函数的签名摘要

函数说明:

pgr_dijkstra(
text sql, -- 用于计算最佳路径的数据来源, 用SQL表示, 例如 
          -- SELECT id (gid), source (线段起点id), target (线段重点ID), cost (起点到终点的成本) [,reverse_cost (终点到起点的成本)] FROM edge_table
integer source,   --  规划路径的起点
integer target,   --  规划路径的终点
boolean directed   --  是否支持双向,如果为true,sql中必须有reverse_cost
);  

官方说明:https://docs.pgrouting.org/3.1/en/pgr_dijkstra.html

返回结果:(seq, path_seq ,node, edge, cost, agg_cost)

node:起点id

edge:目标ID, -1表示终点

SELECT * from  public.pgr_dijkstra(
	'SELECT
	gid AS id,
	source::integer,
	target::integer,
	length::double precision AS cost,
	reverse_cost
	FROM nyc_roads', 
	1, 
	9, 
	false
) 

注意:

  • 许多pgRouting函数都将sql :: text作为参数之一,虽然这开始看起来很混乱,但它使函数非常灵活。用户可以传递任何SELECT语句作为函数参数,只要该SELECT语句返回的结果包含所需数量的属性且包含正确的属性名。
  • 多数pgRouting实现的算法不需要路网几何信息。
  • 大多数pgRouting函数不返回几何信息,而只返回包含节点id或路径id的有序列表。

2.2 Shortest Path A*算法举例

与Shortest Path Dijkstra算法类似,只是SQL需要用到每条线段的起点和终点的坐标,其他参数和pgr_dijkstra都一样。

ALTER TABLE nyc_roads ADD COLUMN x1 double precision;
ALTER TABLE nyc_roads ADD COLUMN y1 double precision;
ALTER TABLE nyc_roads ADD COLUMN x2 double precision;
ALTER TABLE nyc_roads ADD COLUMN y2 double precision;
 
UPDATE nyc_roads SET x1 = ST_x(ST_PointN(geom, 1));  -- 线段起点坐标x
UPDATE nyc_roads SET y1 = ST_y(ST_PointN(geom, 1));  -- 线段起点坐标y
 
UPDATE nyc_roads SET x2 = ST_x(ST_PointN(geom, ST_NumPoints(geom)));  -- 线段终点坐标x
UPDATE nyc_roads SET y2 = ST_y(ST_PointN(geom, ST_NumPoints(geom)));  -- 线段终点坐标y

可能出现x1,y1,x2,y2没赋值成功,通过函数进行逐个分析,有可能存入的数据格式不对,通过PostGIS函数进行转换下就好:

UPDATE "Road"  SET x1 = ST_x(st_pointn(st_geometryn(transform_geom, 1), 1));  -- 线段起点坐标x
UPDATE "Road"  SET y1 = ST_y(st_pointn(st_geometryn(transform_geom, 1), 1));  -- 线段起点坐标y

UPDATE "Road"  SET x2 = ST_x(ST_PointN(st_geometryn(transform_geom, 1), ST_NumPoints(st_geometryn(transform_geom, 1))));  -- 线段终点坐标x
UPDATE "Road"  SET y2 = ST_y(ST_PointN(st_geometryn(transform_geom, 1), ST_NumPoints(st_geometryn(transform_geom, 1))));  -- 线段终点坐标y

函数说明:

pgr_astar(
sql text,     -- SELECT id, source, target, cost, x1, y1, x2, y2 [,reverse_cost] FROM edge_table ,包含了起点和重点坐标,计算速度比Shortest Path Dijkstra算法快一点
source integer,   
target integer, 
directed boolean, 
has_rcost boolean  
);

官方说明:https://docs.pgrouting.org/3.1/en/pgr_aStar.html

返回结果与pgr_dijkstra一样

例子:

SELECT * FROM pgr_astar('
	SELECT gid AS id,
			 source::integer,
			 target::integer,
			 length::double precision AS cost,
			 x1, y1, x2, y2
			FROM nyc_roads',
	1, 9, false);

结果:

以上的node列表示会经过的顶点,edge列表示会经过的路径,cost表示对应单条路径的成本,agg_cost表示路径的总成本。

注意:

  • 返回的cost属性表示edges_sql参数中指定的cost属性。在这个例子中,cost是路径的长度。cost可以是时间、距离或任何其他属性以及自定义公式的组合。
  • 结果中的node属性和edge属性取决于使用pgr_createTopology函数时对顶点标识符的分配。

3 查询的标识符

source列和target列的顶点标识符(对应shenzhen_roads_vertices_pgr的id值)的分配可能不同,因为pgr_createTopology函数随机分配顶点标识符。所以每次运行pgr_createTopology函数建立路网拓扑,source列和target列的顶点标识符都是不同的。(因此仅以文章中的内容作为参考,然后使用你自己的数据进行测试)。

选取两个点

select * from aaa_bbb_vertices_pgr

点1 id为1521

点2 id为1516

SELECT * FROM pgr_dijkstra(
	'SELECT gid AS id,
		source, target,
		cost, reverse_cost
	FROM aaa_bbb',
	1521, 1516,
	directed := FALSE
);

4 效果呈现

4.1 pgr_dijkstra

select * from (
SELECT * FROM pgr_dijkstra(
	'SELECT gid AS id,
		source, target,
		cost, reverse_cost
	FROM aaa_bbb',
	1521, 1516,
	directed := FALSE
))t1 left join aaa_bbb_vertices_pgr t2 on t1.node = t2.id

4.2 pgr_astar

select * from (
SELECT * FROM pgr_astar('
	SELECT id,
			 source::integer,
			 target::integer,
			 length::double precision AS cost,
			 x1, y1, x2, y2
			 FROM "Road"',
	2, 9, false))t1 left join "Road_vertices_pgr" t2 on t1.node = t2.id

5 参考链接

以上是关于PGRouting导航规划-AStar算法的主要内容,如果未能解决你的问题,请参考以下文章

PgRouting求解大数据量最短路径

PgRouting求解大数据量最短路径

Java开源-astar:A 星算法

动态规划在全球导航和输入法中的应用

[Astar_algorithm02]启发函数的比较

如何在Unity中实现AStar寻路算法及地图编辑器