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

如何在Drake仿真中让低刚度连杆以指定压缩量启动?

问题描述

我尝试将连杆建模为弹簧,已在URDF中添加drake:point_contact_stiffness参数。现在有两个需求:

  • 能否让仿真以连杆处于任意挠度的状态启动?
  • 能否让低刚度系数的连杆以特定压缩量启动仿真?

我曾尝试在腿部连杆与髋部质量块之间添加棱柱关节,通过“下压”髋部质量块让连杆初始轻微压缩,但仿真效果差,腿部连杆与髋部质量块会相互飞散。

以下是地面和腿部连杆的碰撞动力学URDF示例:

<visual>
  <origin xyz="0 0 -.25" rpy="0 0 0"/>
  <geometry>
    <box size="10 1 .5" />
  </geometry>
  <material name="green">
    <color rgba="0 1 0 1" />
  </material>
</visual>

<collision name="collision_ground">
  <origin xyz="0 0 -.25" rpy="0 0 0"/>
  <geometry>
    <box size="10 1 .5" />
  </geometry>
  <drake:proximity_properties>
     <drake:hunt_crossley_dissipation value="0.1"/>
     <drake:point_contact_stiffness value="10000"/>
    </drake:proximity_properties>
</collision> 

仿真代码示例(期望腿部连杆初始带压缩量):

builder = DiagramBuilder()
compass_walker, scene_graph = AddMultibodyPlantSceneGraph(builder, time_step=0.0)
Parser(compass_walker).AddModelFromFile(file_name="compass.urdf")

compass_walker.Finalize()
compass_walker.set_name("cw")

meshcat.Delete()
visualizer = MeshcatVisualizer.AddToBuilder(builder, scene_graph, meshcat)
visualizer.set_name("visualizer")
logger = LogVectorOutput(compass_walker.get_state_output_port(), builder)


# finish building the block diagram
diagram = builder.Build()
simulator = Simulator(diagram)


context = simulator.get_mutable_context()
plant_context = compass_walker.GetMyMutableContextFromRoot(context)

context.SetContinuousState([0.0, 0.0, 0.156, -0.312, 0.0, 0.0, -0.3975, -0.3065]) #8 states


visualizer.StartRecording()
simulator.AdvanceTo(0.908)
visualizer.PublishRecording()

log = logger.FindLog(context)
解决方案

核心思路:通过位姿初始化制造预压缩

用碰撞刚度模拟弹簧的本质是依赖接触力实现弹性形变,这类形变属于约束动力学范畴,不能通过硬改关节位置实现,否则会因初始状态违反约束产生巨大冲力导致模型飞散。推荐两种可行方案:

1. 直接调整刚体初始位姿(适配碰撞刚度方案)

手动修改连杆两端刚体的相对位姿,让它们处于压缩接触状态,Drake会自动计算初始接触力维持预压缩:

# 获取目标刚体(替换为你的模型中实际的刚体名称)
leg_mass = compass_walker.GetBodyByName("leg_mass")
leg_link = compass_walker.GetBodyByName("leg_link")

# 获取默认位姿,向下移动髋部质量块制造压缩(0.05m为示例,可根据刚度调整)
mass_pose = leg_mass.default_pose()
current_z = mass_pose.translation()[2]
mass_pose.set_translation([0, 0, current_z - 0.05])

# 设置初始位姿
compass_walker.SetFreeBodyPose(plant_context, leg_mass, mass_pose)

# 清零所有刚体初始速度,避免冲力
compass_walker.SetFreeBodySpatialVelocity(plant_context, leg_mass, SpatialVelocity.Zero())
compass_walker.SetFreeBodySpatialVelocity(plant_context, leg_link, SpatialVelocity.Zero())

2. 改用弹簧阻尼约束(更可控的弹性连杆方案)

如果连杆本质是弹性部件,直接用Drake的LinearSpringDamperConstraint替代碰撞刚度,不仅更贴合物理模型,还能直接设置初始形变:

# 在MultibodyPlant Finalize之前添加弹簧约束
leg_mass = compass_walker.GetBodyByName("leg_mass")
leg_link = compass_walker.GetBodyByName("leg_link")

# 添加线性弹簧阻尼:原长0.5m,刚度1000N/m,阻尼10N·s/m
compass_walker.AddLinearSpringDamperConstraint(
    bodyA=leg_mass,
    pointA=[0, 0, 0],          # 髋部质量块的连接点
    bodyB=leg_link,
    pointB=[0, 0, 0.5],        # 腿部连杆的连接点(对应弹簧原长)
    rest_length=0.5,
    stiffness=1000,
    damping=10
)

# 初始化时调整髋部位置,让弹簧处于压缩状态(原长0.5m,初始距离0.45m)
mass_pose = leg_mass.default_pose()
mass_pose.set_translation([0, 0, mass_pose.translation()[2] - 0.05])
compass_walker.SetFreeBodyPose(plant_context, leg_mass, mass_pose)

棱柱关节方案失败原因

添加的棱柱关节会让髋部与连杆成为串联刚体,而碰撞刚度是基于接触的约束,两者同时作用会产生冗余约束冲突:关节强制保持特定距离,碰撞又禁止穿透,冲突的约束会瞬间产生巨大冲力,导致模型飞散。


内容的提问来源于stack exchange,提问作者Jasmine Terrones

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 13:02:13