"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);
plant
是 MultibodyPlant<double>
类型的引用
context
是 Context<double>
类型的引用
Q
的类型是 Eigen::Matrix<double, 6, 6>
R
的类型是 Vector1d
用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 以使其稍微好一点。
我正在使用以下代码创建 LQR 控制器:
systems::controllers::LinearQuadraticRegulator(
plant, context, Q, R,
Eigen::Matrix<double, 0, 0>::Zero() /* No cross state/control costs */,
actuation_port_index);
plant
是MultibodyPlant<double>
类型的引用
context
是Context<double>
类型的引用
Q
的类型是Eigen::Matrix<double, 6, 6>
R
的类型是Vector1d
用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 以使其稍微好一点。