我用增强型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
(初始状态)和其他转换在需要时工作,我在这里遗漏了什么吗?
1条答案
按热度按时间7eumitmz1#
我发现我创建了与中相同的问题:
Boost MSM only processing internal transitions
通过向
transition_table
添加冗余(空)转换:当我删除它并留下(
OuterSm
转换的第一部分):我看到以下输出:
就像我期待看到的那样。