Udacity机器人软件工程师课程笔记(二十四) - 控制(其二) - PID优化,梯度下降算法,带噪声的PID控制
7.非理想情況
(1)積分飽和
到目前為止,我們一直使用的“理想”形式的PID控制器很少用于工業中?!皶r間常數”形式更為常見。
當前說明了理想形式的一些重大缺陷。
在一個經過良好調整的系統中,積分項能夠通過使控制作用力與累積誤差成比例來消除穩態誤差。然而,這種操作模式會帶來危險。設想,如果設定值突然大幅度改變但系統動力學相應緩慢。例如,如果當前房間的溫度為50°F(10°C),然后將恒溫器上的設定值移至75°F(24°C)。加熱系統可能需要數十分鐘來將溫度驅動到所需的設定值。直到跟蹤誤差為零,積分項將繼續增長(即“飽和”),故名積分飽和。
由于累積的誤差和緩慢的系統動力學,即使達到設定點,控制器仍將繼續運行熔爐(提高溫度),從而導致較大的過沖。然后,系統將花費時間來“消除”累積的誤差,然后再次達到所需的設定點。
可能導致積分飽和的另一種情況是由于執行器飽和。如果將設定點更改得足夠遠,則即使執行器以100%輸出(即飽和)運行,系統也可能永遠無法達到期望的目標。唯一的希望是將設定值提高到可以達到的水平。
已經設計了許多策略來解決積分飽和。一個簡單的方法是在控制器輸出完全飽和時停止對誤差進行積分。
(2)噪音
大多數PID控制器實際上只是PI控制器, 那么微分增益可能帶來哪些問題?
想象一下,四軸飛行器徘徊在所需的高度,但是由于有風,所以飛行器上下顛簸。
dedt≈e?eoldΔt\frac{de}{dt} \approx \frac{e-e_{old}}{Δt}dtde?≈Δte?eold??
此處顯示了導數的有限差分形式的方程式,其中ΔtΔtΔt是一個很小的數字,可能在毫秒或微秒的數量級,最終結果是擴大差異。
在實踐中,這會在存在高頻噪聲的情況下造成嚴重的問題,因為控制器認為空氣信號發生了很大變化,并且做出了巨大的控制努力。
雖然可以添加一個低通濾波器來消除一些高頻噪聲,但是這樣做確實會降低微分控制的性能,因為它依賴于對空氣變化率的響應。通常,需要大量的實驗來平衡效果來獲得令人滿意的性能。
低通濾波器的一個簡單實現是一階遞歸濾波器,其中α\alphaα是平滑因子。α\alphaα越小,抑制的高頻噪聲就越多,這增加了控件設計者必須選擇的另一個參數。
此外,遞歸濾波器還增加了滯后。即,它延遲了控制器向系統的輸入,使系統更難控制。但是,由于此濾波器僅使用一個先前的輸出值來計算當前值,因此延遲的影響通常是比較小的。
編寫一個低通濾波器
import numpy as np
import matplotlib.pyplot as pltf1 = 5 # Hz
w1 = 2*np.pi*f1 # 角頻率
f2 = 50 # Hz
w2 = 2*np.pi*f2 # 角頻率# 創建一個時間點數組
N = 500
t = np.linspace(0, 5, N)# 創建信號
pure = np.sin(w1*t) # 純正弦波
noise = np.sin(w2*t) + np.random.normal(0, 0.2, N) # 正態分布隨機噪聲
# 0 = 正態分布的均值
# 0.2 = 正態分布的標準差
# N = 數組中元素的數目
signal = pure + noise # 嘈雜的正弦波# 遞歸低通濾波器
alpha = 0.01 # 接近零意味著更強的平滑效果filtered = np.zeros(N) # 初始化數組以存儲值
for i in range(N):if i > 1:# 用低通文件的代碼填寫過濾的[i]變量filtered[i] = alpha * (signal[i] - filtered[i-1]) + filtered[i-1]fig = plt.figure()
ax1 = fig.add_subplot(311)
ax1.plot(t, pure)
ax1.set_xlabel('Time, (sec)')
ax1.set_ylabel('Amplitude, (m)')
ax1.set_title('5 Hz, Pure Signal')ax2 = fig.add_subplot(312)
ax2.plot(t, signal)
ax2.set_xlabel('Time, (sec)')
ax2.set_ylabel('Amplitude, (m)')
ax2.set_title('Noisy Signal')ax3 = fig.add_subplot(313)
ax3.plot(t, filtered)
ax3.set_xlabel('Time, (sec)')
ax3.set_ylabel('Amplitude, (m)')
ax3.set_title('Filtered Signal')plt.tight_layout()
plt.show()
輸出如下:
8.控制設計目標和準則
(1)控制器的主要目標
-
穩定性。首先,控制器應提高系統穩定性。實際上,有很多方法可以定義和表征穩定性。適用于線性系統的一個常見定義是縮寫BIBO。BIBO代表有界輸入,有界輸出,它表示只要輸入低于某個值,那么輸出就可以保證也低于某個值。更為嚴格的定義稱為漸近穩定性。如果給出有限的輸入或初始條件,則漸近穩定的系統可以保證收斂到固定的有限值(例如,落下的球最終將落在地面上)。顯然,這對于現實世界的系統而言是非常理想的屬性。
-
跟蹤。跟蹤性能也很重要。跟蹤是指控制器跟蹤或保持參考輸入信號的能力。參考點和實際輸出之間的差異是跟蹤誤差。跟蹤任務的一個示例是建筑物中的供暖和空調系統。可以通過恒溫器設置所需的溫度,該恒溫器具有集成的傳感器以測量當前溫度,如果出現跟蹤錯誤,恒溫器將激活加熱器或空調以將溫度推向設定值。
-
魯棒性。正如統計學家喬治·博克斯(George Box)曾經寫道:“所有模型都是錯誤的,但有些模型是有用的?!崩硐肭闆r下,控制器將不會依賴于參數非常精確的非常詳細的數學模型。
-
干擾抑制。噪聲和其他測量誤差會破壞所有實際系統。雖然嘗試并限制不想要的干擾很重要,但設計可容忍干擾的控制器也很重要。
-
最優性。盡管不是每個控制器都需要,但在許多情況下,優化系統的某些屬性非常重要,例如,最小化控制工作,在給定時間間隔內最大化行進距離或最小化跟蹤誤差。最佳控制需要系統的數學模型,設置控制輸入上限和下限的約束方程式以及成本函數。梯度下降 /上升算法是優化成本函數的流行首選方法。
(2)控制器設計流程
成功的控制器依賴于系統的,多步驟的設計過程。大致而言,步驟為:
- 確定系統的性能規格(例如,最大跟蹤誤差,超調百分比,建立時間等)
- 如果可能,開發一個簡單的系統數學模型 選擇傳感器和控制器類型
- 設計控制器符合性能規格
- 如果可能,請使用仿真來測試控制器性能
- 選擇硬件/軟件來實施控制器
- 在線調音控制器
控制器的目標是促進穩定性,跟蹤性,魯棒性和抑制干擾,但是現在的問題是,“控制信號u(t)u(t)u(t)應該如何起作用才能實現這些目標?”顯然,為了最大程度地減小跟蹤誤差,控制信號應該是誤差的一部分,但是它到底是什么樣的呢?
可以斷定,u(t)u(t)u(t)應該與誤差的大小有關。換句話說,較小的誤差應產生較小的控制輸入,反之亦然。誤差e(t)e(t)e(t)也很重要最終應該變為零,或者至少可以接受的程度。
另一個相當直觀的屬性是控制輸入的變化不應太快。想象一下,如果巡航控制器只能通過完全打開或完全踩下油門和剎車來調節速度,那么旅程將是多么令人不愉快??焖倩虿环€定的輸入至少有可能在執行器上造成不必要的磨損,并可能降低穩定性。最后,如果控制信號不依賴于了解特定的模型參數(例如汽車的質量,空氣阻力系數或地形坡度),那將是有益的。
9.調優策略
到目前為止,重點是了解比例誤差、積分誤差和導數誤差的主要影響。現在把我們的注意力轉移到更系統的方法來選擇PID增益。
多年來,提出了許多不同的參數調優規則和指導原則。一些最古老和仍然被廣泛引用的技術是Ziegler-Nichols (ZN)方法。
齊格勒和尼科爾斯發表了與PID控制調諧相關的最有影響力的論文之一,這篇論文的題目是《自動控制器的最佳設置》。
從準確性和簡潔性的角度來看,研究自動控制的純數學方法無疑是最理想的方法。
然而,不幸的是,控制的數學涉及如此令人困惑的指數函數和三角函數的組合,以至于一般的工程師沒有足夠的時間來鉆研這些函數來解決當前的問題。
為了幫助實踐控制工程師,齊格勒和尼克爾斯發表了兩個經驗推導的方法,可以用于PID調整過程,至少作為一個起點。這些規則很容易遵循,涉及到一個系統的過程,并且對于許多系統都足夠有效,這一事實無疑對這些方法的流行起了很大作用。
盡管Z-N方法不再被認為是“行業標準”,但是有必要熟悉一下它們,因為它們仍然經常遇到,而且許多現代調優指南是原始調優指南的變體。對調優方法的一些批評是:
(1)建議的增益基于來自系統對測試輸入的響應的信息太少,
(2)容易產生太多的超調,
(3)跟蹤性能差。
ZN方法1
假設:
- 該裝置對階躍輸入有s形響應。(或稱,一階加死區時間模型),
- 是開環穩定的。
ZN方法1的目標是實現良好的干擾抑制,他們將其定義為具有“四分之一衰減比”的系統響應(即,第二次超調峰值的振幅除以第一次超調峰值的振幅= 1/4)。
ZN方法2
假設:
- 該系統是一個高階系統,在閉環系統中,只采用比例控制就可以使系統達到穩態振蕩
第二種方法的目標是實現具有25%超調的閉環階躍響應。
這兩種方法都假設PID控制器具有以下形式,
u(t)=Kp(e(t)+1τi∫0te(τ)dτ+τdde(t)dtu(t) = K_p(e(t)+ \frac{1}{\tau_i}\int_0^t e(\tau)d\tau + \tau_d \frac{de(t)}{dt}u(t)=Kp?(e(t)+τi?1?∫0t?e(τ)dτ+τd?dtde(t)?
其中
τi=KPKIτd=KDKP\tau_i = \frac{K_P}{K_I} \qquad \tau_d = \frac{K_D}{K_P}τi?=KI?KP??τd?=KP?KD??
簡單的手動調整
在許多情況下,簡單的手動調整可以提供相當好的性能??梢酝ㄟ^以下方式開始:
- 將Kp設置為小且Ki = Kd = 0,
- 緩慢增加Kp以減少上升時間,
- 緩慢增加Kd以減少過沖和穩定時間。
通過“手動”調整增益,系統響應越快,穩定性越差。反之亦然。訣竅是要在兩者之間找到平衡。但是,使用上述方法找到近似解通??梢宰鳛楦到y的調整方法的起點,我們將在下面討論的梯度下降算法。
10. 梯度下降算法(“Twiddle”)
一種更常的方法是使用梯度下降算法,有時也稱為“Twiddle”。前提是要從三個增益的初始猜測向量開始。通常建議為P設置一個小的非零值,為I和D設置一個零。然后,分別對每個收益進行小幅更改,然后測試成本函數是否降低。如果是這樣,將沿相同方向不斷更改參數,否則嘗試沿相反方向調整參數。如果增益值的增加或減少都不會降低成本函數,則可以減小增益增量的大小并重復。整個循環應繼續進行,直到增量大小降至某個閾值以下。
使用python實現梯度下降算法:
Twiddle.py:
import numpy as np
import matplotlib.pyplot as pltdef ydot(y, t, dt, r, p):''' ydot 函數返回四旋翼的下一個狀態,作為當前狀態和控制輸入的函數。參數:-----------y = 增廣狀態向量(7個元素列表)t = 時間, (sec)dt = 時間間隔, (sec)r = 控制器設定值, (m)p = PID增益列表 = [kp, ki, kd]'''# 模型狀態y1 = y[0] # 高度, (m)y2 = y[1] # 速度, (m/s)y3 = y[2] # 上次誤差, (m)y4 = y[3] # 誤差的積分, (m*sec)y5 = y[4] # 比例作用系數, (m/s/s)y6 = y[5] # 積分作用系數, (m/s/s)y7 = y[6] # 微分作用系數, (m/s/s)# 當前的位置誤差, (m)e = r - y1# 作用力 (i.e., 發動機推力)Kp = p[0]Ki = p[1]Kd = p[2]up = Kp * e # 比例控制效果ui = Ki * (e * dt + y4) # 積分控制效果ud = Kd * (e - y3) / dt # 微分控制效果u = up + ui + ud # 完整控制效果# 執行器限制if u > umax:u = umax # 最大可能的輸出elif u < 0:u = 0 # 四軸發動機不能反向運行# 狀態控制# 如果高度 = 0if (y1 <= 0.):# 如果控制輸入,u <=重力,飛行器在地面上保持靜止,這樣可以防止四旋翼在推力太小時“墜落”地面。if u <= np.absolute(g * m / c):y1dot = 0.y2dot = 0.else:# 否則,如果u>重力,則四軸加速向上y1dot = y2y2dot = g + c / m * u - 0.75 * y2else: # 或者四軸飛行器已經升空y1dot = y2y2dot = g + c / m * u - 0.75 * y2# 計算新的狀態y1 += y1dot * dty2 += y2dot * dty3 = ey4 += e * dty5 = upy6 = uiy7 = udreturn [y1, y2, y3, y4, y5, y6, y7]def hover(p):# 該函數模擬四旋翼在高度設定值發生階躍變化時的運動。狀態作為時間的函數存儲在np.array中。# 初始條件y = [0, 0, 0, 0, 0, 0, 0]# y[0] = 初始高度, (m)# y[1] = 初始速度, (m/s)# y[2] = 當前誤差, (m)# y[3] = 積分誤差, (m*sec)# y[4] = 比例控制# y[5] = 積分控制# y[6] = 微分控制# 初始化數組以存儲值soln = np.zeros((len(time), len(y)))j = 0for t in time:y = ydot(y, t, dt, r, p)soln[j, :] = yj += 1return solndef cost_fun(soln):y0 = soln[:, 0] # 高度rise_time_index = np.argmax(y0 > r)RT = time[rise_time_index]OS = (np.max(y0) - r) / r * 100OS_pen = OSif OS < 0:OS = 0OS_pen = 100# return OS_pen**2 + RT**2return OS_pen ** 2def twiddle(tol=0.05):# 初始增益估計p = [2, 2, 2]dp = [0.10, 0.10, 0.10]soln = hover(p)best_cost = cost_fun(soln)# Twiddle算法it = 0while sum(dp) > tol:print("Iteration {}, best error = {}".format(it, best_cost))for i in range(len(p)):p[i] += dp[i]# 不能有負收益if p[i] < 0:p[i] = 0soln = hover(p)cost = cost_fun(soln)if cost < best_cost:best_cost = costdp[i] *= 1.1else:p[i] -= 2 * dp[i]# 不能有負收益if p[i] < 0:p[i] = 0soln = hover(p)cost = cost_fun(soln)if cost < best_cost:best_cost = costdp[i] *= 1.1else:p[i] += dp[i]# 不能有負收益if p[i] < 0:p[i] = 0dp[i] *= 0.9it += 1return p# 仿真參數
N = 500 # 模擬點的數目
t0 = 0 # 開始時間, (sec)
tf = 30 # 結束時間, (sec)
time = np.linspace(t0, tf, N)
dt = time[1] - time[0] # delta t, (sec)
r = 10 # 高度設置值, (m)# 模型參數
g = -9.81 # 重力, m/s/s
m = 1.54 # 四軸飛行器重量, kg
c = 10. # 機電傳動常數
umax = 5.0 # 最大控制器輸出, (m/s/s)# 使用梯度下降算法
p = twiddle()
print(p)
soln = hover(p)# 繪制結果
SP = np.ones_like(time) * r # 高度設置點
UMAX = np.ones_like(time) * umax
fig = plt.figure()
ax1 = fig.add_subplot(311)
ax1.plot(time, soln[:, 0], time, SP, '--')
ax1.set_xlabel('Time, (sec)')
ax1.set_ylabel('Altitude, (m)')
ax2 = fig.add_subplot(312)
ax2.plot(time, soln[:, 1])
ax2.set_xlabel('Time, (sec)')
ax2.set_ylabel('Speed, (m/s)')ax3 = fig.add_subplot(313)
ax3.plot(time, soln[:, 4], '-r', label="Up")
ax3.plot(time, soln[:, 5], '-b', label="Ui")
ax3.plot(time, UMAX, '--k', label="Umax")
ax3.set_xlabel('Time, (sec)')
ax3.set_ylabel('Cont. Effort, (m/s/s)')
ax3.legend(loc='upper left')
plt.tight_layout()
plt.show()
控制臺輸出如下:
Iteration 0, best error = 1512.7482851742875
Iteration 1, best error = 1328.603631778417
Iteration 2, best error = 1144.8455886580318
Iteration 3, best error = 961.5430897948886
Iteration 4, best error = 783.1182469340695
Iteration 5, best error = 612.6172237006944
Iteration 6, best error = 452.43794261727203
Iteration 7, best error = 305.7984472011611
Iteration 8, best error = 175.35951967585999
Iteration 9, best error = 76.21076989239549
Iteration 10, best error = 18.218737669978054
Iteration 11, best error = 18.218737669978054
Iteration 12, best error = 18.160375187752962
Iteration 13, best error = 0.04143894039440686
Iteration 14, best error = 0.04143894039440686
Iteration 15, best error = 0.04143894039440686
Iteration 16, best error = 0.04143894039440686
Iteration 17, best error = 0.04143894039440686
Iteration 18, best error = 0.04143894039440686
Iteration 19, best error = 0.04143894039440686
Iteration 20, best error = 0.04143894039440686
Iteration 21, best error = 0.04143894039440686
Iteration 22, best error = 0.04143894039440686
Iteration 23, best error = 0.04143894039440686
Iteration 24, best error = 0.04143894039440686
Iteration 25, best error = 0.04143894039440686
Iteration 26, best error = 0.04143894039440686
Iteration 27, best error = 0.04143894039440686
Iteration 28, best error = 0.04143894039440686
Iteration 29, best error = 0.04143894039440686
Iteration 30, best error = 0.001022595671581749
Iteration 31, best error = 0.0001246204006485597
Iteration 32, best error = 0.0001246204006485597
Iteration 33, best error = 0.0001246204006485597
Iteration 34, best error = 0.0001246204006485597
Iteration 35, best error = 0.0001246204006485597
Iteration 36, best error = 0.0001246204006485597
[3.625276313216848, 0.1882787020485744, 1.7111168918908104]
plt輸出如下:
11.帶噪聲的PID控制
考慮實際情況,我們加上噪音來使用前面介紹的幾種控制方法進行優化。
程序如下
hover_plot.py
import numpy as np
import matplotlib.pyplot as plt
from PID_controller import PID_Controller
from quad1d_eom import ydot# 仿真參數
N = 600 # 仿真的點數
t0 = 0 # 起始時間(sec)
tf = 45 # 結束時間(sec)
time = np.linspace(t0, tf, N)
dt = time[1] - time[0] # delta t, (sec)# 核心仿真代碼
# 初始條件 (i.e., 初始狀態向量)
y = [0, 0]
# y[0] = initial altitude, (m)
# y[1] = initial speed, (m/s)# 初始化數組以存儲值
soln = np.zeros((len(time), len(y)))# 創建Open_Controller類的實例
controller = PID_Controller()# 設置kp,ki,kd的值
kp = 1.5
kd = 0.75
ki = 0.12
# 設置最大控制器輸出,單位(N)
umax = 5.0# 設置微分平滑過濾器系數
alpha = 1.0# 設置控制器的Kp值
controller.setKP(kp)# 設置控制器的Ki值
controller.setKI(ki)# 設置控制器的Kd值
controller.setKD(kd)# 設定高度目標
r = 10.0 # meters
controller.setTarget(r)# 模擬四軸運動
j = 0 # 計數器
for t in time:# 評估下一個時間點的狀態y = ydot(y, t, controller)# 儲存結果soln[j, :] = yj += 1##################################################################################
# 繪制結果
# 圖一:四軸飛行器高度隨時間的變化的曲線
SP = np.ones_like(time)*r # 高度設置點
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax1.plot(time, soln[:, 0], time, SP, '--')
ax1.set_xlabel('Time, (sec)')
ax1.set_ylabel('Altitude, (m)')# 圖二:這是四軸直升機的速度隨時間的變化曲線
ax2 = fig.add_subplot(212)
ax2.plot(time, soln[:, 1])
ax2.set_xlabel('Time, (sec)')
ax2.set_ylabel('Speed, (m/s)')
plt.tight_layout()
plt.show()fig2 = plt.figure()
ax3 = fig2.add_subplot(111)
ax3.plot(time, controller.u_p, label='u_p', linewidth=3, color='red')
ax3.plot(time, controller.u_d, label='u_d', linewidth=3, color='blue')
ax3.plot(time, controller.u_i, label='u_i', linewidth=3, color='green')
ax3.set_xlabel('Time, (sec)')
ax3.set_ylabel('Control Effort')
h, l = ax3.get_legend_handles_labels()
ax3.legend(h, l)
plt.tight_layout()
plt.show()##################
y0 = soln[:, 0]
rise_time_index = np.argmax(y0 > r)
RT = time[rise_time_index]
print("The rise time is {0:.3f} seconds".format(RT))OS = (np.max(y0) - r)/r*100
if OS < 0:OS = 0
print("The percent overshoot is {0:.1f}%".format(OS))print("The steady state offset at 45 seconds is {0:.3f} meters".format(abs(soln[-1, 0]-r)))
pid_controller
class PID_Controller:def __init__(self, kp=0.0, ki=0.0, kd=0.0, max_windup=20,start_time=0, alpha=1., u_bounds=[float('-inf'), float('inf')]):self.kp_ = float(kp)self.kd_ = float(kd)self.ki_ = float(ki)# 設置最大收束self.max_windup_ = float(max_windup)# 設置alpha值self.alpha = float(alpha)# 設置作用力飽和限制self.umin = u_bounds[0]self.umax = u_bounds[1]# 存儲相關數據self.last_timestamp_ = 0.0self.set_point_ = 0.0self.start_time_ = start_timeself.error_sum_ = 0.0self.error_past_ = 0.0# 控制效果記錄self.u_p = [0]self.u_d = [0]self.u_i = [0]# 添加一個reset函數來清除類變量def reset(self):self.set_point_ = 0.0self.kp_ = 0.0self.ki_ = 0.0self.kd_ = 0.0self.error_sum_ = 0.0self.last_timestamp_ = 0.0self.error_past_ = 0self.error_past_past_ = 0self.last_windup_ = 0.0def setTarget(self, target):# 設置飛行高度self.set_point_ = float(target)def setKP(self, kp):# 使用提供的變量設置內部kp_值self.kp_ = float(kp)def setKD(self, kd):# 使用提供的變量設置內部kd_值self.kd_ = float(kd)def setKI(self, ki):# 使用提供的變量設置內部ki_值self.ki_ = float(ki)def setMaxWindup(self, max_windup):# 創建函數來設置max_windup_self.max_windup_ = int(max_windup)def update(self, measured_value, timestamp):delta_time = timestamp - self.last_timestamp_if delta_time == 0:# Delta time is zeroreturn 0# 計算誤差error = self.set_point_ - measured_value# 設置 last_timestamp_self.last_timestamp_ = timestamp# 找到 error_sum_self.error_sum_ += error# 計算相對誤差delta_errordelta_error = error - self.error_past_# 存儲本次error,作為下次error_past_使用self.error_past_ = error# 設置error_sum_范圍if self.error_sum_ > self.max_windup_:self.error_sum_ = self.max_windup_elif self.error_sum_ < -self.max_windup_:self.error_sum_ = -self.max_windup_# 計算比例誤差p = self.kp_ * error# 計算積分誤差i = self.ki_ * self.error_sum_# 計算微分誤差,包括誤差平滑d = self.kd_ * (self.alpha * delta_error / delta_time + (1 - self.alpha) * self.error_past_ / delta_time)# 計算總控制效果u = p + d + i# 設置執行器飽和設置if u > self.umax:u = self.umaxelif u < self.umin:u = self.umin# 記錄控制效果self.u_p.append(p)self.u_d.append(d)self.u_i.append(i)return u
quad1d_eom.py
import numpy as npdef ydot(y, t, controller):'''返回下一個時間步長的狀態向量參數:----------y(k) = 狀態向量, a length 2 list= [高度, 速度]t = time, (sec)pid = PID Controller類的實例return-------y(k+1) = [y[0], y[1]] = y(k) + ydot*dt'''# 模型狀態y0 = y[0] # 高度, (m)y1 = y[1] # 速度, (m/s)# 模型參數g = -9.81 # 重力, m/s/sm = 1.54 # 四軸飛行器重量, kgc = 10.0 # 機電系統的傳輸常數# 時間步長, (sec)dt = t - controller.last_timestamp_# 控制效果u = controller.update(measured_value=y0, timestamp=t)# State derivativesif (y0 <= 0.):# 如果控制輸入,u <=重力,飛行器在地面上保持靜止,這樣可以防止四旋翼在推力太小時“墜落”地面。if u <= np.absolute(g*m/c):y0dot = 0.y1dot = 0.else: # 否則,如果u>重力,則四軸加速向上y0dot = y1y1dot = g + c/m*u - 0.75*y1else: # 或者四軸飛行器已經升空# y0dot為速度大小y0dot = y1# y1dot為加速度大小,其中0.75*y1為阻力大小y1dot = g + c/m*u - 0.75*y1y0 += y0dot*dty1 += y1dot*dt# 增加一些高度上的噪聲sigma = 0.1y0 = np.random.normal(y0, sigma, 1)return [y0, y1]
總結
以上是生活随笔為你收集整理的Udacity机器人软件工程师课程笔记(二十四) - 控制(其二) - PID优化,梯度下降算法,带噪声的PID控制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Udacity机器人软件工程师课程笔记(
- 下一篇: Udacity机器人软件工程师课程笔记(