-
Notifications
You must be signed in to change notification settings - Fork 7
Getting Started
ATALibJ programs start at GamePeriods. The only code inside of GamePeriods that the programmer should write is the constructor. Change the new IterativeRobotAdapter("Null")
to a new instance of your robot mode. If you want to implement your own mode choosing mechanism, be careful about modifying GamePeriods.
There are 6 options for robot modes.
The base interface of all other robot modes. You should use this interface if you will take advantage of every method inside of it. It contains Iterative style methods.
An exception-safe executor of robot modes. You can't extend this class, and it every mode is wrapped in it by default in GamePeriods. There isn't many cases where you would want to use this mode.
The base of an iterative-style robot. Contains init, periodic and end methods for every mode. The init method is called once before starting the mode, the periodic method is called in a periodic loop every 20ms during the mode and the end method is called once at the very end of the mode.
An adapter class that lets you choose which methods you need and implement them in your robot mode. If you are not using every method in IterativeRobot, you should be using this class.
The base of a simple-style robot. Contains one method per mode, and executes it once when the mode starts. Every method should loop until the mode is over, doing whatever is necessary in that mode.
An adapter class that lets you choose which methods you need and implement them in your robot mode. If you are not using every method in SimpleRobot, you should be using this class.
A Module is an element of the robot that performs a function. It has init()
, enable()
, disable()
and isEnabled()
methods. These do pretty much what they describe.
Before writing your module, make sure you're not re-inventing the wheel. Check the edu.first.module
package to ensure there is not a module already made for the purpose you need. Almost all wpilibj classes are wrapped as modules, as well as some highly-used controllers like bang-bang.
Most modules should be able to take advantage of StandardModule. The only reason why it wouldn't is if you need to extend another class. In that cass, implement Module yourself. Be sure to adhere to the contracts set in its documentation.
Modules should emulate the structure of the ATALibJ modules. A standard module looks like this:
public class ExampleModule extends Module.StartardModule {
public void init() {
// Performs functions to ensure the module can be enabled and functional
}
public void enableModule() {
// Performs functions to allow the module to work
}
public void disableModule() {
// Performs the functions to reverse `enableModule()`
}
public void foo() {
// Use `ensureEnabled()` when the function requires the module to be enabled (manipulates the module)
ensureEnabled();
}
public void changeSetting(double setting) {
// Changes setting
// Changing settings of a module should not use `ensureEnabled()` simply because it does not do anything harmful
}
}
The general contract for all modules is as follows:
-
Modules contain methods specific to their purpose, but do not expose their composed instances for security reasons
-
Modules are "ready" to work when
init()
has been called, and its functions will work afterenable()
is called. -
"Settings" of a module, AKA its internal state, are changeable even when disabled.
-
Between calling
enable()
anddisable()
,isEnabled()
will return true. Onlyenable()
anddisable()
can effect the output ofisEnabled()
-
If a function is called while the module is disabled, the function should throw an
IllegalStateException
. -
Calling any of the methods more than once in a row will not behave differently because of it.
-
The state of
isEnabled()
should be thread-safe and only returntrue
when it is completely enabled.
A Subsystem is a collection of modules that performs some kind of function. A subsystem should perform some kind of action(s) that would be impossible for the individual modules themselves to do. Subsystems are things like "arms", "shooters" and "compressors". They are elements of the robot with multiple components which act together.
Subsystems look like this:
public class ExampleSubsystem extends Subsystem {
private final ExampleModule module;
private final ExampleModule module2;
public ExampleSubsystem(ExampleModule module, ExampleModule module2) {
super(new Module[] {module, module2});
this.module = module;
this.module2 = module2;
}
public void foo() {
module.foo();
module2.foo();
}
}
The subsystem combines two ExampleModule
instances to perform foo()
on both of them. This is an example of the "group" structure for subsystems. Groups take multiple modules and performs functions on all instances.
Modules passed into the constructor of a subsystem are enabled and disabled along with the subsystem. If you have the intention of keeping a module enabled even when the subsystem it is a part of is disabled, usually you should rethink your structure. It is possible to just not pass the module in the constructor, but you should be aware of the risks that come with that. If a module is not disabled along with the subsytem it is a part of, the user has no guarantee about the system's enabled state. That is particularly dangerous if nothing is in place to disable the module. Be sure that you are safe with modules inside of a subsystem.
A Controller is a looping virtual mechanism that runs a method at a specific rate. It is useful for things like PID controllers. Controllers should look like this:
public class ExampleController extends Controller {
public ExampleController() {
super(0.02, Controller.LoopType.FIXED_RATE);
}
public void run() {
System.out.println(MathUtils.random());
}
}
Although this is a completely useless controller, it is still valid. It will print a random number every 20ms. In the constructor, double
values are considered seconds, and int
values are considered hertz.
Some default controllers have already been written in ATALibJ. It's most likely the case that you will use these and never need to write your own controller. They are found here.