记录多个 meshcat 可视化工具

Recording multiple meshcat visualizers

我想用不同的前缀 id 记录多个 meshcat 可视化工具,这样我最终可以将它们保存到一个 HTML 文件中,我以后可以与之交互。我希望不同的可视化效果相互叠加,并且能够 select/unselect 不同的可视化效果。

这里是问题的最小复制。我希望有两个 cartpole 可视化相互叠加。但是,我最终只看到其中一个被记录下来。回放录音时,另一辆推车好像卡在了终点

import meshcat
from pydrake.common import FindResourceOrThrow
​
from pydrake.multibody.plant import (
    AddMultibodyPlantSceneGraph)
from pydrake.multibody.parsing import Parser
from pydrake.systems.analysis import Simulator
from pydrake.systems.framework import DiagramBuilder
from pydrake.systems.meshcat_visualizer import (
    ConnectMeshcatVisualizer,
)
​
v = meshcat.Visualizer()
file_name = FindResourceOrThrow(
    "drake/examples/multibody/cart_pole/cart_pole.sdf")
builder = DiagramBuilder()
cart_pole, scene_graph = AddMultibodyPlantSceneGraph(builder, 0.0)
Parser(plant=cart_pole).AddModelFromFile(file_name)
cart_pole.Finalize()
​
vis = ConnectMeshcatVisualizer(builder=builder,
                                prefix="vis",
                                scene_graph=scene_graph,
                                open_browser=False)
​
vis2 = ConnectMeshcatVisualizer(
    builder=builder,
    prefix="vis2",
    scene_graph=scene_graph,
    open_browser=False)
vis2.set_name("vis2")
​
diagram = builder.Build()
diagram_context = diagram.CreateDefaultContext()
​
cart_pole_context = diagram.GetMutableSubsystemContext(
    cart_pole, diagram_context)
cart_pole.get_actuation_input_port().FixValue(cart_pole_context, .02)
​
simulator = Simulator(diagram, diagram_context)
simulator.set_publish_every_time_step(False)
vis.start_recording()
vis2.start_recording()
simulator.AdvanceTo(100)
vis.stop_recording()
vis2.stop_recording()
​
vis.publish_recording()
vis2.publish_recording()
​
# f = open("saved.html", "w")
# f.write(v.static_html())
# f.close()

这是一种解决方案。我不喜欢它,但它实现了既定目标。注意变化:

  1. 仅保存和发布一个动画
  2. MultibodyPlant 中为每个 sim 使用不同的名称命名模型
  3. 设置delete_prefix_on_load=False所以它不会清除旧的几何体
import meshcat
from pydrake.common import FindResourceOrThrow

from pydrake.multibody.plant import (AddMultibodyPlantSceneGraph)
from pydrake.multibody.parsing import Parser
from pydrake.systems.analysis import Simulator
from pydrake.systems.framework import DiagramBuilder
from pydrake.systems.meshcat_visualizer import (
    ConnectMeshcatVisualizer,
)

animation = None

for i in range(3):
    file_name = FindResourceOrThrow(
        "drake/examples/multibody/cart_pole/cart_pole.sdf")
    builder = DiagramBuilder()
    cart_pole, scene_graph = AddMultibodyPlantSceneGraph(builder, 0.0)
    Parser(plant=cart_pole).AddModelFromFile(file_name, f"plant{i}")
    cart_pole.Finalize()

    vis = ConnectMeshcatVisualizer(builder=builder,
                                   scene_graph=scene_graph,
                                   delete_prefix_on_load=False,
                                   open_browser=False)
    if animation:
        vis._animation = animation

    diagram = builder.Build()
    diagram_context = diagram.CreateDefaultContext()

    cart_pole_context = diagram.GetMutableSubsystemContext(
        cart_pole, diagram_context)
    cart_pole.get_actuation_input_port().FixValue(cart_pole_context, .02)

    simulator = Simulator(diagram, diagram_context)
    simulator.set_publish_every_time_step(False)
    vis.start_recording()
    simulator.AdvanceTo(10)
    vis.stop_recording()
    animation = vis._animation

vis.publish_recording()