【问题标题】:State Machine design handling data input状态机设计处理数据输入
【发布时间】:2023-04-02 10:02:01
【问题描述】:

我正在开发一个实时机器控制系统,该系统执行一系列任务,并且应该对大量输入做出反应。我决定使用状态机来实现这个系统。

我过去曾使用过简单的基于 switch/case 的状态机,并希望过渡到更易于维护的解决方案。目前我对如何处理输入和转换有点困惑。

例如,我有一个 AnalogInput 类,它为我提供了我应该监控的测量值。假设我有一个状态 WaitForThreshold,它应该读取一个 AnalogInput,然后在达到阈值时转换。

我 a) 将 AnalogInput 类的引用传递给 WaitForThreshold 类,并允许它监控输入本身,向 StateMachine 类发出它希望转换的信号。

b) 创建专用事件,LaserMeasurementAtThreshold 和状态转换图:StateMachine.addTransition(State A, Event e, State B)

c) 创建更多通用事件 AnalogInputChanged 并为每个事件实现事件处理程序,这再次向 StateMachine 发出需要转换的信号

选项 a 本质上是一个简单的 switch/case 状态机的更大版本,它可能会随着时间的推移而变得混乱,但提供了很大的灵活性,并且 b/c 看起来更有条理和干净,但似乎我可能不得不跳过很多箍来实现相对简单的任务,因为事件的数量可能非常大。

有人可以提供一些关于状态机设计的见解,其中必须监控大量输入源和类型,并且事件在很大程度上是特定于状态的(大多数事件仅与单个状态有关)?

是否有其他替代状态机设计来控制必须执行一系列步骤的系统(非线性、循环和分支必须是可能的)

语言:C++

谢谢

【问题讨论】:

  • 您可能想了解State Pattern
  • 你知道 UML 吗?您可以通过 UML 建模器为您的状态机建模并生成相应的 C++ 源代码
  • 现有的框架可以满足您的需求。也许您应该在重新发明轮子之前检查其中的一些:stackoverflow.com/questions/3750177/… 阅读有关 UML 状态机的信息也可能有用。
  • 恕我直言,使用表驱动状态机。该表可以由当前状态、下一个状态的列和指向转换函数的指针组成。表通常比switch 语句更容易维护。另外,访问表的代码只需要测试一次;表格大小会改变,但访问表格的代码不会改变。
  • 如果你愿意使用基于上述State Pattern的框架,也可以试试我的STTCL

标签: c++ events state-machine


【解决方案1】:

我相信这会更清楚地实现为转换表:

typedef (void)((*Pointer_To_Transition_Function)());
struct Table_Entry
{
  Input_Type input_value;
  Pointer_To_Transisiton_Function p_trans_function;
};

static const Table_Entry Transition_Table[] = 
{
  {4, Read_Sensor},
};
static const size_t transition_quantity =  
    sizeof(Transition_Table) / sizeof(Transition_Table[0]);

//...
for (size_t index = 0; index < transition_quantity; ++index)
{
  if (input_value = Transition_Table[index].input_value)
  {
    Pointer_To_Transition_Function p_function = Transition_Table[index].p_trans_function;
    // Call the function:
    p_function();
    break;
  }
}

您可以使用std::map,但std::map 必须在运行时初始化。表(数组)是静态不变的,因此可以放入只读内存段(方便嵌入式系统);并且不使用动态内存分配。

编辑1:表格的ASCII绘图

+-------------+--------------------------------+  
| Input value | Pointer to transition function |  
+-------------+--------------------------------+  
|     4       |   Read sensor                  |
+-------------+--------------------------------+  
|     2       |   Start motor                  |
+-------------+--------------------------------+  

【讨论】:

  • 我已经为嵌入式医疗设备实现了状态/转换表。我们可以更改表中的数据,而无需重新验证访问函数(引擎);因为代码没有改变(只有数据改变了)。
猜你喜欢
  • 1970-01-01
  • 2014-10-20
  • 2011-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多