代数环错误 - 帮助修复虚假依赖

Algebraic loop error - help fixing spurious dependency

tldr:为什么我的工厂被标记为直接馈通,我如何覆盖此标签?

我在 Drake 中创建了一个工厂,它接受电压输入 phi 并使用它加上系统状态 Lam 来计算其导数 Lam_d。然后我将系统插入 FittedValueIteration 以生成我的控制策略。值迭代成功地生成了一个策略(经过检查,它看起来非常合理),但是当我尝试使用图表构建器将它连接到我的系统时,我收到以下消息,表明我有直接馈通:

RuntimeError: Reported algebraic loop detected in DiagramBuilder:
  InputPort[0] (phi) of System ::drake/pydrake/(anonymous)/Impl@000000000648eec0 (Impl<double>::PyLeafSystemBase<drake::pydrake::(anonymous)::Impl<double>::LeafSystemPublic>) is direct-feedthrough to
  OutputPort[0] (Lam) of System ::drake/pydrake/(anonymous)/Impl@000000000648eec0 (Impl<double>::PyLeafSystemBase<drake::pydrake::(anonymous)::Impl<double>::LeafSystemPublic>) is connected to
  InputPort[0] (u0) of System ::drake/systems/BarycentricMeshSystem@0000000005c6d300 (BarycentricMeshSystem<double>) is direct-feedthrough to
  OutputPort[0] (y0) of System ::drake/systems/BarycentricMeshSystem@0000000005c6d300 (BarycentricMeshSystem<double>) is connected to
  InputPort[0] (phi) of System ::drake/pydrake/(anonymous)/Impl@000000000648eec0 (Impl<double>::PyLeafSystemBase<drake::pydrake::(anonymous)::Impl<double>::LeafSystemPublic>)

我相信 vi_policy(错误消息中引用的重心网格)确实存在直接馈通,因为它只是进入一个状态并根据该状态吐出输出。然而,我的工厂使用控制器的输入来产生加速度,所以我对它被标记的原因感到困惑。我的工厂如下图,供参考:

class DEAContinuousSys(LeafSystem):
  def __init__(self):
    LeafSystem.__init__(self)

    self.DeclareContinuousState(2) # two state variables: lam, lam_d
    self.DeclareVectorOutputPort('Lam', BasicVector(2), self.CopyStateOut) # two outputs: lam_d, lam_dd
    self.input_port = self.DeclareVectorInputPort('phi', BasicVector(1)) 

  def DoCalcTimeDerivatives(self, context, derivatives): 
    Lam = context.get_continuous_state_vector().get_value() # get state, cast as regular array
    phi = self.input_port.Eval(context)
    Lam_d = DEA.dynamics(Lam, None, phi) # derive acceleration (no timestep required)
    derivatives.get_mutable_vector().SetAtIndex(0, Lam_d[0]) # set velocity
    derivatives.get_mutable_vector().SetAtIndex(1, Lam_d[1]) # set acceleration

  def CopyStateOut(self, context, output):
    Lam = context.get_continuous_state_vector().CopyToVector()
    output.SetFromVector(Lam)

我认为这个直接馈通通知是错误的,但我在解析文档以解决此问题时遇到了问题。所以我还在想办法:

  1. 为什么将其标记为直接馈通?
  2. 如何添加标签以表明它不是直接馈通?有什么好的例子可以参考吗?

编辑:重新阅读文档,我看到 1. 的答案是默认所有 LeafSystems 都将设置为直接馈通以避免意外循环。如果我的植物是符号表达的简单组合,它就可以得到正确的解释。

默认情况下,OutputPort 的声明依赖于所有 来源——包括输入端口。看来您的输出端口仅取决于您的连续状态。您可以修改您的声明以明确拼写出来。那应该会让你的代数环消失。

尝试:

self.DeclareVectorOutputPort('Lam', BasicVector(2), self.CopyStateOut, 
                             prerequisites_of_calc=set([self.xc_ticket()]))

(我不是 100% 肯定 pydrake 的拼写,但我还是会花钱买这个。)