"This method only supports T = double" 为 MultibodyPlant 创建 LQR 时<double>

"This method only supports T = double" when creating LQR for MultibodyPlant<double>

我正在使用以下代码创建 LQR 控制器:

systems::controllers::LinearQuadraticRegulator(
            plant, context, Q, R,
            Eigen::Matrix<double, 0, 0>::Zero() /* No cross state/control costs */,
            actuation_port_index); 

用gdb调试显示错误来自multibody_plant.cc

MultibodyPlant<T>::CalcPointPairPenetrations

我不确定为什么不使用 MultibodyPlant<double>::CalcPointPairPenetrations

以防万一,我的 plant 对象是从 sdf 文件中加载的,其中包含以下几行

    auto pair = AddMultibodyPlantSceneGraph(&builder, std::make_unique<MultibodyPlant<double>>(FLAGS_time_step));

    MultibodyPlant<double>& plant = pair.plant;

    const std::string model_filename = getSrcDir() + "/../res/plant.sdf";
    Parser(&plant, &scene_graph).AddModelFromFile(model_filename);

FLAGS_time_step 大于零时,我有相同的行为。

FLAGS_time_step 设置为 0.0 解决了我的问题。

想了想,好像是个bug。

虽然我同意错误消息有点迟钝,但我怀疑问题是真实存在的...我敢打赌您正在为一个具有接触动力学(可能是偶然的)而 LQR 没有的系统建模知道如何处理非光滑机制。

当您将 System<double> 传递给 LQR 方法时,它会使用 ToAutoDiffXd() 对其进行转换,然后计算动力学(以获得线性化)。这就是为什么错误是关于 MultibodyPlant<AutoDiffXd>(而不是 double)的原因。对于您的系统,动力学需要调用碰撞引擎,这还不是完全可微的,因此会抛出错误消息。

设置 time_step=0 从时间步进模型更改为连续时​​间模型,并且确实更改了与碰撞引擎的交互。所以在某些情况下可能会有所帮助。

但我认为解决方案是确定您是否只是意外地(通过您的 SDF)包含了碰撞元素——例如您实际上并不是在尝试实施物理学。如果是,请尝试在您的 SDF 中将它们注释掉以解决此问题。也许我们 could/should 提供了一些选项,使 LQR 更容易忽略这些选项。

更新:我已经打开 https://github.com/RobotLocomotion/drake/issues/11120 以使其稍微好一点。