一个Boost Statechart Library有限状态机实用示例

BOOST元状态机用户手册之三教程(Meta State Machine (MSM))(1)——基本前端及例程 本文根据boost元状态教程基本前端实现简单状态翻译而来,并同时添加个人理解内容。程序在C++下能正常运行及各状态转换符合设计 阅读详情

一、前言

boost库提供了两个状态机的库Meta State Machine和Statechart,我写的例程基于boost 1.60.0版本的Statechart库。在boost_1_60_0/libs/statechart/example/源码目录下提供了7个例程,在官方网站的文档中The Boost Statechart Library - Tutorial - 1.60.0提供了一些详细的介绍。但是这7个例程都不能很好地满足我的需求,于是我自己写了一个比较切合我需求的例程,希望对大家也能有所帮助。

二、代码说明

EvAddKey
EvAddKey 1
EvAddKey 0
Start
Work
Stop
  1. 示例程序包含3个源文件main.cpp、key_handler.hpp和key_handler.cpp,示例程序包含1个状态机(KeyHandler类型)和3个状态(Start、Work和Stop),main函数循环向状态机发送包含布尔值的事件,状态机的初始状态为Start,状态机收到第一个事件后会从Start状态跳转到Work状态,在Wrok状态中若收到布尔值为1的事件则忽略该事件,若收到布尔值为0的事件则将状态机中的stop_flag设置为true,然后跳转到Stop状态,main函数读取到状态机的stop_flag为true时则退出循环和程序;
  2. main.cpp中创建了一个KeyHandler类型的状态机,并且循环从键盘输入布尔值、创建一个包含布尔值的事件、向状态机发送事件,然后读取状态机的flag,若flag为1则退出循环;
  3. key_handler.hpp中定义了EvAddKey事件类和KeyHandler状态机类,以及Start、Work和Stop状态类,EvAddKey事件类中有一个用于存储输入布尔值的变量,KeyHandler状态机类中有一个用于存储是否需要退出程序的布尔变量,Start、Work和Stop状态类中各有一个用于响应EvAddKey事件的自定义react函数;
  4. key_handler.cpp中实现了三个状态类的构造函数、析构函数和react函数,在react函数中返回transit<Work>()可以实现状态跳转,在react函数中使用context<KeyHandler>().set_flag(true)可以调用状态机类或者状态类中的函数,在react函数中返回discard_event()可以忽略该事件。

三、代码

main.cpp

#include <iostream>
#include "key_handler.hpp"

bool get_key()
{
    char key;
    std::cout << "Please input 0 or 1: ";
    std::cin >> key;
    if (key == '0')
    {
        return false;
    }
    return true;
}

int main(void)
{
    KeyHandler handler;
    handler.initiate();
    for(int i = 0; i < 5; i++)
    {
        handler.process_event(EvAddKey(get_key()));
        if (handler.get_flag())
        {
            break;
        }
    }
    std::cout << "Exit main." << std::endl;
    return 0;
}

key_handler.hpp

#ifndef KEY_HANDLER_HPP
#define KEY_HANDLER_HPP

#include <boost/statechart/event.hpp>
#include <boost/statechart/state_machine.hpp>
#include <boost/statechart/simple_state.hpp>
#include <boost/statechart/custom_reaction.hpp>

namespace sc = boost::statechart;

struct EvAddKey : sc::event<EvAddKey>
{
public:
    EvAddKey(bool val) : val_(val) {};
    bool get_val() const { return val_; };

private:
    bool val_;
};

struct Start;
struct KeyHandler : sc::state_machine<KeyHandler, Start>
{
public:
    KeyHandler() : stop_flag_(false) {};
    void set_flag(bool flag) { stop_flag_ = flag; };
    bool get_flag() { return stop_flag_; };

private:
    bool stop_flag_;
};

struct Start : sc::simple_state<Start, KeyHandler>
{
    Start();
    ~Start();

    typedef sc::custom_reaction<EvAddKey> reactions;
    sc::result react(const EvAddKey &);
};

struct Work : sc::simple_state<Work, KeyHandler>
{
    Work();
    ~Work();

    typedef sc::custom_reaction<EvAddKey> reactions;
    sc::result react(const EvAddKey &);
};

struct Stop : sc::simple_state<Stop, KeyHandler>
{
    Stop();
    ~Stop();

    typedef sc::custom_reaction<EvAddKey> reactions;
    sc::result react(const EvAddKey &);
};

#endif

key_handler.cpp

#include <iostream>
#include "key_handler.hpp"

Start::Start()
{
    std::cout << "Entering Start" << std::endl;
}

Start::~Start()
{
    std::cout << "Exiting Start" << std::endl;
}

sc::result Start::react(const EvAddKey & event)
{
    std::cout << "Reacting Start" << std::endl;
    std::cout << "Ignore " << event.get_val() << std::endl;
    return transit<Work>();
}

Work::Work()
{
    std::cout << "Entering Work" << std::endl;
}

Work::~Work()
{
    std::cout << "Exiting Work" << std::endl;
}

sc::result Work::react(const EvAddKey & event)
{
    std::cout << "Reacting Work" << std::endl;
    if (event.get_val() == false)
    {
        context<KeyHandler>().set_flag(true);
        return transit<Stop>();
    }
    return discard_event();
}

Stop::Stop()
{
    std::cout << "Entering Stop" << std::endl;
}

Stop::~Stop()
{
    std::cout << "Exiting Stop" << std::endl;
}

sc::result Stop::react(const EvAddKey &)
{
    std::cout << "Reacting Stop" << std::endl;
    return discard_event();
}

四、编译、运行

charming@ubuntu:~/Documents/fsm/handle_key$ ls
key_handler.cpp  key_handler.hpp  main.cpp
charming@ubuntu:~/Documents/fsm/handle_key$ g++ *.* -o test
charming@ubuntu:~/Documents/fsm/handle_key$ ./test 
Entering Start
Please input 0 or 1: 1
Reacting Start
Ignore 1
Exiting Start
Entering Work
Please input 0 or 1: 1
Reacting Work
Please input 0 or 1: 1
Reacting Work
Please input 0 or 1: 0
Reacting Work
Exiting Work
Entering Stop
Exit main.
Exiting Stop
charming@ubuntu:~/Documents/fsm/handle_key$
boost::sml 状态机 boost::sml 阅读详情

相关推荐

boost::sml 状态机之子状态机

boost sml 子状态机

weixin_45591821的博客 968

boost学习之01 - 有限状态机

基于 boost::statechart 模板库的一个秒表计时器   源代码如下: #include #include #include #include #include #include using namespace std; namespace sc = boost::statechart; namespace boost_learning { namespace

大师兄的花果山 702

使用 Boost 中的 statechart 模块实现正交状态和状态查询是非常有用的。我们可以使用该模块来定义状态机,然后让程序根据条件自动跳转到不同的状态。

接下来,我们需要实现状态查询功能。我们需要使用 boost::statechart::state_downcast() 函数来查询特定正交区域内的状态。接下来,我们使用 boost::statechart::state_downcast(&myMachine) 方法来查询第二个正交区域的状态。如果您需要实现更复杂的状态机,您可以使用相同的方法来组合和查询不同的状态。在本篇文章中,我们将介绍如何使用 statechart 模块来实现正交状态和 state_downcast 查询正交区域的状态。

DarcyCode的博客 368

boost 状态机--中级篇

原文:The Boost Statechart Library 译者:penghuster 进阶主题:数码相机 目前一切都很好,然而,上述方法也存在以下限制: 可扩展性差:只要编译器到达 state_machine::initiate() 调用所在位置,大量的模板类实例化将发生,这只有在状态机所有的状态都完整申明后才能成功。这也就是说,状态机的所有代码必须在一个单独编译单元中完成(虽然act...

u010217394的博客 438

使用boost::statechart模块自定义反应进行测试的程序

通过编写测试程序,我们可以对自定义反应进行测试,并不断地改进实现,以确保状态机的行为符合我们的预期。在使用boost::statechart模块开发状态机时,会经常使用自定义反应,来实现对状态转换时的额外处理。在实际开发中,我们可以在这里添加一些额外的逻辑,例如记录事件发生的时间戳、发送一些消息等等。在实际开发中,我们可以根据测试结果来调整自定义反应的实现,以确保状态机的行为符合我们的预期。接下来,我们需要编写一个测试程序,来测试我们开发的自定义反应。首先,我们需要定义一些状态和事件。

Meta_C的博客 159

Boost库中的statechart模块是一个用于实现状态机的工具,它提供了一种面向对象的方式来描述状态机的状态和转移

在statechart库中,默认的复制操作会将整个状态机的状态都复制一遍,包括当前状态和其所属的父状态。因此,在我们向Active状态机对象发送事件时,在默认的复制操作下,Active状态机会被复制一遍,这导致了状态之间的无效转移。然而,在使用statechart模块时,有时会遇到状态转移无效的情况,这种无效结果的产生往往与状态复制操作有关。在输出结果中,状态的变化顺序是:从Idle进入Running,然后到Stopping,接着返回Running,最后回到Idle。

pytorchCode的博客 361

c++ boost 状态机简单case:模拟下载文件

也算备忘录吧,看了一段时间的状态机,记录一下 #include <iostream> #include <boost/statechart/state_machine.hpp> #include <boost/statechart/simple_state.hpp> #include <boost/statechart/transition.hpp> #include <boost/statechart/custom_react...

小罗的学习博客 392

用boost::statechart模块实现状态机的终止测试

随后,发送了一个Event事件给状态机,当状态机接收到该事件时,将调用terminate()函数终止状态机的执行。最后,输出一条消息表明状态机已经被终止。在InitState状态中,定义了一个转移条件Event,当状态机接收到Event事件时,将会调用terminate()函数终止状态机的执行。在使用boost::statechart实现状态机时,为了保证程序的正确性和稳定性,在某些情况下需要手动终止状态机。例如,当状态机执行完一些特定的操作后或者接收到某个特定的事件时,可以选择终止状态机的执行。

ByteNinja的博客 236

boost 有限状态机(FSM)

#include "stdafx.h" #include #include "boost/statechart/state_machine.hpp" #include "boost/statechart/simple_state.hpp" // #include "boost/statechart/transition.hpp" // #include "boost/statechart/ev

BORN TO WIN 3833

基于JavaFX的Http Server模拟器

源码地址 GitHub - DayRain/http-server-simulator: http server 模拟器 功能描述 HttpServer模拟器,通过简单的配置即可模拟第三方服务端,用于接收和响应HTTP请求。 支持同时模拟多个服务、动态添加接口、动态配置返回值。 使用说明 运行 exe运行 编译代码后,点击exe直接运行 代码运行 下载好代码后,运行主类ApplicationStarter即可 新建服务 主界面如下 点击 文件-新建 创建新的服务 ...

小楼夜听雨的博客 2534

Qt for Android:基于libusb实现CH340x串口通信的高效开发方案

本文详细介绍了在Qt for Android环境下,基于libusb实现CH340x串口通信的高效开发方案。通过绕过Android高版本系统的权限限制,利用libusb+JNI技术实现稳定通信,适用于工业手持终端等场景。文章涵盖环境搭建、核心实现、常见问题解决方案及性能调优经验,帮助开发者快速掌握这一关键技术。

weixin_42715608的博客 426

BOOST Statechart 状态机若干注意事项

1、跨进程dll发送(process_event)事件(boost::statechart::event)会导致不明异常;2、多线程时,在某线程发送(process_event)事件(boost::statechart::event)会导致“pOutermostUnstableState_”为空中断;

狂人山庄 3449

FPGA DMA IP核使用指南

数据传输:支持从源地址到目标地址的数据传输。中断管理:提供中断信号,便于CPU处理传输完成事件。传输控制:支持传输大小、方向和暂停/恢复控制。

weixin_66634995的博客 2427

Boost StateChart状态机学习

最近在使用stateChart状态机时遇到一些问题,记录一下 简介 1、定义一个继承自state_machine的结构体作为状态机主体,内部可包含一些切换状态机的接口以及响应不同事件的函数 2、定义一系列状态结构体,继承自simple_state或state(若在entry reaction或exit reaction中需要调用部分函数如post_event()等则需继承后者)...

liu3612162的博客 3268

VMware Workstation Pro 17 最新破解版安装教程(附永久激活密钥)

本文详细介绍了VMware Workstation Pro 17专业版的安装与配置指南,包括系统要求检查、官方版本安装流程、高级配置优化及常见问题排查。通过合规使用官方版本,开发者可以充分利用其强大的虚拟化能力,提升多平台开发与测试效率。

weixin_29327977的博客 3530

西门子SCL出栈入栈算法(附带源码)

栈是一种数据结构,它的特点是数据后入先出(Last In First Out,LIFO)或者说是先入后出,意思是一样的。栈有三个基本动作:初始化、入栈和出栈。接下来给大家介绍下我使用SCL语言编写的栈函数,它以不定长数组作为存储区,以实数作为数据类型,实现了栈的初始化、入栈和出栈的操作。

CHUXUEZHE8210的博客 2330

boost::statechart学习记录

目前项目中突然接收到 状态机的学习,之前一直在组长搭的架子(另一套状态机)上进行开发,熟悉了状态机的套路,然后最近代码中进了一部分boost::statechart 的代码用于处理HMI 相关session.借此机会也研究一番。 将简单的事做好就是不简单。 boost::statechart 主要分为三部分: 状态机(statemachine) | 状态(state) | 事件(event/mes...

yang06lei11的博客 2020

深入解析音频信号处理的核心算法——傅里叶变换、语音增强、回声消除与主动降噪

本文系统介绍了现代音频信号处理的核心技术。首先阐述傅里叶变换作为理论基础的重要性,它能将声音分解为频域成分。随后重点分析三大关键技术:语音增强利用谱减法、维纳滤波和深度学习从噪声中提取人声;回声消除采用自适应滤波器消除通话中的回声;主动降噪通过声波干涉原理抵消环境噪声。文章最后指出,这些技术在实际应用中协同工作,形成完整的音频处理链路,共同提升语音质量和听觉体验。随着算法进步和算力提升,音频处理技术正向着更智能、更高效的方向发展。

程序猿老樊的博客 1325

boost 里面有状态机了_一个很有代表性的boost状态机实例

#include #include #include #include #include namespace sc = boost::statechart;struct Event1 : sc::event{};struct Event2 : sc::event{};struct SimpleState1;struct StateMachine1 : sc::state_machine{State...

weixin_39612499的博客 267

【C语言学习疑难杂症】第20期:0x00007FF7F2821964处引发的异常0xC0000005写入位置 0x0000000000000

检查代码中是否存在野指针访问的情况,确保在进行写入操作之前,内存已经被正确分配或初始化,并且在使用完毕后进行了正确的释放。空指针访问:代码尝试在空指针地址(0x0000000000000000)处进行写入操作,导致访问冲突。检查代码中是否存在数组越界的情况,确保在进行写入操作之前,数组的索引值在合法范围内。检查代码中是否存在空指针访问的情况,确保在进行写入操作之前,指针已经被正确初始化。野指针访问:代码尝试在已释放或未初始化的内存地址进行写入操作,导致访问冲突。

学无止境 828

51单片机 驱动有源/无源蜂鸣器+Proteus仿真

51单片机 驱动有源/无源蜂鸣器+Proteus仿真 相关篇《51单片机 Proteus仿真有源蜂鸣器始终不响原因及解决方法》 电路搭建 采用NPN管驱动有源蜂鸣器电路 采用PNP管驱动有源蜂鸣器电路 采用PNP管驱动无源蜂鸣器 采用NPN管驱动无源蜂鸣器 Proteus元器件列表 实例代码 /************************************************************************************* * 实验现象:下载程序

perseverance51博客 2万+

Android学习 StateMachine与State模式

      Android学习 StateMachine与State模式 一 State模式 意图:   允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。(Objects for States)   对象内部状态决定行为方式,对象状态改变行为方式改变;但这里为何要强调内部状态, 外部状态改变也同样会影响行为方式的改变,通常外部状态的改变都会反映到内部状态上来。 ...

weixin_34183910的博客 623

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Boost 状态图库--初级篇

原文:The Boost Statechart Library 译者:penghuster 基本主题:秒表 接下来我们将创建一个简单的状态机---秒表。此秒表有两个按钮: -开始/停止 -复位 以及两种状态: 停止:指针位于其最后停止的位置,此时秒表处于停止状态。按复位按钮可以复位指针到最初位置,按开始/停止按钮秒表将转变为运行状态。 运行:指针处于移动中,连续显示时间地流逝。按复位按钮将导...

u010217394的博客 291

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

boost 里面有状态机了_有限状态机,boost::msm

一个简单的有限状态机如图所示: 状态机几个要素: 状态state、事件event、动作action。这个状态机有两个状态,State1状态,和结束状态, 在Event1发生时会触发action(或者默认没有action),从而状态发生迁移。boost的状态机库(Boost.MetaStateMachine )分为 back-end 和 front-end; 根据 front-end 的不同有三种实...

weixin_32955207的博客 1220

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

boost 状态机--中级篇(实例)

boost 状态机--中级篇以Camera为例,讲解了Boost状态机模型的使用方法;而本文的主要: 对原文中的Camera模型略加修改与完善; 写出了完整代码;可编译运行; 演示各个对象(事件对象和状态对象)的生命周期; 更清晰的模块化各个组件(事件、状态); 故可以当作一个简单的代码框架; Camera的按键: 配置键(Config Button): 按此键会产生一个EvConfig...

u010217394的博客 278

BOOST c++库学习 状态机 以及基于状态机的交通信号灯程序

状态机是一种数学模型,用于表示系统中有限数量的状态以及它们之间的转移。状态(State):系统在某一时刻所处的条件或情境。事件(Event):触发状态转换的输入信号。转移(Transition):状态之间的转换路径,根据事件的触发发生。动作(Action):在状态转换时执行的操作。当系统接收到一个事件时,状态机会根据当前的状态和预定义的转移规则,改变到另一个状态,并执行相应的动作。这种模式特别适用于处理复杂的逻辑流程,确保系统在任何时候都处于一致的状态。

weixin_44251074的博客 1759
上一篇: 《视觉SLAM十四讲》单应矩阵与cv::decomposeHomographyMat函数源码浅析
下一篇: 一种线程安全的C++单例模式模板类的简易实现
Charming Sun
博客等级 码龄11年 212粉丝 36原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值