Drake框架下发布输出前更新LeafSystem离散状态相关问题咨询
问题1解答
你观察到的行为完全符合Drake Simulator的默认事件处理逻辑。
Drake的离散系统执行时序遵循严格的状态一致性规则:在任意时间点t,Simulator会先完成所有输出端口计算、状态读取操作,再执行PerStepDiscreteUpdateEvent等离散状态更新事件,更新后的离散状态仅会用于t + h(h为离散步长)之后的计算。该设计是为了避免同一步内半更新的状态导致多个输出端口结果不一致,不属于你的实现或理解疏漏。
问题2解答
有两种常用方案可以实现输出计算使用更新后的离散状态:
- 调整事件优先级:声明离散更新事件时,显式指定事件优先级高于输出端口计算的默认优先级,或者直接将更新事件的触发时机设置为
kBeforeOutputPortEvaluation,即可让离散更新在同时间步的输出计算前完成。 - 设置微小时间偏移:如果是固定时间步的控制器,可以将离散更新的触发时间设置为比输出时间早一个可忽略的微小偏移量(如步长为10ms时,设置更新在
t + 0.01 - 1e-12时刻触发),输出在t + 0.01时刻读取到的就是刚更新完成的状态值。
问题3解答
针对该场景,更推荐使用Drake内置的缓存机制实现,比手动管理离散状态更简洁且不易出错:
你可以为该LeafSystem声明一个CacheEntry,将MathematicalProgram的求解逻辑作为缓存条目的计算函数,再将两个输出端口的计算回调设置为依赖该缓存条目。该方案的优势在于:Drake会自动保证同一步内缓存仅被计算一次,两个输出端口读取的是同一份求解结果,不需要你手动处理事件时序、状态更新的顺序问题,也不会出现重复求解MathematicalProgram的性能损耗。
如果你确实需要将求解结果作为离散状态暴露给系统框架的其他模块,也可以继续沿用离散状态的设计,配合问题2中的优先级调整方案即可,不需要额外重构。
内容的提问来源于stack exchange,提问作者Brian Acosta
相关产品推荐
相关产品推荐

