前言
在嵌入式系统和机器人开发中,有限状态机(FSM, Finite State Machine)是处理复杂状态转换的经典设计模式。本项目集成了OpenFSM——一个轻量级、高性能的C++状态机框架,用于处理机器人的底层状态控制和任务流程管理。
与行为树(BehaviorTree)相比,FSM更适合处理明确的状态转换逻辑、实时性要求高的场景。本项目中,FSM可作为行为树的补充,用于处理诸如充电对接、传感器状态机等底层控制逻辑。
本文将深入剖析OpenFSM的设计思想、核心实现、使用方法以及在ROS机器人系统中的应用场景。
核心特性
1. 三层架构设计
- OpenFSMAction:动作层 - 状态内的具体执行逻辑(enter/update/exit)
- OpenFSMState:状态层 - 管理动作序列和状态转换关系
- OpenFSM:控制器层 - 驱动状态机运行和状态切换
2. 全局注册池机制
- OpenFSMPool:单例模式的全局状态/动作注册中心
- 支持在程序启动时全局注册,运行时动态组装状态机
- 避免重复创建,提高内存利用率
3. 灵活的状态关系定义
- Action序列:每个状态可包含多个按顺序执行的Action
- Relation关系:定义状态完成后的默认转换目标
- 动态切换:支持运行时通过
nextState()强制跳转
4. 模板化注册接口
// 注册动作(模板类)
OpenFSM::RegisterAction<ChargeAction>("ChargeAction");
// 注册状态(initializer_list语法糖)
OpenFSM::RegisterState("IdleState", {
"WaitAction", "CheckBatteryAction"});
// 注册状态关系
OpenFSM::RegisterRelation("IdleState", {
"ChargeState", "WorkState"});
系统架构
1. 三层架构图
┌─────────────────────────────────────────────────────────────┐
│ OpenFSM (控制器) │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ vectState_: [State1, State2, State3, ...] │ │
│ │ fsmState_: 当前执行的状态指针 │ │
│ │ eNextState_: 下一个状态ID(用于状态切换) │ │
│ │ actionIdx_: 当前Action索引 │ │
│ └───────────────────────────────────────────────────────┘ │
│ │ │ │
│ │ enterState() │ update() │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌──────────────────┐ │
│ │ 状态进入时调用 │ │ 每帧/周期调用 │ │
│ │ state->enter() │ │ state->update() │ │
│ └─────────────────┘ └──────────────────┘ │
└───────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ OpenFSMState (状态层) │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ eState_: 状态ID(唯一标识) │ │
│ │ stateName_: 状态名称 │ │
│ │ vectAction_: [Action1, Action2, ...] │ │
│ │ vectRelationState_: [NextState1, NextState2, ...] │ │
│ └───────────────────────────────────────────────────────┘ │
│ │ │
│ │ enter() / update() / exit() │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 循环执行vectAction_中的所有Action │ │
│ │ 执行完毕后自动跳转到vectRelationState_[0] │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ OpenFSMAction (动作层) │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ actionName_: 动作名称 │ │
│ │ virtual void enter(OpenFSM& fsm) - 动作开始 │ │
│ │ virtual void update(OpenFSM& fsm) - 动作执行 │ │
│ │ virtual void exit(OpenFSM& fsm) - 动作结束 │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
2. 状态机执行流程图
程序启动
│
▼
┌───────────────────────┐
│ 全局注册阶段 │
│ RegisterAction() │
│ RegisterState() │
│ RegisterRelation() │
└───────────────────────┘
│
▼
┌───────────────────────┐
│ 创建FSM实例 │
│ OpenFSM fsm; │
│ fsm.setStates({...}) │
└───────────────────────┘
│
▼
┌───────────────────────┐
│ 进入初始状态 │
│ fsm.enterState(0) │
└───────────────────────┘
│
▼
┌───────────────────────────────────┐
│ 主循环(每帧/周期) │
│ while(true) { │
│ fsm.update(); │
│ } │
└───────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ update()内部执行流程 │
│ 1. 执行fsmState_->update() │
│ 2. 调用当前Action的update() │
│ 3. 检查eNextState_是否非0 │
│ 4. 如果需要切换状态,调用enterState()│
│ 5. 循环直到eNextState_==0 │
└─────────────────────────────────────┘
3. Action序列执行机制
状态State1包含3个Action: [A1, A2, A3]
默认Relation: [State2]
执行流程:
┌──────────────────────────────────────────────────────┐
│ enterState("State1") │
│ ├─ actionIdx_ = 0 │
│ └─ A1.enter() ← 第一个Action进入 │
└──────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────┐
│ update() 循环调用 │
│ └─ A1.update() ← 第一个Action执行 │
└──────────────────────────────────────────────────────┘
│
▼ A1完成,调用nextAction()
┌──────────────────────────────────────────────────────┐
│ nextAction() │
│ ├─ A1.exit() ← 退出第一个Action │
│ ├─ actionIdx_++ │
│ └─ A2.enter() ← 进入第二个Action │
└──────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────┐
│ update() 循环调用 │
│ └─ A2.update() ← 第二个Action执行 │
└──────────────────────────────────────────────────────┘
│
▼ A2完成,调用nextAction()
┌──────────────────────────────────────────────────────┐
│ nextAction() │
│ ├─ A2.exit() │
│ ├─ actionIdx_++ │
│ └─ A3.enter() ← 进入第三个Action │
└──────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────┐
│ update() 循环调用 │
│ └─ A3.update() ← 第三个Action执行 │
└──────────────────────────────────────────────────────┘
│
▼ A3完成,调用nextAction()
┌──────────────────────────────────────────────────────┐
│ nextAction() │
│ ├─ A3.exit() │
│ ├─ actionIdx_++ (此时actionIdx_==3 >= 3) │
│ └─ 自动跳转到Relation[0]: nextState("State2") │
└──────────────────────────────────────────────────────┘
核心实现
1. OpenFSMAction - 动作基类
文件位置: include/cloud/fsm/openfsm.h
class OpenFSMAction {
public:
OpenFSMAction();
virtual ~OpenFSMAction();
// 动作开始时调用(初始化资源)
virtual void enter(OpenFSM& fsm) const;
// 每帧/周期调用(执行动作逻辑)
virtual void update(OpenFSM& fsm) const;
// 动作结束时调用(清理资源)
virtual void exit(OpenFSM& fsm) const;
protected:
std::string actionName_; // 动作名称
friend class OpenFSM;
};
使用示例 - 自定义充电动作:
class ChargeAction : public OpenFSMAction {
public:
void enter(OpenFSM& fsm) const override {
CLOUD_INFO("Charge action started");
// 发送充电对接指令
Car* car = fsm.custom<Car>();
car->ComniucateWithAutoCharge("192.168.1.100", true);
}
void update(OpenFSM& fsm) const override {
// 检查是否充上电
Car* car = fsm.custom<Car>();
if(car->isCharging()) {
CLOUD_INFO("Charge success, next action");
fsm.nextAction(); // 跳到下一个Action
}
}
void exit(OpenFSM& fsm) const override {
CLOUD_INFO("Charge action completed");
}
};
2. OpenFSMState - 状态类
文件位置: include/cloud/fsm/openfsm.h
class OpenFSMState {
public:
OpenFSMState(int eState, const std::string& stateName);
virtual ~OpenFSMState();
// 状态进入时调用
virtual void enter(OpenFSM& fsm) const;
// 每帧调用(驱动当前Action执行)
virtual void update(OpenFSM& fsm) const;
// 状态退出时调用
virtual void exit(OpenFSM& fsm) const;
protected:
void nextAction(OpenFSM& fsm) const;
int eState_; // 状态ID
std::string stateName_; // 状态名称
std::vector<const OpenFSMAction*> vectAction_; // 动作序列
std::vector<OpenFSMState*> vectRelationState_; // 关联状态
friend class OpenFSM;
};
核心方法实现:
// 状态进入(src/fsm/openfsm.cpp:57)
void OpenFSMState::enter(OpenFSM& fsm) const {
assert(eState_ != 0);
fsm.actionIdx_ = 0; // 重置Action索引
if (fsm.actionIdx_ >= vectAction_.size())
return;
// 调用第一个Action的enter()
vectAction_[fsm.actionIdx_]->enter(fsm);
}
// 状态更新(src/fsm/openfsm.cpp:68)
void OpenFSMState::update(OpenFSM& fsm) const {
// 如果所有Action执行完毕
if (fsm.actionIdx_ >= vectAction_.size()) {
if (!vectRelationState_.empty()) {
// 自动跳转到第一个关联状态
fsm.nextState(vectRelationState_[0]->eState_);
return;
}
assert(false); // 没有关联状态,报错
return;
}

1634

被折叠的 条评论
为什么被折叠?



