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

DRAKE水弹性模型接触扭矩与力可视化异常问题问询

关于Drake水弹性接触力仿真的两个问题

我正在使用DRAKE进行仿真测试,针对Contact_F=results.hydroelastic_contact_info().F_Ac_W().get_coeffs()函数验证水弹性接触力获取功能。初始测试中,记录的接触力与施加力不符,排查发现是包导入问题(疑似来自"manipulation"包),新建虚拟环境并安装最新版DRAKE后,接触力恢复正常,相关代码已更新至GitHub仓库。

但目前仍存在两个问题:

  • 接触扭矩不符合预期:在该简单演示场景中,预期仅y轴存在接触扭矩(τ_y=1N*0.05m/2=0.025 Nm,τ_x=τ_z=0 Nm),但实际记录的τ_x、τ_y、τ_z均异常,即使更换不同施加力,结果仍不符合预期,相关截图:
    • τ_x异常截图
    • τ_y异常截图
    • τ_z异常截图
  • 力可视化异常:力箭头中的蓝色箭头指向错误。

相关演示代码如下:

def Addfloor(plant):
    parser = Parser(plant)
    floor_path= "./verification_floor.sdf"
    floor=parser.AddModelFromFile(floor_path)
    plant.WeldFrames(plant.world_frame(), plant.GetFrameByName("paddle2", floor),  
                   RigidTransform(RotationMatrix.MakeXRotation(np.pi*0/180),
                                    [0,0,0]))
    return floor

def AddBox(plant):
    parser = Parser(plant)
    box_path = "./verification_box.sdf"
    my_box = parser.AddModelFromFile(box_path)
                                           
    false_body1 = plant.AddRigidBody(
        "false_body1", my_box, SpatialInertia(0, [0, 0, 0],
                                              UnitInertia(0, 0, 0)))
    false_body2 = plant.AddRigidBody(
        "false_body2", my_box, SpatialInertia(0, [0, 0, 0],
                                              UnitInertia(0, 0, 0)))
    joint_x = plant.AddJoint(
        PrismaticJoint("joint_x", plant.world_frame(),
                       plant.GetFrameByName("false_body1"), [1, 0, 0], -5, 5))
    plant.AddJointActuator("joint_x", joint_x)
    joint_z = plant.AddJoint(
        PrismaticJoint("joint_z", plant.GetFrameByName("false_body1"),
                       plant.GetFrameByName("false_body2"), [0, 0, 1], -5, 5))
    plant.AddJointActuator("joint_z", joint_z)
    
    joint_theta = plant.AddJoint(
        RevoluteJoint("joint_theta", plant.GetFrameByName("false_body2"),
                       plant.GetFrameByName("paddleh"), [0, 1, 0], 0.5))
    plant.AddJointActuator("joint_theta", joint_theta)
    return my_box


class Box_on_floor(LeafSystem):

    def __init__(self, plant):
        LeafSystem.__init__(self)
        self._plant = plant
        self.contF_box=np.array([0,0,0,0,0,0])
        self.all_command=np.array([0,0,0])
        self.count=0
        self.DeclareAbstractInputPort("contact_results",
                                      AbstractValue.Make(ContactResults()))
        self.DeclareVectorOutputPort("actuation", 3, self.CalcOutput)

    def CalcOutput(self, context, output):
        self.count=self.count+1
        g = self._plant.gravity_field().gravity_vector()[[0,2]]
        results = self.get_input_port(0).Eval(context)
        if results.num_hydroelastic_contacts() == 0:
            self.contF_box = np.vstack((self.contF_box, [0,0,0,0,0,0]))
        for i in range(results.num_hydroelastic_contacts()):
            info = results.hydroelastic_contact_info(i)
            this_F=info.F_Ac_W().get_coeffs()
            self.contF_box = np.vstack((self.contF_box, this_F))    
        k=1/1000
        if self.count < 1500:
            F=[0,0,0]  
        elif self.count < 2500:
            F=[k*(self.count-1500), 0, 0]
        else:
            F=[k*(2500-1500), 0, 0]
        output.SetFromVector(F) 
        self.all_command = np.vstack((self.all_command, F))

# before plant finish 
builder = DiagramBuilder()
plant, scene_graph = AddMultibodyPlantSceneGraph(builder, time_step=0.001)
box = Addfloor(plant)
my_box = AddBox(plant)
plant.GetJointByName("joint_x").set_default_translation(0)
plant.GetJointByName("joint_z").set_default_translation(0.2)
plant.Finalize()

MeshcatVisualizer.AddToBuilder(builder, scene_graph, meshcat)
ContactVisualizer.AddToBuilder(
    builder, plant, meshcat,
    ContactVisualizerParams(radius=0.005))

# add system
controller = builder.AddSystem(Box_on_floor(plant))
zoh = builder.AddSystem(ZeroOrderHold(0.001,AbstractValue.Make(ContactResults())))
builder.Connect(plant.get_contact_results_output_port(), zoh.get_input_port(0))
builder.Connect(zoh.get_output_port(0), controller.get_input_port(0))
builder.Connect(controller.get_output_port(0), plant.get_actuation_input_port())
logger = LogVectorOutput(plant.get_state_output_port(my_box), builder)


# start diagarm
diagram = builder.Build()
simulator = Simulator(diagram)
context = simulator.get_mutable_context()
simulator.set_target_realtime_rate(0.5) # it defines the time step
simulator.AdvanceTo(6); # total time

我的仿真场景为:1kg的箱体静置在地面,通过x轴关节施加线性递增的外力(最大外力不超过最大静摩擦力),箱体处于静止状态。相关SDF文件已上传至上述GitHub仓库,期待得到问题解决的技术指导。

内容的提问来源于stack exchange,提问作者Lin YANG

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 09:04:57