Skip to content
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

[cmd] Control command/subsystem deprecation #5352

Conversation

AngleSideAngle
Copy link
Contributor

@AngleSideAngle AngleSideAngle commented May 20, 2023

See #5067 for motivation. This deprecates PIDCommand, ProfiledPIDCommand, PIDSubsystem, ProfiledPIDSubsystem, and TrapezoidProfileSubsystem. TrapezoidProfileCommand is kept because it manages a lot of variables (timer, profile, io), although it might be useful to incorporate trapezoid profiles into a future api for general trajectory following.

As for documentation, I have so far removed all the ReplaceMeX examples, since they reference deprecated classes and promote bad design practices. There still are many examples that should be edited to avoid using newly deprecated classes, most of which would probably benefit from inlining.

  • Deprecate control subsystems
  • Deprecate control commands
  • Remove ReplaceMe examples
  • Update use-case examples

resolves #5452

@AngleSideAngle AngleSideAngle requested review from a team as code owners May 20, 2023 04:09
@AngleSideAngle
Copy link
Contributor Author

Another thing to note is that TimedCommand doesn't offer a full replacement to TrapezoidProfileCommand (At least, a hypothetical version that took in state suppliers. Currently you have to wrap it in a DeferredCommand, which doesn't exist in WPILib yet.)

eg.

public CommandBase profiledToState(double goal) {
  TrapezoidProfile profile;
  return runOnce(
          () ->
              profile =
                  new TrapezoidProfile(
                      CONSTRAINTS, new State(goal, 0), new State(getPosition(), getVelocity())))
      .andThen(Commands.runTimed(t -> doSomething(profile.calculate(t))));
}

I'm not sure how this would be fixed, or if it's an issue. Maybe it would be better to have a more generalized trajectory following command (related to an idea I had about rewriting the trajectory library).

@Starlight220
Copy link
Member

That example wouldn't work because of reassignment and capture semantics.

@Starlight220
Copy link
Member

I do think there's value in pre-built base classes or templates for integrating control loops into commands, ie a command class that has prebuilt factories for commands like going to a setpoint etc. The problem is naming: we can't just change the semantics of these classes without a deprecation cycle, so maybe templates and docs are the way to go?

@AngleSideAngle
Copy link
Contributor Author

I think the largest benefit to having predefined factories for controller commands would be "encouraging" users to use features like that in a pragmatic way. However, most of these commands wouldn't actually reduce any boilerplate.

Also I just checked the profile command example. That's definitely an issue, since removing TrapezoidProfileCommand would definitely be a regression in that deferring would be the only way to follow a trapezoid profile evaluated at runtime. This extends more generally to initializing anything at runtime in a command, which currently can only be done via subclassing.

@calcmogul calcmogul changed the title Control command/subsystem deprecation [cmd] Control command/subsystem deprecation Dec 2, 2023
@Gold856
Copy link
Contributor

Gold856 commented Dec 7, 2023

Have we decided on whether or not we want to keep the control commands? If we are going to deprecate them, we should do it this year so we won't have to wait another year. We can always un-deprecate stuff as well. Personally, I'm okay with leaving the control commands in, since they aren't terrible, and because the alternative is letting teams implement it themselves, which, for such a common use case, is probably not worth it.

@AngleSideAngle
Copy link
Contributor Author

I personally think, at the very least, the control subsystems should be removed in the future. There is more of a case for the existence of control commands, especially TrapezoidProfileCommand, although I think the latter would benefit from a generalized command for all time parameterized interpolating trajectories.

@calcmogul
Copy link
Member

We tried replacing the controller commands with TrajectoryCommand in #3366, but we couldn't get CI to pass.

@Gold856
Copy link
Contributor

Gold856 commented Dec 11, 2023

Since we're getting close to kickoff, can this PR be rebased and changed to deprecate the control subsystems and remove the subclassing examples? Best to deprecate sooner rather than later.

@AngleSideAngle
Copy link
Contributor Author

Yep, I've been kind of busy this week, but I should be able to get this and proxyAll finalized by tonight.

@AngleSideAngle
Copy link
Contributor Author

AngleSideAngle commented Dec 12, 2023

@Starlight220 How do you feel about TimedCommand? I'm getting everything up to date and not sure if it's worth keeping or not. I could remove only the class and make it a FunctionalCommand in Commands, but its purpose is pretty difficult to justify since trapezoid profile commands are staying.

@AngleSideAngle
Copy link
Contributor Author

/format

@Starlight220
Copy link
Member

If the control commands are staying, I'm not sure it's needed.
If this PR is focused on deprecating control subsystems, TimedCommand is out of scope.

@AngleSideAngle
Copy link
Contributor Author

/format

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.

Fun tidbit: I think this fixed a bug where SetElevatorSetpoint wouldn't do anything because Elevator overrode PIDSubsystem.periodic without calling it, which is what would command the motor.

* @return A command that drives the robot to the provided distance based on the rangefinder.
*/
public Command driveDistanceFromObstacle(double distance) {
return driveDistance(-distance, () -> -getDistanceToObstacle());
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are these negated?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They're negated so that the robot drives forward in order to reduce distance. It's a bit jank, but better than the previous version's negative P gain.

@Starlight220
Copy link
Member

The control subsystems need to go.

However, the control commands are relatively useful, and I'm not sure we should remove them. Thoughts?

@Gold856
Copy link
Contributor

Gold856 commented Dec 14, 2023

If we remove control commands, I'm concerned that less experienced teams will struggle to create commands that use PIDControllers or motion profiles. It may not reduce boilerplate by that much, but teams are forced to adhere to the constructor args, which means it's harder for them to mess up. The ease of use to teams is worth more than the potential diffculty they would have creating their own.

@AngleSideAngle
Copy link
Contributor Author

AngleSideAngle commented Dec 15, 2023

I don't necessarily disagree with the existence of control commands, given the documentation uses them inline rather than subclassing.
However,

new PIDCommand(new PIDController(...), sensor::get, setpoint::get, out -> motor.set(out), this); // the current PIDCommand behavior would have to be changed to implement `isFinished` with `controller.atSetpoint`

Doesn't seem much better than

var controller = new PIDController(...);
run(() -> motor.set(controller.calculate(sensor.get(), setpoint.get()))).until(controller::atSetpoint)

Especially in debugging, where teams can have a much better understanding of what their code does in the second example.
I think the largest contributor to ease of use is just documenting it well, with could be accomplished if examples (and probably docs.wpilib.org) encourage teams to use the latter.

Regarding the constructor forcing teams to structure their commands in certain way: the added level of opacity makes understanding what the code is actually doing more difficult.

@Oblarg
Copy link
Contributor

Oblarg commented Dec 16, 2023

Re: control commands, please see:

https://www.chiefdelphi.com/t/command-based-help/446143/19?u=oblarg

When you write it out directly, it's clear that the PIDCommand abstraction does not save a single line of code (the controller is injected anyway). The only thing it abstracts out is a single calculate call - at the cost of making the representation completely opaque.

AngleSideAngle and others added 2 commits January 6, 2024 00:32
…earsbot/subsystems/Claw.java

Co-authored-by: Joseph Eng <91924258+KangarooKoala@users.noreply.github.com>
@tom131313
Copy link

tom131313 commented May 26, 2024

proxyAll

I'm sorry I'm not fluent in github or allwpilib but maybe this belongs to you - I can't find it again so I don't know the URLs.

There are two very different implementations of proxyAll (same results though). One of them has a typo in the javadoc.
* <p>This is useful to ensure that default commands of subsystems withing a command group are
should be
* <p>This is useful to ensure that default commands of subsystems within a command group are

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: command-based WPILib Command Based Library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Deprecate PIDSubsystem and ProfiledPIDSubsystem for removal
7 participants