我正在实时机器控制系统上工作,该系统执行一系列任务,并且应对大量输入做出反应。我决定使用状态机来实现该系统。
过去,我曾经使用过基于简单开关/案例的状态机,并且希望过渡到更易于维护的解决方案。目前,我对如何处理输入和转换有些困惑。
例如,我有一个AnalogInput类,可为我提供应监视的测量值。假设我有一个状态 WaitForThreshold ,该状态应读取AnalogInput,然后在达到阈值时进行转换。
我要 a)将对AnalogInput类的引用传递给 WaitForThreshold 类,并允许其监视输入本身,并向StateMachine类发出希望转换的信号。
b)创建专用事件 LaserMeasurementAtThreshold 和状态转换图:StateMachine.addTransition(State A,Event e,State B)
c)创建更多通用事件 AnalogInputChanged 并为每个事件实现事件处理程序,这再次向StateMachine发出信号,表明需要进行过渡
选项a本质上是简单的开关/案例状态机的较大版本,可能会随着时间的推移而变得混乱,但提供了极大的灵活性,并且b / c似乎更加结构化和整洁,但似乎我可能不得不跳过很多由于事件数量可能非常大,因此无法实现相对简单的任务。
有人能提供一些关于状态机设计的见识吗,其中必须监视大量的输入源和类型,并且事件很大程度上是特定于状态的(大多数事件仅涉及单个状态)?
状态机设计可能还有其他选择来控制必须执行一系列步骤的系统(必须可以进行非线性,循环和转移)
语言:C ++
谢谢
答案 0 :(得分:0)
我相信将其作为过渡表来实现会更清晰:
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 |
+-------------+--------------------------------+