系统仿真(system simulation)就是根据系统分析的目的,在分析系统各要素性质及其相互关系的基础上,建立能描述系统结构或行为过程的、且具有一定逻辑关系或数量关系的仿真模型,据此进行试验或定量分析,以获得正确决策所需的各种信息。
系统仿真与仿真游戏的区别
系统仿真与仿真游戏本质上没有区别,都是计算机程序对现实的模拟,所不同的是各自对仿真保真度(Simulation Fidelity)的要求不同。
仿真保真度(Simulation Fidelity)用于描述仿真精度,模拟真实对应物有多近似:
- 低保真:对系统的最小模拟,接受输入产生输出
- 中等保真:对刺激能自动响应,有限精度
- 高保真:接近不可辨识或者尽可能地接近真实系统
通常系统仿真对仿真保真度的要求比仿真游戏要高。
计算步长与采样周期
采用计算机进行数值模拟或系统仿真时,经常需要采用数值解法求解模型方程。系统模型一般采用微分方程描述(也有其它形式),采用数值方法求解,就是采用迭代法逐步逼近。
计算步长
积分与微分是互逆。对一个曲线(包括直线)方程求积分,其实就是求曲线与横轴围成的面积。该面积可以用一系列间隔很小的面积块相加得到。这些小间隔的宽度就是计算步长。显然,纯粹从精度的角度考虑,步长越小越精确,因为近似面积更接近实际图形面积。
采样周期
采样周期是对一个实际信号测量时,相邻两次测量之间的时间间隔。有时候,采样周期和计算步长相似,但采样周期要考虑实际限制,且是时间单位,而计算步长不一定是时间单位,且相对自由些。两者在数值上没必然联系。对于同一问题,且都是时间量纲的话,采样周期大于等于计算步长,前者是后者的整数倍。
系统仿真包含系统模型求解,也就是在每个采样周期内,要解出模型方程。控制系统仿真时在采样周期内要解出两个模型方程:控制器模型和系统模型。
一个采样周期内可对系统模型迭代求解一次或多次。
计算步长和采样周期大小的选择
关于采样周期和计算步长的选择,一般考虑以下因素:
从求解精度考虑,越小越好。
从计算量考虑,越大越好。
采样周期与每秒帧数(Frames Per Second,FPS)
采样周期以秒为单位,则
$$FPS=\frac{1}{采样周期}$$
FPS是指每秒画面重绘的次数,用于衡量画面切换速度。FPS越大,则动画效果越平滑,当FPS小于20时,一般就能明显感受到画面的卡滞现象。
当FPS足够大(比如达到60),再增加帧数人眼也不会感受到明显的变化,反而相应地就要消耗更多资源(比如电影的胶片就需要更长了,或是电脑刷新画面需要消耗计算资源等等)。因此,选择一个适中的FPS即可。
NTSC标准的电视FPS是30,PAL标准的电视FPS是25,电影的FPS标准为24。
WebGL动画
WebGL是一种JavaScript API,用于在不使用插件的情况下在任何兼容的网页浏览器中呈现交互式2D和3D图形。但要产生WebGL动画,需要对运动的场景不停的采样,即不停地拍照。JavaScript的采样函数主要有setInterval方法和requestAnimationFrame方法。
setInterval方法
如果要设置特定的FPS(虽然严格来说,即使使用这种方法,JavaScript也不能保证帧数精确性),可以使用JavaScript DOM定义的方法:
1 | setInterval(fn,mesc) |
其中,fn是每过msec毫秒执行的函数,如果将fn定义为重绘画面的函数,就能实现动画效果。setInterval函数返回一个变量timer,如果需要停止重绘,需要使用clearInterval方法,并传入该变量timer。
requestAnimationFrame方法
大多数时候,我们并不在意多久重绘一次,这时候就适合用requestAnimationFrame方法了。它告诉浏览器在合适的时候调用指定函数,通常可能达到60FPS。
- requestAnimationFrame同样有对应的cancelAnimationFrame取消动画
- 和setInterval不同的是,由于requestAnimationFrame只请求一帧画面,因此,除了在init函数中需要调用,在被其调用的函数中需要再次调用requestAnimationFrame
使用stat.js记录FPS
stat.js是Three.js的作者Mr.Doob的另一个有用的JavaScript库。很多情况下,我们希望知道实时的FPS信息,从而更好地监测动画效果。这时候,stat.js就能提供一个很好的帮助,它占据屏幕中的一小块位置(如左上角),显示实时的FPS信息。
在HTML中引用stat.js:
1 | <script type="text/javascript" src="//mrdoob.github.io/stats.js/build/stats.min.js"></script> |
再使用如下代码监视实时FPS:
1 | var stats = new Stats(); |
参考链接
- 计算步长和采样周期,by 王永林.
- 离散和连续模拟之间的实际区别是什么?,by UF Game.
- 系统仿真,by 百度百科.
- 开源的物理引擎,by M. Jones.
- 数值分析,by wikipedia.
- three.js 入门详解(二),by Levi.
- WebGL,by wikipedia.
- stats.js, by mydoob.
- 详解JavaScript中的Event Loop(事件循环)机制,by 暮雨清秋.