Pyslvs 開發進度
- Functional trangle solver
Functional trangle solver
由於要加入速度與加速度的計算,因此決定由三角形的 solver 下手,透過 SymPy 模組協助解題,獲得 x 和 y 軸的分量。
編寫概念類似 PMKS 將方程式存起來,因此每個點都會先獲得一個位置函式,接收數值為角速度 ω 與時間 t:
$$f_{x,y}(\omega,t)$$
首先要定義幾個類型方便計算:
from sympy import pi, sqrt, cos, sin, acos, asin, diff, lambdify
from sympy.abc import w, t
class Coordinate:
def __init__(self, x, y):
self.x = x
self.y = y
#兩座標距離
def distance(self, p):
'''
Coordinate p
'''
return sqrt((p.x - self.x)**2 + (p.y - self.y)**2)
#兩座標與水平軸夾角
def m(self, p):
'''
Coordinate p
'''
return asin((p.y - self.y)/self.distance(p))
#若分量為 SymPy 函式,將其 Lambda 化回傳
@property
def functions(self):
return (
lambdify((t, w), self.x),
lambdify((t, w), self.y))
class FunctionBase:
'''
Input Coordinate should get from position function.
'''
#位置方程式
@property
def p(self):
return Coordinate(self.pxFunc, self.pyFunc)
#速度方程式:微分 1 次
@property
def v(self):
return Coordinate(diff(self.pxFunc, t), diff(self.pyFunc, t))
#加速度方程式:微分 2 次
@property
def a(self):
return Coordinate(diff(self.pxFunc, t, 2), diff(self.pyFunc, t, 2))
#急跳度方程式:微分 3 次
@property
def j(self):
return Coordinate(diff(self.pxFunc, t, 3), diff(self.pyFunc, t, 3))
用兩個固定點可以得到繞行旋轉軸的點座標,接著再構建出其他點的位置。

PLAP
由於輸入項目由角度取代成代數,之前的 PLAP 函式改為 PL 函式,輸入連桿與軸端的座標即可。
這裡採用的是圓周運動公式:
$$\left | \vec{x} \right | = r\, cos\, \theta$$ $$\left | \vec{y} \right | = r\, sin\, \theta$$
Python 程式:
class pl(FunctionBase):
def __init__(self, A, L):
self.pxFunc = A.x+L*cos(w*t)
self.pyFunc = A.y+L*sin(w*t)
PLLP
使用底邊夾角與餘弦定理得到座標。
$$\alpha = sin^{-1}(\frac{y_{B}-y_{A}}{\sqrt{(x_{B}-x_{A})^{2}+(y_{B}-y_{A})^{2}}})$$ $$\beta = cos^{-1}(\frac{L^{2}+L_{b}^{2}-R^{2}}{2\times L\times L_{b}})$$
正向:
$$x = x_{A}+L\, cos(\alpha+\beta)$$ $$y = y_{A}+L\, cos(\alpha+\beta)$$
反向:
$$x = x_{A}+L\, cos(\alpha-\beta)$$ $$y = y_{A}+L\, cos(\alpha-\beta)$$
Python 程式:
class pllp(FunctionBase):
def __init__(self, A, L, R, B, reverse=False):
alpha = A.m(B)
base = A.distance(B)
beta = acos((L**2 + base**2 - R**2)/(2*L*base))
if reverse:
self.pxFunc = A.x+L*cos(alpha-beta)
self.pyFunc = A.y+L*sin(alpha-beta)
else:
self.pxFunc = A.x+L*cos(alpha+beta)
self.pyFunc = A.y+L*sin(alpha+beta)
套入四連桿範例
應用到標準曲柄搖桿範例後,可以繪出四者的曲線圖。

通過 solver 這個函式輸入連桿參數:
def solver(mechanism, progress=False):
results = []
resultCount = len(mechanism)
for i, e in enumerate(mechanism):
if len(e)==2:
foo = pl(*e)
results.append(foo)
else:
e = list(e)
if type(e[0])==int:
e[0] = results[e[0]].p
if type(e[3])==int:
e[3] = results[e[3]].p
foo = pllp(*e)
results.append(foo)
if progress:
print("{} / {}".format(i+1, resultCount))
return results
最後會回傳一組函式物件,可以透過 FunctionBase 和 Coordinate 類型的方法取值。
p0 = Coordinate(0, 0)
p1 = Coordinate(90, 0)
results = solver([
(p0, 35.), #p2
(0, 70., 70., p1), #p3
(0, 40., 40., 1), #p4
], progress=True)
W = pi/180 #rad/s
for T in range(0, 360+1, 5):
xfun, yfun = results[2].p.functions
print("{}\t{}".format(xfun(T, W), yfun(T, W)))
亦可使用 matplotlib 繪出資料。
W = pi/180 #rad/s
plot = []
for T in range(0, 360+1, 5):
plot.append((xfun(T, W), yfun(T, W)))
import matplotlib.pyplot as plt
plt.plot(plot)
plt.show()
不過反覆測試之後,發現竟然沒辦法套用原本八連桿的配置。
這方面還在解決中,看看是輸入方面還是解題方程式哪裡出了問題。
Comments
comments powered by Disqus