一覧CS-14-3 · 数値・待ち行列・モデル

離散時間システムとフィードバック制御

温度の簡単なモデルを時刻順に更新し、比例制御・外乱・入力上限による違いを調べます。

説明

動的モデルは現在の状態と入力から次の状態を計算します。離散時間モデルでは一定の時間刻みごとに更新します。フィードバックは測定した状態を目標と比較し、その差を使って次の入力を決める仕組みです。

室温20度から目標30度へ加熱する例を使います。1刻みの更新をT次=20+0.8(T−20)+uとし、自然冷却と加熱入力uを表します。固定入力から比例制御へ進み、制御の強さ・外乱・入力の上限を変えます。数式で定めた簡略モデルの範囲を確認します。

1現在の状態から次の状態を計算する

温度30度で入力0なら、室温との差10度の80%が次の刻みに残ります。

temperature = 20.0; fixed = [temperature]初期温度と履歴; ambient = 20.0室温; update = lambda temperature,heater: ambient+0.8*(temperature-ambient)+heater冷却と入力を合わせた更新式; update(30,0), update(30,2)加熱なしと入力2

無加熱なら28度、入力2なら30度です。uはこのモデルで1刻みの温度上昇へ換算した値で、ワットをそのまま足しているわけではありません。

2固定入力を繰り返す

室温20から毎回入力2で加熱します。温度が上がるほど冷却量も増えるので、増分は一定ではありません。

for _ in range(6):6刻み temperature = update(temperature,2)前の温度を更新 fixed.append(temperature)履歴へ追加

状態を一刻みずつ引き継ぐ処理です。初期値を毎回20へ戻すと、時間経過のモデルにはなりません。

3固定入力の平衡点

履歴を表示し、入力2で温度30が変化しないことを照合します。

[round(t,3) for t in fixed]温度履歴, update(30,2) == 30平衡点を照合

20→22→23.6と増加し、30へ近づきます。平衡点では自然冷却2と加熱2が釣り合います。最初から毎刻み2度ずつ増え続けるモデルではありません。

4目標との差で入力を補正

平衡維持の入力2に、比例係数k×(30−T)を加えます。温度が低いほど入力を増やします。

def controlled(gain,steps,disturbance=0,limit=None):比例係数・回数・外乱・上限 temperature = 20.0初期温度 history = []履歴 for tick in range(steps):時刻を進める command = 2+gain*(30-temperature)目標との差から入力を決定 heater = command if limit is None else max(0,min(limit,command))入力の飽和 temperature = update(temperature,heater)+disturbance状態と外乱を更新 history.append((tick+1,round(heater,3),round(temperature,3)))入力と温度を記録 return history履歴

出力の各行は刻み番号・実際の入力・更新後の温度です。入力上限が指定された場合だけ0から上限の範囲へ制限します。外乱は更新ごとに温度へ加える項です。

5比例係数と収束

k=0.4とk=2を比較します。まず入力に上限も下限も付けず、数式そのものの挙動を調べます。

controlled(0.4,5)小さい比例係数, controlled(2,5)大きい比例係数

k=0.4では差が前の0.4倍となり収束します。k=2では差が−1.2倍となり、上下しながら大きくなります。負の入力は能動的な冷却を意味するため、加熱器だけでは実現できない部分も含みます。

6誤差の更新式

目標からのずれe=T−30は、外乱も入力制限もなければe次=(0.8−k)eです。係数の絶対値が1未満なら誤差が縮みます。

[(gain,0.8-gain,abs(0.8-gain)<1) for gain in [0,0.4,0.8,1.8,2]]比例係数・誤差倍率・収束条件

k=0.8ならこのモデルでは一回で誤差0になります。k=1.8は係数−1なので誤差が減らず振動します。実際の遅延や測定誤差を加えれば安定する範囲も変わります。

7一定の外乱が加わる

各刻みで追加の冷却−1度を受ける場合を計算します。比例制御だけでは定常的なずれが残ります。

controlled(0.4,12,disturbance=-1)[-3:]追加冷却ありの最後3刻み, 30-1/(0.2+0.4)平衡条件から求めた温度

温度は約28.333度へ近づきます。入力が増えることで冷却を補いますが、目標からの差が入力補正を生むため、その差が残ります。積分制御など別の仕組みを加える理由になります。

8加熱器の出力に上限を設ける

入力を0〜1に制限します。目標30を維持するには入力2が必要なので、この装置では目標に到達できません。

controlled(0.4,12,limit=1)[-3:]入力を制限した温度, update(25,1)上限入力での平衡点

温度は25へ近づきます。係数の調整だけでは入力能力の不足を解消できません。数式上の安定性と、装置の範囲内で目標を達成できるかは別に確認します。

まとめ

状態は前の刻みから引き継ぎ、入力・冷却・外乱を同じ更新式へ反映します。

比例係数を大きくすると常に良くなるわけではなく、振動や発散も起こります。

モデルの安定条件と入力上限を確認し、簡略モデルの外へ結果をそのまま広げません。

操作履歴と解説を振り返れます。

Python 3

1
temperature = 20.0; fixed = [temperature]; ambient = 20.0; update = lambda temperature,heater: ambient+0.8*(temperature-ambient)+heater; update(30,0), update(30,2)
(28.0, 30.0)
2
for _ in range(6): temperature = update(temperature,2) fixed.append(temperature)
3
[round(t,3) for t in fixed], update(30,2) == 30
([20.0, 22.0, 23.6, 24.88, 25.904, 26.723, 27.379], True)
4
def controlled(gain,steps,disturbance=0,limit=None): temperature = 20.0 history = [] for tick in range(steps): command = 2+gain*(30-temperature) heater = command if limit is None else max(0,min(limit,command)) temperature = update(temperature,heater)+disturbance history.append((tick+1,round(heater,3),round(temperature,3))) return history
5
controlled(0.4,5), controlled(2,5)
([(1, 6.0, 26.0), (2, 3.6, 28.4), (3, 2.64, 29.36), (4, 2.256, 29.744), (5, 2.102, 29.898)], [(1, 22.0, 42.0), (2, -22.0, 15.6), (3, 30.8, 47.28), (4, -32.56, 9.264), (5, 43.472, 54.883)])
6
[(gain,0.8-gain,abs(0.8-gain)<1) for gain in [0,0.4,0.8,1.8,2]]
[(0, 0.8, True), (0.4, 0.4, True), (0.8, 0.0, True), (1.8, -1.0, False), (2, -1.2, False)]
7
controlled(0.4,12,disturbance=-1)[-3:], 30-1/(0.2+0.4)
([(10, 2.668, 28.332), (11, 2.667, 28.333), (12, 2.667, 28.333)], 28.333333333333332)
8
controlled(0.4,12,limit=1)[-3:], update(25,1)
([(10, 1, 24.463), (11, 1, 24.571), (12, 1, 24.656)], 25.0)

演習完了