又稱有限狀態自動機。
表示有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型。
FSM 分類
接受/辨識器:
- 產生二元輸出(Yes or No)來表示是否被機器接受。
- 當所有輸入被處理後,如果當前狀態是接受狀態,則輸入被接受,否則被拒絕。
- Input: 字元,(不使用動作)
- Ex. 正規語言
##變換器: - 基於輸入和/或狀態產生輸出。應用於控制。
- Ex. 電梯門控制
FSM的基礎程式概念
兩個特徵:
- 程式執行時可以清楚劃分成數個有限狀態機的步驟
- 不同的步驟程式區段只能透過一組清楚標示的變數(亦即狀態)交換資訊。=> 一程式在任兩個不同時間下,只有狀態數值不同,其餘都一樣。
Python 狀態機
$ pip install python-statemachine
照上面的紅綠燈小嘗試一下
from statemachine import StateMachine, State
import time
class TrafficLightMachine(StateMachine):
green = State('Green', initial = True)
yellow =State('Yellow')
red =State('Red')
cycle = green.to(yello) | yello.to(red) |red.to(green)
def on_enter_green(self):
#self.stop()
time.sleep(50)
def on_enter_yello(self):
#self.go()
time.sleep(10)
def on_enter_red(self):
#self.slowdown()
time.sleep(30)
def show(self):
print("now state: ",self.current_state)
print("is green: ",self.is_green)
print("is yellow: ",self.is_yellow)
print("is red: ",self,is_red)
traffic_light = TrafficLightMachine()
print( [s.identifier for s in traffic_light.states])
print( [t.identifier for t in traffic_light.transitions])
while True:
traffic_light.cycle()
traffic_light.show()
運行結果長這樣
應用在空拍機上
首先我們應先分割空拍機飛越紅色框的步驟
像這樣:
- UAV最初只執行偏航運動,以便搜索目標窗口。一旦正確檢測到目標窗口,它將保持該高度並停止偏航運動。
- 計算其當前位置與所需位置之間的相對角度(其正向將垂直於窗口平面,並且將與窗口中心對齊)。
- 開始在特定方向上移動。執行Y平面中的運動(左/右運動)以及偏航運動以便繼續檢測整個窗口正常。
- 根據窗口中心的高度連續調整其高度。
- 一旦到達所需位置,開始向窗口移動(在X平面中移動)並將迭代地執行前面的步驟。
- 每當它無法檢測到窗口時,默認情況下,它會開始遠離窗口,以便將其置於幀中並再次開始檢測
然後就可以畫出一個FSM的圖
FSM控制空拍機
class sMachine(StateMachine):
hover = State('Hover', initial = True)
correction = State(* Correction')
forward = State('Forward')
addSp = State('AddSp')
to_hover = hover.to(hover) | addSp.to(hover) | correction.to(hover) | forward.to(hover)
to_correction = hover.to(correction) | correction.to(correction) | forward.to(correction)
to_forward = hover.to(forward) | correction.to(forward) | forward.to(forward)
to_addSp = forward.to(addSp) | correction.to(addSp)
class MyModel(object):
def ______init__(self, state):
self.state = state
self.target = (-1,-1,1)
self.center = (480, 320)
self.check = False
self.canLand ~ False
self.rec_time = 0
self. self_jpxib = rospy.Subscriber ( ' /selfDefined' , test, self.cback)
self.cmd_pub - rospy.Publisher('/tello/cmd__vel*, Twist, queue_size = 10)
self.land_sub - rospy.Subscriber('/tello/status¹, TelloStatus, self.ts_callback)
self.land_pub - rospy.Publisher(*/tello/land*, Empty, queue_size - 1)
self.rate = rospy.Rate(10)
de£ cback(self, data):
self.rec_time = rospy.get_time()
self.target = data.11
def ts_callback(self, data):
if data.fly_mode — 12:
self.canLand = True
def run(self, fsm):
tprint(type(self))
while not rospy.is_shutdown():
print(self.state)
if fsm.is_hover:
self.cmd_pub.publish(Twist())
self.rate.sleep()
if (self.target[0] =- -1 and sel£.target[1】 M -1) or (rospy.get_time() - self.rec_tirae > 0.6):
fsm.to_hover()
elif abs(self.target[0] - self.center[0]) >- 60 or abs(self.target[1] - self.center(1]) >- 60:
fsm.to_correction()
elif abs(self.target[0] - self.center[0]) < 60 and abs(self.target[1] - self.center【l]) < 60:
fsm.to_forward()
if __name__ == *__main___':
rospy.init_node('h264_pub', anonymous=True)
obj = MyModel(state='hover')
fsm = sMachine(obj)
obj.run(fsm)
最後一篇將說明Behavior Tree