strongback / strongback-java

A library for FIRST Robotics Competition robots that makes it easier to write and test your robot code.
MIT License
41 stars 38 forks source link

Add PID control functionality #30

Closed rhauch closed 9 years ago

rhauch commented 9 years ago

Added a PIDController class that works with the executor or with commands, and a corresponding PIDCommand classes.

Closes #29

rhauch commented 9 years ago

BTW, the pull request includes an enhancement to the Data Recording framework. Some components might correspond to multiple channels, and the DataRecorder didn't make it easy to register multiple channels, and doing so would require making some access methods public. This pull request adds a DataRecordable interface and DataRecorder.register(String name, DataRecordable), which is basically implemented by calling DataRecordable.registerWith(String name, DataRecorder). (This is basically the mildest form of double dispatch, where 'register' calls back to the registerWith method, allowing the DataRecordable receiver to perform custom logic given the recorder.)

Anyway, there are 3 methods on PIDController that return DataRecordable, and the resulting recordable registers a different set of channels. Basically, they correspond to a few minimal channels, a set of more channels, and all channels (with a lot more detail).

The result is that you can actually have the PID controller output a bit, some, or all of its internal state.

xortive commented 9 years ago

Looks great @rhauch, but I have one suggestion. PIDController should implement a Controller interface that has a generic interface for control loops, allowing teams to create their own controllers that implement custom control loops. Command.approach() could accept these generic controller objects instead of being specific to PID Controllers.

rhauch commented 9 years ago

@granjef3, I agree that we can generalize that concept. The problem is that with only one implementation, it's difficult to know what methods should be in that interface. Just computeOutput()? Or also setpoint(double)? What about tolerance(double)? Right now, the PIDCommand would require all of those.

I'm tempted to not generalize it yet, and to instead generalize it (if possible) when we have a second or third kind of controller. So, I'd want to know: do the current methods work, or should (for example) the setpoint(double) and tolerance(double) method be combined? (I started that way, but think it's better to not have to require a tolerance value.) Are the method names appropriate or too specific?

The good news is that people with other controllers can always implement their own commands unique to those controllers.

rhauch commented 9 years ago

@granjef3, I added a 2nd commit (d5439a3) that generalizes the controller logic into a Controller interface. It's got a fair number of methods, and I'm not sure if they all belong. What do you think? It does allow PIDCommand to be made more general, so I renamed it to ControllerCommand.

xortive commented 9 years ago

Setpoint and tolerance are two common things between all controllers, but are distinct concepts that should have their own methods. d5439a30638151a3d727532febab6d62d6501c0c is perfect, exactly what I envisioned. Setpoint and tolerance shouldn't be limited to more than a double. Maybe a checkTolerance() method would be useful here.

For an example of why generalization is useful, look to CSS transition easing functions. You have your setpoint(desired X and Y). Tolerance is 0, you want an exact position. However, animations that move at constant rates look bad, so there are multiple easing functions to simulate real objects.

If you think about a drivetrain, you could make a DrivetrainController that uses a similar bezier curve to easeInOutSine from the CSS transitions that would slowly accelerate and decelerate.

rhauch commented 9 years ago

@granjef3, what would checkTolerance() do?

xortive commented 9 years ago

Takes in a value, returns a boolean whether or not it is considered "within tolerance".

On Mon, Oct 26, 2015 at 10:41 PM, Randall Hauch notifications@github.com wrote:

@granjef3 https://github.com/granjef3, what would checkTolerance() do?

— Reply to this email directly or view it on GitHub https://github.com/strongback/strongback-java/pull/30#issuecomment-151351522 .

rhauch commented 9 years ago

Okay, I almost renamed the method to Command.control, but based upon the JavaDoc I think Command.use( Controller ...) is the most readable. (I'm trying to avoid any form of run or execute, since the commands don't execute until they are submitted.) Regardless, we can overload use for other non-Controller things, too. Also added a unit test for PIDController.

@granjef3, are you okay with merging this?

xortive commented 9 years ago

use is a great name, fits well.

As of right now, it looks great. If we allow setpoint/tolerance types that aren't double, we can always overload use.

I think this is ready to be merged!

Sent from my iPhone

On Oct 26, 2015, at 11:57 PM, Randall Hauch notifications@github.com wrote:

Okay, I almost renamed the method to Command.control, but based upon the JavaDoc I think Command.use( Controller ...) is the most readable. (I'm trying to avoid any form of run or execute, since the commands don't execute until they are submitted.) Regardless, we can overload use for other non-Controller things, too. Also added a unit test for PIDController.

@granjef3, are you okay with merging this?

— Reply to this email directly or view it on GitHub.