Coder Social home page Coder Social logo

tinyfsm's People

Contributors

digint avatar maxgerhardt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tinyfsm's Issues

non virtual destructor

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?

Should FSM_INITIAL_STATE call entry?

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?

State update loop

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?

Testing tinyFSM state machines with VectorCAST?

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!

Security Disclosure Policy

Is there a security disclosure policy for tinyfsm?

If a vulnerability is found, is it posted anywhere?

Linking error

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

Events double dispatching support

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.

Calling dispatch() and/or transit() from action function

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?

Passing data into the State machine.

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.

transit<> shall be the last statement in react(), but isn't ...

The documentation says:

  1. 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>();
  }
 };
};

Transit only if not already in state

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>(); }

Template specialization fails in gcc < 7.0.0

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

Handle multiple FSMs

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?

Unresolved external symbol tinyfsm::Fsm<...>::current_state

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

Doesn't compile when debug information is enabled.

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?

compile error using gcc 5.4.0 (ubuntu 16.04)

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?!

Remove dependency on standard library

It would be nice if the stdfunctionality (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.

connecting IO class with Tiny FSM

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?

How do you pass a SM to a function?

main()
{
MyStateMachine::start();

gatherInformation();

dispatcherAndDecisionMakingFunction(MyStateMachine );

}

Something like this is what I'd like to accomplish.

How to separate state classes from the state machine class?

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!

Not able to compile with IAR ARM v8.20.2

TinyFSM v.0.3.2 can't be compiled using IAR ARM compiler (V8.20.2):

image

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

Any chance to pass an Action via an Event

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.