Skip to content

Example Best-Practices of Command-Based usage #6618

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 84 commits into from
Closed

Example Best-Practices of Command-Based usage #6618

wants to merge 84 commits into from

Conversation

tom131313
Copy link

Add an Example Best-Practices of Command-Based usage.
Issue #6616
Reference: CD thread
Utilize an LED-based system to show various best-practices in coding Command-Based programs.

@tom131313 tom131313 requested review from a team as code owners May 13, 2024 00:11
Comment on lines 23 to 28
periodicTask.register(()->strip.start(), 0.1, 0.01);
}

public void periodic() {
strip.setData(buffer);
}
Copy link

Choose a reason for hiding this comment

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

Did you mean to put strip.setData(buffer) in the periodic callback and remove periodic() altogether? strip.start() should be invoked once. Any specific reason to offset by 1ms and run at 100ms?

import edu.wpi.first.wpilibj.AddressableLEDBuffer;
import frc.robot.PeriodicTask;

public class RobotSignalsLEDbufferLEDSubsystem {
Copy link

Choose a reason for hiding this comment

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

Not sure why such a verbose name, also I would not include Subsystem suffix since this is no longer a subsystem. How about LEDResource?

Copy link
Author

Choose a reason for hiding this comment

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

I apologize for leaving some trash from the start and then got distracted trying to get output from the example and getting it into a WPILib Pull Request.

My refactored version is available here. Believe it or not it does resemble the original except I have added working output with commentary and didn't pursue the anticipated new AddressableLED functions which we can add when they are readily available. (Xbox controller buttons A, B, and X do something in different robot modes. Now I see that I should document the expected behavior.)

I can't remember - are we including the word subsystem in the Java class/file name or not? I left in subsystem but scrubbed Command and Trigger from names.)

I would appreciate your and @Oblarg comments on what can be done better as a best practice. Thanks.

Copy link
Author

Choose a reason for hiding this comment

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

@illinar I have completed a working example LED resource/subsystem/view based about 99% on your example code.

I did find @SamCarlberg nice addition to the LED process that you recommended. I copied his entire work into my example since I don't see any other way to reference it in my code. All those files would have to be deleted from my example and appropriate imports made to the WPILib when it has those files available.

My changes to your code are trivial to make it a little easier to test. I simulated a couple of events with Xbox controller button presses and changed an onTrue to whileTrue. I added a third view of the LEDs only to display your dynamic Enable/Disable Patterns.

Since the basis of all LED addressable views is the same I have only one class for the LEDview and instantiate it three times for the Top, Main, and EnableDisable views.

I welcome comments from all - you, @Oblarg and anyone to further refine structure.

Thanks for your contribution of a fine example.


*/
@FunctionalInterface
public interface PeriodicTask {
Copy link

Choose a reason for hiding this comment

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

I feel like this should be part of WPILIB API surface if this pattern is an officially blessed mechanism of injecting periodic processing support.

Copy link
Member

@calcmogul calcmogul May 13, 2024

Choose a reason for hiding this comment

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

if this pattern is an officially blessed mechanism of injecting periodic processing support

It's not. The official mechanism is TimedRobot.addPeriodic().

tom131313 added 20 commits May 14, 2024 11:03
…ommandbasedbestpracticeled/subsystems/LEDMainSubsystem.java
…ommandbasedbestpracticeled/subsystems/LEDTopSubsystem.java
…ommandbasedbestpracticeled/subsystems/RobotSignalsLEDbufferLEDSubsystem.java
…ommandbasedbestpracticeled/subsystems/VisionSubsystem.java
…ommandbasedbestpracticeled/subsystems/LEDPattern.java
…ommandbasedbestpracticeled/PeriodicTask.java
…ommandbasedbestpracticeled/subsystems/Shooter.java
@PeterJohnson PeterJohnson changed the title #6616 Example Best-Practices of Command-Based usage Example Best-Practices of Command-Based usage May 20, 2024
@tom131313
Copy link
Author

I've taken this program with a few examples of using command-based as far as I can - it accomplishes all I intended. I can't go any further without WPILib reviewer input. If these examples are of value to WPILib, I'd be happy to recode whatever needs to make it a real WPILib example. The name of the folder should be changed at least to remove the "word" led from it as that is misleading and off-putting. I used LEDs in place of the PWM motor controllers or other devices merely to show actions of the examples.

If these examples aren't what is wanted, I'll close the PR and delete the repository from my account.

Copy link
Contributor

@Gold856 Gold856 left a comment

Choose a reason for hiding this comment

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

The overall structure of this example confuses me a lot. A big overarching theme is that subsystems are used by other subsystems. This feels contradictory to the entire point of the Command-based framework. Why are LEDViews, which are also subsystems, created in RobotSignals, then passed to each subsystem? Why does GroupDisjointTest contain multiple instances of GroupDisjoint? What is GroupDisjointTest trying to show me? There are so many commands, and I'm not sure what they're doing or what it's supposed to demonstrate.

The MooreLikeFSM subsystem also confuses me. It's contradictory to HistoryFSM where it says that commands should not schedule other commands, yet that's what MooreLikeFSM does. MooreLikeFSM also seems like it would be better represented as a giant sequential command since it seems the entire structure is just running commands one after another.

Copy link
Contributor

@spacey-sooty spacey-sooty left a comment

Choose a reason for hiding this comment

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

I agree with all of @Gold856 comments but I also don't see the benefit in adding a new example to show command based best practices. The RapidReactBot example has been used as the up to date and best practice example up until this point in time and I don't see why we should change that. If theres anything that that does incorrectly that should be updated instead of creating a new example. We already have issues keeping current examples up to date, why make that problem worse?

@tom131313
Copy link
Author

These examples of Command-Based programming are intended to illustrate acceptable practices that tend to push usage to all the edges of somewhat unusual usage. Thus, the comments are all valid in that there are multiple examples to sort through and they don't seem to illustrate the normal best practice. Since confusion is anticipated and that is counter to the intention, this project will be dropped and closed.

@tom131313 tom131313 closed this Aug 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants