# 基于网格编码的低空路径规划实践指南
## 1. 概述
无人机配送、设施巡检、应急运输等低空应用场景的快速发展,对三维空间路径规划提出了更高要求。飞行路径需要同时考虑建筑物避让、禁飞区域约束以及多机协同时的冲突检测,传统的二维路径规划难以满足低空场景下精细化的空间计算需求。
那么,有没有一种更简单的方法,让计算机也能高效地"看清"三维空间里的障碍,并快速找到安全的飞行路线呢?答案是:**网格编码**,它的核心思路是,把三维空间切分成无数个小方块,每个格子标记为"能飞"或"不能飞"。由此复杂的三维几何计算就简化成了"查格子"的问题,路径规划变成在棋盘上找路,碰撞检测变成看两架飞机是否占了同一个格子。
Yukon 空间数据库插件的 **`yukon_geogridcoder` 扩展模块** 提供了空间网格编码能力。它集成了多种网格编码标准,能够将三维建筑、二维禁飞区等各类空间对象统一转换为标准网格,并在网格空间中完成高效的路径搜索,从而保障低空飞行的安全。
本文以城市低空配送场景为例,介绍如何使用 Yukon 提供的网格函数,完成"障碍物底图构建 → 路径规划"的完整流程。
---
## 2. 为什么选择网格编码?
在深入了解具体操作之前,先花两分钟理解:为什么不用传统的几何计算,而要选择网格编码?
**传统方法的痛点:**
在三维空间里做路径规划,如果直接对建筑模型、禁飞区进行几何运算,计算机会面临很多难题:
- **计算复杂**:判断无人机是否会撞上一栋形状不规则的建筑,本质上是在做三维空间求交运算,数学上非常复杂,数据量大时速度很慢。
- **异构数据难融合**:低空飞行需要综合建筑、禁飞区、气象等多源数据,这些数据格式、坐标系和精度各异,需要大量的预处理工作。
- **多机协同难**:多架无人机同时飞行时,需要实时检测它们的路径是否会冲突,如果每两架飞行器之间都做几何碰撞检测,计算量会随着飞行器数量急剧增长。
**网格编码的优势:**
网格编码把复杂的三维几何世界转换成了一张"棋盘",让路径规划、障碍避让、冲突检测都变成在棋盘上走格子的高效运算。
- **将几何求交转为网格查询**:传统方法需要做复杂的三维空间求交运算,网格编码只需判断目标网格是否被占用,计算逻辑大幅简化。
- **空间索引原生支持**:网格编码可直接创建 GIN 索引,利用网格的层级结构实现快速空间过滤,海量数据下依然高效。
- **异构数据同源化**:建筑模型、禁飞区、气象等多源数据,均可映射到同一套网格体系,无需为每种数据单独做格式转换和坐标对齐。
- **多机冲突并行检测**:多架无人机的路径冲突检测,简化为检查路径网格集合是否重叠,天然支持并行计算和自动避让。
---
## 3. 功能介绍
本文涉及的三个核心函数由 Yukon 的 `yukon_geogridcoder` 扩展模块提供:
| 函数 | 功能简介 |
| ------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `ST_AsGeoGridCode` | 将空间几何对象(如建筑、禁飞区)转换为统一的网格编码,支持指定层级控制精度,用于构建网格化障碍物底图。 |
| `ST_GridCodeFindMultiDronePath` | 在网格空间中搜索三维安全路径,支持多组起终点、障碍避让、禁飞区绕行等,可自动检测并规避多机路径冲突。 |
| `ST_GeomFromGeoGridCode` | 将网格编码转换回空间几何对象,支持二维和三维网格,用于在地图或三维场景中可视化展示网格。 |
上述函数的完整语法与参数说明,请访问 [接口参考](../../../modular_api/geosot_api.md)。
---
## 4. 最佳实践
### 4.1. 环境要求
**数据库**
- PostgreSQL 16,如使用 GaussDB,需确保内核版本兼容 PostgreSQL 16。
- Yukon 2.2,已创建 `yukon_geogridcoder` 扩展:
```sql
CREATE EXTENSION yukon_geogridcoder;
```
- 数据库 `search_path` 已包含 Yukon 插件所在的 schema:
```sql
SHOW search_path; -- 查看当前 search_path
SET search_path TO public, yukon; -- 设置 search_path
```
- 数据库连接客户端,例如 DBeaver、pgAdmin 或命令行 psql。
**硬件配置建议**
- 内存 16GB 及以上
- CPU 4 核及以上
- 磁盘 SSD,预留 50GB 以上
### 4.2. 数据概况
三维建筑数据,作为底图数据生成网格,空间数据类型为 GeoModel。
---
### 4.3. 数据入库和处理
1. 将三维建筑数据导入 Yukon 数据库,确保数据包含几何字段(GeoModel 类型)。示例数据中建筑表名为 `Building`,空间字段为 `smgeometry`。
2. 为构建更精细的网格,建议使用工具对建筑数据进行预处理。这里使用 SuperMap iDesktopX 的**骨架拆分**功能将三维建筑数据 `Building` 拆分,得到更细粒度的数据集 `building_split`,作为下面构建网格的源数据。
### 4.4. 构建建筑物网格
此步骤是低空飞行的环境建模阶段,构建的建筑物网格将作为低空飞行的底图。
这里构建 24 层级 GeoSOT 网格,网格尺度约 3.9m × 3.9m × 3.9m(1/8″ 网格)。之所以选择 24 层级,是因为这个精度(约 4 米)既能保证无人机与建筑物之间有足够的安全距离,又不会因网格过细而导致数据量爆炸。
---
## 4.5. 网格路径规划
构建好网格底图后,开始在网格空间中搜索安全路径。
### 4.5.1 基础路径规划
选择两个起止点,规划三维路径。
```sql
-- 创建路径结果表
CREATE TABLE result_path (
id SERIAL,
start_point geometry,
end_point geometry,
path geogridcode[]
);
-- 路径计算
WITH data AS (
SELECT (
ST_GridCodeFindMultiDronePath(
ARRAY [
ARRAY ['SRID=4490;POINTZ(116.374115 39.989219 34.615913)', 'SRID=4490;POINTZ(116.376302 39.990080 30.97979)']
]::geometry[],
'[
{
"schema_name": "public", -- 障碍物表所在的 schema
"table_name": "building_grid24", -- 障碍物数据表名
"column_name": "grids", -- 障碍物数据表存储网格编码的字段名
"is_2d": false, -- false 表示该表存储的是三维网格编码,true 表示该表存储的是二维网格编码
"min_level": 24, -- 障碍物网格的最小编码层级
"max_level": 24 -- 障碍物网格的最大编码层级
}
]'::JSONB,
24
)
).*
)
-- 将路径计算结果存入路径结果表
INSERT INTO result_path (start_point, end_point, path)
SELECT start_point, end_point, path FROM data;
```
**关键参数设置说明:**
本次路径规划场景的关键参数选择如下:
| 参数 | 取值 | 参数说明 |
| ----------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------- |
| geogrid_level | 24 | 与建筑物网格层级一致(约 3.9m 精度),确保路径与障碍物在同一精度级别上计算,避免偏差 |
| path_pairs | 一组飞行起终点 | 用 `POINTZ` 表达三维坐标(经度、纬度、高程) |
| obstacle_configs | JSONB 格式字符串 | 配置障碍物数据源,以 JSONB 数组形式传入,每个元素描述一个障碍物表的空间字段、网格层级等信息。当前示例仅配置建筑物网格。 |
| allow_diagonal_movement | false(默认) | 低空飞行中不建议对角穿越网格,保持路径与网格方向一致,飞行更平稳 |
| buffer_distance_meters | 0(默认) | 基础场景暂不设置缓冲区,后续章节单独演示 |
**返回值:** 一张包含多条路径的表,包含 `start_point`(起点)、`end_point`(终点)、`path`(起点到终点的最短路径网格编码数组,路径中的每个网格编码都是一个 `geogridcode` 类型的值,表示无人机飞行过程中经过的每个网格)。
**路径可视化**
```sql
-- 创建路径可视化结果表
CREATE TABLE result_path_vis (
id SERIAL PRIMARY KEY,
path_id INT,
geom geometry(MULTIPOLYGONZ, 4490)
);
-- 将最短路径网格编码转为空间对象,存入路径可视化结果表
INSERT INTO result_path_vis (path_id, geom)
SELECT id,
ST_GeomFromText(
REGEXP_REPLACE(
ST_AsText(ST_GeomFromGeoGridCode(UNNEST(path))),
'POLYHEDRALSURFACE',
'MULTIPOLYGON'
)
)
FROM result_path;
```
**路径规划效果展示**
在地图上,可以看到一条由小方块连成的飞行路线,路径会自动绕开建筑物网格,确保飞行安全。
### 4.5.2 增加禁飞区域
在上一步的基础上,只需向 `obstacle_configs` 中增加禁飞区配置,函数会自动将其识别为不可穿越区域并重新规划绕行路径,其余参数保持不变。
```sql
WITH data AS (
SELECT (
ST_GridCodeFindMultiDronePath(
ARRAY [
ARRAY ['SRID=4490;POINTZ(116.374115 39.989219 34.615913)', 'SRID=4490;POINTZ(116.376302 39.990080 30.97979)']
]::geometry[],
'[
{
"schema_name": "public",
"table_name": "building_grid24",
"column_name": "grids",
"is_2d": false,
"min_level": 24,
"max_level": 24
},
{
/* 新增:禁飞区配置 */
"schema_name": "public", -- 禁飞区表所在的 schema
"table_name": "no_fly_zone", -- 禁飞区数据表名
"column_name": "smgeometry", -- 禁飞区数据表存储空间对象的字段名
"is_2d": true -- 禁飞区数据表存储的是二维面数据
}
]'::JSONB,
24
)
).*
)
INSERT INTO result_path (start_point, end_point, path)
SELECT start_point, end_point, path FROM data;
```
与上一步相比,`obstacle_configs` 中新增了一条禁飞区配置,其中 `is_2d: true` 表示该表存储的是二维面数据(如行政禁飞区、临时管制区等),路径规划引擎会自动将其扩展为对应层级的三维不可穿越网格,无需手动转换。
**路径规划效果对比**
| 场景 | 路径规划效果 |
|------|-------------|
| 仅建筑物障碍 |
|
| 建筑物障碍 + 禁飞区 |
|
### 4.5.3 多机协同路径规划
设置多对起止点,当路径在网格层面发生重叠时,系统会自动调整,防止碰撞。只需修改 path_pairs 参数,障碍物配置可与上一步保持一致:
```sql
WITH data AS (
SELECT (
ST_GridCodeFindMultiDronePath(
ARRAY [
/* 第 1 组起终点 */
ARRAY ['SRID=4490;POINTZ(116.374115 39.989219 34.615913)', 'SRID=4490;POINTZ(116.376302 39.990080 30.97979)'],
/* 第 2 组起终点 */
ARRAY ['SRID=4490;POINTZ(116.375608 39.988837 32.483978)', 'SRID=4490;POINTZ(116.374601 39.989809 26.852046)']
]::geometry[],
'[
{
"schema_name": "public",
"table_name": "building_grid24",
"column_name": "grids",
"is_2d": false,
"min_level": 24,
"max_level": 24
},
{
"schema_name": "public",
"table_name": "no_fly_zone",
"column_name": "smgeometry",
"is_2d": true
}
]'::JSONB,
24
)
).*
)
INSERT INTO result_path (start_point, end_point, path)
SELECT start_point, end_point, path FROM data;
```
- `ST_GridCodeFindMultiDronePath` 函数接收多组起终点数组,在网格空间中同时计算所有路径。当多条路径存在重叠网格时,函数会自动调整其中一条或多条路径,避免碰撞。