Overview | Main | State Machine | Events | IR | Tape | Drivetrain | PWM | Flash | Two Minute Timer | Bump
stateMachines.c
      stateMachines.h
char getStateMachine(void): determine whether to use main play or sudden death
      
      char getTeam(void): determine whether to play as red or green
      
      void mainPlayStateMachine(char event): execute main play state machine
      
      void suddenDeathStateMachine(char event): execute sudden death state machine
      
    
The state machines module implements the brains of The Death Star: two separate strategies for playing the game, one for regular play mode and one for sudden death mode. A state machine is a paradigm for charting and implementing desired behavior. The robot (or other entity) is in a particular “state” at any given time. “States” are purely for record-keeping purposes; the robot cannot take any action while in a “state.” The robot changes “states” in response to “events”, as defined by the events module. It is on the state transitions that the robot performs actions. To this end, the state machines module contains two functions for implementing each of these state machines. It also contains two information-gathering functions needed by the state machines: reading the team ID switch to determine whether the robot is playing as red or green, and reading the play mode switch to determine whether the robot should execute the regular play state machine or the sudden death state machine.
The following description section is significantly longer than those of the other software modules in this project, because the logic of both state machines is described with both words and diagrams (the regular play mode state machine is described in detail; the sudden death state machine is described more lightly, only providing the state machine diagrams and a description of what has changed from regular play mode.) In the diagrams that follow, several shorthand codes are used to identify both sensors and actuator commands on the robot. Those codes are defined in the following paragraphs, to enable easy reading of the diagrams throughout the remaining descriptions.
There are four IR sensors on each side (front and back) of the robot: three at the 9” height and one at the 12” height. Though in the end all three 9” sensors were tuned to “see” the same distance, originally the plan was to have the left and right sensors “see” long-range and the center sensor “see” short-range only. Thus, the names for the eight IR sensors on the robot are IR_12F, IR_9FL_LR, IR_9F_SR, IR_9FR_LR, IR_12B, IR_9BL_LR, IR_9B_SR, and IR_9BR_LR.
There are five tape sensors on the bottom of the robot: one in the exact center point of the base, and four at the corners of a 6” x 6” square around that center point. Thus, the names for the five tape sensors are TP_C, TP_FL, TP_FR, TP_BL, and TP_BR.
Other sensors called out in the state machine diagrams include the bump sensors (front and back) and the flash sensor. These are called BMP_F, BMP_B, and FLSH, respectively.
The actions taken by the state machines in response to an event and state transition are always to send commands to the drivetrain subsystem. This subsystem accepts five movement commands. The robot can stop, drive forward, drive in reverse, rotate clockwise, and rotate counter-clockwise. Given this, the five movement commands called out in the state machine diagrams are STOP, DRV_FWD, DRV_REV, ROT_CW, and ROT_CCW.
The regular play mode state machine begins with a choreographed orientation sequence to not only orient the robot from a random position to driving towards a flag, but in fact to orient the robot to driving towards a particular flag. In the version of the code run on tournament night, this choreographed orientation sequence was skipped (see “Simple Orientation” transitions), due to the imperfection of the IR sensors (the choreography requires the IR sensors to see very far and be able to stay locked onto a flag perfectly once it is found.) Thus, on tournament night The Death Star simply oriented itself to the first flag it saw (on either front or back), and proceeded with flag following and capturing. However, the code to implement the choreographed orientation sequence was still loaded on the robot, is still diagrammed below, and will still be described here. The idea of orienting to a particular flag instead of any flag was to capture a flag further from The Death Star’s goal and initial position first, to increase the chances of being able to get to those flags before the opponent robot.
Figure 1: Regular Play State Machine Page 1
The desired first flag is the flag located five feet away horizontally and two feet away vertically. Given the symmetric nature of The Death Star’s mechanical design, it should be trivial to orient to that flag with no more than 180-degrees of rotation. This algorithm is designed to achieve that orientation with at most only about 90-degrees of rotation. The robot initially rotates clockwise, so that, all else being equal, it sees that flag first. However, if either side of sensors sees a flag duty cycle, that side must be closer to the flags. In that case, the robot rotates counter-clockwise until it sees its home corner beacon on the same side (front or back), and then rotates clockwise again until it sees a flag. In this way it knows it has oriented to the correct flag. If a sensor-side only sees a flag duty cycle after having seen the robot’s home beacon (while still rotating clockwise from the initial condition), then this first flag sighting must be the desired flag. One additional note about this portion of the state machine: regardless of whether simple orientation or scripted orientation is used, the two-minute timer is started when the start flash is detected.
Figure 2: Regular Play State Machine Page 2
Once the robot has detected a flag, it begins “flag following”. Since each side of the robot has three IR sensors that can “see” equally far, the “flag following” algorithm is as follows. As long as the center IR sensor sees the flag, drive straight ahead. If the center IR sensor stops seeing the flag, check which of the other sensors also do not see the flag anymore; if the left side has lost the flag, rotate clockwise; if the right side has lost the flag, rotate counter-clockwise. These rotations continue until the center sensor sees the flag again. Note that the robot can flag follow using both its front sensors and its back sensors; the previous description was written assuming the front is following. If the back is following, then the default case is to drive in reverse; also, a loss on the right side leads to clockwise rotation while a loss on the left side leads to counter-clockwise rotation. Finally, since at this time both flag cavities are empty, it is possible to transition between front following and back following freely, should a flag be lost so badly that the other side of the robot sees it before the original side sees it again.
Flag following is terminated when the bump sensor in the appropriate flag cavity feels the flag. The state machine includes a pair of states to wait for an active set of doors, powered by stepper motors, to close around the flag before proceeding; however, in the tournament version of The Death Star only passive flaps were used to contain the flags, so these steps were skipped. Once the first flag has been captured, the robot rotates counter-clockwise to find the second flag. In the simple orientation scheme used on competition night, the direction of rotation here does not matter; however, in the case of scripted orientation, this direction of rotation ensures that the next flag to be captured will be the flag closest to the robot’s initial starting position, and thus to the goal to which the robot must return.
Figure 3: Regular Play State Machine Page 3
Once the second flag is detected, the same flag following algorithm is used to track it. The only difference here is that it is no longer possible to transition between front and back flag following, since the side not initially following the second flag already has a flag in its cavity and thus cannot capture another flag even if it sees one.
Once the second flag has been captured, the robot’s task is to find a black line and use it to drive to the home goal. Based on the initial positions of the flags, the robot should always be able to find a black line by continuing to drive in the direction it had been to capture the second flag. The only caveat here assuming the flags remain in their initial positions is that the robot may be oriented such that it will drive into a goal zone without ever finding a black line; that edge case is handled in the next portion of the state machine. If the flags do not remain in their initial positions (which they certainly will not when another robot is also playing on the field), another possibility is that the robot encounters a wall before ever seeing a black line; that edge case is not handled in the software, but was never encountered during game play either.
The robot distinguishes between finding a black line versus finding the dead zone at one end of the field using the leading tape sensors (front left and right if the robot is moving forward, back left and right if the robot is driving in reverse.) If by the time the center tape sensor sees black (center is necessary for subsequent orientation on that line), the leading tape sensors have or have not seen black but have always then seen white again, the robot has found a black line. If, on the other hand, one leading tape sensor sees black and then the other sees black as well before the first again sees white, the robot has found a dead zone.
If the robot has found a dead zone, it may be the home dead zone or the away dead zone. If the robot has found the home dead zone, this is good: the robot wanted to drive to its goal anyway, and the assumption that the robot is oriented roughly vertically when it encounters the dead zone is valid since it drove all the way from a flag to the dead zone without ever finding a black line. If the robot has found the away dead zone, this is bad: it now needs to drive all the way back across the field to get to the home goal. Either way, however, the situation is manageable: if the robot has found the home dead zone, it jumps over the states pertaining to following the black line to the parking routine; if the robot has found the away dead zone, it simply starts driving the other direction, again looking for the black line or a dead zone.
What remains is to determine which dead zone the robot is in once it has determined that it is in a dead zone. This is accomplished using (for the first time in the case of simple orientation) the 12” IR sensors and the corner beacons. Once in a dead zone, the robot rotates counter-clockwise until it sees a corner beacon. If it was driving forward and the front sees home or the back sees away, or if it was driving in reverse and the back sees home or the front sees away, the robot is in the home dead zone. If it was driving forward and the front sees away or the back sees home, or if it was driving in reverse and the back sees away or the front sees home, the robot is in the away dead zone. Once this determination has been made, the robot rotates back clockwise to become aligned vertically again (this is necessary if the robot is in the home dead zone and needs to jump right into the parking routine.) The approximate vertical orientation is checked by rotating until the front left (or back right) tape sensor again sees black; since the rotation to a corner beacon was counter-clockwise, it was these tape sensors that would have left the dead zone and will now be re-entering it. This re-orientation to the vertical is also used as an additional safety check; if the robot sees another corner beacon while rotating back to the vertical (presumably having missed it during the counter-clockwise rotation), and can re-evaluate whether it thinks it is in the home or away dead zone before proceeding either forward or reverse.
Figure 4: Regular Play State Machine Page 4
In the case where a black line is encountered (as opposed to a dead zone), the robot orients vertically on the black line by rotating clockwise until the front left (or back right) tape sensor sees black. Just as in the case of the dead zone, the robot now needs to determine which direction is home. The algorithm is basically the same as before: rotate counter-clockwise until a home beacon is encountered and use this to determine the desired direction of travel; rotate back clockwise to get re-oriented vertically on the black line, using any additional corner beacon sightings to verify or correct the choice of travel direction.
The robot is now able to “line follow” towards its home goal. The purpose of using line following to get home rather than driving towards a corner beacon is to ensure that the robot is oriented approximately vertically when it reaches the home dead zone. The line following algorithm is relatively straightforward. Assuming the home goal is in front of the robot (the reader can make the appropriate inversions if in fact the home goal is behind the robot, though the diagram above also spells out both cases), the robot drives forward until either leading tape sensor sees the black line. If the left tape sensor sees the black line, the robot rotates counter-clockwise until that is no longer the case; if the right tape sensor sees the black line, the robot rotates clockwise until that is no longer the case. If during these corrective orientations the other leading tape sensor sees black before the errant leading tape sensor again sees white, the robot concludes that it is now in the dead zone and proceeds to the parking routine. This identification of the dead zone was chosen over attempting to sense the green tape that separates the main play area from the goal area in order to keep the tape sensing binary (white and black) as much as possible.
Once the robot is sure that it is in its home dead zone, it continues driving forward (or backward) until one of the leading tape sensors sees white; since the four non-center tape sensors form a 6” x 6” square around the center, this indicates that the center of the robot now lines up with the center of the goal strip. Thus, if the robot rotates exactly 90-degrees, it will be parked in the goal with both flags in its possession sufficiently within the goal boundaries. Since the tape sensors form a square array, this 90-degree rotation is simple: rotate clockwise until the front right (or back left), which had seen white, sees black, or until the back left (or front right), which had seen black, sees white. This completes the capture the flag task, and so the robot simply stops.
If simple orientation is being used, the only difference between regular play mode and sudden death mode is that in sudden death mode only one flag is sought before returning to the goal region. The initial choreography for orientation is significantly different, however, since the target flag is now the flag closest to the robot’s starting position, and that flag is much harder to pick out from the vantage point of the starting position. Since that choreography was never used in competition, however, a detailed explanation of its logic is omitted; that logic can be deduced by the reader, however, by examining the sudden death state machine diagrams, included below.
Figure 5: Sudden Death State Machine Page 1
Figure 6: Sudden Death State Machine Page 2
Figure 7: Sudden Death State Machine Page 3
Figure 8: Sudden Death State Machine Page 4
(Download Pseudocode .doc 71kb)
    
char getStateMachine(void)
          Initialize the state machine switch’s pin to be an input
    Read the physical switch, returning its state
char getTeam(void)
    Initialize the team ID switch’s pin to be an input
    Read the physical switch to determine the correct team
    Set the module variables homeDC and awayDC appropriately
    Tell the caller which team we're on
void mainPlayStateMachine(char event)
    If the state is MP_WAITING_FOR_FLASH
        If the event is FLSH_NOW_ON
            Rotate clockwise
            Start the two-minute timer
            Go to state MP_NO_DATA
    Else if the state is MP_NO_DATA
        
	        If the event is TIMER_2MIN_EXP
	            Stop
            Go to state MP_TIME_EXPIRED
        Else if we are using the scripted orientation
            If the event is back seeing home
                Rotate clockwise
                Go to state MP_BACK_SAW_HOME
            Else if the event is front seeing home
                Rotate clockwise
                Go to state MP_FRONT_SAW_HOME
            Else if the event is front seeing a flag
                Rotate counter-clockwise
                Go to state MP_FRONT_SAW_FLAG
            Else if the event is back seeing a flag
                Rotate counter-clockwise
                Go to state MP_BACK_SAW_FLAG
        Else if we are using the simple orientation
            If the event is front right seeing a flag
                Rotate clockwise
                Go to state MP_FLAG_1_AHEAD_VEER_CW
            Else if the event is back left seeing a flag
                Rotate clockwise
                Go to state MP_FLAG_1_BEHIND_VEER_CW
    Else if the state is MP_FRONT_SAW_HOME
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back seeing a flag
            Rotate counter-clockwise
            Go to state MP_BACK_SAW_FLAG
        Else if the event is front right seeing a flag
            Rotate clockwise
            Go to state MP_FLAG_1_AHEAD_VEER_CW
    Else if the state is MP_BACK_SAW_HOME
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front seeing a flag
            Rotate counter-clockwise
            Go to state MP_FRONT_SAW_FLAG
        Else if the event is back left seeing a flag
            Rotate clockwise
            Go to state MP_FLAG_1_BEHIND_VEER_CW
    Else if the state is MP_FRONT_SAW_FLAG
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front seeing home
            Rotate clockwise
            Go to state MP_SEEKING_FLAG_1_AHEAD
    Else if the state is MP_BACK_SAW_FLAG
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back seeing home
            Rotate clockwise
            Go to state MP_SEEKING_FLAG_1_BEHIND
    Else if the state is MP_SEEKING_FLAG_1_AHEAD
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front right seeing a flag
            Rotate clockwise
            Go to state MP_FLAG_1_AHEAD_VEER_CW
    Else if the state is MP_SEEKING_FLAG_1_BEHIND
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back left seeing a flag
            Rotate clockwise
            Go to state MP_FLAG_1_BEHIND_VEER_CW
    Else if the state is MP_FLAG_1_AHEAD_VEER_CW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front center seeing a flag
            Drive forward
            Go to state MP_FLAG_1_AHEAD_FOLLOW
        Else if the event is back left seeing a flag
            Rotate clockwise
            Go to state MP_FLAG_1_BEHIND_VEER_CW
    Else if the state is MP_FLAG_1_BEHIND_VEER_CW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back center seeing a flag
            Drive reverse
            Go to state MP_FLAG_1_BEHIND_FOLLOW
        Else if the event is front right seeing a flag
            Rotate clockwise
            Go to state MP_FLAG_1_AHEAD_VEER_CW
    Else if the state is MP_FLAG_1_AHEAD_FOLLOW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front center loses flag
            If front left has also lost the flag
                Rotate clockwise
                Go to state MP_FLAG_1_AHEAD_VEER_CW
            If front right has also lost the flag
                Rotate counter-clockwise
                Go to state MP_FLAG_1_AHEAD_VEER_CCW
        Else if the event is front bump sensor feels flag
            Rotate counter-clockwise
            Go to state MP_SEEKING_FLAG_2_BEHIND
    Else if the state is MP_FLAG_1_BEHIND_FOLLOW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back center loses flag
            If back right has also lost the flag
                Rotate clockwise
                Go to state MP_FLAG_1_BEHIND_VEER_CW
            If back left has also lost the flag
                Rotate counter-clockwise
                Go to state MP_FLAG_1_BEHIND_VEER_CCW
        Else if the event is back bump sensor feels flag
            Rotate counter-clockwise
            Go to state MP_SEEKING_FLAG_2_AHEAD
    Else if the state is MP_FLAG_1_AHEAD_VEER_CCW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front center seeing flag
            Drive forward
            Go to state MP_FLAG_1_AHEAD_FOLLOW
        Else if the event is back right seeing flag
            Rotate counter-clockwise
            Go to state MP_FLAG_1_BEHIND_VEER_CCW
    Else if the state is MP_FLAG_1_BEHIND_VEER_CCW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back center seeing flag
            Drive reverse
            Go to state MP_FLAG_1_BEHIND_FOLLOW
        Else if the event is front left seeing flag
            Rotate counter-clockwise
            Go to state MP_FLAG_1_AHEAD_VEER_CCW
    Else if the state is MP_SEEKING_FLAG_2_AHEAD
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front left seeing flag
            Rotate counter-clockwise
            Go to state MP_FLAG_2_AHEAD_VEER_CCW
    Else if the state is MP_SEEKING_FLAG_2_BEHIND
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back right seeing flag
            Rotate counter-clockwise
            Go to state MP_FLAG_2_BEHIND_VEER_CCW
    Else if the state is MP_FLAG_2_AHEAD_VEER_CW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front center seeing flag
            Drive forward
            Go to state MP_FLAG_2_AHEAD_FOLLOW
    Else if the state is MP_FLAG_2_BEHIND_VEER_CW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back center seeing flag
            Drive reverse
            Go to state MP_FLAG_2_BEHIND_FOLLOW
    Else if the state is MP_FLAG_2_AHEAD_FOLLOW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front center loses flag
            If front left has also lost the flag
                Rotate clockwise
                Go to state MP_FLAG_2_AHEAD_VEER_CW
            If front right has also lost the flag
                Rotate counter-clockwise
                Go to state MP_FLAG_2_AHEAD_VEER_CCW
        Else if the event is front bump sensor feels flag
            Drive forward
            Go to state MP_FIND_BLACK_LINE_AHEAD
    Else if the state is MP_FLAG_2_BEHIND_FOLLOW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back center loses flag
            If back right has also lost the flag
                Rotate clockwise
                Go to state MP_FLAG_2_BEHIND_VEER_CW
            If back left has also lost the flag
                Rotate counter-clockwise
                Go to state MP_FLAG_2_BEHIND_VEER_CCW
        Else if the event is back bump sensor feels flag
            Drive reverse
            Go to state MP_FIND_BLACK_LINE_BEHIND
    Else if the state is MP_FLAG_2_AHEAD_VEER_CCW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front center seeing flag
            Drive forward
            Go to state MP_FLAG_2_AHEAD_FOLLOW
    Else if the state is MP_FLAG_2_BEHIND_VEER_CCW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back center seeing flag
            Drive reverse
            Go to state MP_FLAG_2_BEHIND_FOLLOW
    Else if the state is MP_FIND_BLACK_LINE_AHEAD
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is center seeing black
            Rotate clockwise
            Go to state MP_ORIENT_BLACK_LINE_AHEAD_1
        Else if the event is front left seeing black
            Drive forward
            Go to state MP_BLACK_ON_FRONT_LEFT
        Else if the event is front right seeing black
            Drive forward
            Go to state MP_BLACK_ON_FRONT_RIGHT
    Else if the state is MP_FIND_BLACK_LINE_BEHIND
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is center seeing black
            Rotate clockwise
            Go to state MP_ORIENT_BLACK_LINE_BEHIND_1
        Else if the event is back left seeing black
            Drive reverse
            Go to state MP_BLACK_ON_BACK_LEFT
        Else if the event is back right seeing black
            Drive reverse
            Go to state MP_BLACK_ON_BACK_RIGHT
    Else if the state is MP_BLACK_ON_FRONT_LEFT
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front left now white
            Drive forward
            Go to state MP_FIND_BLACK_LINE_AHEAD
        Else if the event is front right now black
            Rotate counter-clockwise
            Go to state MP_UNKNOWN_GOAL_AHEAD
    Else if the state is MP_BLACK_ON_FRONT_RIGHT
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front right now white
            Drive forward
            Go to state MP_FIND_BLACK_LINE_AHEAD
        Else if the event is front left now black
            Rotate counter-clockwise
            Go to state MP_UNKNOWN_GOAL_AHEAD
    Else if the state is MP_BLACK_ON_BACK_LEFT
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back left now white
            Drive reverse
            Go to state MP_FIND_BLACK_LINE_BEHIND
        Else if the event is back right now black
            Rotate counter-clockwise
            Go to state MP_UNKNOWN_GOAL_BEHIND
    Else if the state is MP_BLACK_ON_BACK_RIGHT
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back right now white
            Drive reverse
            Go to state MP_FIND_BLACK_LINE_BEHIND
        Else if the event is back left now black
            Rotate counter-clockwise
            Go to state MP_UNKNOWN_GOAL_BEHIND
    Else if the state is MP_UNKNOWN_GOAL_AHEAD
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front seeing home or back seeing away
            Rotate clockwise
            Go to state MP_RIGHT_GOAL_AHEAD
        Else if the event is front seeing away or back seeing home
            Rotate clockwise
            Go to state MP_WRONG_GOAL_AHEAD
    Else if the state is MP_UNKNOWN_GOAL_BEHIND
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back seeing home or front seeing away
            Rotate clockwise
            Go to state MP_RIGHT_GOAL_BEHIND
        Else if the event is back seeing away or front seeing home
            Rotate clockwise
            Go to state MP_WRONG_GOAL_BEHIND
    Else if the state is MP_RIGHT_GOAL_AHEAD
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front left seeing black
            Drive forward
            Go to state MP_DRIVING_GOAL_AHEAD
        Else if the event is back seeing home or front seeing away
            Rotate clockwise
            Go to state MP_WRONG_GOAL_AHEAD
    Else if the state is MP_RIGHT_GOAL_BEHIND
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back right seeing black
            Drive reverse
            Go to state MP_DRIVING_GOAL_BEHIND
        Else if the event is front seeing home or back seeing away
            Rotate clockwise
            Go to state MP_WRONG_GOAL_BEHIND
    Else if the state is MP_WRONG_GOAL_AHEAD
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front right seeing white
            Drive reverse
            Go to state MP_FIND_BLACK_LINE_BEHIND
        Else if the event is front seeing home or back seeing away
            Rotate clockwise
            Go to state MP_RIGHT_GOAL_AHEAD
    Else if the state is MP_WRONG_GOAL_BEHIND
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back left seeing white
            Drive forward
            Go to state MP_FIND_BLACK_LINE_AHEAD
        Else if the event is back seeing home or front seeing away
            Rotate clockwise
            Go to state MP_RIGHT_GOAL_BEHIND
    Else if the state is MP_ORIENT_BLACK_LINE_AHEAD_1
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front left seeing black
            Rotate counter-clockwise
            Go to state MP_VERIFY_HOME_AHEAD
    Else if the state is MP_ORIENT_BLACK_LINE_BEHIND_1
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back right seeing black
            Rotate counter-clockwise
            Go to state MP_VERIFY_HOME_BEHIND
    Else if the state is MP_VERIFY_HOME_AHEAD
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front seeing home or back seeing away
            Rotate clockwise
            Go to state MP_ORIENT_BLACK_LINE_AHEAD_2
        Else if the event is front seeing away or back seeing home
            Rotate clockwise
            Go to state MP_ORIENT_BLACK_LINE_BEHIND_2
    Else if the state is MP_VERIFY_HOME_BEHIND
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back seeing home or front seeing away
            Rotate clockwise
            Go to state MP_ORIENT_BLACK_LINE_BEHIND_2
        Else if the event is back seeing away or front seeing home
            Rotate clockwise
            Go to state MP_ORIENT_BLACK_LINE_AHEAD_2
    Else if the state is MP_ORIENT_BLACK_LINE_AHEAD_2
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front left seeing black
            Rotate counter-clockwise
            Go to state MP_BLACK_AHEAD_VEER_CCW
        Else if the event is back seeing home or front seeing away
            Rotate clockwise
            Go to state MP_ORIENT_BLACK_LINE_BEHIND_2
    Else if the state is MP_ORIENT_BLACK_LINE_BEHIND_2
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back right seeing black
            Rotate counter-clockwise
            Go to state MP_BLACK_BEHIND_VEER_CCW
        Else if the event is front seeing home or back seeing away
            Rotate clockwise
            Go to state MP_ORIENT_BLACK_LINE_AHEAD_2
    Else if the state is MP_BLACK_AHEAD_VEER_CW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front right seeing white
            Drive forward
            Go to state MP_BLACK_AHEAD_FOLLOW
        Else if the event is front left seeing black
            Drive forward
            Go to state MP_DRIVING_GOAL_AHEAD
    Else if the state is MP_BLACK_BEHIND_VEER_CW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back left seeing white
            Drive reverse
            Go to state MP_BLACK_BEHIND_FOLLOW
        Else if the event is back right seeing black
            Drive reverse
            Go to state MP_DRIVING_GOAL_BEHIND
    Else if the state is MP_BLACK_AHEAD_FOLLOW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front left seeing black
            Rotate counter-clockwise
            Go to state MP_BLACK_AHEAD_VEER_CCW
        Else if the event is front right seeing black
            Rotate clockwise
            Go to state MP_BLACK_AHEAD_VEER_CW
    Else if the state is MP_BLACK_BEHIND_FOLLOW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back right seeing black
            Rotate counter-clockwise
            Go to state MP_BLACK_BEHIND_VEER_CCW
        Else if the event is back left seeing black
            Rotate clockwise
            Go to state MP_BLACK_BEHIND_VEER_CW
    Else if the state is MP_BLACK_AHEAD_VEER_CCW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front left seeing white
            Drive forward
            Go to state MP_BLACK_AHEAD_FOLLOW
        Else if the event is front right seeing black
            Drive forward
            Go to state MP_DRIVING_GOAL_AHEAD
    Else if the state is MP_BLACK_BEHIND_VEER_CCW
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back right seeing white
            Drive reverse
            Go to state MP_BLACK_BEHIND_FOLLOW
        Else if the event is back left seeing black
            Drive reverse
            Go to state MP_DRIVING_GOAL_BEHIND
    Else if the state is MP_DRIVING_GOAL_AHEAD
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front seeing white
            Rotate clockwise
            Go to state MP_CENTERED_ON_GOAL_AHEAD
    Else if the state is MP_DRIVING_GOAL_BEHIND
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is back seeing white
            Rotate clockwise
            Go to state MP_CENTERED_ON_GOAL_BEHIND
    Else if the state is MP_CENTERED_ON_GOAL_AHEAD
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front right seeing black or back left seeing white
            Stop
            Go to state MP_PARKED_IN_GOAL
    Else if the state is MP_CENTERED_ON_GOAL_BEHIND
        If the event is TIMER_2MIN_EXP
            Stop
            Go to state MP_TIME_EXPIRED
        Else if the event is front right seeing white or back left seeing black
            Stop
            Go to state MP_PARKED_IN_GOAL
void suddenDeathStateMachine(char event)
    If the state is SD_WAITING_FOR_FLASH
        If the event is FLSH_NOW_ON
            Rotate counter-clockwise
            Go to state SD_NO_DATA
    Else if the state is SD_NO_DATA
        If we are using the scripted orientation
            If the event is back seeing home
                Rotate clockwise
                Go to state SD_BACK_SAW_HOME
            Else if the event is front seeing home
                Rotate clockwise
                Go to state SD_FRONT_SAW_HOME
            Else if the event is front seeing a flag
                Rotate counter-clockwise
                Go to state SD_FRONT_SAW_FLAG
            Else if the event is back seeing a flag
                Rotate counter-clockwise
                Go to state SD_BACK_SAW_FLAG
        Else if we are using the simple orientation
            If the event is front left seeing a flag
                Rotate counter-clockwise
                Go to state SD_FLAG_1_AHEAD_TWEAK_CCW
            Else if the event is back right seeing a flag
                Rotate counter-clockwise
                Go to state SD_FLAG_1_BEHIND_TWEAK_CCW
    Else if the state is SD_FRONT_SAW_HOME
        If the event is back seeing a flag
            Rotate counter-clockwise
            Go to state SD_BACK_SAW_FLAG
        Else if the event is front seeing away
            Drive forward
            Go to state SD_FIND_GREEN_LINE_AHEAD_1
    Else if the state is SD_BACK_SAW_HOME
        If the event is front seeing a flag
            Rotate counter-clockwise
            Go to state SD_FRONT_SAW_FLAG
        Else if the event is back seeing away
            Drive reverse
            Go to state SD_FIND_GREEN_LINE_BEHIND_1
    Else if the state is SD_FRONT_SAW_FLAG
        If the event is front seeing home
            Rotate clockwise
            Go to state SD_FRONT_SAW_HOME
        Else if the event is front seeing away
            Drive forward
            Go to state SD_FIND_GREEN_LINE_AHEAD_1
    Else if the state is SD_BACK_SAW_FLAG
        If the event is back seeing home
            Rotate clockwise
            Go to state SD_BACK_SAW_HOME
        Else if the event is back seeing away
            Drive reverse
            Go to state SD_FIND_GREEN_LINE_BEHIND_1
    Else if the state is SD_FIND_GREEN_LINE_AHEAD_1
        If the event is front seeing white
            Drive forward
            Go to state SD_FIND_GREEN_LINE_AHEAD_2
    Else if the state is SD_FIND_GREEN_LINE_BEHIND_1
        If the event is back seeing white
            Drive reverse
            Go to state SD_FIND_GREEN_LINE_BEHIND_2
    Else if the state is SD_FIND_GREEN_LINE_AHEAD_2
        If the event is center seeing green
            Rotate counter-clockwise
            Go to state SD_ORIENT_GREEN_LINE_AHEAD
    Else if the state is SD_FIND_GREEN_LINE_BEHIND_2
        If the event is center seeing green
            Rotate counter-clockwise
            Go to state SD_ORIENT_GREEN_LINE_BEHIND
    Else if the state is SD_ORIENT_GREEN_LINE_AHEAD
        If the event is front right seeing green
            Rotate clockwise
            Go to state SD_GREEN_AHEAD_VEER_CW
    Else if the state is SD_ORIENT_GREEN_LINE_BEHIND
        If the event is back left seeing green
            Rotate clockwise
            Go to state SD_GREEN_BEHIND_VEER_CW
    Else if the state is SD_GREEN_AHEAD_VEER_CW
        If the event is front right lost green
            Drive forward
            Go to state SD_GREEN_AHEAD_FOLLOW
    Else if the state is SD_GREEN_BEHIND_VEER_CW
        If the event is back left lost green
            Drive reverse
            Go to state SD_GREEN_BEHIND_FOLLOW
    Else if the state is SD_GREEN_AHEAD_FOLLOW
        If the event is front left seeing green
            Rotate counter-clockwise
            Go to state SD_GREEN_AHEAD_VEER_CCW
        Else if the event is front right seeing green
            Rotate clockwise
            Go to state SD_GREEN_AHEAD_VEER_CW
        Else if the event is front right seeing black
            Rotate clockwise
            Go to state SD_ROTATE_TO_FLAG_AHEAD
    Else if the state is SD_GREEN_BEHIND_FOLLOW
        If the event is back right seeing green
            Rotate counter-clockwise
            Go to state SD_GREEN_BEHIND_VEER_CCW
        Else if the event is back left seeing green
            Rotate clockwise
            Go to state SD_GREEN_BEHIND_VEER_CW
        Else if the event is back left seeing black
            Rotate clockwise
            Go to state SD_ROTATE_TO_FLAG_BEHIND
    Else if the state is SD_GREEN_AHEAD_VEER_CCW
        If the event is front left lost green
            Drive forward
            Go to state SD_GREEN_AHEAD_FOLLOW
    Else if the state is SD_GREEN_BEHIND_VEER_CCW
        If the event is back right lost green
            Drive reverse
            Go to state SD_GREEN_BEHIND_FOLLOW
    Else if the state is SD_ROTATE_TO_FLAG_AHEAD
        If the event is front left seeing black
            Rotate counter-clockwise
            Go to state SD_FLAG_1_AHEAD_TWEAK_CCW
    Else if the state is SD_ROTATE_TO_FLAG_BEHIND
        If the event is back right seeing black
            Rotate counter-clockwise
            Go to state SD_FLAG_1_BEHIND_TWEAK_CCW
    Else if the state is SD_FLAG_1_AHEAD_TWEAK_CW
        If the event is front center seeing a flag
            Drive forward
            Go to state SD_FLAG_1_AHEAD_APPROACH
        Else if the event is back left seeing a flag
            Rotate clockwise
            Go to state SD_FLAG_1_BEHIND_TWEAK_CW
    Else if the state is SD_FLAG_1_BEHIND_TWEAK_CW
        If the event is back center seeing a flag
            Drive reverse
            Go to state SD_FLAG_1_BEHIND_APPROACH
        Else if the event is front right seeing a flag
            Rotate clockwise
            Go to state SD_FLAG_1_AHEAD_TWEAK_CW
    Else if the state is SD_FLAG_1_AHEAD_APPROACH
        If the event is front center loses flag
            If front left has also lost the flag
                Rotate clockwise
                Go to state SD_FLAG_1_AHEAD_TWEAK_CW
            If front right has also lost the flag
                Rotate counter-clockwise
                Go to state SD_FLAG_1_AHEAD_TWEAK_CCW
        Else if the event is front bump sensor feels flag
            Drive forward
            Go to state SD_FIND_BLACK_LINE_AHEAD
    Else if the state is SD_FLAG_1_BEHIND_APPROACH
        If the event is back center loses flag
            If back right has also lost the flag
                Rotate clockwise
                Go to state SD_FLAG_1_BEHIND_TWEAK_CW
            If back left has also lost the flag
                Rotate counter-clockwise
                Go to state SD_FLAG_1_BEHIND_TWEAK_CCW
        Else if the event is back bump sensor feels flag
            Drive reverse
            Go to state SD_FIND_BLACK_LINE_BEHIND
    Else if the state is SD_FLAG_1_AHEAD_TWEAK_CCW
        If the event is front center seeing flag
            Drive forward
            Go to state SD_FLAG_1_AHEAD_APPROACH
        Else if the event is back right seeing flag
            Rotate counter-clockwise
            Go to state SD_FLAG_1_BEHIND_TWEAK_CCW
    Else if the state is SD_FLAG_1_BEHIND_TWEAK_CCW
        If the event is back center seeing flag
            Drive reverse
            Go to state SD_FLAG_1_BEHIND_APPROACH
        Else if the event is front left seeing flag
            Rotate counter-clockwise
            Go to state SD_FLAG_1_AHEAD_TWEAK_CCW
    Else if the state is SD_FIND_BLACK_LINE_AHEAD
        If the event is center seeing black
            Rotate clockwise
            Go to state SD_ORIENT_BLACK_LINE_AHEAD_1
        Else if the event is front left seeing black
            Drive forward
            Go to state SD_BLACK_ON_FRONT_LEFT
        Else if the event is front right seeing black
            Drive forward
            Go to state SD_BLACK_ON_FRONT_RIGHT
    Else if the state is SD_FIND_BLACK_LINE_BEHIND
        If the event is center seeing black
            Rotate clockwise
            Go to state SD_ORIENT_BLACK_LINE_BEHIND_1
        Else if the event is back left seeing black
            Drive reverse
            Go to state SD_BLACK_ON_BACK_LEFT
        Else if the event is back right seeing black
            Drive reverse
            Go to state SD_BLACK_ON_BACK_RIGHT
    Else if the state is SD_BLACK_ON_FRONT_LEFT
        If the event is front left now white
            Drive forward
            Go to state SD_FIND_BLACK_LINE_AHEAD
        Else if the event is front right now black
            Rotate counter-clockwise
            Go to state SD_UNKNOWN_GOAL_AHEAD
    Else if the state is SD_BLACK_ON_FRONT_RIGHT
        If the event is front right now white
            Drive forward
            Go to state SD_FIND_BLACK_LINE_AHEAD
        Else if the event is front left now black
            Rotate counter-clockwise
            Go to state SD_UNKNOWN_GOAL_AHEAD
    Else if the state is SD_BLACK_ON_BACK_LEFT
        If the event is back left now white
            Drive reverse
            Go to state SD_FIND_BLACK_LINE_BEHIND
        Else if the event is back right now black
            Rotate counter-clockwise
            Go to state SD_UNKNOWN_GOAL_BEHIND
    Else if the state is SD_BLACK_ON_BACK_RIGHT
        If the event is back right now white
            Drive reverse
            Go to state SD_FIND_BLACK_LINE_BEHIND
        Else if the event is back left now black
            Rotate counter-clockwise
            Go to state SD_UNKNOWN_GOAL_BEHIND
    Else if the state is SD_UNKNOWN_GOAL_AHEAD
        If the event is front seeing home or back seeing away
            Rotate clockwise
            Go to state SD_RIGHT_GOAL_AHEAD
        Else if the event is front seeing away or back seeing home
            Rotate clockwise
            Go to state SD_WRONG_GOAL_AHEAD
    Else if the state is SD_UNKNOWN_GOAL_BEHIND
        If the event is back seeing home or front seeing away
            Rotate clockwise
            Go to state SD_RIGHT_GOAL_BEHIND
        Else if the event is back seeing away or front seeing home
            Rotate clockwise
            Go to state SD_WRONG_GOAL_BEHIND
    Else if the state is SD_RIGHT_GOAL_AHEAD
        If the event is front left seeing black
            Drive forward
            Go to state SD_DRIVING_GOAL_AHEAD
        Else if the event is back seeing home or front seeing away
            Rotate clockwise
            Go to state SD_WRONG_GOAL_AHEAD
    Else if the state is SD_RIGHT_GOAL_BEHIND
        If the event is back right seeing black
            Drive reverse
            Go to state SD_DRIVING_GOAL_BEHIND
        Else if the event is front seeing home or back seeing away
            Rotate clockwise
            Go to state SD_WRONG_GOAL_BEHIND
    Else if the state is SD_WRONG_GOAL_AHEAD
        If the event is front right seeing white
            Drive reverse
            Go to state SD_FIND_BLACK_LINE_BEHIND
        Else if the event is front seeing home or back seeing away
            Rotate clockwise
            Go to state SD_RIGHT_GOAL_AHEAD
    Else if the state is SD_WRONG_GOAL_BEHIND
        If the event is back left seeing white
            Drive forward
            Go to state SD_FIND_BLACK_LINE_AHEAD
        Else if the event is back seeing home or front seeing away
            Rotate clockwise
            Go to state SD_RIGHT_GOAL_BEHIND
    Else if the state is SD_ORIENT_BLACK_LINE_AHEAD_1
        If the event is front left seeing black
            Rotate counter-clockwise
            Go to state SD_VERIFY_HOME_AHEAD
    Else if the state is SD_ORIENT_BLACK_LINE_BEHIND_1
        If the event is back right seeing black
            Rotate counter-clockwise
            Go to state SD_VERIFY_HOME_BEHIND
    Else if the state is SD_VERIFY_HOME_AHEAD
        If the event is front seeing home or back seeing away
            Rotate clockwise
            Go to state SD_ORIENT_BLACK_LINE_AHEAD_2
        Else if the event is front seeing away or back seeing home
            Rotate clockwise
            Go to state SD_ORIENT_BLACK_LINE_BEHIND_2
    Else if the state is SD_VERIFY_HOME_BEHIND
        If the event is back seeing home or front seeing away
            Rotate clockwise
            Go to state SD_ORIENT_BLACK_LINE_BEHIND_2
        Else if the event is back seeing away or front seeing home
            Rotate clockwise
            Go to state SD_ORIENT_BLACK_LINE_AHEAD_2
    Else if the state is SD_ORIENT_BLACK_LINE_AHEAD_2
        If the event is front left seeing black
            Rotate counter-clockwise
            Go to state SD_BLACK_AHEAD_VEER_CCW
        Else if the event is back seeing home or front seeing away
            Rotate clockwise
            Go to state SD_ORIENT_BLACK_LINE_BEHIND_2
    Else if the state is SD_ORIENT_BLACK_LINE_BEHIND_2
        If the event is back right seeing black
            Rotate counter-clockwise
            Go to state SD_BLACK_BEHIND_VEER_CCW
        Else if the event is front seeing home or back seeing away
            Rotate clockwise
            Go to state SD_ORIENT_BLACK_LINE_AHEAD_2
    Else if the state is SD_BLACK_AHEAD_VEER_CW
        If the event is front right seeing white
            Drive forward
            Go to state SD_BLACK_AHEAD_FOLLOW
        Else if the event is front left seeing black
            Drive forward
            Go to state SD_DRIVING_GOAL_AHEAD
    Else if the state is SD_BLACK_BEHIND_VEER_CW
        If the event is back left seeing white
            Drive reverse
            Go to state SD_BLACK_BEHIND_FOLLOW
        Else if the event is back right seeing black
            Drive reverse
            Go to state SD_DRIVING_GOAL_BEHIND
    Else if the state is SD_BLACK_AHEAD_FOLLOW
        If the event is front left seeing black
            Rotate counter-clockwise
            Go to state SD_BLACK_AHEAD_VEER_CCW
        Else if the event is front right seeing black
            Rotate clockwise
            Go to state SD_BLACK_AHEAD_VEER_CW
    Else if the state is SD_BLACK_BEHIND_FOLLOW
        If the event is back right seeing black
            Rotate counter-clockwise
            Go to state SD_BLACK_BEHIND_VEER_CCW
        Else if the event is back left seeing black
            Rotate clockwise
            Go to state SD_BLACK_BEHIND_VEER_CW
    Else if the state is SD_BLACK_AHEAD_VEER_CCW
        If the event is front left seeing white
            Drive forward
            Go to state SD_BLACK_AHEAD_FOLLOW
        Else if the event is front right seeing black
            Drive forward
            Go to state SD_DRIVING_GOAL_AHEAD
    Else if the state is SD_BLACK_BEHIND_VEER_CCW
        If the event is back right seeing white
            Drive reverse
            Go to state SD_BLACK_BEHIND_FOLLOW
        Else if the event is back left seeing black
            Drive reverse
            Go to state SD_DRIVING_GOAL_BEHIND
    Else if the state is SD_DRIVING_GOAL_AHEAD
        If the event is front seeing white
            Rotate clockwise
            Go to state SD_CENTERED_ON_GOAL_AHEAD
    Else if the state is SD_DRIVING_GOAL_BEHIND
        If the event is back seeing white
            Rotate clockwise
            Go to state SD_CENTERED_ON_GOAL_BEHIND
    Else if the state is SD_CENTERED_ON_GOAL_AHEAD
        If the event is front right seeing black or back left seeing white
            Stop
            Go to state SD_PARKED_IN_GOAL
    Else if the state is SD_CENTERED_ON_GOAL_BEHIND
        If the event is front right seeing white or back left seeing black
            Stop
            Go to state SD_PARKED_IN_GOAL
    

 
  
	   
	   
	   
	   
	   
	   
	  