Pinocchio 运动学与动力学双 Data 隔离(方案 1)
问题
pinocchio::Data 内部有共享的工作缓冲区(data.a[], data.v[]),不同算法共用同一 data 对象时会产生交叉污染:
computeFK(运动学):
computeJointJacobians(q) → 在 data.a[]/data.v[] 中留临时中间值
computePbrTau(动力学):
rnea(data, q, v, a) → 读到上一步的脏残留 → 结果错误(如重力 +30% 偏差)
解决方案 1:双 Data 对象物理隔离
原则:运动学管线和动力学管线分别拥有独立的 pinocchio::Data 对象,互不干扰。
// 头文件
pinocchio::Data pin_data_; // 运动学专用:computeFK, wbcSolve
pinocchio::Data pin_data_dyn_; // 动力学专用:computePbrTau
初始化
// on_configure 或 initTargets 中
pin_data_ = pinocchio::Data(pin_model_);
pin_data_dyn_ = pinocchio::Data(pin_model_);
computeFK / wbcSolve
// computeFK:用 pin_data_,不做改动
pinocchio::framesForwardKinematics(pin_model_, pin_data_, q_full);
pinocchio::updateFramePlacements(pin_model_, pin_data_);
pinocchio::computeJointJacobians(pin_model_, pin_data_, q_full);
// wbcSolve:用 pin_data_,读取 FK 结果
const auto& J_task = pin_data_.J; // FK 计算的雅可比
computePbrTau
// 用 pin_data_dyn_,不会被 computeFK 污染
pinocchio::rnea(pin_model_, pin_data_dyn_, q_full, v_ref, a_ref);
// 或用 nonLinearEffects + crba 两步:
// pinocchio::nonLinearEffects(pin_model_, pin_data_dyn_, q_full, v_ref);
// pinocchio::crba(pin_model_, pin_data_dyn_, q_full);
检查清单
-
pin_data_dyn_仅在computePbrTau(及initDob)中使用 -
pin_data_仅在computeFK/wbcSolve/initTargets中使用 - 两个
Data对象都从同一个pin_model_创建 - 初始化在同一生命周期阶段完成(
on_configure或initTargets)
禁止做法
// ❌ 禁止:运动学函数中使用 pin_data_dyn_
computeFK() {
pinocchio::computeJointJacobians(pin_model_, pin_data_dyn_, q); // 污染动力学 data
}
// ❌ 禁止:动力学函数中使用 pin_data_
computePbrTau() {
pinocchio::rnea(pin_model_, pin_data_, q, v, a); // 读到运动学残留
}