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