层次状态机(Hierarchical State Machine, HSM),从基本原理、结构设计、实现方法以及如何结合 Qt 进行具体实现等方面进行分析。
层次状态机是一种用于管理复杂系统行为的状态机模型,它通过将状态组织成层次结构来简化设计和维护。这种结构使得复杂的逻辑可以分解为更小、更易于管理的部分。
在设计层次状态机时,需要仔细规划状态之间的关系以及如何组织这些状态。以下是一些设计原则和步骤:
识别顶级状态:
定义子状态:
确定事件和转换:
实现继承和委托:
编写动作函数:
定义初始状态和历史状态:
假设我们设计一个简单的电视遥控器状态机,包含以下状态:
事件包括:
POWER
CHANNEL_UP
, CHANNEL_DOWN
VOLUME_UP
, VOLUME_DOWN
MODE_SWITCH
+-------------------+
| Standby |
+--------+----------+
|
POWER
|
+----v-----+
| Running |
+--+-+------+
| |
CHANNEL_UP|VOLUME_DOWN
/ | \
/ v \
+------------+ +------------+
| Browse Mode| |Volume Ctrl|
+------------+ +------------+
在实际编程中,层次状态机可以通过多种方式实现。以下是一个使用 C++ 和 Qt 的具体示例。
首先,我们定义状态、事件及其处理函数的类型:
#include
#include
#include
namespace HSMUtilityDef {
typedef uint32_t HSM_EVENT;
// 定义常见事件
const uint32_t MAX_DEPTH = 5;
const HSM_EVENT HSME_NULL = 0;
const HSM_EVENT HSME_START = 1;
const HSM_EVENT HSME_INIT = static_cast<HSM_EVENT>(-3);
const HSM_EVENT HSME_ENTRY = static_cast<HSM_EVENT>(-2);
const HSM_EVENT HSME_EXIT = static_cast<HSM_EVENT>(-1);
// 自定义事件
const HSM_EVENT POWER = 100;
const HSM_EVENT CHANNEL_UP = 101;
const HSM_EVENT CHANNEL_DOWN = 102;
const HSM_EVENT VOLUME_UP = 103;
const HSM_EVENT VOLUME_DOWN = 104;
const HSM_EVENT MODE_SWITCH = 105;
}
创建一个抽象基类 HSMState
,包含处理事件的虚函数:
class HSMState : public QObject {
Q_OBJECT
public:
explicit HSMState(HSMState *parent = nullptr) : QObject(parent), m_parent(parent) {}
virtual ~HSMState() {}
// 处理事件的主要接口
virtual HSMUtilityDef::HSM_EVENT handleEvent(HSMUtilityDef::HSM_EVENT event, void* param = nullptr) {
switch (event) {
case HSMUtilityDef::HSME_ENTRY:
onEntry(param);
break;
case HSMUtilityDef::HSME_EXIT:
onExit(param);
break;
default:
return unhandledEvent(event, param);
}
return HSMUtilityDef::HSME_NULL;
}
protected:
// 进入状态时执行的动作
virtual void onEntry(void* param) {}
// 离开状态时执行的动作
virtual void onExit(void* param) {}
// 处理未定义事件的方法
virtual HSMUtilityDef::HSM_EVENT unhandledEvent(HSMUtilityDef::HSM_EVENT event, void* param) {
qDebug() << "Unhandled event" << event;
return event;
}
// 获取父状态
HSMState* parent() const { return m_parent; }
private:
HSMState *m_parent;
};
创建具体的派生状态类,实现特定的逻辑:
// 待命状态(Standby)
class StandbyState : public HSMState {
Q_OBJECT
public:
explicit StandbyState(HSMState* parent = nullptr) : HSMState(parent) {}
protected:
void onEntry(void* param) override {
qDebug() << "Entering Standby State";
}
void onExit(void* param) override {
qDebug() << "Exiting Standby State";
}
HSMUtilityDef::HSM_EVENT unhandledEvent(HSMUtilityDef::HSM_EVENT event, void* param) override {
if (event == HSMUtilityDef::POWER) {
return static_cast<HSMUtilityDef::HSM_EVENT>(HSMUtilityDef::HSME_INIT);
}
return HSMState::unhandledEvent(event, param);
}
};
// 运行状态(Running)
class RunningState : public HSMState {
Q_OBJECT
public:
explicit RunningState(HSMState* parent = nullptr) : HSMState(parent) {}
protected:
void onEntry(void* param) override {
qDebug() << "Entering Running State";
}
void onExit(void* param) override {
qDebug() << "Exiting Running State";
}
HSMUtilityDef::HSM_EVENT unhandledEvent(HSMUtilityDef::HSM_EVENT event, void* param) override {
if (event == HSMUtilityDef::POWER) {
return static_cast<HSMUtilityDef::HSM_EVENT>(HSMUtilityDef::HSME_EXIT);
}
return HSMState::unhandledEvent(event, param);
}
};
// 频道选择状态(Channel Selection)
class ChannelSelectionState : public HSMState {
Q_OBJECT
public:
explicit ChannelSelectionState(HSMState* parent = nullptr) : HSMState(parent), m_currentMode(BROWSE_MODE) {}
protected:
void onEntry(void* param) override {
qDebug() << "Entering Channel Selection State";
}
void onExit(void* param) override {
qDebug() << "Exiting Channel Selection State";
}
HSMUtilityDef::HSM_EVENT unhandledEvent(HSMUtilityDef::HSM_EVENT event, void* param) override {
switch (event) {
case HSMUtilityDef::CHANNEL_UP:
channelUp();
break;
case HSMUtilityDef::CHANNEL_DOWN:
channelDown();
break;
case HSMUtilityDef::MODE_SWITCH:
modeSwitch();
break;
default:
return HSMState::unhandledEvent(event, param);
}
return HSMUtilityDef::HSME_NULL;
}
private:
enum Mode {
BROWSE_MODE,
LOCK_MODE
};
Mode m_currentMode;
void channelUp() {
if (m_currentMode == BROWSE_MODE) {
qDebug() << "Channel Up in Browse Mode";
} else if (m_currentMode == LOCK_MODE) {
qDebug() << "Channel Up in Lock Mode";
}
}
void channelDown() {
if (m_currentMode == BROWSE_MODE) {
qDebug() << "Channel Down in Browse Mode";
} else if (m_currentMode == LOCK_MODE) {
qDebug() << "Channel Down in Lock Mode";
}
}
void modeSwitch() {
if (m_currentMode == BROWSE_MODE) {
m_currentMode = LOCK_MODE;
qDebug() << "Switched to Lock Mode";
} else {
m_currentMode = BROWSE_MODE;
qDebug() << "Switched to Browse Mode";
}
}
};
// 音量控制状态(Volume Control)
class VolumeControlState : public HSMState {
Q_OBJECT
public:
explicit VolumeControlState(HSMState* parent = nullptr) : HSMState(parent) {}
protected:
void onEntry(void* param) override {
qDebug() << "Entering Volume Control State";
}
void onExit(void* param) override {
qDebug() << "Exiting Volume Control State";
}
HSMUtilityDef::HSM_EVENT unhandledEvent(HSMUtilityDef::HSM_EVENT event, void* param) override {
switch (event) {
case HSMUtilityDef::VOLUME_UP:
volumeUp();
break;
case HSMUtilityDef::VOLUME_DOWN:
volumeDown();
break;
default:
return HSMState::unhandledEvent(event, param);
}
return HSMUtilityDef::HSME_NULL;
}
private:
void volumeUp() {
qDebug() << "Volume Up";
}
void volumeDown() {
qDebug() << "Volume Down";
}
};
创建一个管理状态转换的主类 HSM
:
class HSM : public QObject {
Q_OBJECT
public:
explicit HSM(QObject* parent = nullptr) : QObject(parent), m_currentState(nullptr) {}
void start(HSMState* initialState) {
if (m_currentState == nullptr) {
initialize(initialState);
}
}
void processEvent(HSMUtilityDef::HSM_EVENT event, void* param = nullptr) {
if (m_currentState != nullptr) {
HSMState* nextState = m_currentState;
HSMUtilityDef::HSM_EVENT nextEvent = event;
// 处理事件,直到返回 HSME_NULL
while (nextEvent != HSMUtilityDef::HSME_NULL) {
nextState = processSingleEvent(nextState, nextEvent, param);
nextEvent = nextState->handleEvent(event, param);
}
}
}
private:
HSMState* m_currentState;
void initialize(HSMState* initialState) {
if (initialState != nullptr) {
// 初始化状态栈
QVector<HSMState*> stateStack;
while (initialState != nullptr) {
stateStack.append(initialState);
initialState = initialState->parent();
}
// 从顶层状态开始初始化
for (int i = stateStack.size() - 1; i >= 0; --i) {
HSMState* currentState = stateStack[i];
currentState->handleEvent(HSMUtilityDef::HSME_ENTRY, nullptr);
}
m_currentState = stateStack.last();
}
}
HSMState* processSingleEvent(HSMState* currentState, HSMUtilityDef::HSM_EVENT event, void* param) {
switch (event) {
case HSMUtilityDef::HSME_INIT:
return initializeChildStates(currentState);
case HSMUtilityDef::HSME_ENTRY:
currentState->onEntry(param);
break;
case HSMUtilityDef::HSME_EXIT:
currentState->onExit(param);
return processSingleEvent(currentState->parent(), HSMUtilityDef::HSME_EXIT, param);
}
return currentState;
}
HSMState* initializeChildStates(HSMState* parentState) {
if (parentState == nullptr) {
return nullptr;
}
QVector<HSMState*> childStates = findInitialStates(parentState);
for (HSMState* state : childStates) {
processSingleEvent(state, HSMUtilityDef::HSME_ENTRY, nullptr);
}
return childStates.last();
}
QVector<HSMState*> findInitialStates(HSMState* parentState) const {
// 在实际应用中,可能需要更复杂的逻辑来确定初始子状态
// 这里简单地假设每个父状态只有一个直接的初始子状态
QVector<HSMState*> children;
QObjectList childObjects = parentState->children();
for (QObject* obj : childObjects) {
HSMState* state = qobject_cast<HSMState*>(obj);
if (state != nullptr) {
children.append(state);
}
}
// 返回第一个子状态作为初始状态
return children;
}
};
在 main
函数中构建并运行层次状态机:
#include
#include
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 创建状态对象
StandbyState* standby = new StandbyState();
RunningState* running = new RunningState(standby);
ChannelSelectionState* channelSel = new ChannelSelectionState(running);
VolumeControlState* volumeCtrl = new VolumeControlState(running);
// 构建层次结构
running->setParent(standby);
channelSel->setParent(running);
volumeCtrl->setParent(running);
// 创建状态机并启动
HSM hsm;
hsm.start(standby);
// 处理事件
hsm.processEvent(HSMUtilityDef::POWER); // 切换到运行模式
hsm.processEvent(HSMUtilityDef::CHANNEL_UP); // 选择频道向上
hsm.processEvent(HSMUtilityDef::MODE_SWITCH); // 切换到锁定模式
hsm.processEvent(HSMUtilityDef::VOLUME_UP); // 增加音量
hsm.processEvent(HSMUtilityDef::POWER); // 关闭电视
return a.exec();
}
Qt 提供了强大的信号和槽机制,可以用来进一步简化状态机的设计和实现。以下是如何将 Qt 的信号和槽与层次状态机结合使用的方法。
HSMState
类以支持信号和槽在 HSMState
中添加信号来通知状态转换或动作执行:
#include
#include
#include
namespace HSMUtilityDef {
typedef uint32_t HSM_EVENT;
// 定义常见事件
const uint32_t MAX_DEPTH = 5;
const HSM_EVENT HSME_NULL = 0;
const HSM_EVENT HSME_START = 1;
const HSM_EVENT HSME_INIT = static_cast<HSM_EVENT>(-3);
const HSM_EVENT HSME_ENTRY = static_cast<HSM_EVENT>(-2);
const HSM_EVENT HSME_EXIT = static_cast<HSM_EVENT>(-1);
// 自定义事件
const HSM_EVENT POWER = 100;
const HSM_EVENT CHANNEL_UP = 101;
const HSM_EVENT CHANNEL_DOWN = 102;
const HSM_EVENT VOLUME_UP = 103;
const HSM_EVENT VOLUME_DOWN = 104;
const HSM_EVENT MODE_SWITCH = 105;
}
class HSMState : public QObject {
Q_OBJECT
public:
explicit HSMState(HSMState *parent = nullptr) : QObject(parent), m_parent(parent) {}
virtual ~HSMState() {}
// 处理事件的主要接口
virtual HSMUtilityDef::HSM_EVENT handleEvent(HSMUtilityDef::HSM_EVENT event, void* param = nullptr) {
switch (event) {
case HSMUtilityDef::HSME_ENTRY:
onEntry(param);
break;
case HSMUtilityDef::HSME_EXIT:
onExit(param);
break;
default:
return unhandledEvent(event, param);
}
return HSMUtilityDef::HSME_NULL;
}
signals:
// 信号用于通知状态转换或动作执行
void stateEntered(HSMState* state);
void stateExited(HSMState* state);
protected:
// 进入状态时执行的动作
virtual void onEntry(void* param) {
emit stateEntered(this);
}
// 离开状态时执行的动作
virtual void onExit(void* param) {
emit stateExited(this);
}
// 处理未定义事件的方法
virtual HSMUtilityDef::HSM_EVENT unhandledEvent(HSMUtilityDef::HSM_EVENT event, void* param) {
qDebug() << "Unhandled event" << event;
return event;
}
// 获取父状态
HSMState* parent() const { return m_parent; }
private:
HSMState *m_parent;
};