- 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
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.
User code:
- OpModeRobot used as the robot base class
- LinearOpMode and PeriodicOpMode are provided opmode base classes
- In Java, annotations can be used to automatically register opmode classes
Additional user code functionality:
- OpMode (string) is available in addition to the overall
auto/teleop/test robot mode
- OpMode does not indicate enable (enable/disable is still separate)
- The HAL API uses integer UIDs; these are exposed at the user API level
as well for faster checks
- User code creates opmodes on startup (these have name, category,
description, etc).
DS:
- DS will present opmode selection lists for auto and teleop for
match/practice. During a match, the DS will automatically activate the
selected opmode in the corresponding match period.
- For testing, an overall mode is selected (e.g. teleop/auto/test) and a
single opmode is selected
Future work:
- Command framework support/integration
- Python annotation support
- Unit tests (needs race-free DS sim updates)
- Porting of examples
Co-authored-by: Joseph Eng <91924258+KangarooKoala@users.noreply.github.com>
#8385 changed gamepad types to follow SDL_GamepadType, so 20 and 21
(previously `kHIDJoystick` and `kHIDGamepad`, respectively) are no
longer valid constants. This meant that after leaving the disconnected
state of the sim GUI, `GamepadType.getGamepadType()` would return null
(since it didn't match any constants). Since there aren't analogous
generic joystick and gamepad constants anymore, this PR changes
GlfwSystemJoystick and KeyboardJoystick to both unconditionally report
as kStandard.
This also updates the GenericHID.SetRumble doc comment to reflect the
two new types of rumble and changes some switch labeled statement groups
to use switch rules instead. If we want to keep on using switch labeled
statement groups (e.g. for consistency with C++, though
GenericHID::SetRumble currently uses if-else), then I could drop the
last change- I just made it since GenericHID.setRumble() previously used
switch rules and general switch rules are nice since there's no risk of
fall-through.
This changes the HAL notifier interface to:
- Use wpiutil signal objects. This means waiting is done through the
`WPI_WaitObject` API instead of a dedicated function and allows for
higher level code to simultaneously wait on notifiers and other events.
- Interval timers are supported at the HAL layer
- Handlers are now required to acknowledge notifications. This is
invisible to users unless they're directly using the HAL API.
- For interval timers, an overrun count is maintained to detect if the
handler didn't acknowledge
The underlying implementation still uses condition variables for the
actual waiting. In basic testing using this approach seemed to be lower
jitter than timerfd.
Currently, the simulation and systemcore implementations are nearly
identical except for a few additional sim hook bits. This could be
refactored, but keeping them separate may make sense to keep the
systemcore implementation easy to read and reason about, or if we ever
choose to use a different underlying timer implementation on systemcore.
The simulation side API is unchanged in form but does change in
function--waiting for notifiers now only waits for currently running (or
newly signaled) notifiers to acknowledge. To avoid a race condition in
sim stepTiming, users of the low level API must make any alarm updates
(especially for one-shot alarms) prior to acknowledging the previous
alarm.
The only current use of the interval timer feature is the `Notifier`
class. The `TimedRobot` implementation still uses a single notifier and
its own interval timing logic to ensure consistent callback order. Using
separate notifiers for each user-level interval would substantially
increase complexity. `Watchdog` also doesn't use the interval timer, as
it's looking for an amount of time since the last `set` call rather than
a recurring interval time.
To reduce flicker, the sim GUI uses a fade out when a timeout goes from
set to unset.
This fixes tsan for wpilib and commands, and also fixes some spurious
test failures.
Support joystick outputs, including Rumble and LEDs.
Also requires an update to Joystick descriptors, as that has also
changed in mrccomm to support showing what outputs are supported.
clang-format 21 made some formatting changes. Since wpiformat's stdlib
task was removed, I removed NOLINT comments for it and removed some
std:: prefixes it added to comments.
Instead of just having a max count for joystick values, there's an available mask of values. This is because in the future we're expecting there to be holes in the list of available buttons and axes. This updates everything to support that scenario.
Also, Joystick buttons, axes, and POVs all now start at 0 instead of 1.
Currently in the entire C API of WPILib we have ~8 different ways of handling strings. The C API actually isn't built for pure C callers (We don't actually have any of those). Instead, they're built for interop between languages like LabVIEW and C# which can talk to C API's directly.
For output parameters, the choice was fairly obvious. An output struct containing a const string pointer and a length makes the most sense. Its easy to use these from most other languages, and doesn't require special null termination handling. Freeing these is also easy, as if you ever receive one of these string structures, theres just a single function call to free it.
Input parameters are a bit more complex. To be used from pure C, and from LabVIEW, a null terminated string is the best in most cases. However, null terminated strings in general have a lot of downsides. Additionally, from LabVIEW there are other considerations around encoding that having a wrapper struct helps make a bit easier. From a language like C#, a wrapper struct is by far the easiest, as custom marshalling can make it trivial to marshal both UTF8 and UTF16 strings down.
The final consideration is its nice to have an identical concept for both input and output. It makes the rules fairly easy to understand.
WPILib will not have any APIs that manipulate a string allocated externally. This means WPI_String can be const, as across the boundary it is always const.
If a WPILib API takes a const WPI_String*, WPILib will not manipulate or attempt to free that string, and that string is treated as an input. It is up to the caller to handle that memory, WPILib will never hold onto that memory longer than the call.
If a WPILib API takes a WPI_String*, that string is an output. WPILib will allocate that API with WPI_AllocateString(), fill in the string, and return to the caller. When the caller is done with the string, they must free it with WPI_FreeString().
If an output struct contains a WPI_String member, that member is considered read only, and should not be explicitly freed. The caller should call the free function for that struct.
If an array of WPI_Strings are returned, each individual string is considered read only, and should not be explicitly freed. The free function for that array should be called by the caller.
If an input struct containing a WPI_String, or an input array of WPI_Strings is passed to WPILib, the individual strings will not be manipulated or freed by WPILib, and the caller owns and should free that memory.
Callbacks also follow these rules. The most common is a callback either getting passed a const WPI_String* or a struct containing a WPI_String. In both of these cases, the callback target should consider these strings read only, and not attempt to free them or manipulate them.