Fro Programming Guide
Fro Programming Guide
Command
Based
Frogramming
Guide
Purpose: This guide is intended to lay out the basic needs of programming within the
Command Based architecture for someone with a rudimentary understanding of C++
programming.
Scope: This guide covers only the intricacies of working within the Command-based
architecture of C++ FRC programming. It is not intended to provide information on C++
programming in general or introduce programming concepts. It should be viewed in the
context of sample code such as the FRC provided GearsBot code or at a minimum the
template structure provided with the FRC libraries and resources, as the examples here are
limited to very short (1-5 lines) samples of code to demonstrate a specific concept.
1. Subsystems
Subsystems are groups of components, and the functions associated with them. Each
subsystem gets a .h file and a .cpp file. You should expect to jump back and forth between
these two files while developing the subsystem. “ExSubsystem” is used as the name of a
hypothetical subsystem throughout.
1.1. ExSubsystem.h
1.1.1. Define TBD
1.1.2. Includes
Note the Subsystem.h is exactly that, not to be confused with ExSubsystem. Also worth
noting that while this include appears in the template and sample code of several teams,
the actual file is nowhere to be found.
Commands/Subsystem.h
WPILib.h
1.2.2. Code
1.2.2.1. Default Command
Each of the functions of the subsystem are coded here. Subsystems may have an
“InitDefaultCommand”, which is the default command to operate on this subsystem.
For example, a drive train may have a default driving mode (as opposed to a
braking mode or precision mode). This is initiated by:
setDefaultCommand(new ExCommand());
Where ExCommand is the desired default command. This will run whenever the
subsystem is otherwise idle, i.e. no other commands are using the subsystem. May
subsystems will not have a default command, and the method can simply contain no
code for this (commenting is recommended).
A Drive subsystem will always have a default. This should be the controller
movement command.
2.1.3. Code
2.1.3.1. Declarations
N/A?
2.1.3.2. Prototypes
The following prototypes exist for every command. Each of these is explained in the
ExCommand.cpp section. These should all be declared with their proper parameter
types in the header file.
Constructor(type, type…) //method with the name of the command
Initialize(type, type…)
Execute(type, type…)
IsFinished(type, type) //always a Boolean function, see 2.2.2.2.4
End(type, type…)
Interrupted(type, type…)
2.2. ExCommand.cpp
2.2.1. Includes
ExCommand.h
2.2.2. Code
2.2.2.1. Declarations
2.2.2.2. Methods
2.2.2.2.1. ExCommand() //Constructor for the class
Constructor must include a Requires statement for each subsystem that will be
used by the class. This reserves that subsystem for the command and interrupts
any other command using the subsystem (invoking the other command’s
Interrupted method). Ex.
Requires(exsubsystem);
Note the subsystem reference is the initialized static version created in
CommandBase.cpp. See that section (3.2.2.2.2) for information on this
initialization.
2.2.2.2.2. Initialize
2.2.2.2.3. Execute
This method is what runs over and over again as long as ExCommand is
scheduled to run.
2.2.2.2.4. IsFinished
This is always a Boolean function and serves as a flag to tell the scheduler to
begin shutting down this command. Make this function return TRUE when the
command no longer needs to run. For a continuously running function, such as a
Drive command, this can be hard coded to never end, eg. return false;
2.2.2.2.5. End
This method is called once after IsFinished returns true and contains any actual
code for shutting down the command, e.g. any reset, possibly a subsequent
command to initialize.
2.2.2.2.6. Interrupted
This method is called when another scheduled command requires the same
subsystem.
3.1.3. Code
3.1.3.1. Declarations
N/A?
3.1.3.2. Prototypes
Command Groups have only one function, and are the constructor for that class.
This should be declared with its proper parameter types in the header file.
Constructor(type, type…) //method with the name of the command group
3.2. ExCommandGroup.cpp
4. Supporting Files
4.1. RobotMap.h
RobotMap is a file which only contains constants for each channel that joysticks, motor
controllers, sensors, pneumatics are plugged into. Constant integers are declared with
logical names. When the device is declared in the subsystem, the channel constant is used
as the parameter. This allows one stop shopping for reviewing and changing of device
channels.
4.1.1. Includes
WPILib.h
4.1.2. Code
Entire content of this file is a series of const int's. Comments are used to separate it into
sections. It is fairly simple and straightforward.
4.2. CommandBase
CommandBase stores and creates each subsystem. Every subsystem will be referenced
in the CommandBase header and code files.
4.2.1. CommandBase.h
4.2.1.1. Includes
Commandbase should include each and EVERY subsystem in the form:
#include “Subsystems/ExSubsystem.h”
where Subsystems is the directory containing the header file for the relevant
subsystem. If there is a deeper directory structure, that should be reflected in the
include (ex. Subsystems/Sensors/Encoders.h). As well as:
OI.h
WPILib.h
4.2.1.2.2. Declarations
CommandBase class declares each subsystem as a static with a pointer. The
pointer, in FRC examples, is the same name as the subsystem, except all lower
case. E.g.
static DriveBase *drivebase;
4.2.2. CommandBase.cpp
4.2.2.1. Includes
CommandBase.h
Scheduler.h
4.2.2.2. Code
4.2.2.2.1. Declarations
Each and every subsystem must be initialized. A single static instance should be
initialied to null. E.g.
ExSubsystem* ComandBase::exsubsystem = NULL;
4.2.2.2.2. Creation
Create a single static instance of each and every subsystem. E.g.
exsubsystem = new ExSubsystem();
4.3. OI
4.3.1. OI.h
4.3.1.1. Includes
WPILib.h
4.3.1.2. Code
4.3.1.2.1. Declarations
Each Joystick should be declared here as a pointer. Ex.
Joystick *LogitechStick;
Each button that should also be declared here as a pointer. Ex.
Button *LeftTrigger1;
4.3.1.2.2. Prototypes
Each function within the OI should be prototyped here, starting with a constructor
function named OI.
4.3.2. OI.cpp
4.3.2.1. Includes
In addition to those listed below, each h file for every Command that uses an OI
device should be included here.
OI.h
RobotMap.h
4.3.2.2. Code
4.4.2.1.2. SmartDashboard
Where Robot.cpp is being used to call and establish SmartDashboard data,
pointers must be established for Live Window and any widgets that have code in
Robot.cpp. This will be in the form of:
LiveWindow *lw
SendableChooser *autoMode
Sendable Chooser is a SmartDashboard default type. Other types exist and will
be added/discussed in a later version of this document.
4.4.2.2. Methods
Most of the code in Robot.cpp is auto generated by the template when the files are
set up. This should only be edited by advanced users, and are not discussed in this
version of the document.
4.4.2.2.1. Autonomous
Fightin’ Robotic Owls 5401 Page 8 of 9
4.4.2.2.1.1. AutonomousInit()
This defines the command to execute when Autonomous mode is first
enabled. At this point of our development capability, this should call the
command or command group that will execute our Autonomous Mode code.
This will come in one of two forms:
ExCommand -> Start(); //This is your simple Call the Command or Command Group code.
Or
autonomousCommand -> Start(); //where autonomousCommand is the pointer declared above,
which has been assigned a function based on some logic or user input – see SmartDashboard
section below.
4.4.2.2.1.2. AutonomousPeriodic()
TBD – don’t mess with this at this time
4.4.2.2.2. SmartDashboard
A more complete discussion of the SmartDashboard will be completed in a later
version and in its own section of this document. This section is focused on using
the SmartDashboard to select an Autonomous Mode.
4.4.2.2.2.1. SendableChooser
SendableChooser is a class that presents a list of options to the Smart
Dashboard. The user declares an instance of it in the form of:
autoMode = new SendableChooser();
Once declared, the following functions are invoked to create options on the
list and assign a value to them.
autoMode -> AddDefault(“Option Name”, new ExCommand());//This option will be the default if
nothing is user-selected
autoMode -> AddObject(“Option Name”, new ExCommand());
4.4.2.2.2.2. GetSelected
autonomousCommand = (Command *) autoMode -> GetSelected();
This reads the selected value from the SendableChooser on the
SmartDashboard. You would write this value to a pointer before initiating the
command that was selected here. E.g.
autonomousCOmmand -> Start(); //actually executes the command, assuming the value in the
selection is a command like ExCommand()
5. Sensors
6. Smart Dashboard