我正在寻找一些通用的
关于我当前的C ++ Hierarchical State Machine实现的建议。
variable isMicOn = false
variable areSpeakersOn = false
variable stream = false
state recording
{
//override block for state recording
isMicOn = true //here, only isMicOn is true
//end override block for state recording
}
state playback
{
//override block for state playback
areSpeakersOn = true //here, only areSpeakersOn = true
//end override block for state playback
state alsoStreamToRemoteIp
{
//override block for state alsoStreamToRemoteIp
stream = true //here, both areSpeakersOn = true and stream = true
//end override block for state alsoStreamToRemoteIp
}
}
goToState(recording)
goToState(playback)
goToState(playback.alsoStreamToRemoteIp)
目前,HSM是作为树结构实现的,其中每个州可以具有可变数量的状态作为子节点。
每个状态都包含一个可变数量的“覆盖”块(在std :: map中),它们会覆盖基值。在根状态,状态机具有一组初始化为某些默认值的变量(函数,属性...)。每次我们进入子状态时,“覆盖”列表定义应该替换父状态中相同名称的变量和值的变量和值。为了清晰起见,更新了原件。
在运行时,当前状态存储在堆栈中。
每次引用变量时,都会执行向下堆栈遍历以查找最高覆盖,或者在没有覆盖的情况下执行默认值。
每次切换到单个状态帧时,状态都会被压入堆栈。
每次切换到状态时,我都会追踪一个树形下降,它将我从当前状态转移到根状态。然后我从目标状态到树状态下降到根状态,直到我看到当前跟踪与前一个跟踪匹配。我宣布这两条轨迹相遇的交叉点。然后,为了切换到目标状态,我从源下降,从堆栈弹出状态帧,直到我到达交叉点。然后我升入目标节点并将状态帧推入堆栈。
所以对于上面的代码示例
状态切换的执行跟踪
目标状态= alsoStreamToRemoteIp
来自source = recording-> root(trace = [root])
目标的下降= alsoStreamToRemoteIp-> playback-> root(trace = [playback,root])
在root上相交。
从录音切换到alsoStreamToRemoteIp,
答案 0 :(得分:1)
我不确定我是否遵循此处的所有细节。但是,您似乎正在描述具有多个状态机的FSM(有限状态机)实现。有时,当特定事件(E1)发生在FSM F1的特定状态(S1)时,您需要输入新的FSM(称之为F2)以简化整体处理。
如果是这种情况,那么当S1中出现E1时,您需要调用一个接管事件读取的动作例程并实现F2 FSM。调用时,它开始在F2的开始状态下处理,并处理相关的子事件。当它到达其结束状态时,F2的解释器结束。它可能会将一些信息返回到F2运行时暂停的F1动作例程,并且F1中的下一个状态可能会受到影响。
您的描述的其余部分 - 例如“覆盖块” - 对于无法访问您的实现的人来说没有多大意义。
答案 1 :(得分:1)
两件事:
1:对于大多数情况,只是将程序的状态表示为模型,并直接或通过MVC模式与其进行交互。
2:如果你真的需要一个FSM,即你想随机地为你的模型做一堆动作,那么在某些时候只允许其中一些动作。然后....
仍然将程序的状态保持在模型中(或多个模型取决于分解和复杂性)并表示状态和转换,如。
class State:
def __init__(self):
self.neighbors = {}
其中邻居包含{Action: State}
的字典,以便您可以执行类似
someAction.execute() # Actions manipulate the model (use classes or lambdas)
currentState = currentState.neighbors[someAction]
甚至更酷,有一个无限循环从邻居中随机选择一个动作,执行它,并无限期地移动状态。这是测试你的程序的好方法。