Pregunta

Estoy buscando un poco de general

  1. Optimización
  2. corrección
  3. Extensibilidad

consejos sobre mi implementación actual de la Máquina de estado jerárquica de C ++.

Muestra

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)

Implementación

Actualmente, el HSM se implementa como una estructura de árbol donde cada estado puede tener un número variable de estados como hijos.

Cada estado contiene un número variable de " anular " bloques (en un std :: map) que anulan los valores base. En el estado raíz, la máquina de estado tiene un conjunto de variables (funciones, propiedades ...) inicializadas con algunos valores predeterminados. Cada vez que ingresamos a un estado secundario, aparece una lista de " anulaciones " Defina variables y valores que deben reemplazar las variables y valores del mismo nombre en el estado principal. Original actualizado para mayor claridad.

Variables de referencia

En el tiempo de ejecución, los estados actuales se almacenan en una pila.

Cada vez que se hace referencia a una variable, se realiza un recorrido hacia abajo de la pila buscando la anulación más alta, o en el caso de no anulaciones, el valor predeterminado.

Estados de conmutación

Cada vez que se cambia a un solo cuadro de estado, el estado se coloca en una pila.

Cada vez que se cambia un estado, trazo una pendiente de árbol que me lleva desde el estado actual al estado raíz. Luego hago un descenso del árbol desde el estado de destino al estado raíz hasta que veo que la traza actual coincide con la traza anterior. Declaro una intersección en donde se encuentran esos 2 rastros. Luego, para cambiar al estado de destino, desciendo de la fuente, haciendo estallar los cuadros de estado de la pila hasta llegar al punto de intersección. Luego asciendo al nodo objetivo y empujo los cuadros de estado en la pila.

Así que para el ejemplo de código anterior

Seguimiento de ejecución para cambio de estado

  • Estado de origen = grabación
  • Estado de destino = alsoStreamToRemoteIp

  • descensión de la fuente = grabación- > raíz (trace = [raíz])

  • descensión de target = alsoStreamToRemoteIp- > playback- > root (trace = [playback, root])

  • Intersecta en la raíz.

Para pasar de la grabación a también StreamToRemoteIp,

  1. Pop " grabación " de la pila (y llamar a su función de salida ... no se define aquí).
  2. Presiona " reproducción " en la pila (y llamar a la función entrar).
  3. Presione " alsoStreamToRemoteIp " en la pila (y llame a la función enter).
¿Fue útil?

Solución

Dos cosas:

1: para la mayoría de los casos, solo representa el estado de tu programa como modelo e interactúa con él directamente oa través del patrón MVC.

2: si realmente necesita un FSM, es decir, desea realizar al azar un montón de acciones para su modelo, solo algunas de las cuales se permiten en ciertos momentos. Entonces ....

Aún mantiene el estado de su programa en un Modelo (o varios Modelos dependiendo de la descomposición y la complejidad) y representa estados y transiciones como.

class State:
   def __init__(self):
      self.neighbors = {}

Donde los vecinos contienen un diccionario de {Action: State} , para que puedas hacer algo como

someAction.execute() # Actions manipulate the model (use classes or lambdas)
currentState = currentState.neighbors[someAction]

O incluso más frío, haga que un bucle infinito seleccione aleatoriamente una acción de los vecinos, la ejecute y se mueva de forma indefinida. Es una excelente manera de probar tu programa.

Otros consejos

No estoy seguro de seguir todos los detalles aquí. Sin embargo, parece que está describiendo una implementación de FSM (máquina de estado finito) donde tiene varias máquinas de estado. A veces, cuando ocurre un evento en particular (E1) en un estado particular (S1) de FSM F1, debe ingresar un nuevo FSM (llámelo F2) para simplificar el procesamiento en general).

Si ese es el caso, entonces cuando E1 se produce en S1, debe invocar una rutina de acción que asuma la lectura del evento e implemente el FSM F2. Cuando se invoca, comienza a procesarse en el estado de inicio de F2 y maneja los eventos secundarios relevantes. Cuando alcanza su estado final, el intérprete de F2 finaliza. Puede devolver algo de información a la rutina de acción F1 que se suspendió mientras se ejecutaba F2, y el siguiente estado en F1 puede verse afectado por eso.

El resto de su descripción, cosas como 'anular bloques', no tendrá mucho sentido para las personas sin acceso a su implementación.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top