连续时间系统和离散时间系统仿真的入门理解

背景

项目需要用到SIMULINK转C,不得不摸索一下SIMULINK仿真工具。这个过程中涉及到一些概念,比如连续时间系统和离散时间系统,真让我头大,归其原因还是自身基础不牢,应用经验不足。

作为使用者,我的目标其实不是要弄清楚过多的算法和过多的原理,而是要重点梳理使用的逻辑,这样才能了解使用过程存在的潜在风险点。

围绕着这个目标我翻阅了微积分、信号与系统等课程,再次了解了泰勒展开、S变换、Z变换,经过了若干个混沌的夜晚,最终在克服了拿来主义的思想后,搭建了个简单仿真模型,才有了点具象的感受,在此做个总结,此文概念不一定准确,描述不一定正确,但对于我来说却有比较直观的感受,大拿们不要见笑。

怎么理解这几个概念

"什么叫连续系统仿真和离散系统仿真?

有网友说,连续系统仿真输出波形是平滑的,离散系统仿真波形是锯齿的

有网友说,计算机进行的仿真时间上都是离散的,还说连续系统仿真是解常微分方程,不依赖于前一状态,离散系统仿真则是依赖于解差分方程,必须知道之前的状态

这种概念在网上一搜一大把,懂的人是都懂,不懂的人是真不理解啊!!

从简单的仿真出发

连续时间仿真

图1是一个简单的仿真模型,simdata来源于workspace,simout存储至workspace。图2是子系统,一个最简单的积分器,这是一个连续时间系统,仿真步长为0.0002s。图3是仿真结果。

图1 仿真模型

图2 连续时间系统积分器

图3 连续时间系统仿真结果

离散时间仿真

图4 离散化处理

图4 离散化后的积分器

图5 离散化后的仿真波形

问题的摸索

连续波形和锯齿波形

确实如网友所说,连续系统的仿真波形是平滑的,离散系统的仿真波形是锯齿的,但这是真的么?

从workspace的仿真输出结果来看,不论是离散系统,还是连续系统,其仿真输出都是离散的点,步长都是仿真步长0.0002s,那说明连续系统的仿真波形也不是物理世界的连续的呀,为什么画出来的波形一个是连续的,一个是锯齿的呢?

图6

原来啊,仿真输出的结果使用的timeseries结构体,它有一个成员变量叫DataInfo,连续时间系统DataInfo的值是linear(线性插值),而离散时间系统DataInfo的值是ZOH(零阶保持,这个在离散化时可以设置),这就导致MATLAB画图时波形是不一样的。

分析到这里我总算理解了,为什么仿真结果都是离散的点,而仿真波形一个看起来是连续平滑的,一个看起来是锯齿的呢。

差分方程和微分方程

既然连续时间系统在计算机系统中的仿真也是离散的,那连续时间系统的“连续”又是指的什么呢?其实,连续时间系统和离散时间系统的“连续”和“离散”指的计算方法,确实如网友所说 连续时间系统的仿真计算基于微分方程,而离散时间系统的仿真计算基于差分方程。

这一点很多网友都提到了,并且网上一推资料在讲连续系统仿真的微分方程的,比如欧拉、龙格-库塔等等,但对于我这种入门级选手来说,总感受始终没有点破。

为了弄清楚此事,这里我们来看一下连续系统和离散系统转成C代码后的主要差别。

连续系统积分环节和离散积分环节转C代码

代码框架一致

通过定时器或中断每仿真步长触发一次计算

计算方法不一致

离散系统(左侧)采用的是差分计算方法,而连续系统(右侧)采用的是微分计算方法

在微分求解器中,有MajorTimeStep步长和MinorTimeStep步长两个概念,MajorTimeStep步长即仿真步长(这里是0.0002s),而MINOR步长则需要根据具体求解器来,对于本仿真采用的ODE3求解器来说,在每个MajorTimeStep下,实际上执行了三次MinorTimeStep步长的计算,这个概念在离散时间系统中是没有的,离散时间系统下每一个仿真步长只会计算一次。

具体来看求解器函数rt_ertODEUpdateContinuousStates,发现wxhtest_derivatives函数执行了三次,这是由ODE3求解器确定的,这个求解器的相关参数定义在rt_ODE3_A和rt_ODE3_B中,为什么这个参数可以用于求解,这个时候就需要去了解欧拉、龙格库塔这些个远古大神了。

这一顿操作下来,当前仿真步长下的值就计算完成了。

static void rt_ertODEUpdateContinuousStates(RTWSolverInfo *si )
{
  /* Solver Matrices */
  static const real_T rt_ODE3_A[3] = {
    1.0/2.0, 3.0/4.0, 1.0
  };

  static const real_T rt_ODE3_B[3][3] = {
    { 1.0/2.0, 0.0, 0.0 },

    { 0.0, 3.0/4.0, 0.0 },

    { 2.0/9.0, 1.0/3.0, 4.0/9.0 }
  };

  time_T t = rtsiGetT(si);
  time_T tnew = rtsiGetSolverStopTime(si);
  time_T h = rtsiGetStepSize(si);
  real_T *x = rtsiGetContStates(si);
  ODE3_IntgData *id = (ODE3_IntgData *)rtsiGetSolverData(si);
  real_T *y = id->y;
  real_T *f0 = id->f[0];
  real_T *f1 = id->f[1];
  real_T *f2 = id->f[2];
  real_T hB[3];
  int_T i;
  int_T nXc = 1;
  rtsiSetSimTimeStep(si,MINOR_TIME_STEP);

  /* Save the state values at time t in y, we'll use x as ynew. */
  (void) memcpy(y, x,
                (uint_T)nXc*sizeof(real_T));

  /* Assumes that rtsiSetT and ModelOutputs are up-to-date */
  /* f0 = f(t,y) */

  //第一次计算,时刻为0
  rtsiSetdX(si, f0);
  wxhtest_derivatives();  

  /* f(:,2) = feval(odefile, t + hA(1), y + f*hB(:,1), args(:)(*)); */
  hB[0] = h * rt_ODE3_B[0][0];
  for (i = 0; i < nXc; i++) {
    x[i] = y[i] + (f0[i]*hB[0]);
  }

  //第二次计算,时刻为0 + 0.0002*0.5 = 0.0001
  rtsiSetT(si, t + h*rt_ODE3_A[0]);
  rtsiSetdX(si, f1);
  wxhtest_step();
  wxhtest_derivatives();

  /* f(:,3) = feval(odefile, t + hA(2), y + f*hB(:,2), args(:)(*)); */
  for (i = 0; i <= 1; i++) {
    hB[i] = h * rt_ODE3_B[1][i];
  }

  for (i = 0; i < nXc; i++) {
    x[i] = y[i] + (f0[i]*hB[0] + f1[i]*hB[1]);
  }

  //第三次计算,时刻为0 + 0.0002*0.75 = 0.00015
  rtsiSetT(si, t + h*rt_ODE3_A[1]);
  rtsiSetdX(si, f2);
  wxhtest_step();
  wxhtest_derivatives();

  /* tnew = t + hA(3);
     ynew = y + f*hB(:,3); */
  for (i = 0; i <= 2; i++) {
    hB[i] = h * rt_ODE3_B[2][i];
  }

  for (i = 0; i < nXc; i++) {
    x[i] = y[i] + (f0[i]*hB[0] + f1[i]*hB[1] + f2[i]*hB[2]);
  }

  rtsiSetT(si, tnew);
  rtsiSetSimTimeStep(si,MAJOR_TIME_STEP);
}

分析到这里我总算摸到了 “连续系统仿真基于微分方程、离散系统仿真基于差分方程”这句话的样子了,过程很艰难,但真是大快人心呀!

再次追问基本概念

前文已经提到了,连续时间系统和离散时间系统的“连续”和“离散”指的计算方法不同,物理世界是连续的,而计算机只能是离散的,那为什么采用ODE3求解器或是其它的微分求解器的“离散点计算”能被称之连续时间系统仿真呢?

我想这又是一个基础概念的问题,因为ODE3求解器的理论基础就是在某一点N阶可导,可导即连续,这样才有局部线性化、泰勒公式、微分方程、欧拉方程、龙格-库塔等等不断延伸的概念和方法。。。。

反思一下

应该说大多数工程师在使用各种工具时往往只专注于会用,但这样在工程中常常遇到各种问题,比如文章的这些最基本的概念实际上大学课程都有学过,但一旦用起来才发现其实都不懂,我也在反思,大学里面都是从概念讲起,弱化了应用,应付了考试,其实没有真正理解,而工程上从应用开始,碰到问题后再继续回溯,最终又回到了基础概念。所以啊,解决一切问题的基础就是追本溯源,夯实基础,强化应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值