Search code examples
stateboost-msm

boost msm submachine current_state for accessing sub state


any idea how, using boost msm 1_60, I can get the current_state(s) of a submachine? Consider the following code, describing an outer state machine that allows for chosing between two different traffic lights (standard red, yellow, green one and another with alternating two yellow lights for instance):

class SMBigMom : public msmf::state_machine_def<SMBigMom>
{
public:
SMBigMom() {};

using initial_state = SMSelectorState;

class SMLightBase : public msmf::state_machine_def<SMLightBase>
{
public:
    SMLightBase() {};

    using initial_state = BaseState;
    struct transition_table : mpl::vector<> {};
};
using SMBaseBackend = msm::back::state_machine<SMLightBase>;

class SMCommonRYG : public SMLightBase
{
public:
    SMCommonRYG() = default;
    ~SMCommonRYG() {};

    using initial_state = Red; // init state

    struct transition_table : mpl::vector<
        //         Start, Event, Target, Action, Guard
        msmf::Row< Red, evNext, RedYellow, msmf::none, msmf::none >,
        msmf::Row< RedYellow, evNext, Green, msmf::none, msmf::none >,
        msmf::Row< Green, evNext, Yellow, msmf::none, msmf::none >,
        msmf::Row< Yellow, evNext, Red, msmf::none, msmf::none >
    > {};
};
using SMCommonRYGBackend = msm::back::state_machine<SMCommonRYG>;

class SMYellowAlternate : public SMLightBase
{
public:
    SMYellowAlternate() = default;
    ~SMYellowAlternate() {};

    using initial_state = Yellow; // init state

    struct transition_table : mpl::vector<
        //         Start, Event, Target, Action, Guard
        msmf::Row< Yellow, evNext, Yellow2, msmf::none, msmf::none >,
        msmf::Row< Yellow2, evNext, Yellow, msmf::none, msmf::none >
    > {};
};
using SMYellowAlternateBackend = msm::back::state_machine<SMYellowAlternate>;

struct transition_table : mpl::vector<
    msmf::Row< SMSelectorState, evSelectCommonRYG, SMCommonRYGBackend, msmf::none, msmf::none >,
    msmf::Row< SMSelectorState, evSelectYellowAlternate, SMYellowAlternateBackend, msmf::none, msmf::none >
> {};

};

using SMBackend = msm::back::state_machine<SMBigMom>;

Now, I can skip into the RYG via

SMBackend oSM. oSM.process_event(evSelectCommonRYG());

But how can I get the current state of the RYG submachine?

oSM.current_state()[0]

returns 1 only (as this is the state of the outer state machine BigMom...)...

Thanks for help!


Solution

  • I figured it out meanwhile, the solution is rather simple. Just, using the functor front end, add an action (4th column in a ROW) function which is called like this:

    struct submachineAction
    {
      toNext() {};
      ~toNext() {};
      template<class TFsm, class TEvent, class TStateIn, class TStateOut>
      void operator() (const TEvent& p_rEV, const TFsm& p_rFSM, TStateIn&   p_rStateIn, TStateOut& p_rStateOut)
      { 
        std::cout << "Substate: " << p_rFSM.current_state()[0] << std::endl;
      }
    };
    

    If you have several "master" machines running and need to know which one called the submachineAction, you can define, for instance, a base front end class with an additional identifier (string, int, you name it) and derive the submachines from that class. Then, following this thread, you can set the identifier, which can be accessed via p_rFSM in the above functor: How to Pass data to the current boost meta state machine(MSM) substate

    Hope this helps someone else sometime.