Skip to main content

TF 树梳理与变换管理:YAML/JSON 外参加载、图路径与环检测、直接关系重写、局部求逆、标定链路替换 UI、变换矩阵计算

Project description

tftree-manager

当前版本:0.0.7

TF 树梳理与变换管理:从 YAML 目录或 mdrive4 JSON 目录加载/保存外参与顺序,构建无向图、路径查找、环检测、变换矩阵计算。

安装

pip install tftree-manager

功能特性

  • yaml_dir/extrinsics/*.yamlorder_manifest.yaml 加载/保存外参与顺序
  • 从 mdrive4 JSON 目录读取 source_frame->root_frame 外参并导出 tftree YAML
  • 无向图构建、BFS 路径查找、有向环检测
  • 沿路径累积 4x4 变换矩阵、从根节点计算到所有可达节点
  • 更新变换、求逆、删除有向边(remove_transform)、重排顺序并写回 YAML
  • 相邻直接链路求逆(invert_adjacent_relation):传入两个节点,自动识别当前真实方向并翻转保存
  • 直接关系重写(rewrite_direct_relations):删除被更新相机旧链路,按外部 YAML 声明方向写入新直接边,并在 order_manifest.yaml 记录原始计算链路 link_nodes
  • 标定链路替换(replace_link_for_calibration / launch_prune_ui):输入新标定外参,在当前唯一路径上选择一条既有链接更新,拓扑不变
  • 可选 Flask API 服务与命令行入口

快速开始

from tftree_manager import TFTreeManager

manager = TFTreeManager("/path/to/yaml_dir")
manager.load_from_yaml()

# 所有坐标系
frames = manager.get_all_frames()

# 两节点间变换矩阵
T = manager.get_transform("lidar", "camera")

# 从根节点计算到所有节点
transforms = manager.compute_all_transforms_from_root("world")

# 检测环
cycles = manager.detect_cycles()

# 保存
manager.save_to_yaml()

mdrive4 JSON 输入

V0.0.7 中 TFTreeManager.load_from_mdrive4_json(input_dir, root_frame="ego") 消费 mdrive4_json.load_numpy_calibration()

规则:

  • 复用 mdrive4_json.load_numpy_calibration 读取 JSON,按 mdrive4 JSON 原始语义解释为 sensor_id->ego,不在本库做求逆。
  • Python API 默认 root_frame="ego" 仅为兼容旧调用;官方一致性用法请显式传 root_frame="vrf_ground"。这里的 vrf_ground 是后轴中心接地点,不等同 vrf
  • JSON 主 frame 优先来自 frame_id,缺失时回退文件名 stem;camera_id/文件名 alias 不会写入 tftree 边。
  • JSON RPY 按“度制 ZYX”(Rz(yaw) * Ry(pitch) * Rx(roll))转换为四元数 [qx, qy, qz, qw]
  • PB/YAML 外参约定为右前上 xyz,mdrive4 JSON 约定为前左上 xyz;两类数据禁止直接混用,轴系转换或方向纠偏应在业务流程中显式处理。
  • V0.0.6 的 JSON 入口输出过 ego->sensor_id;需要旧方向语义时继续使用 V0.0.6。

Python 示例:

from tftree_manager import TFTreeManager

manager = TFTreeManager("/path/to/yaml_output")
manager.load_from_mdrive4_json("/path/to/json_dir", root_frame="vrf_ground")
manager.save_to_yaml()

CLI:

tftree-manager load-json /path/to/json_dir --output-dir /path/to/yaml_output
tftree-manager load-json /path/to/json_dir --output-dir /path/to/yaml_output --root-frame vrf_ground

官方 root 输出边示例:front_30->vrf_groundat128p_front->vrf_groundins->vrf_ground

相邻链路局部求逆

V0.0.6 新增 TFTreeManager.invert_adjacent_relation(left, right, output_dir=None, save=True)

规则:

  • 只允许两节点之间存在一条直接边;多跳路径不允许求逆。
  • 若实际存在 left->right,则翻转为 right->left;若实际存在 right->left,则翻转为 left->right
  • 缺失节点、非相邻节点、同时存在 A->BB->A 都会抛出 TFTreeValidationError
  • 推荐指定 output_dir,避免覆盖原始 YAML 工作目录。
from tftree_manager import TFTreeManager

manager = TFTreeManager("/path/to/yaml_dir")
manager.load_from_yaml()
result = manager.invert_adjacent_relation("at128p_front", "vrf", output_dir="/path/to/inverted_yaml")
print(result.original_edge, result.output_edge)

直接关系重写

V0.0.4 新增 TFTreeManager.rewrite_direct_relations(update_yaml_path, prune_frames=None, output_dir=None, save=True),用于处理 PB 解析后的 YAML 工作目录。C04 负责产出 IPM 自动计算后的直接关系 YAML,pb_calibration 继续负责 PB parse/build。

本库已提供的模板能力:

  • 读取 direct_relations.yaml,校验 direct_relations 格式、重复边、反向重复边与无向闭环。
  • 删除 replace_framesprune_frames 命中的旧边,按 update YAML 顺序追加新的直接边。
  • 写出重写后的 extrinsics/*.yamlorder_manifest.yaml,并在 direct_relations_meta 保留追溯元数据。
  • 提供 Python API 与 CLI 两种触发方式。

调用方需要单独开发的接口/适配层:

  • 直接关系 YAML 生成接口:业务侧根据 IPM、标定结果或其它计算结果生成 direct_relations,本库不负责计算外参。
  • PB 工作目录准备接口:业务侧负责调用 pb_calibration parse,准备包含 extrinsics/order_manifest.yaml 的 YAML 工作目录。
  • 重写触发接口:业务侧可封装 Python API 或 CLI,把 YAML 工作目录、update YAML、输出目录与错误处理接入 C04 或其它流程。
  • PB 回写接口:业务侧继续调用 pb_calibration build,把重写后的 YAML 转回 PB;本库不直接读写 PB。

输入 YAML 格式:

direct_relations:
  - source_frame: at128p_front
    target_frame: front_120
    link_nodes: [at128p_front, vrf, front_120]
    translation: {x: 0.0, y: 0.0, z: 0.0}
    rotation: {qx: 0.0, qy: 0.0, qz: 0.0, qw: 1.0}
    replace_frames: [front_120]

规则:

  • source_frame -> target_frame 是最终写入 extrinsics/*.yaml 的方向,不自动反转。
  • link_nodes 仅作为原始计算链路元数据保存到 order_manifest.yamldirect_relations_meta,不写入单条 extrinsic YAML。
  • link_nodes 长度必须 >= 2,首节点等于 source_frame,尾节点等于 target_frame
  • 未提供 replace_frames 时默认删除 target_frame 相关旧边;也可通过 API/CLI 额外传入 prune_frames
  • 重写后会校验不存在 A->BB->A 反向重复边,且无无向闭环;允许森林结构。

推荐接入策略:

  • 有输出隔离需求时使用 output_dir,避免覆盖 pb_calibration parse 生成的原始 YAML。
  • 单相机更新时 replace_frames 默认填目标相机 frame 即可;显式写出更利于排查。
  • 多相机更新时每条 direct relation 都显式写 replace_frames,避免误删无关外参。
  • 捕获到 TFTreeValidationError 时不要继续执行 PB build,应保留原 YAML 并把错误详情返回给上层流程。

Python 示例:

from tftree_manager import TFTreeManager

manager = TFTreeManager("/path/to/yaml_dir")
manager.load_from_yaml()
result = manager.rewrite_direct_relations(
    "/path/to/direct_relations.yaml",
    output_dir="/path/to/rewritten_yaml",
)
print(result.added_relations[0].link_nodes)

命令行

# 以 YAML 目录为参数,加载并打印树与环信息
tftree-manager /path/to/yaml_dir

# 按 direct_relations YAML 重写直接边;默认写回 yaml_dir
tftree-manager rewrite-direct /path/to/yaml_dir /path/to/direct_relations.yaml

# 输出到新目录,不修改原 YAML 目录
tftree-manager rewrite-direct /path/to/yaml_dir /path/to/direct_relations.yaml --output-dir /path/to/rewritten_yaml

# 读取 mdrive4 JSON 并导出 YAML
tftree-manager load-json /path/to/json_dir --output-dir /path/to/yaml_output

# 自动识别 A/B 的直接边真实方向并求逆;推荐输出到新目录
tftree-manager invert-edge /path/to/yaml_dir at128p_front vrf --output-dir /path/to/inverted_yaml

# 额外删除指定 frame 相关旧边
tftree-manager rewrite-direct /path/to/yaml_dir /path/to/direct_relations.yaml --prune-frame front_120

# 启动 Flask API 服务(默认 0.0.0.0:5000)
tftree-manager-server

环境变量 TFTREE_DATA_DIR 可指定 API 默认数据目录(默认 ./data)。

标定链路替换 UI

V0.0.7 中 prune-ui 的语义是“标定外参链路替换”:标定程序传入新外参 source_frame->target_frame 后,tftree 找到当前树中连接两端点的路径;若两端点直接相邻则自动更新该边;若是多跳路径,则打开 PySide6 UI,只允许用户选择路径上的一条既有链接进行替换。UI 只读取/保存 PB parse 后的 YAML 工作目录,不直接生成 PB,也不会新增或删除边。

其它程序接入

其它 Python 程序应把 launch_prune_ui 当作稳定公共入口;tftree_manager.prune_ui.window.PruneWindow 是当前内部 Qt 实现,暂不承诺作为可嵌入组件的稳定 API。调用方只需要准备三类输入:PB parse 后的 YAML 工作目录、新标定得到的 Transform 或 4x4 矩阵、以及这条新外参的 source_frame/target_frame

from pathlib import Path

import numpy as np

from tftree_manager import LinkReplacementResult, Transform, launch_prune_ui


def replace_calibrated_link(yaml_dir: Path, selected_edge: str | None = None) -> LinkReplacementResult:
    T_new = np.eye(4)
    T_new[:3, 3] = [1.2, 0.0, 0.3]
    calibrated = Transform.from_matrix(T_new, "at128p_front", "front_120")

    return launch_prune_ui(
        yaml_dir=str(yaml_dir),
        source_frame="at128p_front",
        target_frame="front_120",
        calibrated_transform=calibrated,
        selected_edge=selected_edge,
        save=True,
        output_dir=None,
        title="标定链路替换",
        layout_mode="auto",
    )

接入行为:

  • selected_edge 不为空时走非 GUI 自动化路径,不需要安装 PySide6。
  • source_frame/target_frame 直接相邻时自动更新唯一边,也不需要安装 PySide6。
  • 多跳路径且未传 selected_edge 时才打开 PySide6 UI;图形界面依赖通过 pip install "tftree-manager[ui]" 安装。
  • 返回值固定为 LinkReplacementResult,可检查 replaced_edgepathyaml_dirsavedcancelleddirect_adjacent

Python API:

from tftree_manager import Transform, launch_prune_ui

result = launch_prune_ui(
    yaml_dir="/path/to/yaml_dir",
    source_frame="at128p_front",
    target_frame="front_120",
    calibrated_transform=Transform.from_matrix(T_new, "at128p_front", "front_120"),
    title="标定链路替换",
    layout_mode="auto",
)
print(result.replaced_edge)

非 GUI API:

from tftree_manager import TFTreeManager

manager = TFTreeManager("/path/to/yaml_dir")
manager.load_from_yaml()
result = manager.replace_link_for_calibration(
    "at128p_front",
    "front_120",
    T_new,
    selected_edge="vrf->front_120",
)

CLI:

tftree-manager prune-ui /path/to/yaml_dir \
  --update-yaml /path/to/new_calibration.yaml \
  --layout auto

# 自动化/测试入口:不打开 UI,直接更新选中路径边并覆盖 YAML
tftree-manager prune-ui /path/to/yaml_dir \
  --update-yaml /path/to/new_calibration.yaml \
  --selected-edge 'vrf->front_120' \
  --layout tree

UI 操作:

  • 布局支持 autotreestar,右侧按钮可即时切换;autovrf_ground 星型图使用中心环绕,否则使用左根右展树形布局。
  • 鼠标滚轮按当前位置缩放,右键按住拖拽平移画布。
  • 左键点击路径边可选中;非路径边不可选。
  • 左键依次点击两个直接相邻节点时,若两点之间的边属于标定路径,会自动选中该边;非相邻节点或非路径相邻边只更新节点高亮,不触发替换。

保存策略:

  • 默认直接覆盖 yaml_dir/extrinsics/*.yamlorder_manifest.yaml,不自动备份。
  • 保存前校验拓扑不存在反向重复边和无向闭环。
  • 只更新被选中的一条既有链接,保留原 key 方向与边顺序,calib_json/ 等辅助目录不参与修改。

依赖

  • Python >= 3.10
  • numpy >= 1.20.0
  • PyYAML >= 5.4.0
  • Flask >= 2.0.0(API 与 server 入口需要)
  • mdrive4-json >= 0.0.1(load-jsonload_from_mdrive4_json 需要)
  • PySide6(仅 prune-ui 图形界面需要,可通过 pip install tftree-manager[ui] 安装)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tftree_manager-0.0.8.tar.gz (34.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tftree_manager-0.0.8-py3-none-any.whl (35.0 kB view details)

Uploaded Python 3

File details

Details for the file tftree_manager-0.0.8.tar.gz.

File metadata

  • Download URL: tftree_manager-0.0.8.tar.gz
  • Upload date:
  • Size: 34.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.19

File hashes

Hashes for tftree_manager-0.0.8.tar.gz
Algorithm Hash digest
SHA256 4cf2017150535c56260bd5df22d2bea2c39574a1077438a654a6fc91c6f6dfda
MD5 da7b4a677f4220cf05d3a9600fd15dd8
BLAKE2b-256 702eaba5b526d871e327b49975cb20e6f4e626c294af5e475fccc0a56c07d824

See more details on using hashes here.

File details

Details for the file tftree_manager-0.0.8-py3-none-any.whl.

File metadata

  • Download URL: tftree_manager-0.0.8-py3-none-any.whl
  • Upload date:
  • Size: 35.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.19

File hashes

Hashes for tftree_manager-0.0.8-py3-none-any.whl
Algorithm Hash digest
SHA256 e0741348f7cd7105da085f470b3721628544819da7fc340252be4b47062aa92e
MD5 75f6429e2fa09d66f7d055e2c4b82b71
BLAKE2b-256 ee8f4341b3b23ed461d4027152e35b7a2090bb2288276248dde3bda9d78596d8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page