SimuPy离散时间系统指南:采样数据仿真与零阶保持变换全解析
【免费下载链接】simupyA framework for modeling and simulating dynamical systems项目地址: https://gitcode.com/gh_mirrors/si/simupy
SimuPy 是开源的动力学系统仿真框架,本指南面向新手,完整讲解如何用 SimuPy 建模离散时间系统、进行采样数据仿真,并通过零阶保持(Zero-Order Hold)变换把连续时间模型精确离散化。全程只需一个采样参数dt和几行矩阵运算,无需任何 Simulink 环境。
为什么需要离散时间仿真?
真实世界的物理过程是连续的,但数字控制器(单片机、FPGA、软件 PLC)只能在固定时刻采样输入、更新输出。因此控制系统设计有两条必须走通的路:
| 场景 | 需要的模型 |
|---|---|
| 物理对象 / 数学推导 | 连续时间模型dx/dt = Ax + Bu |
| 数字控制器 / 嵌入式实现 | 离散时间模型x[k+1] = Ad·x[k] + Bd·u[k] |
SimuPy 的 DynamicalSystem 基类用同一个接口同时支持这两类系统:状态方程函数对连续系统解释为导数,对离散系统解释为状态更新方程x[k+1]。关键区分点就是采样率参数dt:
dt = 0(默认)→ 连续时间系统;dt > 0→ 离散时间系统,每经过一个采样周期更新一次状态。
第一步:建立连续时间 LTI 系统
以常见的二阶双积分器(弹簧-阻尼-质量)为例,使用LTISystem传入 A、B、C 矩阵即可,完整可运行版本见 examples/discrete_lti.py:
import numpy as np from scipy import signal, linalg from simupy.systems import LTISystem m, d, b, k = 1.0, 1.0, 1.0, 1.0 Ac = np.c_[[0, -k/m], [1, -b/m]] Bc = np.r_[0, d/m].reshape(-1, 1) Cc = np.eye(2) ct_sys = LTISystem(Ac, Bc, Cc) ct_sys.initial_condition = [1, 0]第二步:零阶保持变换精确离散化
零阶保持假设:两个采样时刻之间输入u保持为常数。对这个假设下的线性时不变(LTI)系统,scipy.signal.cont2discrete给出的离散等效矩阵Ad、Bd 是精确的——在每个采样时刻t = kT,离散系统与连续系统的状态完全一致,不存在近似误差。
变换只需一行(示例代码 examples/discrete_lti.py):
dT = 1 / (2 * np.max(np.abs(np.linalg.eigvals(Ac)))) # 采样周期 Ad, Bd, Cd, Dd, dT = signal.cont2discrete((Ac, Bc, Cc, Dc), dT) dt_sys = LTISystem(Ad, Bd, Cd, dt=dT) # dt 参数声明这是离散系统 dt_sys.initial_condition = [1, 0]💡采样周期怎么选?上式的启发式规则是dT = 1/(2·|最大特征值|):特征值越大,系统动态越快,所需采样频率越高。实际工程中还会结合奈奎斯特采样定理(采样频率 ≥ 2 倍信号最高频率)适当留裕量。
dt 参数揭秘:SimuPy 如何模拟采样
很多人好奇:SimuPy 的求解器是面向连续时间初值问题的(默认dopri5),它怎么跑离散系统?
答案在 simupy/systems/init.py 的dt属性中:当dt > 0时,SimuPy 自动把系统转换为事件驱动形式——
- 构造一个周期性事件方程
sin(πt / dt),在每个采样时刻过零触发事件; - 平时状态导数恒为 0(状态"冻结"),事件触发时由
update_equation_function调用真实的状态更新方程,一次性推进到下一采样时刻; - 无状态的离散环节(如离散控制器)则采用"保持上一次输出"的零阶保持语义。
也就是说,离散时间仿真在 SimuPy 内部是通过不连续性事件机制精确复现采样行为的,这正是它能与连续环节、反馈闭环无缝联仿的原因。
闭环反馈:离散控制器与离散系统联仿
离散化后的系统可以直接和离散控制器组成闭环,用BlockDiagram连接并调用simulate仿真(见 examples/discrete_lti.py):
from simupy.block_diagram import BlockDiagram Kd = np.linalg.solve(Bd.T @ Sd @ Bd + R, Bd.T @ Sd @ Ad) # 离散 LQR 增益 dt_ctr = LTISystem(-Kd, dt=dT) # 无状态离散控制器 dtdt_bd = BlockDiagram(dt_sys, dt_ctr) dtdt_bd.connect(dt_sys, dt_ctr) # 状态反馈给控制器 dtdt_bd.connect(dt_ctr, dt_sys) # 控制量回到系统 res = dtdt_bd.simulate(Tsim) # res.t / res.x / res.y 存放结果simulate返回的SimulationResult带有t、x、y数组属性,第一维索引时刻,第二维索引各信号分量,可直接喂给 matplotlib 绘图。示例脚本还会把"连续系统 + 离散控制器"与"全离散等效系统"的仿真结果画在同一张图上,直观验证零阶保持变换的精确性。
核心概念速查表
| 概念 | SimuPy 对应 | 说明 |
|---|---|---|
| 采样周期 | LTISystem(..., dt=T) | dt=0为连续系统,dt>0为离散系统 |
| 零阶保持变换 | scipy.signal.cont2discrete | LTI 系统下精确离散化 |
| 离散状态更新 | state_equation_function | 解释为x[k+1] = f(t, x, u) |
| 初始状态 | initial_condition | 默认全零 |
| 闭环联仿 | BlockDiagram | 支持连续/离散环节混接 |
快速上手
pip install simupy要求 Python ≥ 3.6、NumPy ≥ 1.11、SciPy ≥ 0.18;更多接口细节可参考 docs/api/systems.rst 与 docs/api/block_diagram.rst。
🎯 掌握本文三个关键点——dt参数声明离散系统、cont2discrete零阶保持变换、BlockDiagram 闭环联仿——你就已经具备了用 SimuPy 完成采样数据控制系统仿真的全部基础,下一步可以打开 examples/discrete_lti.py 动手改参数、换模型,感受离散等效的精确性。
【免费下载链接】simupyA framework for modeling and simulating dynamical systems项目地址: https://gitcode.com/gh_mirrors/si/simupy
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考