Simple C++ State Machine

I’ve attached a generic state machine class that could be useful in autonomous programming this year. My team is looking at using the IterativeRobot base class so we needed a way to keep state information in between iterations. I have not yet tested this on a robot but will try to this week as we get our control system setup.

The class uses templates to let you customize things a bit. The first parameter is the state identifier type, we will most likely use an enum, but you could use anything most likely including strings. The other two parameters are for the method callbacks (the class type we are passing an instance of in the constructor and the method signature). You then need to associate states with method callbacks for each state you want to use then set the initial state. During the perodic call the call to CallCurrentState will delegate control to whatever callback you’ve set using AddStateCallback.

It has been a while since I’ve written C++ (I work more with C# these days) so this code may be rough. Below is an example I wrote from memory without testing so it definitely won’t compile without some work.

Example (not tested):

#include "StateMachine.h"

enum AutoState
{
    AUTO_START,
    AUTO_TURN,
    AUTO_GOAL1
};

class MyBot : public IterativeRobot
{
private:
    StateMachine<AutoState, MyBot, void (MyBot::*)(void)> *m_state;

public:
    MyBot(void)
    {
        m_state = new StateMachine<AutoState, MyBot, void (MyBot::*)(void)>(this);
        m_state->AddStateCallback(AUTO_START, &MyBot::Autonomous_State_Start);
        m_state->AddStateCallback(AUTO_TURN, &MyBot::Autonomous_State_Turn);
        m_state->AddStateCallback(AUTO_GOAL1, &MyBot::Autonomous_State_Goal1);
    }

    ~MyBot(void)
    {
        delete m_state;
    }

    void AutonomousInit(void)
    {
        m_state->SetCurrentState(AUTO_START);
    }

    void AutonomousPeriodic(void)
    {
        m_state->CallCurrentState();
    }

    void Autonomous_State_Start(void)
    {
        //... DO STUFF ...
        m_state->SetCurrentState(AUTO_TURN);
    }

    void Autonomous_State_Turn(void)
    {
        //... DO STUFF ...
        m_state->SetCurrentState(AUTO_GOAL1);
    }
    void Autonomous_State_Goal1(void)
    {
        //... DO STUFF ...
        m_state->SetCurrentState(AUTO_TURN);
    }
};
```<br><br><a class='attachment' href='/uploads/default/original/3X/6/d/6d353784043c983a4b91e481eb294689d8f5b942.h'>StateMachine.h</a> (2.28 KB)<br><br><br><a class='attachment' href='/uploads/default/original/3X/6/d/6d353784043c983a4b91e481eb294689d8f5b942.h'>StateMachine.h</a> (2.28 KB)<br>

I haven’t written code for a FIRST robot in quite a while, with the exception of trying to teach myself LabVIEW this weekend. Can you explain to me why you are choosing the iterative robot class? I was excited about the possibility of non-iterative, because it feels more natural to me.

However, 98% of the code I’ve written in the last few years has been math/engineering/modeling, so I have a different view point: I’m interested in yours.

My main motivation for doing iterative is for the similarity to how we’ve programmed in the past. Plus I am used to the whole main loop method of programming that you see a lot in game and GUI programming.

I am still exploring the RobotBase class and the possibility of just overriding StartCompetition and running our own flavor.

When you talk about iterative being similar to how you’ve programmed in the past, are you referring to the default code of previous years? WPILib was available for the past two years and previous versions resemble the “Simple Robot” class much more than interative.

At any rate,

It’s possible I’m not understanding this properly but why would you create a specialized class to handle this? Can’t information that you need to be maintained between iterations be kept as members of your robot class itself without having to be dynamically allocated? While the stacks for the functions may be popped off as you go through iterations, isn’t the original instance of the entire class used throughought the running of the program? Wouldn’t it be much simpler to use a simple switch statement in your periodic functions with an enumerator to determine which function to call at the appropriate time?

I suspect the motivation is to help compartmentalize and organize the code. If you’re doing any sort of complicated state machine, a switch statement can get out of hand rather quickly, unless you’re building up separate functions for each case. Which makes the switch statement largely similar to this StateMachine Class, except that adding a new state requires adding a new case to your switch statement, etc. etc. Adding a new state to this state machine looks a bit easier. Also, since it’s dynamically allocated, you can change the state callbacks at runtime. If, for instance, you wanted to run a different set of states depending on your alliance or robot position. Instead of having two switches, or a bunch of conditionals, or whatever else.

I was referring to the MPLAB C code not the old WPILib.

As Kevin pointed out the main reason for doing this as opposed to a switch is abstraction and cleanliness of code. With the power behind the new controller I am not to worried about using dynamic memory allocation or STL containers. Also this method opens up an interesting path of possible polymorphic state.

I’ve attached an update version that has been refactored a bit. The AddStateCallback method is now SetStateCallback method and the template only takes two parameters. I was able to change it so the third parameter is inferred.

Update example:

#include "StateMachine.h"

enum AutoState
{
    AUTO_START,
    AUTO_TURN,
    AUTO_GOAL1
};

class MyBot : public IterativeRobot
{
private:
    StateMachine<AutoState, MyBot> *m_state;

public:
    MyBot(void)
    {
        m_state = new StateMachine<AutoState, MyBot>(this);
        m_state->SetStateCallback(AUTO_START, &MyBot::Autonomous_State_Start);
        m_state->SetStateCallback(AUTO_TURN, &MyBot::Autonomous_State_Turn);
        m_state->SetStateCallback(AUTO_GOAL1, &MyBot::Autonomous_State_Goal1);
    }

    ~MyBot(void)
    {
        delete m_state;
    }

    void AutonomousInit(void)
    {
        m_state->SetCurrentState(AUTO_START);
    }

    void AutonomousPeriodic(void)
    {
        m_state->CallCurrentState();
    }

    void Autonomous_State_Start(void)
    {
        //... DO STUFF ...
        m_state->SetCurrentState(AUTO_TURN);
    }

    void Autonomous_State_Turn(void)
    {
        //... DO STUFF ...
        m_state->SetCurrentState(AUTO_GOAL1);
    }
    void Autonomous_State_Goal1(void)
    {
        //... DO STUFF ...
        m_state->SetCurrentState(AUTO_TURN);
    }
};
```<br><br><a class='attachment' href='/uploads/default/original/3X/4/e/4e0d90687d57a90e7047950d4866b096b733998c.h'>StateMachine.h</a> (2.33 KB)<br><br><br><a class='attachment' href='/uploads/default/original/3X/4/e/4e0d90687d57a90e7047950d4866b096b733998c.h'>StateMachine.h</a> (2.33 KB)<br>

Thanks for clearing that up. Right now we’re focusing on the simple robot class, but this is something I’ll definately check out.

Thanks for posting this. I’ve preached state machines to several local teams for quite a few years now, and this is one place where C++ really helps clean up implementation.

Possibly just a matter of preference, but wouldn’t it make more sense to require the callbacks to return an AutoState and just use that to update the current state? That way, the callbacks can be blissfully ignorant of which instance of state machine is invoking them. I realize it’s highly unlikely to have two state machine instances with the same state enumerations… but it still seems neater to me.

Also, who said you had to use this in in the IterativeRobot framework? It would work just fine in the SimpleRobot framework as well. You’d simply create a while loop around the CallCurrentState calls. Do whatever SimpleRobot stuff you want in the callbacks, with waits and everything else. Then when you’ve finished processing that state, it will loop around and process the next state. If your code has more than two or three cases to deal with, you’d be using switches, if-elses, and other things, and this helps clean those up regardless of what they’re doing.