2001-02-16 01:13:55 +00:00

165 lines
5.2 KiB
Python

"""Finite State Machine module: contains the FSM class"""
from DirectObject import *
class FSM(DirectObject):
"""FSM class: Finite State Machine class"""
# create FSM DirectNotify category
notify = directNotify.newCategory("FSM")
#notify.setDebug(1)
# special methods
def __init__(self, name, states=[], initialStateName=None,
finalStateName=None):
"""__init__(self, string, State[], string, string)
FSM constructor: takes name, list of states, initial state and
final state as:
fsm = FSM.FSM('stopLight',
[ State.State('red', enterRed, exitRed, ['green']),
State.State('yellow', enterYellow, exitYellow, ['red']),
State.State('green', enterGreen, exitGreen, ['yellow']) ],
'red',
'red')
"""
self.setName(name)
self.setStates(states)
self.setInitialState(initialStateName)
self.setFinalState(finalStateName)
# Enter the initial state.
# It is assumed that the initial state takes no arguments.
self.__currentState = self.__initialState
#self.__enter(self.__initialState)
def enterInitialState(self):
self.__enter(self.__initialState)
def __str__(self):
"""__str__(self)"""
return "FSM: name = %s \n states = %s \n initial = %s \n final = %s \n current = %s" % (self.__name, self.__states, self.__initialState, self.__finalState, self.__currentState)
# setters and getters
def getName(self):
"""getName(self)"""
return(self.__name)
def setName(self, name):
"""setName(self, string)"""
self.__name = name
def getStates(self):
"""getStates(self)"""
return(self.__states)
def setStates(self, states):
"""setStates(self, State[])"""
self.__states = states
def getInitialState(self):
"""getInitialState(self)"""
return(self.__initialState)
def setInitialState(self, initialStateName):
"""setInitialState(self, string)"""
self.__initialState = self.getStateNamed(initialStateName)
def getFinalState(self):
"""getFinalState(self)"""
return(self.__finalState)
def setFinalState(self, finalStateName):
"""setFinalState(self, string)"""
self.__finalState = self.getStateNamed(finalStateName)
def getCurrentState(self):
"""getCurrentState(self)"""
return(self.__currentState)
# lookup funcs
def getStateNamed(self, stateName):
"""getStateNamed(self, string)
Return the state with given name if found, issue warning otherwise"""
for state in self.__states:
if (state.getName() == stateName):
return state
FSM.notify.warning("[%s] : getStateNamed: %s no such state" %
(self.__name, str(stateName)))
# basic FSM functionality
def __exitCurrent(self, argList):
"""__exitCurrent(self)
Exit the current state"""
FSM.notify.debug("[%s]: exiting %s" % (self.__name,
self.__currentState.getName()))
self.__currentState.exit(argList)
messenger.send(self.getName() + '_' +
self.__currentState.getName() + '_exited')
self.__currentState = None
def __enter(self, aState, argList=[]):
"""__enter(self, State)
Enter a given state, if it exists"""
if (aState in self.__states):
FSM.notify.debug("[%s]: entering %s" % (self.__name,
aState.getName()))
self.__currentState = aState
messenger.send(self.getName() + '_' +
aState.getName() + '_entered')
aState.enter(argList)
else:
FSM.notify.error("[%s]: enter: no such state" % self.__name)
def __transition(self, aState, enterArgList=[], exitArgList=[]):
"""__transition(self, State, enterArgList, exitArgList)
Exit currentState and enter given one"""
self.__exitCurrent(exitArgList)
self.__enter(aState, enterArgList)
def request(self, aStateName, enterArgList=[], exitArgList=[]):
"""request(self, string)
Attempt transition from currentState to given one.
Return true is transition exists to given state,
false otherwise.
"""
if (aStateName in self.__currentState.getTransitions()):
self.__transition(self.getStateNamed(aStateName),
enterArgList,
exitArgList)
return 1
# We can implicitly always transition to our final state.
elif (aStateName == self.__finalState.getName()):
FSM.notify.debug("[%s]: implicit transition to final state: %s" %
(self.__name, aStateName))
self.__transition(self.getStateNamed(aStateName),
enterArgList,
exitArgList)
return 1
else:
FSM.notify.debug("[%s]: no transition exists to %s" %
(self.__name, aStateName))
return 0