过零检测
变步长求解器可动态调整时间步大小,使其在某个变量缓慢变化时增加,在该变量迅速变化时减小。此行为使求解器在不连续点的附近执行许多小的时间步,因为该变量在此区域中迅速变化。这可以提高精确性,但可能会导致过多的仿真时间。
Simulink® 使用一种称为过零检测的技术来准确定位不连续性,无需借助于过小的时间步。通常这种方法可以缩短仿真运行时间,但它可能会导致某些仿真在预期完成时间之前停止。
Simulink 为此使用两种算法:非自适应算法和自适应算法。有关这些方法的信息,请参阅Zero-Crossing Algorithms。
展示过多过零检测的影响
此示例提供三个说明过零行为的模型:example_bounce_two_integrators
、example_doublebounce
和 example_bounce
。
example_bounce_two_integrators
模型演示了在不使用自适应算法的情况下,过多的过零点如何导致仿真在预期完成时间之前停止。
example_bounce
模型使用比 example_bounce_two_integrators
更好的模型设计,该设计使用双精度积分器实现球的动态特性。
example_doublebounce
模型说明了自适应算法如何使用两个不同的过零要求成功解算复杂的系统。
以 example_bounce_two_integrators
模型为例。它使用两个单个积分器来计算仿真过程中球的垂直速度和位置。
通过在命令行运行
open_system('example_bounce_two_integrators')
打开模型。出现模块图后,将模型配置参数的求解器窗格中的求解器详细信息 > 过零选项 > 算法参数设置为
Nonadaptive
。将模型的停止时间设置为 20 秒。您可以在 Simulink 工具条或模型配置参数的求解器窗格中更改此设置。对模型进行仿真。
现在,您可以查看和分析仿真结果。
仔细检查仿真的最后一部分,您将看到速度略高于零。
将仿真停止时间更改为 25 秒,然后对模型进行仿真。由于 Compare To Zero 和 Position 模块连续发生过多的过零事件,仿真将停止并显示错误。
Simulink will stop the simulation of model 'example_bounce_two_integrators' because the 2 zero crossing signal(s) identified below caused 1000 consecutive zero crossing events in time interval between 20.357636989536076 and 20.357636990631594. -------------------------------------------------------------------------------- Number of consecutive zero-crossings : 1000 Zero-crossing signal name : RelopInput Block type : RelationalOperator Block path : 'example_bounce_two_integrators/Compare To Zero/Compare' -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- Number of consecutive zero-crossings : 500 Zero-crossing signal name : IntgLoLimit Block type : Integrator Block path : 'example_bounce_two_integrators/Position' --------------------------------------------------------------------------------
虽然您可以通过调整模型配置参数 > 求解器 > 连续过零点数参数来增加此限制,但进行此更改后仍不能使仿真持续 25 秒。
将模型配置参数的求解器窗格中的求解器详细信息 > 过零选项 > 算法参数更改为 Adaptive
,并再次仿真该模型 25 秒。
放大仿真的最后 5 秒,您可以看到结果更完整,更接近弹球动态的预期解析解。您看到的震颤量是系统状态接近零时的效果,这在数值仿真的预期之内。
example_bounce
模型使用 Second-Order Integrator 模块对弹球的动态建模。从求解器性能方面来说,这是首选的球动态二重积分建模方法。要比较 example_bounce_two_integrators
和 example_bounce
的求解器性能,请尝试在两个模型上运行求解器探查工具。有关两种模型的详细比较,请参阅弹球的仿真。
有关自适应和非自适应过零检测算法的并排比较,请参阅Double Bouncing Ball: Use of Adaptive Zero-Crossing Location。
防止过多过零
可以使用下表帮助您防止模型中出现过多过零错误。
更改类型 | 更改过程 | 优势 |
---|---|---|
增加允许的过零数量 | 增加“配置参数”对话框中求解器窗格上连续过零点数选项的值。 | 这可能会给您的模型提供足够多的时间来解决过零情况。 |
放宽信号阈值 | 在“配置参数”对话框的求解器窗格上,从算法下拉列表中选择自适应,并增加信号阈值选项的值。 | 求解器需要较少的时间来准确定位过零点。这可以缩短仿真时间,并消除过多的连续过零错误数。不过,放宽信号阈值可能会降低精度。 |
使用自适应算法 | 在“配置参数”对话框的求解器窗格上,从算法下拉列表中选择自适应。 | 此算法会动态调整过零阈值,这可提高准确性,并减少检测到的连续过零点数。借助该算法,您可以同时指定时间容差和信号阈值。 |
对特定模块禁用过零检测 |
| 在本地禁用过零检测可以防止特定模块由于出现过多连续过零点而停止仿真。所有其他模块将继续受益于过零检测所提供的更高准确性。 |
对整个模型禁用过零检测 | 在“配置参数”对话框的求解器窗格上,从过零控制下拉列表中选择 | 这可防止在您模型中的任意位置检测到过零点。结果是您的模型将无法再受益于过零检测所提供的更高准确性。 |
如果使用 | 在“配置参数”对话框的求解器窗格上,从 | 有关详细信息,请参阅 Maximum order。 |
减小最大步长 | 在“配置参数”对话框的求解器窗格上,为 | 求解器可以采用足够小的步长来解决过零情况。但是,减小步长可能会增加仿真时间,在使用自适应算法时很少有必要这么做。 |
仿真器如何错过过零事件
弹球的仿真和Double Bouncing Ball: Use of Adaptive Zero-Crossing Location中的弹球和双弹球模型显示了有关不连续性的高频率波动(震颤)可能会导致仿真过早停止。
如果求解器误差容限太大,求解器还可能会完全错过过零点。这可能是因为过零检测方法会检查信号值在主时间步之后是否发生变化。符号变化指示出现过零,然后过零算法将搜索精确的过零时间。但是,如果某个时间步内发生过零,但该时间步开始和结尾的值没有指示符号变化,则求解器将越过过零而不检测它。
下图显示过零的信号。在第一个实例中,积分器越过该事件,因为符号在时间步之间没有变化。在第二实例中,求解器检测到符号变化,因此检测过零事件。
以弹球模型的双积分器实现为例。
使用求解器探查工具对仿真的最后 0.5 秒进行探查显示,仿真在 Compare To Zero 模块检测到 44 个过零事件,在 Position 模块的输出端检测到 22 个事件。
将相对容差参数的值增加到 1e-2
,而不是默认的 1e-3
。您可以在配置参数对话框的求解器窗格的求解器详细信息部分更改此参数,或使用 set_param
将 RelTol
指定为 '1e-2'
。
用求解器的新相对容差对仿真的最后 0.5 秒进行探查,结果表明,它仅在 Compare To Zero 模块上检测到 24 个过零事件,在 Position 模块的输出端检测到 12 个事件。
模块中的过零检测
模块可以记录一系列过零变量,其中每个变量都是关于可能出现不连续点的状态变量的函数。当出现不连续点时,过零函数会发生由正值或负值穿过零值的相应情况。记录的过零变量将在每个仿真步的末尾更新,符号有变化的任何变量都将视为出现了过零事件。
如果检测到任何过零点,Simulink 软件会在符号有变化的每个变量的上一个值和当前值之间进行插值,以估计过零(即不连续点)时间。
注意
过零检测算法只能包含 double
数据类型的信号的过零事件。
记录过零点的模块
下表列出了记录过零点的模块,并解释了模块如何使用过零点。
模块 | 过零检测次数 |
---|---|
一个:用于检测输入信号在上升或下降方向上过零的情况。 | |
两个,一个用于检测达到上阈值的情况,一个用于检测达到下阈值的情况。 | |
一个:用于检测信号等于常量的情况。 | |
一个:用于检测信号等于零的情况。 | |
两个:一个用于检测进入死区(输入信号减去下限)的情况,一个用于检测退出死区(输入信号减去上限)的情况。 | |
一个:如果 Enable 端口位于 Subsystem 模块内,它会提供过零检测功能。有关详细信息,请参阅使用使能子系统。 | |
一个:用于检测输入信号在上升或下降方向上出现不连续点的情况。 | |
一个:用于检测输入信号在上升或下降方向上出现不连续点的情况。 | |
一个或两个。如果没有任何输出端口,则只存在一个过零点,用于检测输入信号达到阈值的情况。如果有一个输出端口,将使用第二个过零点以便将输出从 1 恢复为 0,从而创建类似于脉冲的输出。 | |
一个:用于检测满足 If 条件的情况。 | |
如果存在重置端口,则检测发生重置的情况。 如果输出是有限的,则存在三个过零点:一个用于检测达到饱和上限的情况,一个用于检测达到饱和下限的情况,另一个用于检测不再处于饱和状态的情况。 | |
一个:对于输出向量的每个元素,用于检测输入信号是新的最小值或最大值的情况。 | |
一个:用于检测满足指定关系的情况。 | |
一个:如果中继处于关闭状态,则检测接通点。如果中继处于打开状态,则检测断开点。 | |
两个,一个用于检测达到或离开上限的情况,一个用于检测达到或离开下限的情况。 | |
五个,两个用于检测达到状态 x 上限或下限的情况,两个用于检测达到状态 dx/dt 上限或下限的情况,一个用于检测离开饱和状态的情况。 | |
一个:用于检测输入跨越零点的情况。 | |
一个:用于检测输入信号在上升或下降方向上出现不连续点的情况。 | |
一个:用于检测步长时间。 | |
一个:用于检测发生开关条件的情况。 | |
一个:用于检测满足 case 条件的情况。 | |
一个:如果 Triggered 端口位于 Subsystem 模块内,它会提供过零检测功能。有关详细信息,请参阅使用触发子系统。 | |
两个,一个用于使能端口,一个用于触发端口。有关详细信息,请参阅:使用使能触发子系统 | |
一个:用于检测输入信号在上升或下降方向上出现不连续点的情况。 |
注意
过零检测还适用于使用连续时间模式的 Stateflow® 图。有关详细信息,请参阅 Configure a Stateflow Chart for Continuous-Time Simulation (Stateflow)。
实现示例:Saturation 模块
Saturation 模块是注册了过零的 Simulink 模块的一个示例。过零检测可以在 Saturation 模块中标识以下状态事件:
输入信号达到上限。
输入信号离开上限。
输入信号达到下限。
输入信号离开下限。
定义自己的状态事件的 Simulink 模块被视为具有内部过零点。使用 Hit Crossing 模块接收过零事件的显式通知。请参阅记录过零点的模块,获取包含过零点的模块列表。
状态事件检测取决于内部过零信号的构造。模块图无法访问此信号。对于 Saturation 模块,用于检测上限过零点的信号是 zcSignal = UpperLimit
- u
,其中 u
是输入信号。
过零信号具有方向特性,它可包含下列值:
上升沿 - 当信号上升到零或通过零时,或信号离开零并变为正值时,将出现一个过零事件。
下降沿 - 当信号下降到零或通过零时,或信号离开零并变为负值时,将出现一个过零事件。
任一沿 - 无论是发生上升还是下降情况,都出现过零事件。
对于 Saturation 模块的上限,过零的方向是任一沿。这样可以使用同一过零信号检测进入和离开饱和状态的事件。