# 基于网格编码的低空路径规划实践指南 ## 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 米)既能保证无人机与建筑物之间有足够的安全距离,又不会因网格过细而导致数据量爆炸。
GeoSOT 网格层级对照表
```sql -- 创建网格编码表 CREATE TABLE building_grid24 ( id SERIAL, grids geogridcode[] ); -- 创建 GIN 索引,加速查询 CREATE INDEX building_grid24_gin ON building_grid24 USING GIN (grids); -- 插入网格数据 INSERT INTO building_grid24 (grids) SELECT ST_AsGeoGridCode( ST_Translate( ST_SetSRID(ST_Boundary(smgeometry), 4490), 0, 0, -6378137 ), 24, 'geosot' ) FROM building_split; -- smgeometry 为表 building_split 的空间字段(GeoModel 类型) ``` **函数说明:** - `ST_Boundary` 获取建筑对象的边界; - `ST_SetSRID` 设置坐标系为 EPSG 4490,`ST_AsGeoGridCode` 当前仅支持 SRID=4490; - `ST_Translate` 将模型的高程原点从地心平移到地表,相当于把海拔基准面"拉"到地面上,便于后续以米为单位进行空间分析; **24 层级网格显示效果** 建筑物网格化效果 --- ## 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` 函数接收多组起终点数组,在网格空间中同时计算所有路径。当多条路径存在重叠网格时,函数会自动调整其中一条或多条路径,避免碰撞。