国家机器实施

时间:2009-09-11 04:42:50

标签: c++ tree stack state-machine

我正在寻找一些通用的

  1. 优化
  2. 正确性
  3. 扩展
  4. 关于我当前的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,

    1. 从堆栈中弹出“录制”(并调用其退出函数...此处未定义)。
    2. 将“回放”推入堆栈(并调用enter函数)。
    3. 将“alsoStreamToRemoteIp”推入堆栈(并调用enter函数)。

2 个答案:

答案 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]

甚至更酷,有一个无限循环从邻居中随机选择一个动作,执行它,并无限期地移动状态。这是测试你的程序的好方法。