2017-04-13 117 views
0

我有一個通用警戒條件,我想在某些情況下有條件地禁止轉換。下面是我想要做的一些C++/Pseudocode。BOOST :: MSM檢查警戒狀態下的狀態轉換

bool operator()(Event const& evt, FSM & fsm, SourceState& src, TargetState& tgt) 
{ 
    bool transition = (current_state != next_state); 
    bool transitionAllowed = (x | y | z); //some custom condition 
    return (transition && transitionAllowed); 
} 

我想知道,如果目標狀態是從源狀態不同,並基於該決定我們是否能夠允許基於其他參數的轉變。到目前爲止,我還沒有找到很多成功的文檔。

回答

1

看來你的問題包含兩部分。 一個是如何檢查當前狀態和下一個狀態。另一個是如何檢查自定義條件。

爲了檢查當前狀態和下一個狀態,可以使用std::is_same元函數。

這裏是一個防護件的一個示例:

struct Guard1 { 
    template <class Event, class Fsm, class Source, class Target> 
    bool operator()(Event const&, Fsm& fsm, Source& src, Target&) const { 
     bool transition = !std::is_same<Source, Target>::value; 
     bool transitionAllowed = x() || fsm.y || src.z; 
     return transition && transitionAllowed; 
    } 
}; 

這裏是轉換表:

// Transition table 
struct transition_table:mpl::vector< 
    //   Start Event Next Action  Guard 
    //   source and target is the same 
    msmf::Row < State1, Event1, State1, msmf::none, Guard1 >, 

    //   source and target is different 
    msmf::Row < State1, Event2, State2, msmf::none, Guard1 > 
> {}; 

引起事件1的過渡具有相同的源和目標的狀態。兩者都是State1。 Event2引起的轉換具有不同的來源和目標狀態。源狀態是State1,目標狀態是State2。

前一種情況std::is_same<Source, Target>::value返回true,後一種情況返回false。 變量transition是結果的嘮叨。

您可以將此用作返回值的一部分。

爲了評估自定義條件,您需要從某些來源獲取評估值。 我寫了三個來源的例子。

  • x()是全局函數。當然,你可以像這樣使用全局變量。
  • y是狀態機的成員變量。
  • z是源狀態State1的成員變量。

下面是完整的代碼:

#include <iostream> 
#include <boost/msm/back/state_machine.hpp> 

#include <boost/msm/front/state_machine_def.hpp> 
#include <boost/msm/front/functor_row.hpp> 
#include <boost/static_assert.hpp> 

namespace msm = boost::msm; 
namespace msmf = boost::msm::front; 
namespace mpl = boost::mpl; 

// You can test changing the value 
bool const example_value = true; 

struct Event1 {}; 
struct Event2 {}; 

// example of a condition 
bool x() { return example_value; } 

struct Sm_:msmf::state_machine_def<Sm_> 
{ 
    // States 
    struct State1:msmf::state<> { 
     template <class Event,class Fsm> 
     void on_entry(Event const&, Fsm&) const { 
      std::cout << "State1::on_entry()" << std::endl; 
     } 
     template <class Event,class Fsm> 
     void on_exit(Event const&, Fsm&) const { 
      std::cout << "State1::on_exit()" << std::endl; 
     } 
     bool z = example_value; // example of a condition 
    }; 
    struct State2:msmf::state<> { 
     template <class Event,class Fsm> 
     void on_entry(Event const&, Fsm&) { 
      std::cout << "State2::on_entry()" << std::endl; 
     } 
     template <class Event,class Fsm> 
     void on_exit(Event const&, Fsm&) const { 
      std::cout << "State2::on_exit()" << std::endl; 
     } 
     int property; 
    }; 
    // Set initial state 
    typedef State1 initial_state; 

    // Guards 
    struct Guard1 { 
     template <class Event, class Fsm, class Source, class Target> 
     bool operator()(Event const&, Fsm& fsm, Source& src, Target&) const { 
      bool transition = !std::is_same<Source, Target>::value; 
      bool transitionAllowed = x() || fsm.y || src.z; 
      return transition && transitionAllowed; 
     } 
    }; 

    // Transition table 
    struct transition_table:mpl::vector< 
     //   Start Event Next Action  Guard 
     //   source and target is the same 
     msmf::Row < State1, Event1, State1, msmf::none, Guard1 >, 

     //   source and target is different 
     msmf::Row < State1, Event2, State2, msmf::none, Guard1 > 
    > {}; 
    bool y = example_value; // example of a condition 
}; 

// Pick a back-end 
typedef msm::back::state_machine<Sm_> Sm; 

int main() { 
    Sm sm; 
    sm.start(); 

    std::cout << "> Send Event1()" << std::endl; 
    sm.process_event(Event1()); 

    std::cout << "> Send Event2()" << std::endl; 
    sm.process_event(Event2()); 
} 

您可以更改自定義條件的值。

// You can test changing the value 
bool const example_value = true; 

如果將example_value設置爲false,則不滿足自定義條件。

如果不滿足自定義條件,則Event1Event2都不會進行轉換。 如果自定義條件得到滿足,Event1不會進行轉換,因爲源和目標狀態相同。 Event2進行了轉換。

這裏是正在運行的演示。

殼體example_value = true

https://wandbox.org/permlink/6qHcW9e6JX4QXAuH

殼體example_value = false

https://wandbox.org/permlink/HxaGpAr90YLEc5l8

+0

這是純溶液。我找到了一種方法來做到這一點,通過使用onEntry事件中的'stateNum'來填充源和目標狀態。 (即在實際狀態的onEntry中,stateNum = fsm.current_state(),其中當前狀態分別指向每個狀態的唯一狀態標識符) 雖然我喜歡你的解決方案!這看起來比我更優雅一些:-) – Edwin