digint / tinyfsm Goto Github PK
View Code? Open in Web Editor NEWA simple C++ finite state machine library
Home Page: https://digint.ch/tinyfsm
License: MIT License
A simple C++ finite state machine library
Home Page: https://digint.ch/tinyfsm
License: MIT License
Hi,
I like you take on a simple state machine. When building with -Wnon-virtual-dtor you got some warning. I would add
virtual ~MooreMachine() noexcept = default;
to the MooreMachine template.
There is some reason I am missing why it is not there?
Great project here. One thing I was a little confused about was why entry state isn't being called when setting initial state. I expected this because the pattern seems to be that entry is the first call to every state, but INIT seems to be exception. I updated the MACRO to work as expected, but is there a better way to do this? Or should it not be done at all?
Might be a dumb question. But my understanding is that the react
method of each state is used to update the current state.
Is there some way of including an update method that is called on each loop of the main program? Making it possible to perform an operation for the duration of the state?
Does anyone have any experience testing tinyFSM state machines using a unit test tool like VectorCAST? For the application we are considering, we need to be able to provide events/stimulus and verify that each state handles the appropriate event and that transitions are executed correctly.
Any suggestions for setting up a state machine and unit test project to cover all possible events and state transitions would be greatly appreciated!
is it possible to instantiate multiple Elevators classes, using the same elevator.hpp and .cpp? if so, how?
Thanks
Is there a security disclosure policy for tinyfsm?
If a vulnerability is found, is it posted anywhere?
Hello, Is there any elegant solution to trace the previous state?
Sometimes this demand is reasonable.
Hello,
I have some troubles using the fsm. When I compile the elevator example in the console using make everything compiles fine. When I make a new project in Qt Creator I get a linker error undefined reference to tinyfsm::Fsm::set_initial_state().
Can somebody tell what the reason is for this?
Thanks in advance
John
Looking at the examples, all the member variables of the states are static.
Since declare typedef F const * state_ptr_const_t;
in class Fsm, we cannot get more than one instance for a specific Fsm. Is there any way to avoid this?
If I have two state machines with identical states Reset
And they are both setup with FSM_INITIAL_STATE(FsmA, Reset)
The code compiles fine, but it seems to seg fault. Any tips here? Thanks.
What do you think about making Events to be double dispatch-able? For now it is necessary to explicitly specify event type when dispatching event, however since it is c++ library it can be useful to take advantage of polymorphic events.
In the comment for transit function there is a note: do not send events in action_function definisions.
As I understand, that limitation is bacause of order of operations inside transit() functions:
current_state_ptr->exit();
action_function();
current_state_ptr = &_state_instance<S>::value;
current_state_ptr->entry();
Any state change caused by action_function() will be overriden by the next line.
What if we rearrange operations so that action is last:
current_state_ptr->exit();
current_state_ptr = &_state_instance<S>::value;
current_state_ptr->entry();
action_function();
Now we can call all API functions without limitation. Any state change caused by action_function() will count as any other.
What do you think?
I was wondering how I might pass data into the state machine either during initialization or after it's been initialized.
I seen this question came up before but the author closed it without providing a solution and I can't find it in the examples provided.
Do you have any suggestions on how to pass data to the state machine during construction . The templates sometimes get hard to understand :(
Something like fsm::start(12,12312);
or any suggestions of a work around ?
The documentation says:
- Implement Actions and Event Reactions
In most cases, event reactions consist of one or more of the following steps:
Change some local data Send events to other state machines Transit to different state
Important: Make sure that the transit<>() function call is the last command executed within a reaction function!
However in elevator.cpp:
class Moving
: public Elevator
{
void react(FloorSensor const & e) override {
cout << "Reached floor " << e.floor << endl;
int floor_expected = current_floor + Motor::getDirection();
if(floor_expected != e.floor)
{
cout << "Floor sensor defect (expected " << floor_expected << ", got " << e.floor << ")" << endl;
transit<Panic>(CallMaintenance);
}
current_floor = e.floor;
if(e.floor == dest_floor)
transit<Idle>();
};
};
If the expected floor is not the reported floor it transits to Panic, still sets the current floor to the floor sensor information and might even transit to Idle.
Yeah I know it's more or less cosmetic, but to avoid to confuse newbies (like me) I'd suggest:
class Moving
: public Elevator
{
void react(FloorSensor const & e) override {
int floor_expected = current_floor + Motor::getDirection();
if(floor_expected != e.floor)
{
cout << "Floor sensor defect (expected " << floor_expected << ", got " << e.floor << ")" << endl;
transit<Panic>(CallMaintenance);
}
else
{
cout << "Reached floor " << e.floor << endl;
current_floor = e.floor;
if(e.floor == dest_floor)
transit<Idle>();
}
};
};
Would it make sense to add a transitIfNotIn
method next to transit
, that prevents calling entry and exit? Like so:
template <typename S> void transit(void) {
current_state_ptr->exit();
current_state_ptr = &_state_instance<S>::value;
current_state_ptr->entry();
}
template <typename S> void transitIfNotIn(void) {
if (current_state_ptr == &_state_instance<S>::value)
return;
current_state_ptr->exit();
current_state_ptr = &_state_instance<S>::value;
current_state_ptr->entry();
}
Example usage:
virtual void react(NoWifiEvent const &) { transitIfNotIn<LostWifiState>(); }
Hi Axel,
I'm trying to compile the tinyfsm under ubuntu 16.04, my g++ version is 5.4.0. But when I run make under example, I get the following error:
In file included from motor.cpp:1:0:
../../include/tinyfsm.hpp:235:63: error: specialization of ‘template<class F> static void tinyfsm::Fsm<F>::set_initial_state()’ in different namespace [-fpermissive]
template<> void tinyfsm::Fsm< _FSM >::set_initial_state(void) { \
^
motor.cpp:62:1: note: in expansion of macro ‘FSM_INITIAL_STATE’
FSM_INITIAL_STATE(Motor, Stopped)
^
../../include/tinyfsm.hpp:96:17: error: from definition of ‘template<class F> static void tinyfsm::Fsm<F>::set_initial_state()’ [-fpermissive]
static void set_initial_state();
^
Makefile:90: recipe for target 'motor.o' failed
make: *** [motor.o] Error 1
Would you help me to fix it ?
Thank you,
Husky
I'm, not too savvy with C++ templates and would like some help with this topic.
I would like to print a stribg for example with the state of my SM.
I have the need to have, in parallel, several FSM that are exactly the same, but that will be in different states as they respond to a button, but that button is different for all of them.
Considering tinyfsm FSMs are not instances, what is the best way to handle this?
Hi Axel,
I'm trying to use tinyfsm in a Windows DLL, i.e. my concrete FSM is defined in DLL and referenced in an (unit test) executable that links this DLL's import library :
in DLL sources :
class __declspec (dllexport) AutopilotFSM : public tinyfsm::Fsm<AutopilotFSM> {...}
in executable sources :
class __declspec (dllimport) AutopilotFSM : public tinyfsm::Fsm<AutopilotFSM> {...}
It builds and runs OK, until I try to dispatch an event from the executable :
AutopilotFSMList::template dispatch<EventType>(event);
When I try to link the executable, I get a linker error below.
I've double-checked the DLL (with dependency walker), and current_state IS defined there.
error LNK2001: unresolved external symbol "private: static class AP::AutopilotFSM * tinyfsm::Fsm::current_state" (?current_state@?$Fsm@VAutopilotFSM@AP@@@tinyfsm@@0PAVAutopilotFSM@AP@@A)
Would you have any suggestions ?
Thanks,
Eugene
Related to reliability.
After enabling debug information:
#include <iostream>
#define DBG(str) do { std::cerr << str << std::endl; } while( false )
DBG("*** dbg_example *** " << __PRETTY_FUNCTION__);
the projects don't compile:
$ make
g++ -c -I ../../include -MMD -Os -std=c++11 -fno-exceptions -fno-rtti -Wall -Wextra -Wctor-dtor-privacy -Wcast-align -Wpointer-arith -Wredundant-decls -Wshadow -Wcast-qual -Wcast-align -pedantic -o motor.o motor.cpp
In file included from motor.cpp:1:
../../include/tinyfsm.hpp:46:19: error: expected unqualified-id before ‘do’
46 | #define DBG(str) do { std::cerr << str << std::endl; } while( false )
| ^~
../../include/tinyfsm.hpp:47:2: note: in expansion of macro ‘DBG’
47 | DBG("*** dbg_example *** " << __PRETTY_FUNCTION__);
| ^~~
../../include/tinyfsm.hpp:46:57: error: expected unqualified-id before ‘while’
46 | #define DBG(str) do { std::cerr << str << std::endl; } while( false )
| ^~~~~
../../include/tinyfsm.hpp:47:2: note: in expansion of macro ‘DBG’
47 | DBG("*** dbg_example *** " << __PRETTY_FUNCTION__);
| ^~~
make: *** [Makefile:90: motor.o] Error 1
$
Any hint?
I get the following compile error for the (unmodified) elevator example:
g++ -c -I ../../include -MMD -Os -std=c++11 -fno-exceptions -fno-rtti -Wall -Wextra -Wctor-dtor-privacy -Wcast-align -Wpointer-arith -Wredundant-decls -Wshadow -Wcast-qual -Wcast-align -pedantic -o motor.o motor.cpp
In file included from motor.cpp:1:0:
../../include/tinyfsm.hpp:235:63: error: specialization of ‘template static void tinyfsm::Fsm::set_initial_state()’ in different namespace [-fpermissive]
template<> void tinyfsm::Fsm< _FSM >::set_initial_state(void) {
^
motor.cpp:62:1: note: in expansion of macro ‘FSM_INITIAL_STATE’
FSM_INITIAL_STATE(Motor, Stopped)
^
../../include/tinyfsm.hpp:96:17: error: from definition of ‘template static void tinyfsm::Fsm::set_initial_state()’ [-fpermissive]
static void set_initial_state();
^
Makefile:90: recipe for target 'motor.o' failed
make: *** [motor.o] Error 1
Any hint appreciated, my C++ template skills seem quite a bit rusty?!
It would be nice if the std
functionality (currently only those 3 compile time checks) could be disabled using a define
so that it would be easy to integrate tinyfsm into a microcontroller toolchain.
Alternatively, the is_same
and result_of
could be implemented independently.
Hi,
I am working on some project (studying C++). I have an IO class providing interface to send/receive (boost::asio async raw socket) with the following methods:
class IO {
public:
...
void do_receive()
void do_send(char* data_, std::size_t length)
...
so there is object of that class:
IO s(io_context, argv[1]);
And I can send data to FSM passing buffer inside an Event but would like also to be able to generate packets outbound so from FSM. What way would you recommend to implement exchange with network ? Maybe you have some quick examples doing the same?
Minor compilation issue with most of the makefiles on Mac as "-B" is not supported on Mac.
main()
{
MyStateMachine::start();
gatherInformation();
dispatcherAndDecisionMakingFunction(MyStateMachine );
}
Something like this is what I'd like to accomplish.
It's been quite some time since I've developed cpp but I'm stuck on trying to separate out the state classes from the State Machine Class's cpp file. No matter how I rearrange the code, I get an expected class-name before '{' token
error defining the state class.
Using the Elevator example, let's say I wanted to pull out the Panic state class into it's own file. How would I do that?
If I put the panic class into panic.hpp and include it in Elevator.hpp, then I get
In file included from elevator.hpp:5,
from elevator.cpp:3:
panic.h:3:1: error: expected class-name before ‘{’ token
3 | {
The doc states
Note that the "elevator" example source code does not declare the states separately, but rather defines the code directly in the declaration.
So my question would be, how would I declare the states separately?
Thanks!
Is there any plan for a tag release ?
TinyFSM v.0.3.2 can't be compiled using IAR ARM compiler (V8.20.2):
The compiler seems to think that the derived state classes are unreleated to the base class. Using GCC the same code compiles and works fine without any warnings.
Adding a reinterpret_cast in line 137 allows compilation, but maybe there is a better solution/workaround for this?
current_state_ptr = reinterpret_cast<state_ptr_t>(&_state_instance<S>::value);
Thanks and best regards
Marvin
Is it possible to change the initial_state at runtime?
I am storing the the states of my machine in the database and at restart, I would like to start from the last known stored state. Is it possible to set the FSM_initial_state at runtime, without using the transit function?
Thanks
Probably this is more a general C++ question than it is a tinyfsm one, but maybe some did this already.
I have an event called ShouldEstimateAndSend which transits to a new state on a few conditions. I'd like to have it call transit<NewState>(ShoudEstimateAndSend::action_function).
Using std::function would work, but this introduces some runtime overhead and pulls in exception handling which is not what I like on my embedded target. Using a template event class 'breaks' inheritance and would need a template react function as far as I can see?!
Can't wiggle my head around this.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.