Skip to content
Published on

信号処理・制御システム完全ガイド: フーリエ変換からPID制御まで

Authors

1. 信号とシステムの基礎

1.1 信号の分類

信号(Signal)とは情報を伝達する物理量の変化です。主な分類を以下に示します。

連続時間信号 vs 離散時間信号

連続時間(CT)信号はすべての tRt \in \mathbb{R} で定義されます。例: アナログ音声信号 x(t)=Acos(ω0t+ϕ)x(t) = A\cos(\omega_0 t + \phi)

離散時間(DT)信号は整数インデックス nZn \in \mathbb{Z} でのみ定義されます。例: デジタル音声サンプル列 x[n]x[n]

エネルギー信号と電力信号

信号のエネルギー EE と平均電力 PP:

E=x(t)2dtE = \int_{-\infty}^{\infty} |x(t)|^2 \, dt

P=limT12TTTx(t)2dtP = \lim_{T \to \infty} \frac{1}{2T} \int_{-T}^{T} |x(t)|^2 \, dt

E<E < \infty ならエネルギー信号、0<P<0 < P < \infty なら電力信号です。

1.2 基本信号

単位インパルス(Unit Impulse)

δ(t)={t=00t0,δ(t)dt=1\delta(t) = \begin{cases} \infty & t = 0 \\ 0 & t \neq 0 \end{cases}, \quad \int_{-\infty}^{\infty} \delta(t) \, dt = 1

サンプリング性質: x(t)δ(tt0)dt=x(t0)\int_{-\infty}^{\infty} x(t)\delta(t - t_0) \, dt = x(t_0)

単位ステップ(Unit Step)

u(t)={1t00t<0u(t) = \begin{cases} 1 & t \geq 0 \\ 0 & t < 0 \end{cases}

関係式 u(t)=tδ(τ)dτu(t) = \int_{-\infty}^{t} \delta(\tau) \, d\tau が成立します。

1.3 線形時不変(LTI)システム

LTIシステムは2つの核心的な性質を満たします。

  • 線形性(Linearity): T{ax1(t)+bx2(t)}=aT{x1(t)}+bT{x2(t)}\mathcal{T}\{ax_1(t) + bx_2(t)\} = a\mathcal{T}\{x_1(t)\} + b\mathcal{T}\{x_2(t)\}
  • 時不変性(Time Invariance): y(t)=T{x(t)}T{x(tt0)}=y(tt0)y(t) = \mathcal{T}\{x(t)\} \Rightarrow \mathcal{T}\{x(t-t_0)\} = y(t-t_0)

1.4 畳み込み(Convolution)

LTIシステムの出力は入力とインパルス応答の畳み込みで表されます。

y(t)=x(t)h(t)=x(τ)h(tτ)dτy(t) = x(t) * h(t) = \int_{-\infty}^{\infty} x(\tau) h(t - \tau) \, d\tau

離散時間の場合:

y[n]=x[n]h[n]=k=x[k]h[nk]y[n] = x[n] * h[n] = \sum_{k=-\infty}^{\infty} x[k] h[n - k]

畳み込みは交換律・結合律・分配律を満たします。


2. フーリエ級数 (Fourier Series)

2.1 周期信号のフーリエ級数

周期 T0T_0 を持つ信号 x(t)x(t) は基本周波数 ω0=2π/T0\omega_0 = 2\pi/T_0 の複素指数関数の和で表せます。

x(t)=k=ckejkω0tx(t) = \sum_{k=-\infty}^{\infty} c_k e^{jk\omega_0 t}

フーリエ係数:

ck=1T0T0x(t)ejkω0tdtc_k = \frac{1}{T_0} \int_{T_0} x(t) e^{-jk\omega_0 t} \, dt

2.2 矩形波(Square Wave)の例

振幅 A、周期 T、デューティサイクル 50% の矩形波のフーリエ係数:

ck={A/2k=0Akπsin(kπ2)k0c_k = \begin{cases} A/2 & k = 0 \\ \frac{A}{k\pi} \sin\left(\frac{k\pi}{2}\right) & k \neq 0 \end{cases}

奇数次高調波のみが存在し、高次になるほど振幅は減少します。不連続点付近ではギブス現象(Gibbs Phenomenon)が現れます。

2.3 パーセバルの定理

1T0T0x(t)2dt=k=ck2\frac{1}{T_0} \int_{T_0} |x(t)|^2 \, dt = \sum_{k=-\infty}^{\infty} |c_k|^2

時間領域の平均電力と周波数領域の係数の二乗和が等しくなります。


3. フーリエ変換 (Fourier Transform)

3.1 連続時間フーリエ変換 (CTFT)

非周期信号のフーリエ変換ペア:

X(jω)=x(t)ejωtdt(正変換)X(j\omega) = \int_{-\infty}^{\infty} x(t) e^{-j\omega t} \, dt \quad \text{(正変換)}

x(t)=12πX(jω)ejωtdω(逆変換)x(t) = \frac{1}{2\pi} \int_{-\infty}^{\infty} X(j\omega) e^{j\omega t} \, d\omega \quad \text{(逆変換)}

3.2 重要な変換ペア

信号フーリエ変換
δ(t)\delta(t)11
112πδ(ω)2\pi\delta(\omega)
ejω0te^{j\omega_0 t}2πδ(ωω0)2\pi\delta(\omega - \omega_0)
cos(ω0t)\cos(\omega_0 t)π[δ(ωω0)+δ(ω+ω0)]\pi[\delta(\omega-\omega_0)+\delta(\omega+\omega_0)]
u(t)u(t)πδ(ω)+1/(jω)\pi\delta(\omega) + 1/(j\omega)
eatu(t),a>0e^{-at}u(t), \, a>01/(a+jω)1/(a+j\omega)
rect(t/τ)\text{rect}(t/\tau)τsinc(ωτ/2)\tau \cdot \text{sinc}(\omega\tau/2)

3.3 フーリエ変換の性質

  • 線形性: ax1(t)+bx2(t)aX1(jω)+bX2(jω)ax_1(t) + bx_2(t) \leftrightarrow aX_1(j\omega) + bX_2(j\omega)
  • 時間シフト: x(tt0)ejωt0X(jω)x(t-t_0) \leftrightarrow e^{-j\omega t_0} X(j\omega)
  • 周波数シフト(変調): ejω0tx(t)X(j(ωω0))e^{j\omega_0 t} x(t) \leftrightarrow X(j(\omega - \omega_0))
  • 畳み込み定理: x(t)h(t)X(jω)H(jω)x(t)*h(t) \leftrightarrow X(j\omega)H(j\omega)
  • 乗算定理: x(t)h(t)12πX(jω)H(jω)x(t)h(t) \leftrightarrow \frac{1}{2\pi}X(j\omega)*H(j\omega)
  • 微分: dxdtjωX(jω)\frac{dx}{dt} \leftrightarrow j\omega X(j\omega)
  • パーセバル: x(t)2dt=12πX(jω)2dω\int|x(t)|^2 dt = \frac{1}{2\pi}\int|X(j\omega)|^2 d\omega

3.4 PythonによるFFT計算

import numpy as np
from scipy.fft import fft, ifft, fftfreq, fftshift
import matplotlib.pyplot as plt

# 矩形波信号の生成
fs = 1000       # サンプリング周波数 (Hz)
T = 1.0         # 信号長 (秒)
t = np.linspace(0, T, int(fs * T), endpoint=False)

from scipy.signal import square
x = square(2 * np.pi * 10 * t)   # 10Hz 矩形波

# FFT計算
N = len(x)
X = fft(x)
freqs = fftfreq(N, 1/fs)

# 両側スペクトル (正規化)
magnitude = np.abs(fftshift(X)) / N
freq_shifted = fftshift(freqs)

plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(t[:100], x[:100])
plt.title('Square Wave (time domain)')
plt.xlabel('Time (s)')

plt.subplot(1, 2, 2)
plt.plot(freq_shifted, magnitude)
plt.xlim(-100, 100)
plt.title('Fourier Transform (frequency domain)')
plt.xlabel('Frequency (Hz)')
plt.tight_layout()
plt.show()

4. 離散フーリエ変換 (DFT) と FFT

4.1 離散時間フーリエ変換 (DTFT)

離散時間信号 x[n]x[n] の DTFT:

X(ejω)=n=x[n]ejωnX(e^{j\omega}) = \sum_{n=-\infty}^{\infty} x[n] e^{-j\omega n}

逆変換:

x[n]=12πππX(ejω)ejωndωx[n] = \frac{1}{2\pi} \int_{-\pi}^{\pi} X(e^{j\omega}) e^{j\omega n} \, d\omega

DTFTは連続な周波数 ω\omega を持ち、2π2\pi 周期です。

4.2 DFTの定義

N点DFTはDTFTをN個の周波数で等間隔サンプリングしたものです。

X[k]=n=0N1x[n]ej2πkn/N,k=0,1,,N1X[k] = \sum_{n=0}^{N-1} x[n] e^{-j2\pi kn/N}, \quad k = 0, 1, \ldots, N-1

逆DFT:

x[n]=1Nk=0N1X[k]ej2πkn/N,n=0,1,,N1x[n] = \frac{1}{N} \sum_{k=0}^{N-1} X[k] e^{j2\pi kn/N}, \quad n = 0, 1, \ldots, N-1

4.3 FFTアルゴリズム

直接DFT計算の計算量は O(N2)O(N^2) ですが、FFT(クーリー・テューキーアルゴリズム)は N=2mN = 2^m のとき分割統治法で O(NlogN)O(N \log N) を実現します。

旋回因子(Twiddle Factor): WNk=ej2πk/NW_N^k = e^{-j2\pi k/N}

4.4 スペクトル解析の例

import numpy as np
from scipy.fft import fft, fftfreq
import matplotlib.pyplot as plt

# 複合信号の生成: 50Hz + 120Hz
fs = 1000           # サンプリング周波数 (Hz)
N = fs              # サンプル数 (1秒)
t = np.linspace(0, 1, N, endpoint=False)

# ノイズ付き複合信号
signal = (np.sin(2 * np.pi * 50 * t)
          + 0.5 * np.sin(2 * np.pi * 120 * t)
          + 0.2 * np.random.randn(N))

# FFT計算
yf = fft(signal)
xf = fftfreq(N, 1/fs)

# 片側スペクトル (正の周波数のみ)
half = N // 2
amplitude = 2.0 / N * np.abs(yf[:half])
freq_pos = xf[:half]

plt.figure(figsize=(10, 4))
plt.plot(freq_pos, amplitude)
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
plt.title('Single-Sided Amplitude Spectrum')
plt.axvline(x=50,  color='r', linestyle='--', label='50 Hz')
plt.axvline(x=120, color='g', linestyle='--', label='120 Hz')
plt.legend()
plt.grid(True)
plt.show()

print(f"周波数分解能: {fs/N} Hz")
print(f"ナイキスト周波数: {fs/2} Hz")

4.5 ナイキスト・シャノンのサンプリング定理

エイリアシング(折り返し歪み)なしに信号を復元するには、サンプリング周波数 fsf_s が信号の最大周波数 fmaxf_{max} の2倍以上必要です。

fs2fmax(ナイキスト条件)f_s \geq 2 f_{max} \quad \text{(ナイキスト条件)}


5. ラプラス変換 (Laplace Transform)

5.1 定義

両側ラプラス変換:

X(s)=x(t)estdt,s=σ+jωX(s) = \int_{-\infty}^{\infty} x(t) e^{-st} \, dt, \quad s = \sigma + j\omega

片側ラプラス変換:

X(s)=0x(t)estdtX(s) = \int_{0^-}^{\infty} x(t) e^{-st} \, dt

5.2 重要な変換ペア

信号 x(t)x(t)変換 X(s)X(s)収束領域
δ(t)\delta(t)11全s平面
u(t)u(t)1/s1/sRe(s)>0\text{Re}(s) > 0
eatu(t)e^{-at}u(t)1/(s+a)1/(s+a)Re(s)>a\text{Re}(s) > -a
teatu(t)te^{-at}u(t)1/(s+a)21/(s+a)^2Re(s)>a\text{Re}(s) > -a
sin(ω0t)u(t)\sin(\omega_0 t)u(t)ω0/(s2+ω02)\omega_0/(s^2+\omega_0^2)Re(s)>0\text{Re}(s) > 0
cos(ω0t)u(t)\cos(\omega_0 t)u(t)s/(s2+ω02)s/(s^2+\omega_0^2)Re(s)>0\text{Re}(s) > 0

5.3 伝達関数 (Transfer Function)

LTIシステムの入出力関係をs領域で表現:

H(s)=Y(s)X(s)=bmsm+bm1sm1++b0ansn+an1sn1++a0H(s) = \frac{Y(s)}{X(s)} = \frac{b_m s^m + b_{m-1} s^{m-1} + \cdots + b_0}{a_n s^n + a_{n-1} s^{n-1} + \cdots + a_0}

極(Poles): H(s)H(s) \to \infty となる ss の値(分母 = 0)

零点(Zeros): H(s)=0H(s) = 0 となる ss の値(分子 = 0)

すべての極がs平面の左半面(LHP)にあればBIBO安定です。

5.4 2次標準系

H(s)=ωn2s2+2ζωns+ωn2H(s) = \frac{\omega_n^2}{s^2 + 2\zeta\omega_n s + \omega_n^2}

  • ωn\omega_n: 固有角周波数(Natural Frequency)
  • ζ\zeta: 減衰比(Damping Ratio)
    • ζ<1\zeta < 1: 不足減衰(Underdamped) — 振動応答
    • ζ=1\zeta = 1: 臨界減衰(Critically Damped) — 最速無振動
    • ζ>1\zeta > 1: 過減衰(Overdamped) — 緩慢無振動

6. Z変換

6.1 定義

離散時間信号 x[n]x[n] のZ変換:

X(z)=n=x[n]zn,zCX(z) = \sum_{n=-\infty}^{\infty} x[n] z^{-n}, \quad z \in \mathbb{C}

z=ejωz = e^{j\omega} (単位円上)と置換するとDTFTに一致します。

6.2 Z変換とラプラス変換の関係

連続時間システムをサンプリング周期 TsT_s で離散化すると:

z=esTsz = e^{sT_s}

この写像によりs平面とz平面が対応します。

  • s平面の虚軸 \leftrightarrow z平面の単位円
  • s平面の左半面 \leftrightarrow z平面の単位円内部

6.3 安定性解析

離散時間システムが安定であるためには、すべての極が単位円の内部になければなりません。

zi<1すべての極に対して|z_i| < 1 \quad \text{すべての極に対して}

6.4 重要なZ変換ペア

信号 x[n]x[n]Z変換 X(z)X(z)
δ[n]\delta[n]11
u[n]u[n]z/(z1)z/(z-1)
anu[n]a^n u[n]z/(za)z/(z-a)
nanu[n]n \cdot a^n u[n]az/(za)2az/(z-a)^2
cos(ω0n)u[n]\cos(\omega_0 n)u[n]z(zcosω0)/(z22zcosω0+1)z(z-\cos\omega_0)/(z^2-2z\cos\omega_0+1)

7. デジタルフィルタ設計

7.1 FIRフィルタ vs IIRフィルタ

FIR(有限インパルス応答)フィルタ

y[n]=k=0Mbkx[nk]y[n] = \sum_{k=0}^{M} b_k x[n-k]

  • インパルス応答が有限長
  • 常に安定(フィードバックなし)
  • 線形位相を実現可能
  • 急峻な遮断特性には高次数が必要

IIR(無限インパルス応答)フィルタ

y[n]=k=0Mbkx[nk]k=1Naky[nk]y[n] = \sum_{k=0}^{M} b_k x[n-k] - \sum_{k=1}^{N} a_k y[n-k]

  • フィードバックを含み、インパルス応答は無限
  • 低次数で急峻な遮断特性
  • 位相が非線形(位相歪みの可能性)
  • 設計不良の場合は不安定になりうる

7.2 フィルタの種類

  • 低域通過フィルタ(LPF): 低周波を通過、高周波を遮断
  • 高域通過フィルタ(HPF): 高周波を通過、低周波を遮断
  • 帯域通過フィルタ(BPF): 特定の周波数帯域のみ通過
  • 帯域阻止フィルタ(BEF/Notch): 特定の周波数帯域を遮断

7.3 古典的フィルタの種類

バタワース(Butterworth): 通過帯域で最大限平坦な応答

チェビシェフ I 型: 通過帯域にリップルを許容し、より急峻な遮断特性

楕円(Elliptic): 通過帯域と阻止帯域の両方にリップルを持ち、最小次数で最大減衰

7.4 scipy.signalによるフィルタ設計

import numpy as np
from scipy import signal
import matplotlib.pyplot as plt

fs = 1000  # サンプリング周波数 (Hz)

# バタワース低域通過フィルタ (4次、遮断周波数100Hz)
nyq = fs / 2
cutoff = 100 / nyq  # 正規化周波数 (0〜1)
b_butter, a_butter = signal.butter(N=4, Wn=cutoff, btype='low')

# チェビシェフ I 型 (4次、1dBリップル、遮断周波数100Hz)
b_cheby, a_cheby = signal.cheby1(N=4, rp=1, Wn=cutoff, btype='low')

# 周波数応答の計算
w, h_butter = signal.freqz(b_butter, a_butter, fs=fs)
w, h_cheby  = signal.freqz(b_cheby,  a_cheby,  fs=fs)

plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.plot(w, 20 * np.log10(np.abs(h_butter)), label='Butterworth')
plt.plot(w, 20 * np.log10(np.abs(h_cheby)),  label='Chebyshev I')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Magnitude (dB)')
plt.title('Filter Frequency Response')
plt.legend()
plt.grid(True)
plt.ylim(-80, 5)

# ノイズ信号のフィルタリング
t = np.linspace(0, 1, fs, endpoint=False)
clean    = np.sin(2 * np.pi * 50 * t)
noisy    = clean + 0.5 * np.sin(2 * np.pi * 300 * t)
filtered = signal.filtfilt(b_butter, a_butter, noisy)

plt.subplot(1, 2, 2)
plt.plot(t[:200], noisy[:200],    alpha=0.5, label='Noisy')
plt.plot(t[:200], filtered[:200],            label='Filtered')
plt.xlabel('Time (s)')
plt.legend()
plt.title('Filtering Result')
plt.tight_layout()
plt.show()

7.5 FIRフィルタ設計 (窓関数法)

from scipy.signal import firwin, freqz

# Hamming窓を用いたFIR LPF
# タップ数 = 51、遮断周波数 = 100Hz
numtaps = 51
cutoff_hz = 100
b_fir = firwin(numtaps, cutoff_hz / (fs / 2), window='hamming')

w_fir, h_fir = freqz(b_fir, [1.0], fs=fs)
print(f"FIRフィルタ次数: {numtaps - 1}")
print(f"線形位相: True (対称係数)")

8. 制御システムの基礎

8.1 開ループ vs 閉ループ制御

開ループ(Open-Loop)制御: 出力が制御動作に影響を与えません。シンプルですが外乱やモデル誤差に弱いです。

閉ループ(Closed-Loop)制御: 出力を計測して基準入力と比較し、誤差を最小化します。フィードバックにより堅牢性が高まります。

基本的なフィードバックループの伝達関数:

Y(s)R(s)=G(s)1+G(s)H(s)\frac{Y(s)}{R(s)} = \frac{G(s)}{1 + G(s)H(s)}

ここで G(s)G(s) はプラント、H(s)H(s) はセンサの伝達関数です。

8.2 安定性: ラウス・フルビッツ基準

特性方程式 1+G(s)H(s)=01 + G(s)H(s) = 0 のすべての根がs平面の左半面にあれば安定です。

ラウス配列(Routh Array)を用いると、係数だけから極の位置を判定できます。第1列の符号変化の回数が右半面の極の数と等しくなります。

8.3 ボード線図 (Bode Plot)

周波数応答 H(jω)H(j\omega) を対数スケールで表現します。

  • ゲイン線図: 20log10H(jω)20\log_{10}|H(j\omega)| [dB] vs log10ω\log_{10}\omega
  • 位相線図: H(jω)\angle H(j\omega) [度] vs log10ω\log_{10}\omega

安定余裕:

  • 位相余裕(Phase Margin, PM): ゲインが0 dBのときの位相が -180度からどれだけ余裕があるか
  • ゲイン余裕(Gain Margin, GM): 位相が -180度のときのゲインが 0 dB からどれだけ余裕があるか

PM > 45度、GM > 6 dB が一般的に良好な設計の目安です。

from scipy import signal
import matplotlib.pyplot as plt
import numpy as np

# 2次伝達関数: H(s) = 10 / (s^2 + 2s + 10)
num = [10]
den = [1, 2, 10]
sys = signal.TransferFunction(num, den)

w, mag, phase = signal.bode(sys)

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 6))
ax1.semilogx(w, mag)
ax1.set_ylabel('Magnitude (dB)')
ax1.set_title('Bode Plot')
ax1.grid(True, which='both')

ax2.semilogx(w, phase)
ax2.set_ylabel('Phase (degrees)')
ax2.set_xlabel('Frequency (rad/s)')
ax2.grid(True, which='both')

plt.tight_layout()
plt.show()

9. PID制御器

9.1 PID制御動作

PID制御器は3つの制御動作の和です。

u(t)=Kpe(t)+Ki0te(τ)dτ+Kdde(t)dtu(t) = K_p e(t) + K_i \int_0^t e(\tau) d\tau + K_d \frac{de(t)}{dt}

ここで e(t)=r(t)y(t)e(t) = r(t) - y(t) は誤差信号です。

  • 比例(P)制御: 現在の誤差に比例した制御出力。速い応答が得られますが定常偏差が残ります。
  • 積分(I)制御: 累積誤差を解消して定常偏差をゼロに。応答が遅くなります。
  • 微分(D)制御: 誤差の変化率に反応してオーバーシュートを抑制。ノイズに敏感。

伝達関数:

C(s)=Kp+Kis+Kds=Kp(1+1Tis+Tds)C(s) = K_p + \frac{K_i}{s} + K_d s = K_p\left(1 + \frac{1}{T_i s} + T_d s\right)

9.2 ジーグラー・ニコルス調整法

方法1(開ループステップ応答):

プロセス反応曲線から無駄時間 LL と時定数 TT を求めます。

制御器KpK_pTiT_iTdT_d
PT/LT/L--
PI0.9T/L0.9T/L3L3L-
PID1.2T/L1.2T/L2L2L0.5L0.5L

方法2(閉ループ限界感度法):

Ki=Kd=0K_i = K_d = 0 として KpK_p を増加させ、持続振動が起きる限界ゲイン KuK_u と振動周期 TuT_u を求めます。

制御器KpK_pTiT_iTdT_d
PID0.6Ku0.6K_u0.5Tu0.5T_u0.125Tu0.125T_u

9.3 PythonによるPIDシミュレーション

import numpy as np
import matplotlib.pyplot as plt

class PIDController:
    def __init__(self, kp, ki, kd, dt):
        self.kp = kp
        self.ki = ki
        self.kd = kd
        self.dt = dt
        self.integral = 0.0
        self.prev_error = 0.0

    def update(self, setpoint, measured):
        error = setpoint - measured
        self.integral += error * self.dt
        derivative = (error - self.prev_error) / self.dt
        output = self.kp * error + self.ki * self.integral + self.kd * derivative
        self.prev_error = error
        return output

# 1次プラント: dy/dt = -y + u (時定数1秒)
def plant_step(y, u, dt):
    return y + dt * (-y + u)

dt = 0.01
t = np.arange(0, 10, dt)
setpoint = 1.0

pid = PIDController(kp=2.0, ki=1.0, kd=0.5, dt=dt)
y = 0.0
y_list = []

for _ in t:
    u = pid.update(setpoint, y)
    u = np.clip(u, -10, 10)   # アクチュエータ飽和
    y = plant_step(y, u, dt)
    y_list.append(y)

plt.figure(figsize=(10, 4))
plt.plot(t, y_list, label='Plant Output')
plt.axhline(setpoint, color='r', linestyle='--', label='Setpoint')
plt.xlabel('Time (s)')
plt.ylabel('Output')
plt.title('PID Control Simulation')
plt.legend()
plt.grid(True)
plt.show()

10. 状態空間表現 (State Space)

10.1 状態方程式

連続時間LTIシステムの状態空間表現:

x˙(t)=Ax(t)+Bu(t)\dot{\mathbf{x}}(t) = \mathbf{A}\mathbf{x}(t) + \mathbf{B}\mathbf{u}(t) y(t)=Cx(t)+Du(t)\mathbf{y}(t) = \mathbf{C}\mathbf{x}(t) + \mathbf{D}\mathbf{u}(t)

  • x\mathbf{x}: 状態ベクトル (n×1n \times 1)
  • u\mathbf{u}: 入力ベクトル (m×1m \times 1)
  • y\mathbf{y}: 出力ベクトル (p×1p \times 1)
  • A\mathbf{A}: システム行列 (n×nn \times n)
  • B\mathbf{B}: 入力行列 (n×mn \times m)
  • C\mathbf{C}: 出力行列 (p×np \times n)
  • D\mathbf{D}: 直達行列 (p×mp \times m)

伝達関数との関係: H(s)=C(sIA)1B+DH(s) = \mathbf{C}(s\mathbf{I} - \mathbf{A})^{-1}\mathbf{B} + \mathbf{D}

10.2 可制御性と可観測性

可制御性(Controllability): 任意の初期状態から有限時間内に任意の目標状態へ移行できるか?

可制御性行列 C=[B  AB  A2B    An1B]\mathcal{C} = [\mathbf{B} \; \mathbf{AB} \; \mathbf{A}^2\mathbf{B} \; \cdots \; \mathbf{A}^{n-1}\mathbf{B}] のランクが nn なら完全可制御。

可観測性(Observability): 出力だけから初期状態を決定できるか?

可観測性行列 O=[CT  (CA)T    (CAn1)T]T\mathcal{O} = [\mathbf{C}^T \; (\mathbf{CA})^T \; \cdots \; (\mathbf{CA}^{n-1})^T]^T のランクが nn なら完全可観測。

10.3 線形二次レギュレータ (LQR)

二次コスト関数を最小化する最適状態フィードバック制御:

J=0(xTQx+uTRu)dtJ = \int_0^{\infty} (\mathbf{x}^T \mathbf{Q} \mathbf{x} + \mathbf{u}^T \mathbf{R} \mathbf{u}) \, dt

最適制御入力: u=Kx\mathbf{u}^* = -\mathbf{K}\mathbf{x}

Q\mathbf{Q} は状態誤差の重み、R\mathbf{R} は制御入力エネルギーの重みです。

import numpy as np
from scipy import linalg

# 二重積分器: x_ddot = u
A = np.array([[0, 1], [0, 0]])
B = np.array([[0], [1]])

# LQR重み: 位置誤差を重視
Q = np.diag([10, 1])
R = np.array([[1]])

# 連続時間代数リカッチ方程式を解く
P = linalg.solve_continuous_are(A, B, Q, R)
K = np.linalg.inv(R) @ B.T @ P

print("LQRゲインK:", K)
print("閉ループ極:", np.linalg.eigvals(A - B @ K))

11. AI/MLと信号処理

11.1 1D CNNによる信号分類

1次元畳み込みニューラルネットワークはECG、地震波、音声などの時系列信号のパターン認識に優れています。

import torch
import torch.nn as nn

class Signal1DCNN(nn.Module):
    def __init__(self, num_classes=5):
        super().__init__()
        self.conv_layers = nn.Sequential(
            nn.Conv1d(1, 32, kernel_size=7, padding=3),
            nn.BatchNorm1d(32),
            nn.ReLU(),
            nn.MaxPool1d(2),
            nn.Conv1d(32, 64, kernel_size=5, padding=2),
            nn.BatchNorm1d(64),
            nn.ReLU(),
            nn.MaxPool1d(2),
            nn.Conv1d(64, 128, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.AdaptiveAvgPool1d(8)
        )
        self.classifier = nn.Sequential(
            nn.Flatten(),
            nn.Linear(128 * 8, 256),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(256, num_classes)
        )

    def forward(self, x):
        x = self.conv_layers(x)
        return self.classifier(x)

# 使用例
model = Signal1DCNN(num_classes=5)
# 入力形状: (batch_size, channels=1, sequence_length=1000)
x = torch.randn(8, 1, 1000)
output = model(x)
print("出力形状:", output.shape)  # (8, 5)

11.2 STFTとメルスペクトログラム

音声AIシステムでは信号を時間-周波数表現に変換してからCNNで処理する手法が広く使われています。

import librosa
import numpy as np

# STFT (Short-Time Fourier Transform)
# D = librosa.stft(y)
# S_db = librosa.amplitude_to_db(np.abs(D), ref=np.max)

# メルスペクトログラム
# mel_spec = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=128)
# mel_db   = librosa.power_to_db(mel_spec, ref=np.max)

# MFCC (メル周波数ケプストラム係数)
# mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)

print("STFT: ハン窓, hop_length=512, n_fft=2048")
print("メルフィルタバンク: 128バンド, 0Hz〜ナイキスト")
print("MFCC: 音声認識では13次元がよく使われる")

11.3 信号処理 + ディープラーニングの応用例

  • ECG不整脈分類: 1D CNN + LSTMによる心拍リズム異常の検出
  • 異常振動検知: FFT特徴抽出後にオートエンコーダで異常検出
  • 音声認識: MFCC + Transformerアーキテクチャ(Whisper, wav2vec 2.0)
  • 地震検知: 地震計信号のP波・S波の自動分類
  • 脳波(EEG)解析: 周波数帯域別パワースペクトルで集中度・睡眠状態を分類

12. 確認問題

Q1. サンプリング周波数が8000 Hzのシステムで、エイリアシングなしに表現できる最大信号周波数は?

解答: 4000 Hz

解説: ナイキスト・シャノンのサンプリング定理により、エイリアシングなしに表現できる最大周波数はサンプリング周波数の半分であるナイキスト周波数(4000 Hz)です。電話音声コーデック(8 kHzサンプリング)が最大4 kHzの音声を扱える理由がこれです。

Q2. FIRフィルタがIIRフィルタと比べて持つ最大の利点は何ですか?

解答: 線形位相特性と無条件安定性

解説: FIRフィルタはフィードバックがないため常にBIBO安定です。また係数を対称に設計すれば線形位相(linear phase)が保証され、すべての周波数成分の群遅延が同一になります。これはデータ通信など位相歪みが許容されない場合に重要です。一方IIRフィルタは低次数で急峻な遮断特性が得られるという利点があります。

Q3. PID制御器における微分(D)動作の役割と欠点は何ですか?

解答: 誤差の変化率に反応してオーバーシュートを抑制しますが、測定ノイズに非常に敏感です。

解説: D動作は誤差が急激に変化するときに強い制御出力を生成し、システムが目標値を行き過ぎる現象(オーバーシュート)を抑制します。しかしノイズを含む測定値を微分するとノイズが増幅されます。実用的なPIDでは微分項にローパスフィルタを追加するか、出力を直接微分するDerivative on Measurement方式が使われます。

Q4. Z変換においてデジタルフィルタの安定条件は何ですか?

解答: すべての極がz平面の単位円の内側に位置すること。

解説: 離散時間システムの極の位置と安定性の関係: 単位円内部(絶対値1未満)なら安定、単位円上なら限界安定、単位円外部なら不安定です。これは連続時間で極がs平面の左半面にある場合に安定することと対応しています。z = exp(sT)の写像により左半面が単位円内部に対応します。

Q5. ボード線図において位相余裕(Phase Margin)が負の場合、システムはどうなりますか?

解答: 不安定(Unstable)になります。

解説: 位相余裕はゲイン交差周波数(ゲインが0 dBになる周波数)における位相が -180度からどれだけ離れているかを示します。位相余裕が負であればゲインが0 dBのときにすでに位相が -180度を超えていることを意味し、閉ループシステムは不安定になります。一般に安定で良好な応答特性を得るためにPMは45度〜60度を目標に設計します。


参考文献

  1. Oppenheim, A. V. & Schafer, R. W.Discrete-Time Signal Processing (3rd ed.), Prentice Hall, 2010
  2. Ogata, K.Modern Control Engineering (5th ed.), Prentice Hall, 2010
  3. Proakis, J. G. & Manolakis, D. G.Digital Signal Processing, Prentice Hall, 2007
  4. SciPy Signal Processing Documentationhttps://docs.scipy.org/doc/scipy/reference/signal.html
  5. MIT OpenCourseWare 6.003 — Signals and Systems — https://ocw.mit.edu/courses/6-003-signals-and-systems-fall-2011/
  6. NumPy FFT ドキュメントhttps://numpy.org/doc/stable/reference/routines.fft.html