Skip to content

Conversation

@SamCarlberg
Copy link
Member

Trigger.getAsBoolean() behavior has been changed from passing through the underlying boolean supplier to returning the latest cached signal as determined by the most recent call to poll(). This allows rising and falling edge triggers to have a consistent return value over an entire polling cycle, rather than only being high for the first check in a cycle.

Closes #8309

@SamCarlberg SamCarlberg requested a review from a team as a code owner November 12, 2025 02:25
@SamCarlberg SamCarlberg added 2027 2027 target component: commands v3 WPILib commands library version 3 labels Nov 12, 2025
Comment on lines 257 to 259
// Ensure bindings. Triggers aren't polled when no bindings have been added.
baseTrigger.addBinding(BindingScope.global(), BindingType.RUN_WHILE_HIGH, command);
risingEdgeTrigger.addBinding(BindingScope.global(), BindingType.RUN_WHILE_HIGH, command);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like a major footgun that base triggers need a binding in order for any derived triggers to work. At least from what I've seen in commandsv2, it's not unheard of for triggers to be composed from temporary objects, and silently always using false is those cases would probably cause a lot of confusion and frustration.
One possibility would be for Triggers to track their base trigger(s), so that when a binding is added to a Trigger, it can first make sure all of its base trigger(s) (and their base(s) and so on) are added to the event loop.
Another, simpler but less user-friendly approach is for getAsBoolean() to give a descriptive error or warning if the trigger has not been added to an event loop.

Only binding when a command binding is added would have resulted in intermediate edge triggers never firing
@KangarooKoala
Copy link
Contributor

When we made EventLoop bind on construction, it caused issues since then the instances would never be GC'd. We then added button caching to fix the issue, so it's not so much of an issue, but I'm still hesitant to introduce that kind of behavior.

This allows intermediate unbound triggers to still function
Copy link
Contributor

@KangarooKoala KangarooKoala left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally seems okay to me (someone who has not really interacted with commandsv3, just commandsv2 and BooleanEvent), for what it's worth. Hopefully someone else could also review?

* from {@code getAsBoolean()} may not agree with the result of checking the signal directly.
*
* <p>Triggers are only bound to an event loop when at least one command has been bound to the
* trigger. This method will always return {@code false} before commands have been bound.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe adjust this to reflect that commands being bound to dependencies will also bind the Trigger to an event loop?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2027 2027 target component: commands v3 WPILib commands library version 3

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants