Ben_R_R
30-03-2011, 16:16
Hello all.
The season is over for my team, and though next year is quite a ways off, I'm already looking ahead to next season. One question that has been weighing on my mind is the best way to actually go about implementing the state machine for autonomous in Java.
The most common way, based on the code I've seen posted here, seems to be some kind of large if-else if structure, or a switch block. We took this route for the code at our first regional. I personally have always found this method difficult to read and maintain.
The way we did it at our second regional was to create an inner abstract class with one abstract method, getNextState(), then in the body of the method we put the actions for that state. We then put the states into a hashtable with the name of the state as the key. Here is an example (not from our final code, and with the boring repetitive bits removed for brevity and ease of reading):
public class StateTestAutonomousFF implements AutonomousFF {
// snip...
/** Autonomous state, put actions in the getNextState() method. */
private abstract class State{
public abstract State getNextState();
};
/** String-keyed table of all the states */
private Hashtable states;
/** Stores the current Autonomous state */
private State currState;
// snip...
/**
* The basic autonomous routine: Raise the arm, drive straight to the wall
* then hang the tube.
*
* @return The first state in the basic autonomous routine. calling method
* should set currState equal to the returned state.
*/
private State loadBasicSM(){
states = new Hashtable();
// snip... Example State:
states.put("raiseArm", new State(){ public State getNextState() {
// return next state when the arm is raised
if(arm.raiseArm(RobotArmFF.TOP)){
return (State)states.get("driveToWall");
}
return this;
}});
// snip...
return (State)states.get("firstState");
}
// snip...
/** Call once per autonomous loop */
public void periodicUpdate(){
if(currState != null){
currState = currState.getNextState();
} else {
stopEverything();
}
}
// snip...
}// End class
To me this code is much more readable and self documenting, and adding a new state or even a whole new state machine is relatively easy. I am curious what the other Java programmers on Chief Delphi think. Do you find this method easier/harder to read? Do you have other criticisms? Has anyone done anything similar? Has anyone done anything better?
The season is over for my team, and though next year is quite a ways off, I'm already looking ahead to next season. One question that has been weighing on my mind is the best way to actually go about implementing the state machine for autonomous in Java.
The most common way, based on the code I've seen posted here, seems to be some kind of large if-else if structure, or a switch block. We took this route for the code at our first regional. I personally have always found this method difficult to read and maintain.
The way we did it at our second regional was to create an inner abstract class with one abstract method, getNextState(), then in the body of the method we put the actions for that state. We then put the states into a hashtable with the name of the state as the key. Here is an example (not from our final code, and with the boring repetitive bits removed for brevity and ease of reading):
public class StateTestAutonomousFF implements AutonomousFF {
// snip...
/** Autonomous state, put actions in the getNextState() method. */
private abstract class State{
public abstract State getNextState();
};
/** String-keyed table of all the states */
private Hashtable states;
/** Stores the current Autonomous state */
private State currState;
// snip...
/**
* The basic autonomous routine: Raise the arm, drive straight to the wall
* then hang the tube.
*
* @return The first state in the basic autonomous routine. calling method
* should set currState equal to the returned state.
*/
private State loadBasicSM(){
states = new Hashtable();
// snip... Example State:
states.put("raiseArm", new State(){ public State getNextState() {
// return next state when the arm is raised
if(arm.raiseArm(RobotArmFF.TOP)){
return (State)states.get("driveToWall");
}
return this;
}});
// snip...
return (State)states.get("firstState");
}
// snip...
/** Call once per autonomous loop */
public void periodicUpdate(){
if(currState != null){
currState = currState.getNextState();
} else {
stopEverything();
}
}
// snip...
}// End class
To me this code is much more readable and self documenting, and adding a new state or even a whole new state machine is relatively easy. I am curious what the other Java programmers on Chief Delphi think. Do you find this method easier/harder to read? Do you have other criticisms? Has anyone done anything similar? Has anyone done anything better?