I am using Boost MSM to model the behavior of a robot. There are multiple states, as "ManualMove", "AutoMove", "Work", "Idle", etc... However I need to be able to force stop the robot from any state, putting it in state where it cannot move and cannot receive new commands, so I created an "EmergencyStopped" state. When the robot is asked to rearm itself, the robot should go back to the "Idle" state.
However, Boost does not recommend to create a transition from all state to a single one, and prefer to use orthogonal states.
So I could for example do "AllOk" and an interrupt_state "EmergencyStopped" orthogonal states.
The problem is, while I can easily put the robot in "EmergencyStopped", I cannot quit it and put the robot into the "Idle" state from the state it was before. For example, if the robot do:
- [Work, AllOk] -> stop
- [Work,EmergencyStopped] -> recover
The robot will be in the state [Work, AllOk], while I want it to go in the state [Idle, AllOk].
So my questions are:
- Can and should I use orthogonal states for this workflow? If yes, how to force the state to "Idle" when I qui the orthogonal state "EmergencyStopped"?
- Or should I make "EmergencyStopped" non-orthogonal and declare a transition from all states to it?
- Or is there another solution?
There is another solution. In your case, composite state is better choice. See the diagram.
How to avoid writing many transitions to "EmergencyStopped".
Em-place all states that need to transition to "EmergencyStopped" if "stop" event is happend into "Normal" state. And put the transition that is from "Normal" to "EmergencyStopped". Its trigger event is "stop". This approach can avoid writing many transitions to "EmergencyStopped". Even if you would add other child state of "Normal", you don't need to add the transition for the added state. That is one of benefit of the composite state approach.
How to transition to "Idle" state if "recover" event is happened.
Set "Idle" state to
initial_state. It reflect to Initial puseudo state in UML state-machine diagram.If transition target is parent state "Normal", then transition target state is "Idle" state because it is marked as
initial_state.Those two technique solve your question.
Here is the complete code:
and running demo https://wandbox.org/permlink/uBm6jTvG0YL3gSgl