我習慣在 Matlab 中進行離散時間控制系統模擬,現在我正在嘗試 python 和 numpy。
所以,我的下面的代碼正在作業,但我想迭代 numpy 向量而不是將值附加到串列中。可能嗎?
換句話說,而不是使用
xl.append(xt)
ul.append(uc)
我想使用一些 Matlab 等價物,例如 x[:, k 1] = np.dot(Ad, x[:, k]) Bd*uc,但它不適用于我的代碼。如果我這樣做,而不是獲得預期的兩行列向量,我得到一個 2x2 矩陣和一個錯誤。
另一個問題:為什么需要使用 plt.plot(tk, u[:, 0], label='u') 代替 plt.plot(tk, u, label='u') ?
from control.matlab import *
import math
import numpy as np
import matplotlib.pyplot as plt
Ts = 0.1
N = 50
#x = np.zeros((2, N 1))
tk = np.zeros(N)
u = np.zeros(N)
v = np.random.randn(N)/86.6 #% measurement noise
wn = 1.12
wn2 = pow(wn, 2)
A = [[0, 1], [-1.5, -1.4]]
B = [[0], [1.5]]
C = [[1, 0]]
D = 0
# Control gains
K = np.array([2.64, 3.41071429])
# Now build a feedback with control law u = -K*x
Ad = np.eye(2) np.multiply(A, Ts)
Bd = np.multiply(B, Ts)
Cd = C
xt = [[1.0], [0.12]] # initial states
xl = []
ul = []
for k in range(0, N):
tk[k] = k*Ts
uc = -K.dot(xt)
xt = np.dot(Ad, xt) Bd*uc
xt[1, 0] = v[k]
xl.append(xt)
ul.append(uc)
x = np.array(xl)
u = np.array(ul)
#x = np.delete(x, N, 1) # delete the last position of x
#s = TransferFunction.s
#Gs = wn2/(s**2 0*s wn2) # This is the KF solution
#yout, T = step(Gs)
plt.rcParams["figure.figsize"] = (10, 7)
plt.figure()
#plt.plot(T, yout, label='Open loop')
plt.plot(tk, x[:, 0], label='x_0')
plt.plot(tk, x[:, 1], label='x_1')
plt.plot(tk, u[:, 0], label='u')
plt.legend()
plt.title('Pendulum ex. 7.14 Franklin book')
plt.xlabel('Time')
plt.ylabel('amp.')
plt.show()
我想要的是這樣的代碼:
from control.matlab import *
import math
import numpy as np
import matplotlib.pyplot as plt
Ts = 0.1
N = 50
x = np.zeros((2, N 1))
tk = np.zeros(N)
u = np.zeros(N)
v = np.random.randn(N)/86.6 #% measurement noise
wn = 1.12
wn2 = pow(wn, 2)
A = [[0, 1], [-1.5, -1.4]]
B = [[0], [1.5]]
C = [[1, 0]]
D = 0
# Control gains
K = np.array([2.64, 3.41071429])
# Now build a feedback with control law u = -K*x
Ad = np.eye(2) np.multiply(A, Ts)
Bd = np.multiply(B, Ts)
Cd = C
for k in range(0, N):
tk[k] = k*Ts
u[k] = -K.dot(x[:, k])
x[1, k] = v[k]
x[:, k 1] = np.dot(Ad, x[:, k]) Bd*u[k]
x = np.delete(x, N, 1) # delete the last position of x
#s = TransferFunction.s
#Gs = wn2/(s**2 0*s wn2) # This is the KF solution
#yout, T = step(Gs)
plt.rcParams["figure.figsize"] = (10, 7)
plt.figure()
#plt.plot(T, yout, label='Open loop')
plt.plot(tk, x[:, 0], label='x_0')
plt.plot(tk, x[:, 1], label='x_1')
plt.plot(tk, u[:, 0], label='u')
plt.legend()
plt.title('Pendulum ex. 7.14 Franklin book')
plt.xlabel('Time')
plt.ylabel('amp.')
plt.show()
但這會導致以下錯誤:
Traceback (most recent call last):
File "C:\Users\ ... \np_matrices_v1.py", line 46, in <module>
x[:, k 1] = np.dot(Ad, x[:, k]) Bd*u[k]
ValueError: could not broadcast input array from shape (2,2) into shape (2,)
uj5u.com熱心網友回復:
我不知道為什么,但如果你嘗試:
A = np.array([[1, 2], [2, 3]])
x = np.array([[0.5], [2.0]])
y = A.dot(x)
print(y)
xa = np.zeros((2, 10))
xa[:, 2] = A.dot(x)
你會得到:
Traceback (most recent call last):
File "C:\Users\eletr\.spyder-py3\temp.py", line 19, in <module>
xa[:, 2] = A.dot(x)
ValueError: could not broadcast input array from shape (2,1) into shape (2,)
但如果你這樣做:
import numpy as np
A = np.array([[1, 2], [2, 3]])
x = np.array([[0.5], [2.0]])
y = A.dot(x)
print(y)
xa = np.zeros((2, 10))
# xa[:, 2] = A.dot(x)
xa[:, [2]] = A.dot(x)
print(xa)
你會得到正確答案:
[[4.5]
[7. ]]
[[0. 0. 4.5 0. 0. 0. 0. 0. 0. 0. ]
[0. 0. 7. 0. 0. 0. 0. 0. 0. 0. ]]
誰能解釋一下?
uj5u.com熱心網友回復:
In [248]: A = np.array([[1, 2], [2, 3]])
...: x = np.array([[0.5], [2.0]])
In [249]: A.shape, x.shape
Out[249]: ((2, 2), (2, 1))
In [250]: y = A.dot(x)
In [251]: y.shape
Out[251]: (2, 1)
注意形狀。 x是 (2,1),因此y也是。 y可以分配給 (2,1) 槽,但不能分配給 (2,) 形狀。
In [252]: xa = np.zeros((2,5),int)
In [253]: xa
Out[253]:
array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]])
In [254]: xa[:,2]
Out[254]: array([0, 0]) # (2,) shape
In [255]: xa[:,[2]]
Out[255]:
array([[0], # (2,1) shape
[0]])
與 MATLAB 相比,numpy陣列可以是 1d,例如 (2,)。與尾隨相反,前導尺寸也是最外層的。MATLAB 很容易將 (2,3,1) 形狀簡化為 (2,3),但 (2,1,1) 僅變為 (2,1)。
broadcasting該方式numpy使用形狀不同的陣列。兩個基本規則是
- leading size 1 dimensions can added automatically to match
- size 1 dimensions can be adjusted to match
因此 (2,) 可以變成 (1,2)。
如果從 中洗掉內部 [] x,則會得到一個一維陣列:
In [256]: x = np.array([0.5, 2.0])
In [257]: x.shape
Out[257]: (2,)
In [258]: A.dot(x)
Out[258]: array([4.5, 7. ]) # (2,) shape
然后可以將其分配給一行xa:xa[:,2] = A.dot(x)
reshape并可ravel用于洗掉尺寸。還索引A.dot(x)[:,0]
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/505852.html
