Metadata-Version: 2.4
Name: tftree-manager
Version: 0.0.4
Summary: TF 树梳理与变换管理：YAML 外参加载/保存、图路径与环检测、直接关系重写、变换矩阵计算
License-Expression: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.20.0
Requires-Dist: PyYAML>=5.4.0
Requires-Dist: Flask>=2.0.0
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"

# tftree-manager

**当前版本：0.0.4**

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

## 安装

```bash
pip install tftree-manager
```

## 功能特性

- 从 `yaml_dir/extrinsics/*.yaml` 与 `order_manifest.yaml` 加载/保存外参与顺序
- 无向图构建、BFS 路径查找、有向环检测
- 沿路径累积 4x4 变换矩阵、从根节点计算到所有可达节点
- 更新变换、求逆、删除有向边（`remove_transform`）、重排顺序并写回 YAML
- 直接关系重写（`rewrite_direct_relations`）：删除被更新相机旧链路，按外部 YAML 声明方向写入新直接边，并在 `order_manifest.yaml` 记录原始计算链路 `link_nodes`
- 可选 Flask API 服务与命令行入口

## 快速开始

```python
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()
```

## 直接关系重写

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。

输入 YAML 格式：

```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.yaml` 的 `direct_relations_meta`，不写入单条 extrinsic YAML。
- `link_nodes` 长度必须 >= 2，首节点等于 `source_frame`，尾节点等于 `target_frame`。
- 未提供 `replace_frames` 时默认删除 `target_frame` 相关旧边；也可通过 API/CLI 额外传入 `prune_frames`。
- 重写后会校验不存在 `A->B` 与 `B->A` 反向重复边，且无无向闭环；允许森林结构。

Python 示例：

```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)
```

## 命令行

```bash
# 以 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

# 额外删除指定 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`）。

## 依赖

- Python >= 3.10
- numpy >= 1.20.0
- PyYAML >= 5.4.0
- Flask >= 2.0.0（API 与 server 入口需要）

## License

MIT
