c++ Boost MSM process_event不会在SM状态之间转换

11dmarpk  于 2023-02-01  发布在  其他
关注(0)|答案(1)|浏览(108)

我用增强型MSM创建了一个HSM。

图示:


代码:

#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/back/tools.hpp>
#include <boost/msm/front/euml/operator.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>

// TODO - move this from here to different module
struct EventConfigure {};
struct EventSendDetailsRsp {};

struct EventSendGrantsRsp {};
struct EventGetGrantsRsp {};
struct EventGetStatsRsp {};
struct EventCycleTimeout {};
struct EventStartWaitTimerExpired {};
struct EventGapTimerExpired {};

// ---------------------- CYCLING STATE MACHINE----------------------//

/* Internal Cycling SM */
struct CyclingSm_
        : msmf::state_machine_def<CyclingSm_> {

    CyclingSm_() {}

    struct FillingDetails : msmf::state<> {

        template <class Event, class Fsm>
        void on_entry(const Event& rEvent, Fsm& rFsm) const
        {
            // add here name maybe
            LOG4CXX_INFO(Logger(), "FillingDetails::on_entry");

        }

        template <class Event, class Fsm>
        void on_exit(const Event& rEvent, Fsm& rFsm) const
        {
            LOG4CXX_INFO(Logger(), "FillingDetails::on_exit");
        }

    };

    struct SendingGrants : msmf::state<> {

        template <class Event, class Fsm>
        void on_entry(const Event& rEvent, Fsm& rFsm) const
        {
            // add here name maybe
            LOG4CXX_INFO(Logger(), "SendingGrants::on_entry");
        }

        template <class Event, class Fsm>
        void on_exit(const Event& rEvent, Fsm& rFsm) const
        {
            LOG4CXX_INFO(Logger(), "SendingGrants::on_exit");
        }
    };

    struct GettingGrants : msmf::state<> {

        template <class Event, class Fsm>
        void on_entry(const Event& rEvent, Fsm& rFsm) const
        {
            // add here name maybe
            LOG4CXX_INFO(Logger(), "GettingGrants::on_entry");
        }

        template <class Event, class Fsm>
        void on_exit(const Event& rEvent, Fsm& rFsm) const
        {
            LOG4CXX_INFO(Logger(), "GettingGrants::on_exit");
        }
    };

    template <class Event, class Fsm>
    void on_entry(const Event& rEvent, Fsm& rFsm) const
    {
        // add here name maybe
        LOG4CXX_INFO(Logger(), "CyclingSm::on_entry");

        // Need to prepare here the next cycle (cms_groups)

    }

    template <class Event, class Fsm>
    void on_exit(const Event& rEvent, Fsm& rFsm) const
    {
        LOG4CXX_INFO(Logger(), "CyclingSm::on_exit");
    }

    struct PseudoCycleExit : public msmf::exit_pseudo_state<msmf::none> {};

    typedef FillingDetails initial_state;

    struct transition_table : mpl::vector<
    //         Start                            Event                         Next                               Action                                          Guard
    //        +-------------------------------+-----------------------------+----------------------------------+----------------------------------------------+----------+
    msmf::Row<FillingDetails,                  EventSendDetailsRsp,           SendingGrants,                     msmf::none,                                     msmf::none>,
    //        +-------------------------------+-----------------------------+----------------------------------+-----------------------------------------------+----------+
    msmf::Row<SendingGrants,                   EventSendGrantsRsp,            GettingGrants,                     msmf::none,                                     msmf::none>,
    //        +-------------------------------+-----------------------------+----------------------------------+------------------------------------------------+----------+
    msmf::Row<GettingGrants,                   EventGetGrantsRsp,             PseudoCycleExit,                   msmf::none,                                     msmf::none>

    >, OBJECTS_COUNTER(transition_table) {};

    template<class Fsm, class Event>
    void no_transition(Event const& e, Fsm& rFsm, int state)
    {
        typedef typename Fsm::stt Stt;
        typedef typename msm::back::generate_state_set<Stt>::type all_states; //all states
        std::string state_name;
        // fill state_name for state
        boost::mpl::for_each<all_states,boost::msm::wrap<mpl::placeholders::_1> >
                  (msm::back::get_state_name<Stt>(state_name, state));

         LOG4CXX_WARN(Logger(), "no_transition from state " << state_name << " by event " << typeid(e).name());
    }

    template <class Fsm, class Event>
    void exception_caught (Event const& event, Fsm& rFsm, const std::exception& e)
    {
        LOG4CXX_ERROR(Logger(), " exception_caught: " << e.what() <<" by event " << typeid(event).name());
    }

}; // CyclingSm_

typedef msm::back::state_machine<CyclingSm_> CyclingSm;

// ----------------- OUTER STATE MACHINE ---------------//

struct OuterSm_
        : msmf::state_machine_def<OuterSm_>  {

    OuterSm_() {}

    struct StateStandby : msmf::state<> {

        template <class Event, class Fsm>
        void on_entry(const Event& rEvent, Fsm& rFsm) const
        {
            // add here name maybe
            LOG4CXX_INFO(Logger(), "StateStandby::on_entry");
        }

        template <class Event, class Fsm>
        void on_exit(const Event& rEvent, Fsm& rFsm) const
        {
            LOG4CXX_INFO(Logger(), "StateStandby::on_exit");
        }

    };

    struct StateStartWaiting : msmf::state<> {

        template <class Event, class Fsm>
        void on_entry(const Event& rEvent, Fsm& rFsm) const
        {
            // add here name maybe
            LOG4CXX_INFO(Logger(), "StateStartWaiting::on_entry");
        }

        template <class Event, class Fsm>
        void on_exit(const Event& rEvent, Fsm& rFsm) const
        {
            LOG4CXX_INFO(Logger(), "StateStartWaiting::on_exit");
        }

    };

    // ---------------------- OPERATIONAL STATE MACHINE----------------------//

    struct OperationalSm_ : msmf::state_machine_def<OperationalSm_> {

        OperationalSm_() {}

        struct GettingStats : msmf::state<> {

            template <class Event, class Fsm>
            void on_entry(const Event& rEvent, Fsm& rFsm) const
            {
                // add here name maybe
                LOG4CXX_INFO(Logger(), "GettingStats::on_entry");
            }

            template <class Fsm>
            void on_exit(const EventGetStatsRsp& rEvent, Fsm& rFsm) const
            {
                LOG4CXX_INFO(Logger(), "GettingStats::on_exit (EventGetStatsRsp)");
            }

            template <class Event, class Fsm>
            void on_exit(const Event& rEvent, Fsm& rFsm) const
            {
                LOG4CXX_INFO(Logger(), "GettingStats::on_exit");
            }
        };

        struct GapWaiting : msmf::state<> {

            template <class Event, class Fsm>
            void on_entry(const Event& rEvent, Fsm& rFsm) const
            {
                // add here name maybe
                LOG4CXX_INFO(Logger(), "GapWaiting::on_entry");
            }

            template <class Event, class Fsm>
            void on_exit(const Event& rEvent, Fsm& rFsm) const
            {
                LOG4CXX_INFO(Logger(), "GapWaiting::on_exit");
            }
        };

        template <class Event, class Fsm>
        void on_entry(const Event& rEvent, Fsm& rFsm) const
        {
            // add here name maybe
            LOG4CXX_INFO(Logger(), "Operational::on_entry");
        }

        template <class Event, class Fsm>
        void on_exit(const Event& rEvent, Fsm& rFsm) const
        {
            LOG4CXX_INFO(Logger(), "Operational::on_exit");
        }

        struct GuardStatsTimerExpired {
            template <class Event, class Fsm, class SRC, class DST>
            bool operator()(const Event& rEvent, const Fsm& rFsm, const SRC&, const DST&)
            {
                LOG4CXX_INFO(Logger(), "GuardStatsTimerExpired");
                return true;
            }
        };

        // Struct defining cycling sub-state
        struct Cycling : CyclingSm {
            Cycling() : CyclingSm() {}
        };

        typedef GettingStats initial_state;

        struct transition_table:mpl::vector<
        //         Start                                Event                          Next                    Action           Guard
        //        +------------------------------------+------------------------------+-----------------------+----------------+---------+
        msmf::Row<Cycling::exit_pt
                      <Cycling::PseudoCycleExit>,        msmf::none,                    GapWaiting,            msmf::none,      msmf::none>,
        msmf::Row<GapWaiting,                            EventGapTimerExpired,          GettingStats,    msmf::none,      GuardStatsTimerExpired>,
        msmf::Row<GapWaiting,                            EventGapTimerExpired,          CyclingSm,             msmf::none,      msmf::none>,
        msmf::Row<GettingStats,                          EventGetStatsRsp,              CyclingSm,             msmf::none,      msmf::none>

        >, OBJECTS_COUNTER(transition_table) {};

        template<class Fsm, class Event>
        void no_transition(Event const& e, Fsm& rFsm, int state)
        {
            typedef typename Fsm::stt Stt;
            typedef typename msm::back::generate_state_set<Stt>::type all_states; //all states
            std::string state_name;
            // fill state_name for state
            boost::mpl::for_each<all_states,boost::msm::wrap<mpl::placeholders::_1> >
                      (msm::back::get_state_name<Stt>(state_name, state));

             LOG4CXX_WARN(Logger(), "no_transition from state "
                                                             << state_name << " by event "
                                                             << typeid(e).name());
        }

        template <class Fsm, class Event>
        void exception_caught (Event const& event, Fsm& rFsm, const std::exception& e)
        {
            LOG4CXX_ERROR(Logger(), " exception_caught: " << e.what() <<" by event " << typeid(event).name());
        }

    }; // OperationalSm_

    typedef msm::back::state_machine<OperationalSm_> OperationalSm;

    struct GuardEnabled {
        template <class Event, class Fsm, class SRC, class DST>
        bool operator()(const Event& rEvent, Fsm& rFsm, SRC&, DST&) const
        {
            LOG4CXX_INFO(Logger(), "GuardEnabled");
            return true;
        }
    };

    struct GuardWithinCurrentCycleInterval {
        template <class Event, class Fsm, class SRC, class DST>
        bool operator()(const Event& rEvent, Fsm& rFsm, SRC&, DST&)
        {
            LOG4CXX_INFO(Logger(), "GuardWithinCurrentCycleInterval");
            return true;
        }
    };

    struct GuardWithinFutureCycleInterval {
        template <class Event, class Fsm, class SRC, class DST>
        bool operator()(const Event& rEvent, Fsm& rFsm, SRC&, DST&)
        {
            LOG4CXX_INFO(Logger(), "GuardWithinFutureCycleInterval");
            return false;
        }
    };

    using GuardIsEnabledAndWithinCurrentCyclingInterval = msmf::euml::And_<GuardEnabled, GuardWithinCurrentCycleInterval>;
    using GuardIsEnabledAndWithinFutureCyclingInterval = msmf::euml::And_<GuardEnabled, GuardWithinFutureCycleInterval>;

    typedef StateStandby initial_state;

    struct transition_table : mpl::vector<
    //         Start                              Event                        Next                               Action            Guard
    //        +----------------------------------+---------------------------+----------------------------------+-----------------+----------+
    msmf::Row<StateStandby,                        EventConfigure,             OperationalSm,                     msmf::none,       GuardIsEnabledAndWithinCurrentCyclingInterval>,
    msmf::Row<StateStandby,                        EventConfigure,             StateStartWaiting,                 msmf::none,       GuardIsEnabledAndWithinFutureCyclingInterval>,
    msmf::Row<StateStandby,                        EventConfigure,             msmf::none,                        msmf::none,       msmf::none>,
    //        +----------------------------------+-------------------------+---------------------------------+--------------------+----------+
    msmf::Row<StateStartWaiting,                   EventConfigure,             OperationalSm,                     msmf::none,       GuardIsEnabledAndWithinCurrentCyclingInterval>,
    msmf::Row<StateStartWaiting,                   EventConfigure,             msmf::none,                        msmf::none,       GuardIsEnabledAndWithinFutureCyclingInterval>,
    msmf::Row<StateStartWaiting,                   EventConfigure,             StateStandby,                      msmf::none,       msmf::none>,
    msmf::Row<StateStartWaiting,                   EventStartWaitTimerExpired, OperationalSm,                     msmf::none,       msmf::none>,
    //        +----------------------------------+-------------------------+---------------------------------+--------------------+----------+
    msmf::Row<OperationalSm,                       EventConfigure,             msmf::none,                        msmf::none,       GuardIsEnabledAndWithinCurrentCyclingInterval>,
    msmf::Row<OperationalSm,                       EventConfigure,             StateStartWaiting,                 msmf::none,       GuardIsEnabledAndWithinFutureCyclingInterval>,
    msmf::Row<OperationalSm,                       EventConfigure,             StateStandby,                      msmf::none,       msmf::none>,
    msmf::Row<OperationalSm,                       EventCycleTimeout,          msmf::none,                        msmf::none,       GuardIsEnabledAndWithinCurrentCyclingInterval>,
    msmf::Row<OperationalSm,                       EventCycleTimeout,          StateStartWaiting,                 msmf::none,       GuardIsEnabledAndWithinFutureCyclingInterval>,
    msmf::Row<OperationalSm,                       EventCycleTimeout,          StateStandby,                      msmf::none,       msmf::none>
    //        +----------------------------------+-------------------------+---------------------------------+--------------------+----------+
    >, OBJECTS_COUNTER(transition_table) {};

    template<class Fsm, class Event>
    void no_transition(Event const& e, Fsm& rFsm, int state)
    {
        typedef typename Fsm::stt Stt;
        typedef typename msm::back::generate_state_set<Stt>::type all_states; //all states
        std::string state_name;
        // fill state_name for state
        boost::mpl::for_each<all_states,boost::msm::wrap<mpl::placeholders::_1> >
                  (msm::back::get_state_name<Stt>(state_name, state));

         LOG4CXX_INFO(Logger(), "no_transition from state "
                                                         << state_name << " by event "
                                                         << typeid(e).name());
    }

    template <class Fsm, class Event>
    void exception_caught (Event const& event, Fsm& rFsm, const std::exception& e)
    {
        LOG4CXX_ERROR(Logger(), " exception_caught: " << e.what() <<" by event " << typeid(event).name());
    }

}; // OuterSm_

typedef msm::back::state_machine<OuterSm_> OuterSm;
typedef OuterSm::stt Stt;
typedef msm::back::generate_state_set<Stt>::type all_states;

我创建了一个小的单元测试,只是为了检查基本转换是否可以与guard一起工作。

int main() {

    /// State machine
    OuterSm sm;
    sm.start();

    
    LOG4CXX_INFO(Logger(), "current state: " << *sm_.current_state());
    auto res = sm.process_event(EventConfigure());
    LOG4CXX_INFO(Logger(), "process result: " << res);
    LOG4CXX_INFO(Logger(), "current state: " << *sm_.current_state());

    return 0;
}

哪个输出是:

4 [0x7faaa5996380] INFO staticLogger null - StateStandby::on_entry
4 [0x7faaa5996380] INFO mainLogger:0x1000000:0 null - current state: 0
4 [0x7faaa5996380] INFO mainLogger:0x1000000:0 null - process result: 1
4 [0x7faaa5996380] INFO mainLogger:0x1000000:0 null - current state: 0
4 [0x7faaa5996380] INFO staticLogger null - StateStandby::on_exit

这意味着我的事件被处理了,但实际上没有从StateStandby转换到OperationalSm
我看过这样的评论:
Boost MSM only processing internal transitions
但我假设它与我的情况无关,因为我创建了两个guards(And)元组,其中一个总是返回false,另一个总是返回true。
为了让outerSm调用OperationalSm(初始状态)和其他转换在需要时工作,我在这里遗漏了什么吗?

7eumitmz

7eumitmz1#

我发现我创建了与中相同的问题:
Boost MSM only processing internal transitions
通过向transition_table添加冗余(空)转换:

msmf::Row<StateStandby,                        EventConfigure,             msmf::none,                        msmf::none,       msmf::none>,

当我删除它并留下(OuterSm转换的第一部分):

msmf::Row<StateStandby,                        EventConfigure,             OperationalSm,                     msmf::none,       GuardIsEnabledAndWithinCurrentCyclingInterval>,
msmf::Row<StateStandby,                        EventConfigure,             StateStartWaiting,                 msmf::none,       GuardIsEnabledAndWithinFutureCyclingInterval>

我看到以下输出:

4 [0x7faaa5996380] INFO staticLogger null - StateStandby::on_entry
4 [0x7faaa5996380] INFO mainLogger:0x1000000:0 null - current state: 0
4 [0x7fc282a66380] INFO staticLogger null - GuardConfigCanBeUsed
4 [0x7fc282a66380] INFO staticLogger null - GuardWithinFutureCycleInterval
4 [0x7fc282a66380] INFO staticLogger null - GuardConfigCanBeUsed
4 [0x7fc282a66380] INFO staticLogger null - GuardWithinCurrentCycleInterval
4 [0x7fc282a66380] INFO staticLogger null - StateStandby::on_exit
4 [0x7fc282a66380] INFO staticLogger null - Operational::on_entry
4 [0x7fc282a66380] INFO staticLogger null - GettingStats::on_entry

就像我期待看到的那样。

相关问题