机器人开发项目经验回顾之OpenFSM有限状态机框架(前期方案)

前言

在嵌入式系统和机器人开发中,有限状态机(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;
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值