Switching to Iterative

Hey! I’ve been working on some code that seems a bit too elaborate for the SimpleRobot template, so I wanted to try out Iterative. I looked for a template, and didn’t find one, so then I searched the forum here, and found that the “BuiltinDefaultCode” is essentially the template, with a lot of code I’d probably never use mixed in. I realized that I actually know very little about FRC programming (or at least feel like it). Could someone please help explain a the different methods in the BuiltinDefaultCode (and some of the other things they threw into the code for kicks)? I’ve removed most of the “actual code” that I’m pretty sure isn’t necessary (but I still have questions about), and this is what I was left with (in case it helps).

#include "WPILib.h"
class BuiltinDefaultCode : public IterativeRobot{
	UINT32 m_autoPeriodicLoops;
	UINT32 m_disabledPeriodicLoops;
	UINT32 m_telePeriodicLoops;
		
public:
	BuiltinDefaultCode(void){
		m_autoPeriodicLoops = 0;
		m_disabledPeriodicLoops = 0;
		m_telePeriodicLoops = 0;
	}	
	
	////Init Routines///
	
	void RobotInit(void) {
		/* Actions which would be performed once (and only once) 
		 *upon initialization of the robot would be put here  */
	}
	
	void DisabledInit(void) {
		m_disabledPeriodicLoops = 0;			// Reset the loop counter for disabled mode
		/**/
	}

	void AutonomousInit(void) {
		m_autoPeriodicLoops = 0;				// Reset the loop counter for autonomous mode
		/**/
	}

	void TeleopInit(void) {
		m_telePeriodicLoops = 0;
		/**/
	}

	////Periodic Routines////
	
	void DisabledPeriodic(void)  {
		/**/
	}

	void AutonomousPeriodic(void) {
		/**/
	}
	
	void TeleopPeriodic(void) {
		/**/
	} 

	////Continuous Routines////

	void DisabledContinuous(void) {
		/**/
	}

	void AutonomousContinuous(void)	{
		/**/
	}

	void TeleopContinuous(void) {
		/**/
	}		
};

START_ROBOT_CLASS(BuiltinDefaultCode);

Thanks!

I can’t help too much with that code, but if you want a simpler Iterative Robot to play with team 2704 made a custom iterative robot this year, you can get a PDF copy of our code at http://www.firstplusplus.com/samplerobot-code.html

Our iterative robot is in our O2C class, if you just want the code it should be:
The .h


#ifndef O2C_H	// If not Defined
#define O2C_H	// Define
				// Assures that it does not define multiple times.

// This is our field class. It recieves inputs from the field and determines whether the robot should be in
// Autonomous, Teleoperated or test. It also ascertains whether or not an Initialization is needed for the
// Controller that it posesses.
#include "RobotBase.h"
#include "Timer.h"
#include "Watchdog.h"

#include "O2CDEF.h"

#include "O2CCONTROLLER.h"

class O2C : public RobotBase	// O2C is derived from RobotBase
{
public:
	O2C();	// Constructor
	virtual void StartCompetition();	// Is ran once at the start of the competition

private:
	// For the purposes of telling when initialization is needed.
	int autoiterations;
	int teleiterations;
	int testiterations;
	int disablediterations;
	int enablediterations;
	int firsttime;
	double currenttime;
	
	Timer O2CTimer;
	O2CCONTROLLER O2CController;	// O2C HAS a O2CController
	// For the purposes of telling when initialization is needed.
};

#endif //End O2C_H

and the .cpp:

#include "O2C.h"


O2C :: O2C()	// Constructor
{
	autoiterations = 0;
	teleiterations = 0;
	testiterations = 0;
	disablediterations = 0;
	enablediterations = 0;
	firsttime = 0;
	GetWatchdog().Feed();	// Need to feed Watchdog at start.
}

void O2C :: StartCompetition()
{
	O2CTimer.Start();
	while (1)
	{
		currenttime = O2CTimer.Get();
		O2CDatabuffer.Time = currenttime;
		GetWatchdog().Feed();	// Feed watchdog at the start of every iteration
		if (firsttime == 0)
		{
			// Put Robot Initialization here
			O2CController.Init();	// O2CController initialization.
			firsttime = 1;
			O2CTimer.Reset();
			currenttime = O2CTimer.Get();
			O2CDatabuffer.Time = currenttime;
		}
		if (IsEnabled())	// If any mode is enabled.
		{
			if (enablediterations == 0)
			{
				O2CTimer.Reset();
				currenttime = O2CTimer.Get();
				O2CDatabuffer.Time = currenttime;
				enablediterations = 1;
				// Enabled Initialization here
			}
			else
			{
				if (IsAutonomous())	// Autonomous Mode is enabled
				{
					if (autoiterations == 0)
					{
						// Auto Initialization goes here
						O2CController.AutoInit();
						O2CTimer.Reset();
						currenttime = O2CTimer.Get();
						O2CDatabuffer.Time = currenttime;
					}
					else
					{
						// Auto goes here
						O2CController.Autonomous();
					}
					autoiterations = autoiterations + 1; // Don't Touch
				}
				else if (IsOperatorControl()) // Teleoperated Mode is enabled
				{
					if (teleiterations == 0)
					{
						// Teleoperated Initializations
						
					}
					else
					{
						// Teleoperated goes here
						O2CController.Teleoperated();
					}
					teleiterations = teleiterations + 1; // Don't Touch
				}
				else if (IsTest())	// Test mode, for testing specific pieces of code.
				{
					if (testiterations == 0)
					{
						// Test Initialization goes here
						
					}
					else
					{
						// Test goes here
						
					}
					testiterations = testiterations + 1; // Don't Touch
				}
				else
				{
					// THIS SHOULD REALLY NEVER HAPPEN!
					// Only would happen if it was enabled and not in any mode.
					
				}
				// Enabled Stuff goes in here
				enablediterations = enablediterations + 1; // Don't Touch
															// Would also  work as enablediterations++;
			}
		}
		else if (IsDisabled())
		{
			if (disablediterations == 0)
			{
				// Disabled Init goes here.
			}
			else
			{
				//Disabled goes here.
			}
			disablediterations = disablediterations + 1;
		}
		else
		{
			// If you get here there is a problem.
			// It isn't ours though.
		}
		Wait(WAITTIME);
	} 
}

START_ROBOT_CLASS(O2C) // MACRO needed to show where the entry point is.

The stuff inside of the ifs is where the code would go for your robot.

Edit: If you want to learn how to do Object Oriented Coding for FRC and if you have an NXT our website FirstPlusPlus.com has a full tutorial that can teach you how we do Iterative, Event Driven Coding

Check out http://users.wpi.edu/~bamiller/WPIRoboticsLibrary/dd/d91/class_iterative_robot.html

Init() functions – each of the following functions is called once when the appropriate mode is entered:

DisabledInit() – called only when first disabled
AutonomousInit() – called each and every time autonomous is entered from another mode
TeleopInit() – called each and every time teleop is entered from another mode
Periodic() functions – each of these functions is called iteratively at the appropriate periodic rate (aka the “slow loop”). The default period of the iterative robot is 10,000 microseconds, giving a periodic frequency of 100Hz (100 times per second).

DisabledPeriodic()
AutonomousPeriodic()
TeleopPeriodic()
Continuous() functions – each of these functions is called repeatedly as fast as possible:

DisabledContinuous()
AutonomousContinuous()
TeleopContinuous()

The basic idea is you have the ability to initialize something (call it once) when starting each mode. Then you have the ability to do stuff in a repeated fashion, without putting in your own loops - using while or for loops in this type of robot structure is something best to be avoided!

They provide two different types of loops. The basic idea here being that there’s stuff that you need to update periodically, like the values you send to your drive motors, but that doesn’t have to be done as quickly as possible (waiting 1/100 of a second is OK). But there are other things that you need to do as frequently as possible, like try to detect state changes on a limit switch. You can rely on these functions being called for you repeatedly for as long as the robot is in that state (teleop, auto, disabled).

This resource is out of date. It was last updated for the beta code in 2008. The up to date version is installed with the C++ update and can be found at C:\windriver\docs\extensions\FRC\WPILib C++ Reference.chm

In particular, the continuous methods no long exist, periodic rate has changed, and there are now test methods.

RobotInit() – provide for initialization at robot power-on

Init() functions – each of the following functions is called once when the appropriate mode is entered:

DisabledInit() – called only when first disabled
AutonomousInit() – called each and every time autonomous is entered from another mode
TeleopInit() – called each and every time teleop is entered from another mode
TestInit() – called each and every time test is entered from another mode

Periodic() functions – each of these functions is called iteratively at the appropriate periodic rate (aka the “slow loop”). The default period of the iterative robot is synced to the driver station control packets, giving a periodic frequency of about 50Hz (50 times per second).

DisabledPeriodic()
AutonomousPeriodic()
TeleopPeriodic()
TestPeriodic()

Here is what the java iterative template looks like. C++ should be similar.

RobotTemplate.java (1.53 KB)


RobotTemplate.java (1.53 KB)

That’s what I get for following google’s first search results (which are usually accurate enough when I need to look wpilib stuff up and don’t have access to one of the team’s development laptops)

Also, if you look at what was originally posted, it contains the continuous functions, so it’s possible the OP is not using the latest revision of the base code.

I’m using the base code we had at the end of the season this year. One of the volunteers gave us the “latest” update on a flash drive at the competition (thanks, whoever that was!). The original code had these comments, though:

/**
 * This "BuiltinDefaultCode" provides the "default code" functionality as used in the "Benchtop Test."
 * 
 * The BuiltinDefaultCode extends the IterativeRobot base class to provide the "default code"
 * functionality to confirm the operation and usage of the core control system components, as 
 * used in the "Benchtop Test" described in Chapter 2 of the 2009 FRC Control System Manual.
...]**/

So is there some replacement for the continuous functions?

BuiltinDefaultCode.cpp (15.9 KB)


BuiltinDefaultCode.cpp (15.9 KB)

The continuous methods were easy to mis-use, so they were removed. From 2014 Software Changelog and Known Issues | Getting Started With the 2014 Control System | 2014 FRC Control System

Iterative robot templates no longer have the continuous methods. That is AutonomousContinuous, TeleopContinuous and DisabledContinuous methods are no longer included in the library. If you are looking for similar functionality threads is a possible alternative.

I filed a bug since I think the BuiltinDefaultCode sample should not have any reference to the continuous methods, even if they were commented out previously.

Thanks all! So what should have gone into continuous? Is it like the all-encompassing “while isEnabled()” of SimpleRobot? How do teams that use iterative know how often something needs to be called, and on that matter, how do you set how often something gets called (in Periodic)?

How 2704 does our code (and it’s different than most teams) is we program entirely with Event Driven State Machines, so our code is written as a lot of reactions to what is happening instead of like a script. Then if we want to run it we pretty much just tell the code to go.

Edit:
So in periodic the code only gets called as often as you call it, in our code it is called every iteration and figures out what needs to do from that. In 2704’s paradigm we assume that our code is called every single iteration, even if it does nothing that iteration.

Edit #2:
In Periodic it runs through the entire code every iteration, every 50ms all of teleop will run, or all of autonomous will run; wheras in SimpleRobot you write it more like a script, loop here loop there, in Iterative you write it in a lot of State Machines

That seems like a pretty solid way to do things. Since I started I did some work programming LED patterns with state machines, but am still a bit confused with how to set the rate at which commands happen, and the rate at which each command needs to be executed. Is there some documentation somewhere about this? Like how often you need to query sensors or read joystick values or send motors commands? I still don’t understand Periodic(). I thought you put stuff inside it like this:

UINT16 numloop_within_second = numloops % (UINT32)GetLoopsPerSec();
if (numloop_within_second == GetLoopsPerSec/2){ //do something }

Is there some other way to set timed events?

How we would do that type of thing would be like this:


// in .h:
int led_state;
int pled_state;

double starttime;

// in .cpp
void LED_FLASHER::Init()
{
     starttime = clock.Now();
}

void LED_FLASHER::Run()
{
     switch(led_state)
     {
     case RED:
          // Output Red
          if((clock.Now - starttime)>TIME_TO_SWITCH)
          {
               starttime = clock.Now;
               led_state = NEXT_COLOR;
          }
     break;
     // ect.
     }
     pled_state = led_state;
}

Instead of using the “commands” (which is more of a Java type thing) we actually program our classes ourselves, it requires quite a bit more setup, but that means that we can have more control.

The idea is that you have full control over what runs every iteration, and the entire code runs each iteration. So maybe you only call LED_FLASHER.Run() every time (clock.Now()%5) == 0 (every five miliseconds), but you have full control over what is going on.