-
Notifications
You must be signed in to change notification settings - Fork 653
[wpimath] Add copySignPow to MathUtil for joystick input shaping #8013
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
[wpimath] Add copySignPow to MathUtil for joystick input shaping #8013
Conversation
The current C++ units library doesn't support fractional exponents, so I think we do have to use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the detailed PR comment! (Though the example snippet includes redeclarations of the same variable (which isn't allowed) and a usage of the non-existent valueWithDeadband
)
Overall, the code seems fine to me, but you'll need approval from an official WPILib maintainer.
Whoops! Decided half way through writing the snippet to rename them all to just Thanks for the review! |
One thing to note when applying power curves to individual joystick axes with the intention of using their output for controlling a drivetrain (or other systems that use 2 axes), assuming your controller's joystick profile is a circle you will "lose" power output when the joystick is pointed at a diagonal. The transformed profile will turn into more of a funky "+" shape at higher exponent values. Here's a very quick and dirty example of what happens with a joystick pointed at 45 degrees. X axis is the exponent, Y is the resulting norm (1 is the desired value for Y). Not sure if implementing something that accounts for this is in the scope of this PR, but I figured I'd mention it since the primary use-case here seems to be drivetrain control. The solution involves multiplying each axis by their norm^(exponent - 1). double x = hid.getLeftX();
double y = hid.getLeftY();
double multiplier = Math.pow(Math.hypot(x, y), exponent - 1.0);
x *= multiplier;
y *= multiplier; |
That is a good catch. In our own code base for our teams robot we do something kinda similar (doing deadband on the norm than squaring the norm). I have been working my way through a list that I kept of a bunch of small features that I would have loved to have in WPILib. I wanted to add this method first, and then see about adding Translation2d versions of applyDeadband and this method in a new PR if this one gets approved. Very helpful graph by the way! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, for what it's worth.
EDIT: Name of method has been updated to copySignPow
This PR adds the simple util method of
applyPowerCurve(value, exponent, maxMagnitude)
to the Java and C++MathUtil
classes. This method transformsvalue
to be on the power curve of x to theexponent
while keeping its sign. It also handles a maxMagninude value that is used to keep the curve consistent (and the value in range) whethervalue
is between the default of [-1,1] or some other magnitude like [-100,100].Usage:
This technique is commonly used in to improve fine control at low speeds and enable quicker ramp-up at higher joystick deflections, most often with an exponent of 2 (squaring the input).
Including this function in
MathUtil
puts both commonly used joystick input transformations in one location and makes them easier for new teams to find and use.This PR also updates the
DifferentialDrive
class to useapplyPowerCurve
in place of its previous manual implementation.Feedback is appreciated, particularly on the method name and documentation comment, as well as better ways to implement this in C++ without calling
.value()
on unit types. This is my first time trying to add an actually new feature, mostly for the learning experience. I hope it’s a useful addition!