Meta State Machine PseudoExit transitions

Hello, I'm trying to implement a PseudoExitState in my boost meta state machine. This is the situation: http://i55.tinypic.com/2a83yar.png. Currently, when going from Transport to either Situation A or B, it throws an "no_transition" in the SubState for the "convertible event" needed by the PseudoExit state. (This is event6 in the example described below) According to the documentation (http://www.boost.org/doc/libs/1_46_1/libs/msm/doc/HTML/ch03s02.html#d0e930) and the corresponding example, there should be some kind of transition triggered by "event6" from SubState2 to Substate1 (see http://www.boost.org/doc/libs/1_46_1/libs/msm/doc/HTML/examples/DirectEntryT..., in the transition table for SubFsm2). I don't see an arrow in the state diagram between SubState2 and SubState1, nor can I figure out why I would want such a transition. In my SubState's transition table, I have defined the transition from Transport to PseudoExit1 and 2: g_row< Transport , Sensor , Exit1 , &SubFront::SDownstreamCheck >, g_row< Transport , Sensor , Exit2 , &SubFront::SDownstreamNoCheck > and in the TopState from PseudoExit1 and 2 to SituationA and B: _row< Sub::exit_pt< SubFront::Exit1 > , TransportDone , SituationA >, _row< Sub::exit_pt< SubFront::Exit2 > , TransportDone , SituationB >, So do i have to handle an "TransportDone" event in the SubState? And what are my Start and End states? I would appreciate your help :) Best Regards, Johan

Hello,
I'm trying to implement a PseudoExitState in my boost meta state machine. This is the situation: http://i55.tinypic.com/2a83yar.png. Currently, when going from Transport to either Situation A or B, it throws an "no_transition" in the SubState for the "convertible event" needed by the PseudoExit state. (This is event6 in the example described below)
According to the documentation (http://www.boost.org/doc/libs/1_46_1/libs/msm/doc/HTML/ch03s02.html#d0e930) and the corresponding example, there should be some kind of transition triggered by "event6" from SubState2 to Substate1 (see http://www.boost.org/doc/libs/1_46_1/libs/msm/doc/HTML/examples/DirectEntryT..., in the transition table for SubFsm2). I don't see an arrow in the state diagram between SubState2 and SubState1, nor can I figure out why I would want such a transition.
Hi, the missing arrow has just been reported (today) to me and I just fixed it (in the trunk) It is irrelevant in your case, that's why it wasn't in the diagram. It's just a transition which happens to be triggered by event6.
In my SubState's transition table, I have defined the transition from Transport to PseudoExit1 and 2:
g_row< Transport , Sensor , Exit1 , &SubFront::SDownstreamCheck >, g_row< Transport , Sensor , Exit2 , &SubFront::SDownstreamNoCheck >
and in the TopState from PseudoExit1 and 2 to SituationA and B:
_row< Sub::exit_pt< SubFront::Exit1 > , TransportDone , SituationA >, _row< Sub::exit_pt< SubFront::Exit2 > , TransportDone , SituationB >,
So do i have to handle an "TransportDone" event in the SubState? And what are my Start and End states? I would appreciate your help :)
It depends what you want to do. The UML Standard actually only foresees the possibility to move into a pseudo exit triggered by an event (in your case Sensor) and exit it with this exact event. If it's what you want, no problem, replace TransportDone by Sensor in your outer transitions and it will work. Just don't forget to indicate it in the pseudo exit definition: struct Exit1 : public msm::front::exit_pseudo_state<Sensor> // Pseudo exit will forward Sensor events MSM also offers you the non-standard possibility to have another event constructed and forwarded by the pseudo exit. The condition is that this outer event can be constructed from the inner one. So TransportDone could be, for example: struct TransportDone { TransportDone(){} // copy construct from any other event template <class Event> TransportDone(Event const&){} }; Now you should have no more calls to no_transition. Unfortunately, to my surprise, it has been reported shortly that the compiler does not throw an error if the copy-constructor is forgotten (which I think to remember once was the case). I'll try to find a way to force him to do so to avoid this easy-to-make mistake.
Best Regards, Johan
HTH, Christophe

Hi, Thank you very much for your quick and detailed reply. I will try this tomorrow, but i'm already very confident this will solve the issue. Also, I actually had the TransportDone struct you described defined in my code, but I guess something else was wrong. Nonetheless, I will use the easy solution. Some feedback on the boost library: As the library can be fairly hard to understand at first, after spending some hours in the documentation the result looks all nice and clean. Boost rocks! Thanks again! Best regards, Johan

Hi,
Thank you very much for your quick and detailed reply. I will try this tomorrow, but i'm already very confident this will solve the issue. Also, I actually had the TransportDone struct you described defined in my code, but I guess something else was wrong. Nonetheless, I will use the easy solution.
Hi, I got why it compiles and should not. This is the good part of the news. The bad part is that I probably cannot catch a wrong event inside a pseudo exit at compile-time, only at run-time. So all I can do is add an assert to at least catch the error in debug mode.
Some feedback on the boost library: As the library can be fairly hard to understand at first, after spending some hours in the documentation the result looks all nice and clean. Boost rocks!
In order to make the doc better, where did you encounter difficulties?
Thanks again!
Welcome! Regards, Christophe

I got why it compiles and should not. This is the good part of the news. The bad part is that I probably cannot catch a wrong event inside a pseudo exit at compile-time, only at run-time. So all I can do is add an assert to at least catch the error in debug mode.
Hi, This solution is fine because it eventually achieves the same thing: Make the user aware of his/her mistake. And on the other hand: The compiler errors aren't always that enlightening either. (Try to make a mistake in the transition table for example, you'll hit the "error motherload" soon enough ;) )
In order to make the doc better, where did you encounter difficulties?
I was confused by the fact that "event6" also triggered a normal transition. Also, in the diagram, the arrows from Substate3 to PseudoExit1 and from PseudoExit1 to State2 both have "event5" as text, but I think it is more consistent when the second arrow has "event6". I really admire the fact that the documentation has such a high value for you guys, other projects should really take this as an example. Great work! Keep it up! Best regards, Johan

Hi, I tried to make it work, but sadly I didn't succeed. It almost looks like the PseudoExit state doesn't forward the event to the TopState. I currently commented out all other states in the SubState to make debugging easier and set the last State (Transport) to the initial_state. Of course I left Exit1 and Exit2 as they were. As i keep triggering Sensor Events ( they also get handled later on in the state machine ), it's almost like it fights its way through the errors... I have put the timeline with the code, debug prints and my comments below: row< Transport , Sensor , Exit2 , &SubFront::ActionSensor , &SubFront::SDownstreamNoCheck > Current state: 0 Event: Sensor SubState Guard: Sensor Downstream Active and No Check? SubState Action: Sensor SubState no_transition: Invalid state transition! --> 2 Type: N10controller19TopStateFront6SensorE, N5boost3msm4back13state_machineIN10controller19TopStateFront6SubStateAFrontENS_9parameter5void_ES8_S8_S8_EE The Current state in the debug prints is for SubState. I don't know which states these exactly are, but I guess Transport is state 0 and Exit2 is state 2. So, you see that the first sensor action triggers the transition and moves from Transport to Exit2. Why is no_transition called when the event already finished? Current state: 2 Event: Sensor SubState no_transition: Invalid state transition! --> 2 Type: N10controller19TopStateFront6SensorE, N5boost3msm4back13state_machineIN10controller19TopStateFront6SubStateAFrontENS_9parameter5void_ES8_S8_S8_EE TopState Guard: Exit2 TopState Action: Sensor After sending another Sensor event the SubState still complains about no_transition. Because I have defined guards for all transitions with debug prints, the failing transition is most likely generated from within the PseudoExit. As you can see it does execute the Exit2 guard and completes the transition. This code in the TopState will handle it: row< Sub::exit_pt< SubFront::Exit2 > , Sensor , SituationB , &TopFront::ActionSensor , &TopFront::Exit2Guard >, And Exit2 is defined (in SubState) as: struct Exit2 : public msm::front::exit_pseudo_state<Sensor> {}; Current state: 2 Event: Sensor TopState Guard: Situation B and beyond TopState Action: Sensor Here we are, in Situation B. So, one way or another ... it actually works. Strange... Any ideas?? Best regards, Johan

Hi,
I tried to make it work, but sadly I didn't succeed. It almost looks like the PseudoExit state doesn't forward the event to the TopState. I currently commented out all other states in the SubState to make debugging easier and set the last State (Transport) to the initial_state. Of course I left Exit1 and Exit2 as they were. As i keep triggering Sensor Events ( they also get handled later on in the state machine ), it's almost like it fights its way through the errors... <snip>
Hi, could you attach your example or some minimalistic code? I think it'll be much faster this way. Thanks, Christophe

could you attach your example or some minimalistic code? I think it'll be much faster this way.
Hi, After i finished the minimalistic code for the state machine, I came to the conclusion the error has to be elsewhere, because the minimal code actually runs fine. I should have done this much earlier. But all regrets aside, I will look into this and maybe just refactor the whole source code. It could use an upgrade. Thank you very much for your assistance :) Best Regards, Johan
participants (2)
-
Christophe Henry
-
Johan Gielens