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 小时前
智能体在科研辅助中的自动化实验设计
人工智能·算法
ouliten3 小时前
石子合并模型
c++·算法
weixin_461769403 小时前
5. 最长回文子串
数据结构·c++·算法·动态规划
补三补四3 小时前
XGBoost(eXtreme Gradient Boosting)算法的核心原理与底层实现技术
算法·集成学习·boosting
多打代码3 小时前
2026.1.2 删除二叉搜索树中的节点
开发语言·python·算法
渡我白衣3 小时前
计算机组成原理(12):并行进位加法器
网络协议·tcp/ip·算法·信息与通信·tcpdump·计组·数电
mu_guang_3 小时前
算法图解3-递归
算法
散峰而望3 小时前
【算法竞赛】C++入门(三)、C++输入输出初级 -- 习题篇
c语言·开发语言·数据结构·c++·算法·github
jianfeng_zhu3 小时前
二叉排序树的建立和插入
算法