Drake中kuka.desired_state输入端口尺寸为0的报错解决问询
kuka.desired_state输入端口尺寸为0的报错问题 问题根源
你遇到的RuntimeError核心原因是执行器未关联控制器实例:虽然URDF里的6个<transmission>标签被Drake解析为6个执行器(因此plant.num_actuators()返回6),但这些执行器没有绑定控制器逻辑,导致输入端口kuka.desired_state的尺寸被设为0,而非预期的6(对应6个关节)。actuator.has_controller()返回False也直接证实了这一点——Drake不会为使用PositionJointInterface这类硬件接口的执行器自动生成控制器。
解决方案
方法1:修改URDF的硬件接口(推荐)
将URDF中<joint>和<actuator>标签内的<hardwareInterface>替换为Drake原生的控制器接口,让Drake加载时自动生成对应控制器:
<!-- 替换joint中的硬件接口 --> <joint name="arm_a1" type="revolute"> <!-- 其他属性保持不变 --> <hardwareInterface>drake::PositionControlled</hardwareInterface> </joint> <!-- 替换transmission中actuator的硬件接口 --> <transmission name="tran_a1"> <!-- 其他属性保持不变 --> <actuator name="motor_a1"> <hardwareInterface>drake::PositionControlled</hardwareInterface> <!-- 其他属性保持不变 --> </actuator> </transmission>
根据你的控制需求,还可以选择drake::VelocityControlled或drake::EffortControlled接口,Drake会自动生成对应类型的输入端口,尺寸匹配关节数。
方法2:代码中显式添加控制器
如果无法修改URDF,可在加载Plant后、调用Finalize()之前,手动为每个执行器添加控制器。以位置控制器为例:
// 假设plant是已加载URDF的MultibodyPlant实例 for (const auto& actuator : plant->GetActuators()) { if (!actuator.has_controller()) { const auto& joint = plant->GetJointByName(actuator.joint().name()); plant->AddJointPositionController(joint.name()); } } // 必须在Finalize前完成控制器添加,否则无法修改Plant结构 plant->Finalize();
若需要力矩或速度控制,可替换为AddJointEffortController或AddJointVelocityController。
方法3:检查Transmission的命名空间配置
确保URDF头部声明了Drake的命名空间,否则drake:gear_ratio和drake:rotor_inertia参数无法被正确解析,可能影响控制器生成:
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" xmlns:drake="http://drake.mit.edu" name="kuka_arm"> <!-- URDF内容 --> </robot>
验证方法
完成上述操作后,可通过以下方式确认问题解决:
- 检查
actuator.has_controller()是否对所有执行器返回True; - 调用
plant->GetInputPort("kuka.desired_state").size(),确认返回值为6; - 重新运行代码,输入端口类型检查报错应消失。
内容的提问来源于stack exchange,提问作者Michael Zeng

