You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用LCM消息初始化ManipulationStationHardwareInterface而非默认值?

Drake中ManipulationStationHardwareInterface初始化输出默认值的问题解决

问题重现

在使用Drake控制KUKA IIWA机器人、通过ManipulationStationHardwareInterface做LCM通信,并以mock_station_simulation测试时,会遇到初始化后硬件接口输出默认零向量的问题:即便给iiwa_position输入端口设置了current_position,调用simulator.Initialize()后,iiwa_position_measured的输出仍是零向量,而非预设的位置值。示例代码如下:

drake::systems::DiagramBuilder<double> builder;
auto *interface = builder.AddSystem<ManipulationStationHardwareInterface>();
interface->Connect();
auto diagram = builder.Build();

drake::systems::Simulator<double> simulator(*diagram);
auto &simulator_context = simulator.get_mutable_context();
auto &interface_context = interface->GetMyMutableContextFromRoot(&simulator_context);
interface->GetInputPort("iiwa_position").FixValue(&interface_context, current_position);

simulator.set_publish_every_time_step(false);
simulator.set_target_realtime_rate(1.0);
simulator.Initialize();
auto q = interface->GetOutputPort("iiwa_position_measured").Eval(interface_context);
std::cout << "after initialization, interface think that the position of robot is" << q << std::endl;

该问题会导致DifferentialInverseKinematicsIntegrator用默认零向量初始化内部状态,触发机器人剧烈运动;同时LogVectorOutput的第一条记录也会是无效的默认值。

原因分析

问题根源在于ManipulationStationHardwareInterface内部依赖的LcmSubscriberSystem:系统初始化阶段,订阅器不会自动读取或处理已有的LCM消息,而是使用端口的默认值(零向量)。即便给输入端口设置了位置,硬件接口的测量输出是从LCM订阅器获取的,而订阅器在初始化时还未处理任何消息,因此输出默认值。

解决方案

1. 手动给内部LCM订阅器设置初始消息

直接找到ManipulationStationHardwareInterface内部的LCM订阅器,手动传入预设的位置消息,更新其输出状态:

simulator.Initialize();

// 获取硬件接口内部的IIWA状态订阅器
const auto& iiwa_state_sub = interface->GetSubsystemByName<drake::lcm::LcmSubscriberSystem>("iiwa_state_subscriber");
auto& iiwa_sub_context = iiwa_state_sub.GetMyMutableContextFromRoot(&simulator_context);

// 构造对应的LCM状态消息
lcmt_iiwa_status iiwa_status_msg;
iiwa_status_msg.utime = 0;
iiwa_status_msg.num_joints = current_position.size();
iiwa_status_msg.joint_position_measured = current_position;
// 按需填充其他必要字段(比如关节速度、力矩等)

// 让订阅器手动处理这条消息,更新输出
iiwa_state_sub.HandleMessage(iiwa_sub_context, &iiwa_status_msg);

// 此时再获取测量输出就是预设的current_position了
auto q = interface->GetOutputPort("iiwa_position_measured").Eval(interface_context);

2. 改进逆运动学积分器的初始化逻辑

使用DifferentialInverseKinematicsIntegrator时,无需断开robot_state输入端口,只需在初始化后手动同步其内部状态:

// 假设integrator是你创建的DifferentialInverseKinematicsIntegrator实例
auto& integrator_context = integrator->GetMyMutableContextFromRoot(&simulator_context);
integrator->SetPositions(&integrator_context, current_position);

这样既保留了输入端口的连接,又确保积分器用实际位置初始化,避免运动突变。

3. 初始化后触发一次LCM消息发布(仅适用于mock环境)

在mock测试场景中,可在初始化后手动发布一次包含current_position的LCM消息,让订阅器自动接收处理:

// 初始化模拟器后
simulator.Initialize();

// 构造并发布IIWA状态消息
lcmt_iiwa_status iiwa_status_msg;
iiwa_status_msg.utime = drake::systems::Simulator::Now(&simulator_context) * 1e6;
iiwa_status_msg.num_joints = current_position.size();
iiwa_status_msg.joint_position_measured = current_position;

// 假设你有一个LCM实例
lcm_.publish("IIWA_STATUS", &iiwa_status_msg);

// 让模拟器步进来处理消息
simulator.AdvanceTo(simulator_context.get_time() + 1e-3);

补充说明

目前Drake的LcmSubscriberSystem默认不会在初始化阶段自动拉取最新LCM消息,必须通过手动干预来设置初始状态。上述方法可有效解决初始化后输出默认值的问题,让硬件接口和依赖模块使用正确的机器人初始位置。

内容的提问来源于stack exchange,提问作者Chen Wang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 17:55:15