2017-05-31 53 views
0

我有一個狀態機,其中如果我進入特定狀態,有時需要定期轉換到另一個狀態,而其他時間我需要返回到以前的狀態。Boost狀態圖:返回到以前的狀態

例如,具有狀態ABC,說過渡S將狀態A移動到C並從B移動到C.我需要一個轉換T將C移動到A,當S發生在狀態A和C發生在B時狀態B.

在下面的代碼中,轉換S發生在狀態B中,因此我希望轉換T返回到狀態B(而當前它返回到狀態A)。

#include <boost/mpl/list.hpp> 

#include <boost/statechart/state_machine.hpp> 
#include <boost/statechart/simple_state.hpp> 
#include <boost/statechart/event.hpp> 
#include <boost/statechart/transition.hpp> 

// states 
struct A; 
struct B; 
struct C; 
struct D; 

// events 
struct S : boost::statechart::event<S> {}; 
struct T : boost::statechart::event<T> {}; 
struct U : boost::statechart::event<U> {}; 

// fsm 
struct FSM : boost::statechart::state_machine<FSM, B> {}; 

// fully defined states/transitions 
struct A : boost::statechart::simple_state<A, FSM> { 
    typedef boost::statechart::transition<S, C> reactions; 

    A() { std::cout << "entered A" << std::endl; } 
}; 

struct B : boost::statechart::simple_state<B, FSM> { 
    typedef boost::statechart::transition<S, C> reactions; 

    B() { std::cout << "entered B" << std::endl; } 
}; 

struct C : boost::statechart::simple_state<C, FSM> { 
    typedef boost::mpl::list< 
       boost::statechart::transition<T, A>, 
       boost::statechart::transition<T, B>, 
       boost::statechart::transition<U, D> > reactions; 

    C() { std::cout << "entered C" << std::endl; } 
}; 

struct D : boost::statechart::simple_state<D, FSM> { 
    D() { std::cout << "entered D" << std::endl; } 
}; 

int main() { 
    FSM fsm; 

    fsm.initiate(); 

    fsm.process_event(S()); 
    fsm.process_event(T()); 
    fsm.process_event(S()); 
    fsm.process_event(U()); 

    return 0; 
} 

上面的代碼返回:

entered B 
entered C 
entered A 
entered C 
entered D 

,我想,而不是看:

entered B 
entered C 
entered B 
entered C 
entered D 

有沒有乾淨的方式來做到這一點使用boost ::狀態圖?

+1

請提供[最小,完整和可驗證示例](https://stackoverflow.com/help/mcve) – FortyTwo

回答

1

我發現了一個〜好的方法 - 通過爲狀態創建枚舉映射,將以前的狀態存儲在最外層上下文(頂層fsm)中,然後對T事件使用自定義反應:

#include <boost/mpl/list.hpp> 

#include <boost/statechart/state_machine.hpp> 
#include <boost/statechart/simple_state.hpp> 
#include <boost/statechart/event.hpp> 
#include <boost/statechart/transition.hpp> 
#include <boost/statechart/custom_reaction.hpp> 

// states 
struct A; 
struct B; 
struct C; 
struct D; 

// state enum mapping 
enum class state_mapping { 
    A = 0, 
    B, 
    C, 
    D 
}; 

// events 
struct S : boost::statechart::event<S> {}; 
struct T : boost::statechart::event<T> {}; 
struct U : boost::statechart::event<U> {}; 

// fsm 
struct FSM : boost::statechart::state_machine<FSM, B> { 
    state_mapping previous_state = state_mapping::B; 
}; 

// fully defined states/transitions 
struct A : boost::statechart::simple_state<A, FSM> { 
    typedef boost::statechart::transition<S, C> reactions; 

    A() { std::cout << "entered A" << std::endl; } 
    virtual ~A() { outermost_context().previous_state = state_mapping::A; } 
}; 

struct B : boost::statechart::simple_state<B, FSM> { 
    typedef boost::statechart::transition<S, C> reactions; 

    B() { std::cout << "entered B" << std::endl; } 
    virtual ~B() { outermost_context().previous_state = state_mapping::B; } 
}; 

struct C : boost::statechart::simple_state<C, FSM> { 
    typedef boost::mpl::list< 
       boost::statechart::custom_reaction<T>, 
       boost::statechart::transition<U, D> > reactions; 

    C() { std::cout << "entered C" << std::endl; } 

    boost::statechart::result react(const T&) { 

     switch(outermost_context().previous_state) { 

     case state_mapping::A: 
      return transit<A>(); 
     case state_mapping::B: 
      return transit<B>(); 
     default: 
      return discard_event(); 

     } 

    } 
}; 

struct D : boost::statechart::simple_state<D, FSM> { 
    D() { std::cout << "entered D" << std::endl; } 
}; 

int main() { 
    FSM fsm; 

    fsm.initiate(); 

    fsm.process_event(S()); 
    fsm.process_event(T()); 
    fsm.process_event(S()); 
    fsm.process_event(U()); 

    return 0; 
} 

如果有人有更好的建議我全部耳朵,否則我會在一兩天內接受。