LLRFLibsPy库中basic_rf_controller函数解读

source code: Github

这个函数名为basic_rf_controller,主要用于生成一个连续状态空间控制器的模型,并可以选择性地添加PI控制和频率陷波器。让我们逐步解读这个函数的实现和功能:

函数签名和参数说明

1
def basic_rf_controller(Kp, Ki, notch_conf=None, plot=False, plot_pno=1000, plot_maxf=0.0):
  • 参数
    • Kp: 比例(P)增益。
    • Ki: 积分(I)增益。
    • notch_conf: 字典类型,包含以下键:
      • freq_offs: 需要陷波的频率偏移列表,单位为Hz。
      • gain: 对应每个陷波器的增益列表(抑制比的倒数)。
      • half_bw: 对应每个陷波器的带宽一半列表,单位为rad/s。
    • plot: 布尔值,指示是否绘制控制器的频率响应图。
    • plot_pno: 绘图时的点数。
    • plot_maxf: 绘图时的频率范围(正负),单位为Hz。

参数检查和处理

1
2
3
4
5
6
7
8
9
10
# check the input
if (Kp < 0) or (Ki < 0):
return (False,) + (None,)*4

if notch_conf is not None:
if (not isinstance(notch_conf, dict)) or \
('freq_offs' not in notch_conf.keys()) or \
('gain' not in notch_conf.keys()) or \
('half_bw' not in notch_conf.keys()):
return (False,) + (None,)*4
  • 首先检查KpKi是否为非负数,如果有任何一个小于零,函数返回False和四个None
  • 如果notch_conf不为None,则检查它是否为字典,并且包含必要的键(freq_offsgainhalf_bw)。如果有任何不符合条件的情况,同样返回False和四个None

参数设置和默认值处理

1
2
plot_pno = 1000 if (plot_pno <= 0) else plot_pno
plot_maxf = 1e6 if (plot_maxf <= 0) else plot_maxf
  • 如果plot_pno小于等于0,则设置默认值为1000。
  • 如果plot_maxf小于等于0,则设置默认值为1e6(即100万Hz)。

PI控制器设计

1
2
# first get the PI controller
K_num, K_den = add_tf([Kp], [1.0], [Ki], [1.0, 0.0])
  • 使用add_tf函数创建PI控制器的传递函数表达式。这里的K_numK_den分别是传递函数的分子和分母系数。

添加陷波器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# add the notch filters
if notch_conf is not None:
# get the notch parameters
nt_f = notch_conf['freq_offs'] # frequency offset, Hz
nt_g = notch_conf['gain'] # gain
nt_wh = notch_conf['half_bw'] # half bandwidth of the notch filter, rad/s

# add the notch filter transfer functions
for i in range(len(nt_f)):
K_num, K_den = add_tf(K_num, K_den,
[nt_g[i] * nt_wh[i]],
[1.0, nt_wh[i] - 1j*2*np.pi*nt_f[i]])
K_num, K_den = add_tf(K_num, K_den,
[nt_g[i] * nt_wh[i]],
[1.0, nt_wh[i] + 1j*2*np.pi*nt_f[i]])
  • 如果notch_conf不为None,则从notch_conf中获取陷波器的参数,然后依次添加陷波器到PI控制器的传递函数中。每个陷波器由两个传递函数组成,分别对应正负偏移频率。

获得状态空间模型

1
2
# get the state-space model
Akc, Bkc, Ckc, Dkc = signal.tf2ss(K_num, K_den)
  • 使用signal.tf2ss函数将PI控制器和陷波器的传递函数转换为状态空间模型,得到状态空间的系数矩阵AkcBkcCkcDkc

绘制频率响应图

1
2
3
4
5
6
7
8
9
10
11
# plot the response
if plot:
# calculate the response
w, h = signal.freqs(K_num, K_den,
worN=np.linspace(-2*np.pi*plot_maxf,
2*np.pi*plot_maxf,
plot_pno))

# make the plot
from rf_plot import plot_basic_rf_controller
plot_basic_rf_controller(w, h)
  • 如果plotTrue,则计算PI控制器加陷波器的频率响应,并调用plot_basic_rf_controller函数绘制频率响应图。

返回结果

1
2
# return the results
return True, Akc, Bkc, Ckc, Dkc
  • 最后,返回一个元组,第一个元素为True表示函数执行成功,后面四个元素是状态空间模型的系数矩阵。

总结

这个函数实现了一个可以配置PI控制器和陷波器的连续状态空间控制器生成器。它能够根据输入的参数设置,生成相应的控制器模型,并且在需要时绘制控制器的频率响应图。

示例代码

以下是一个示例,演示如何使用basic_rf_controller函数来生成一个带有PI控制和陷波器的控制器,并绘制其频率响应图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

def basic_rf_controller(Kp, Ki, notch_conf = None, plot = False, plot_pno = 1000, plot_maxf = 0.0):
# check the input
if (Kp < 0) or (Ki < 0):
return (False,) + (None,)*4

if notch_conf is not None:
if (not isinstance(notch_conf, dict)) or \
('freq_offs' not in notch_conf.keys()) or \
('gain' not in notch_conf.keys()) or \
('half_bw' not in notch_conf.keys()):
return (False,) + (None,)*4

plot_pno = 1000 if (plot_pno <= 0) else plot_pno
plot_maxf = 1e6 if (plot_maxf <= 0) else plot_maxf

# first get the PI controller
K_num, K_den = add_tf([Kp], [1.0], [Ki], [1.0, 0.0])

# add the notch filters
if notch_conf is not None:
# get the notch parameters
nt_f = notch_conf['freq_offs'] # frequency offset, Hz
nt_g = notch_conf['gain'] # gain
nt_wh = notch_conf['half_bw'] # half bandwidth of the notch filter, rad/s

# add the notch filter transfer functions
for i in range(len(nt_f)):
K_num, K_den = add_tf(K_num, K_den,
[nt_g[i] * nt_wh[i]],
[1.0, nt_wh[i] - 1j*2*np.pi*nt_f[i]])
K_num, K_den = add_tf(K_num, K_den,
[nt_g[i] * nt_wh[i]],
[1.0, nt_wh[i] + 1j*2*np.pi*nt_f[i]])

# get the state-space model
Akc, Bkc, Ckc, Dkc = signal.tf2ss(K_num, K_den)

# plot the response
if plot:
# calculate the response
w, h = signal.freqs(K_num, K_den,
worN = np.linspace(-2*np.pi*plot_maxf,
2*np.pi*plot_maxf,
plot_pno))

# make the plot
from rf_plot import plot_basic_rf_controller
plot_basic_rf_controller(w, h)

# return the results
return True, Akc, Bkc, Ckc, Dkc

# 设置控制器参数
Kp = 1.0
Ki = 0.1

# 设置陷波器配置
notch_conf = {
'freq_offs': [50.0, 100.0], # 频率偏移列表,单位Hz
'gain': [0.5, 0.5], # 陷波器增益列表(抑制比的倒数)
'half_bw': [10.0*np.pi, 10.0*np.pi] # 陷波器带宽一半列表,单位rad/s
}

# 调用函数生成控制器模型
success, Akc, Bkc, Ckc, Dkc = basic_rf_controller(Kp, Ki, notch_conf, plot=True, plot_pno=1000, plot_maxf=200.0)

# 如果绘图成功,显示频率响应图
if success:
plt.title('Frequency Response of RF Controller')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Gain')
plt.grid(True)
plt.show()

示例解释

  1. 导入必要的库:导入了numpymatplotlib.pyplot用于绘图,以及scipy.signal中的函数用于处理信号的频率响应。
  2. 设置控制器参数:设置了比例增益Kp为1.0和积分增益Ki为0.1。
  3. 设置陷波器配置:定义了一个包含两个陷波器的配置字典notch_conf,每个陷波器的频率偏移、增益和带宽一半都有明确的设定。
  4. 调用函数生成控制器模型:调用basic_rf_controller函数,并传递设置好的参数和配置。设置plot=True表示要绘制频率响应图,plot_pno=1000plot_maxf=200.0为绘图时的点数和频率范围设置。
  5. 显示频率响应图:如果控制器模型生成成功并绘图成功,则显示频率响应图,展示控制器的频率响应特性。

example-basic-rf-controller-1.png

example-basic-rf-controller-2.png

请注意,示例中的plot_basic_rf_controller函数是一个占位符,需要根据实际情况修改或者实现,以便正确地绘制控制器的频率响应图。