地图文件、渲染与内容同步
12.1 GET /v1/api/maps
query scene_name:string 可选,为名称前缀过滤。无分页参数。响应 data:
{"total":1,"maps":[{"name":"office_1f","path":"/maps/office_1f","size":1024000,"file_count":4,"created_time":1794556800.0,"modified_time":1794556800.0,"resolution":0.05,"origin":[-10.0,-5.0,0.0]}]}
| MapInfo 字段 | 类型 | 含义 |
|---|---|---|
name | string | 地图名称 |
path | string | /maps/{name} 形式的虚拟路径,不是主机文件系统绝对路径 |
size、file_count | integer | 目录总字节数、文件数 |
created_time、modified_time | number | Unix 秒 |
resolution | number | 地图分辨率,通常米/像素;未读取到时为 0 |
origin | number[] / null | 地图原点 [x,y,theta],未读取到时可为 null |
12.2 POST /v1/api/maps/import
请求 Content-Type 为 multipart/form-data,由 HTTP 客户端生成 boundary。
| 表单字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
file | file | 是 | ZIP 地图包;文件名决定地图名 |
overwrite | boolean 文本 | 否,false | 同名地图是否允许替换;推荐仅传 true / false |
上传 office_1f.zip 时,核心文件必须同名,接受以下两种布局之一,不能混用:
office_1f.zip
├── office_1f.yaml
├── office_1f.pgm
├── office_1f.pcd
└── office_1f.path.json
或在 ZIP 内只有一个 office_1f/ 顶层目录,四个核心文件放在该目录内。不是任意名称的 path.json。
当前限制:压缩包 1 字节–2 GiB、解压总量不超过 8 GiB、最多 128 个文件条目;还会检查文件布局、路径、核心格式与内容。禁止越界路径和不安全文件类型。YAML 的 image 必须引用同名 PGM;path JSON 要有 base_frame、frame_id,fields 为 ["x","y","z","yaw"],path 非空且每点四个有限数。
curl -sS -X POST -H "Authorization: Bearer $ORSUS_TOKEN" \
-F 'file=@office_1f.zip' -F 'overwrite=false' \
"$ORSUS_ORIGIN/v1/api/maps/import"
响应 data:
{"map_name":"office_1f","overwritten":false,"file_count":4}
非法文件名/ZIP/核心内容:400/1001;同名且未覆盖或地图占用:409/1007。overwrite 不会绕过地图占用与版本保护。
12.3 DELETE /v1/api/maps/{map_name}
path map_name 为地图名,无请求体。成功 data 不是 null:
{"msg":"success"}
不存在为 404/1002;占用或同步状态冲突可为 409/1007。删除地图会影响使用该地图的导航资源,应用应在执行删除前向操作人员展示具体地图名称。
12.4 PUT /v1/api/maps/{map_name}
更新地图 PGM,不上传完整 ZIP。multipart 表单:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
pgm_file | file | 是 | 更新后的 PGM;最大 400,000,128 字节 |
parent_release_id | string | 内容同步启用时需要 | 最近查询到的父版本,防止覆盖他人编辑 |
curl -sS -X PUT -H "Authorization: Bearer $ORSUS_TOKEN" \
-F 'pgm_file=@office_1f.pgm' -F 'parent_release_id=release-from-versions' \
"$ORSUS_ORIGIN/v1/api/maps/office_1f"
未启用内容同步时成功 data=null;启用时返回 MapVersions。不要把图片 PNG 上传到 pgm_file,也不要认为任意尺寸改变一定能通过地图格式/版本校验。父版本冲突为 409/1007,重新读取当前内容并处理冲突后再提交。
12.5 地图文件清单与下载
GET /v1/api/maps/{map_name}/files
返回:
{"map_name":"office_1f","total":4,"render_supported":true,"versioned":true,"files":[{"name":"office_1f.pgm","path":"office_1f.pgm","full_path":"/maps/office_1f/files/office_1f.pgm","size":1024,"created_time":1794556800.0,"modified_time":1794556800.0,"mime_type":"image/x-portable-graymap"}]}
示例 files 仅展示一个文件;total 为完整文件数量。FileInfo 字段均见示例,size 为字节,时间为 Unix 秒;versioned=false 时该字段可省略。下载 URL 应用 map_name 和 files[].path 构造,不把 full_path 当成无需认证的外部 URL。
GET /v1/api/maps/{map_name}/files/{file_path}
path file_path 是地图内相对路径,可包含子目录。成功直接返回文件内容,没有信封。不要请求 .. 越界路径。
curl --fail-with-body -sS -H "Authorization: Bearer $ORSUS_TOKEN" \
"$ORSUS_ORIGIN/v1/api/maps/office_1f/files/office_1f.yaml" -o office_1f.yaml
GET /v1/api/maps/{map_name}/archive
无请求体,成功为 ZIP,下载名 {map_name}.zip。
curl --fail-with-body -sS -H "Authorization: Bearer $ORSUS_TOKEN" \
"$ORSUS_ORIGIN/v1/api/maps/office_1f/archive" -o office_1f.zip
12.6 地图渲染 PNG
| 接口 | 输入 | 成功响应 |
|---|---|---|
GET /v1/api/maps/{map_name}/render | 地图名 | MapRender JSON,Cache-Control: no-store |
GET /v1/api/maps/{map_name}/render/{asset_key} | 上一步的 key | image/png 二进制 |
MapRender:
{"key":"png-v1-example-digest","width":800,"height":600,"bytes":12000,"resolution":0.05,"origin":[-10.0,-5.0,0.0]}
width/height 为像素,bytes 为 PNG 大小,key 为内容缓存标识。图片响应包含 ETag 与 private, max-age=31536000, immutable, no-transform;HTTP 条件请求可能返回 304。地图修改后先刷新 render 获取新 key;旧 key 不是永久历史资源,可能 404。若装配的地图服务不支持渲染,可直接返回无 JSON 信封的 HTTP 501。
12.7 地图内容版本接口
依赖 [map_versions].enabled;未启用为 400/1001。
| 接口 | 请求 | 响应 |
|---|---|---|
GET /v1/api/maps/{map_name}/versions | 无 | MapVersions |
GET /v1/api/maps/{map_name}/versions/{release_id}/files/{role} | release_id 字符串,role=yaml/pgm/pcd/path | 文件二进制;无 JSON 信封 |
POST /v1/api/maps/{map_name}/versions/apply | {"release_id":"release-from-versions"} | 更新后的 MapVersions;请求体最大 4096 字节 |
POST /v1/api/maps/{map_name}/versions/retry | 无请求体 | null,重新排队上传 |
不要把版本接口当成可无限回滚的历史仓库。当前实现以最新内容及安装/同步状态为中心,实际可下载内容以当前返回的 releases 为准。
MapVersions
| 字段 | 类型 | 说明 |
|---|---|---|
schema_version | integer | 地图内容协议版本;不同于 MQTT 的字符串 v1 |
map_id、local_instance_id、scene_name | string | 地图身份、本地实例身份、场景名称 |
current_release_id | string | 当前记录的内容版本 |
installed_release_id | string | 磁盘已安装版本,不能证明运行时已加载 |
deleted、mapping | boolean | 已删除、正在建图保留状态 |
applying | string,可省略 | 正在应用的内容意图;不是 boolean |
received | boolean,可省略 | 接收状态标记 |
installation_id | string,可省略 | 安装关联标识 |
releases | LocalRelease[] | 当前记录的内容与上传状态 |
edit_receipts | MapEditReceipt[],可省略 | 云端地图编辑回执 |
LocalRelease
| 字段 | 类型 | 说明 |
|---|---|---|
manifest | Manifest | 内容清单 |
digest、base_digest | string | 内容摘要及基础摘要 |
metadata | Metadata | 解析出的地图元信息 |
created_at | string | 创建时间 |
local | boolean | 本地来源标记 |
upload_state | string | pending / uploading / verified / blocked |
session_id、upload_error、retry_at | string,可省略 | 上传会话、错误、重试时间 |
attempts | integer | 上传尝试计数 |
Manifest 字段:schema_version:integer、map_id:string、release_id:string、可选 parent_release_id:string、local_instance_id:string、scene_name:string、profile:string(当前协议 gshub-ros-map-v1)、original_grid_available:boolean、可选 generation:integer、files:File[]。File 为 {role,name,size,sha256},size 为整数,其余字符串。
Metadata 字段:width、height 为整数;resolution:number、origin:number[]、points:integer、pcd_encoding:string、path_frame:string、base_frame:string。
MapEditReceipt 包含 request(编辑请求身份与校验条件)、release_id、digest、state、可选 settled_at;由云端编辑流程维护,不建议客户端自行伪造回执。
编辑流程:读取 versions → 下载对应内容 → 上传 pgm_file 与 parent_release_id → 检查返回版本 → 若当前与安装版本不同,且设备允许应用,再调用 apply → 再检查导航环境加载情况。若当前正在建图或应用、地图被占用,返回冲突,不能通过重新启动导航隐式跳过待应用内容。
本章地图错误统一原则:不存在 404/1002;版本、占用、配额及同名冲突 409/1007;名称、包、格式非法及版本功能禁用 400/1001;其余通常 500/6001。