Skip to content

[Feature] 将静态 TF 替换为更加友好的版本 #31

@creeper5820

Description

@creeper5820

背景

当前项目中使用 fast_tf 作为 TF(Transform)树管理库,但在实际使用中发现接口设计存在一些不够友好的地方。我们已经在 rmcs_auto_aim_v2 中实现了一个更友好的 static_tf 接口,希望评估是否可以替换 fast_tf

接口对比

fast_tf 接口设计

定义方式:

// 需要为每个 Link 特化 Joint 模板
template <>
struct fast_tf::Joint<rmcs_description::OdomImu> : fast_tf::ModificationTrackable {
    using Parent = rmcs_description::PitchLink;
    Eigen::Quaterniond transform = Eigen::Quaterniond::Identity();
};

// 使用 JointCollection 作为容器
using Tf = fast_tf::JointCollection<
    GimbalCenterLink, YawLink, PitchLink, MuzzleLink, 
    TransmitterLink, CameraLink, OdomImu, ...>;

使用方式:

// 需要实例化对象
InputInterface<rmcs_description::Tf> rmcs_tf;

// 获取变换需要传入类型参数和实例
auto transform = fast_tf::lookup_transform<
    rmcs_description::BaseLink, 
    rmcs_description::OdomImu
>(*rmcs_tf);

// 设置变换需要实例
rmcs_tf->set_transform<From, To>(value);

特点:

  • ✅ 类型安全(使用类型作为链接标识)
  • ❌ 需要为每个 Link 编写模板特化代码
  • ❌ 需要实例化 JointCollection 对象
  • ❌ 接口分散(lookup_transform 是全局函数,set_transform 是成员函数)
  • ❌ 错误提示不够友好(模板错误信息冗长)

static_tf 接口设计

定义方式:

// 使用嵌套 Joint 构造树结构,声明式风格
constexpr auto static_tf = Joint {
    Link<"0">(),
    Joint {
        Link<"0.0", Eigen::Isometry3d>(),
        Joint { Link<"0.0.0", Eigen::Isometry3d>() },
    },
    Joint {
        Link<"0.1", Eigen::Isometry3d>(),
        Joint { Link<"0.1.1", Eigen::Isometry3d>() },
    },
};
using SentryTf = decltype(static_tf);

使用方式:

// 静态方法,无需实例化
auto transform = SentryTf::look_up<"0.1.1", "0.0.0.0", Eigen::Isometry3d>();

// 获取/设置状态使用字符串名称
auto state = SentryTf::get_state<"0.0", Eigen::Isometry3d>();
SentryTf::set_state<"0.0">(Eigen::Isometry3d::Identity());

// 支持 YAML 序列化
auto result = serialize_from<SentryTf>(yaml);

特点:

  • ✅ 声明式树结构定义,直观易读
  • ✅ 使用 StaticString(编译时字符串)作为链接标识
  • ✅ 静态接口,无需实例化
  • ✅ 统一的接口设计(所有操作都是静态方法)
  • ✅ 友好的中文错误提示
  • ✅ 支持 YAML 序列化/反序列化
  • ✅ 编译时树结构验证
  • ⚠️ 使用字符串而非类型(类型安全性稍弱,但编译时检查)

功能对比

功能 fast_tf static_tf
树结构定义 模板特化 + JointCollection 嵌套 Joint 构造
链接标识 类型(Type) 字符串(StaticString)
实例化 需要 不需要(静态)
获取变换 lookup_transform<From, To>(instance) Tree::look_up<"from", "to", Type>()
设置变换 instance.set_transform<From, To>(value) Tree::set_state<"name">(value)
获取状态 instance.get_transform<From, To>() Tree::get_state<"name", Type>()
YAML 序列化
错误提示 模板错误(英文) 友好的中文提示
编译时验证
运行时性能 相同(都是编译时计算) 相同

待讨论的问题

  1. 是否需要保持与 fast_tf 的兼容性?
  2. 字符串标识 vs 类型标识的权衡
  3. 迁移成本和风险评估
  4. 性能对比(虽然理论上应该相同)

相关代码

Metadata

Metadata

Labels

No fields configured for Feature.

Projects

Status

Todo

Relationships

None yet

Development

No branches or pull requests

Issue actions