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

Projects

Status

Todo

Relationships

None yet

Development

No branches or pull requests

Issue actions