portal 在scene graph 中怎么生成?

在你的框架里,portal 不是"凭空造一个概念" ,而是从你已经有的地图/拓扑/语义里自动抽出来的"通往未知的入口点"。最常用、最稳的生成方式有 3 条主线(你可以同时用,互相校验):


1) 从 2D 占据栅格的 Frontier 生成(最推荐、最通用)

这是最标准的:portal ≈ frontier cluster 的代表点

步骤

  1. Frontier 检测

    在 2D occupancy grid 上找满足条件的格子:

  • 当前格子是 free

  • 邻域里存在 unknown

    这就是 frontier cell。

  1. Frontier 聚类(cluster)

    对 frontier cells 做连通域聚类(4/8 邻接都行),得到多个簇 C_i。每个簇基本对应一个"未知方向的入口边界"。

  2. 为每个 cluster 选一个 portal anchor(代表点)

    常见选法:

  • centroid:簇的几何中心(简单)

  • best-reachable:簇内距离机器人最近且 A* 可达的点(更稳)

  • max-visibility:在簇附近采样几个候选位姿,选"能看到更多未知"的那个(更像 IG)

  1. 估计 portal 的朝向 normal / heading(关键)

    你需要知道"未知大概在 portal 的哪一侧",做法:

  • 取代表点 p 周围一个小环带,统计 unknown cells 的方向分布

  • unknown 多的方向就是 portal 的法向 n(heading)

  1. 估计 portal 宽度(可选但很有用)

    沿着与 n 垂直的方向,在 frontier cluster 上测量长度(格子数量×分辨率),得到 width

    用途:过滤"太窄不可通行"的 portal;或者区分"门洞 vs 大开口"。

生成到 scene graph 的形式

  • 新建节点 Portal_i(type=portal)

  • 属性:position(x,y,z), heading(yaw), width, cluster_size, confidence

  • 连边:

    • Portal_i --attached_to--> Place/Region_j(它属于哪个已探索区域)

    • Portal_i --leads_to--> UnknownRegion_i(后面未知)

你现在的 target_points_node.cpp 已经做了 frontier 检测/可见性/目标点选择,这条链路通常最容易直接复用。


2) 从拓扑 Place Graph / Scene Graph 的"边界节点"生成(与你的 GraphDecoder 很搭)

如果你有 places(可行走节点)和它们的连边:

思路

  • 在 place graph 里,找那些靠近未知边界的 place(boundary place)

  • 对 boundary places 做聚类/合并

  • 每一簇生成一个 portal

怎么判断 place 是否 boundary?

对每个 place 节点 v

  • 在它附近(半径 r)的 occupancy grid 上统计 unknown 比例

  • unknown 比例 > 阈值 → v 是 boundary candidate

优势:portal 天然和你的拓扑图绑定,后续做路径规划/代价估计很顺。


3) 从语义结构生成(Door / Opening)(增强但别单独依赖)

如果你的 scene graph 里已经有 door / opening 之类结构节点:

做法

  • 对每个 door 节点:

    • 用其 3D bbox/中心作为 portal position

    • 朝向用门框平面法向(或用两侧 free/unknown 分布估计)

  • 然后用 occupancy/frontier 验证:门的一侧是否真的通向未知或未探索区域

    • 如果门两侧都已探索,那它不是 portal(只是室内连接)

优势:更"语义正确",尤其在房间级规划时很好用。

坑:语义门检测不稳时会漏/错,所以最好与 frontier-based 互补。


推荐你用的"组合策略"(最稳)

主干用 Frontier → Portal(方案 1),再用 door/拓扑做增强:

  1. Frontier 聚类生成 Portal_frontier

  2. door 节点生成 Portal_door

  3. 空间上做合并(2D/3D 距离 < ε 且朝向相近):

    • 如果 door portal 和 frontier portal 重合 → 提升置信度

    • 如果 door portal 不对应 frontier → 先降权(可能是假门/已探索门)

  4. 输出 portal 集合给 scene graph


你可以直接照抄的伪代码(偏工程实现)

复制代码
portals = []

frontiers = detectFrontier(occupancy)
clusters = clusterFrontier(frontiers)

for each cluster Ci:
    p = chooseAnchor(Ci, mode="reachable_nearest")  // centroid / nearest reachable / best visibility
    n = estimateNormalFromUnknown(occupancy, p)     // direction to unknown
    w = estimateWidth(Ci, n, resolution)
    if w < min_width: continue

    portal = Portal(
        pos = gridToWorld(p),
        yaw = atan2(n.y, n.x),
        width = w,
        confidence = f(cluster_size, w)
    )
    portals.push(portal)

door_portals = portalsFromDoors(scene_graph_doors)
portals = mergeAndValidate(portals, door_portals, occupancy)

attachPortalsToGraph(portals, place_graph_or_regions)

Scene graph 里"Portal 节点"的推荐字段

(你后面要做 IG、代价、补全,这些字段很关键)

  • id

  • type = portal

  • pos (x,y,z)

  • yaw(通往未知的朝向)

  • width

  • source = {frontier, door, place_boundary}

  • confidence

  • connected_region_id(它属于哪个已探索 room/region)

  • unknown_region_id(它指向哪个 UnknownRegion)


如果你告诉我你现在的地图表示是哪一种最方便(2D occupancy/frontier 已有 、还是 place graph 已有 、还是 door 节点已检测 ),我可以按你现有代码结构(比如你 target_points_node.cpp 的 frontier 输出格式)给你一份更贴你工程的 C++/ROS 接口设计:订阅哪些 topic、portal message 怎么定义、在哪一层插入 scene graph。

相关推荐
啊森要自信3 小时前
CANN ops-cv:AI 硬件端视觉算法推理训练的算子性能调优与实战应用详解
人工智能·算法·cann
仟濹4 小时前
算法打卡day2 (2026-02-07 周五) | 算法: DFS | 3_卡码网99_计数孤岛_DFS
算法·深度优先
驭渊的小故事4 小时前
简单模板笔记
数据结构·笔记·算法
YuTaoShao4 小时前
【LeetCode 每日一题】1653. 使字符串平衡的最少删除次数——(解法一)前后缀分解
算法·leetcode·职场和发展
VT.馒头4 小时前
【力扣】2727. 判断对象是否为空
javascript·数据结构·算法·leetcode·职场和发展
goodluckyaa4 小时前
LCR 006. 两数之和 II - 输入有序数组
算法
孤狼warrior4 小时前
YOLO目标检测 一千字解析yolo最初的摸样 模型下载,数据集构建及模型训练代码
人工智能·python·深度学习·算法·yolo·目标检测·目标跟踪
Σίσυφος19005 小时前
PCL法向量估计 之 RANSAC 平面估计法向量
算法·机器学习·平面
xhbaitxl5 小时前
算法学习day39-动态规划
学习·算法·动态规划
I_LPL5 小时前
day23 代码随想录算法训练营 回溯专题2
算法·hot100·回溯算法·求职面试