Commands are no longer able to outlive their schedule-site's scope,
regardless of how they were scheduled (set as a default command, bound
to a trigger, or manually scheduled)
As a consequence, default commands need better tracking so the default
command setting can be released when their scope exits and the next-most
appropriate default command can be rescheduled (eg, an opmode sets a
default command, then the globally-scoped default is restored when the
opmode exits). Some complexity is required here to make it work well for
edge cases.
Like `schedule()`, `setDefaultCommand()` will immediately start the new
default command if called inside of another command to avoid 1-loop
delays. However, this does not apply when called by the _current_
default command, as it would result in attempting to cancel the default
command while it's mounted (which is impossible and would throw an
exception)
```java
class Robot extends OpModeRobot {
final Drive drive = new Drive();
final CommandXboxController controller = new CommandXboxController(1);
public Robot() {
// global default command, active unless overridden in an opmode or command
drive.setDefaultCommand(drive.stop());
// global trigger binding, always active
controller.rightBumper().onTrue(drive.setX());
}
}
@Teleop
class ExampleOpMode extends PeriodicOpMode {
public ExampleOpMode(Robot robot) {
// opmode-specific default command
robot.drive.setDefaultCommand(robot.drive.operatorControl(robot.controller));
// opmode-specific binding
robot.controller.leftBumper().whileTrue(robot.drive.stop());
// opmode-specific binding that takes precedence over the global binding
// because it happens last; it "wins out" over the `setX()` binding
robot.controller.rightBumper().onTrue(robot.drive.selfTest());
}
@Override
public void periodic() {
Scheduler.getDefault().run();
}
}
```
Since sched_setscheduler() requires non-RT priorities to be 0, we can
use that as a sentinel value for disabling RT and condense the Java API
to just two functions with fewer parameters. The thread priority setter
is deprecated since only experts should use it.
The HAL Notifier thread priority setter was replaced with setting the
priority in the thread itself.
The C++ Notifier non-RT and RT constructors were deduplicated.
The real-time scheduler was changed from SCHED_FIFO to SCHED_RR, which
is SCHED_FIFO with threads allowed to run for a maximum time quantum
before yielding (100 ms by default).
#7695, #7696, #7697, #7701, #7724, #7753, #7861 removed various features
from the HAL, but forgot to clean up the handles, the WS API, or both.
Additionally, since AnalogInput is the only remaining analog I/O,
AnalogJNI was renamed to the more specific AnalogInputJNI.
Some discussion with the tech team showed that there were some real
advantages to being able to pass a 2nd type. It allows separating the DS
and Robot. Additionally, we can make the DriverStationBase class
actually usable instead of the existing DriverStation class which is
impossible to handle in intellisense because it has too much.
This won't fully be doable in C++, but we will need to implement
something similar in python.
- Remove status return from HAL level (clock getting should never fail)
- Remove 32-bit timestamp expand function
- Make monotonic_clock.hpp (formerly fpga_clock.hpp) header-only and
move to root hal include directory
Makes Java `Alert.Level.ERROR`, `Alert.Level.WARNING`, and
`Alert.Level.INFO` proper aliases (instead of separate enum constants
with the same value).
Cleans up Python tests.
Makes the Alert tests more consistent between languages.
I left "free speed" alone since that's the technical term for it. In
general, velocity is a vector quantity, and speed is a magnitude (i.e.,
a strictly positive value).
This PR also replaces the speed verbiage in MotorController with duty
cycle.
Fixes#8423.
Linear OpModes have several major downsides with no obvious solutions:
- Some things stop working automatically--e.g. in a linear opmode,
simulation will not work out-of-the-box; the user must explicitly call
sim themselves. there's a few other things we do periodically, but this
is the big one (it also forces some decisions on other parts of the
library—eg if we want Tunable to work in linear without the user
manually calling refresh, we have to run it on a background thread,
which means it must be thread safe throughout). We can help in some
areas (e.g. have sleep functions call background things), but if the
user is writing a loop that waits to drive a certain distance with no
sleep, it's an easy footgun
- Writing code with no sleeps is easy to do, and can hog an entire
processing core easily--yes, there's more than one core, but it could
still easily impact e.g. vision processing
- Many people I've talked to want robot-level periodic and periodic sim
functions. Given linear opmodes, we have two options, neither of which
is great: (1) don't provide robot-level periodic functions, and the
users who want those must set those up themselves and remember to call
them explicitly from every periodic opmode, or (2) provide them, but
only call them automatically from periodic opmodes, which could be
confusing for linear opmode users (they'd have to call them manually if
they wanted them). Currently we do (1) but someone in the community
already opened a change to do (2).
- Restarting the robot program fixes the "stuck in auto for the rest of
the match" problem but still feels like an ugly hack because the startup
time is not unlikely to make the robot not immediately ready for teleop
Removing LinearOpMode resolves these issues by moving to a periodic-only
structure. We can address the few notable use cases of LinearOpMode
(e.g. very basic autonomous sequences) in other ways such as Blocks
generated code, better state machine tutorials/documentation, etc.
#8626 needs to switch to using reflection to load the robot class. Do
that with this PR so it's separate.
Also, remove the duplicated main files from the template, and instead
fixup vscode to handle this properly.