Wpilib recommends that we use the units library in our code. However, it seems to make my code two times more complicated, especially when performing computations. I’m also concerned that the RIO’s 800mhz potato will get GC issues if objects are created and dumped repeatedly.
We use meters daily in my country, so I don’t get the point. Why don’t we just use radians and SI units throughout the code? There will never be a problem with the wrong units.
I know that imperial units are more commonly used in FRC than meters, but all we have to do is Units.inchesToMeters(), right?
Decrease the likelihood of bugs caused by unit errors, such writing down a value in terms of inches when the code that uses it assumes it’s in feet (or meters, in your case). Using units means your code will either be free of those bugs (if you use the built-in math functions, which Java does make unnecessarily verbose), or you’ll be forced to explicitly say in your code what units you’re working in (eg someDistance.in(Meters) * someAngle.in(Radians)), which makes it much easier to spot unit-related bugs.
Increase visibility into what your numbers mean. This is particularly important for things like PID constants, where programmers often just punch in random numbers like 0.001 without knowing what they physically correspond to
It’s totally up to you if you feel these are useful for your team. Personally, I’d use it at the very least for storing configuration values (eg robot dimensions, wheel sizes, etc) and doing any math with those values converted to specific units.
If you’re worried about memory and GC impact, use mutable objects to avoid allocations; that’s why they exist.
I’ve always found it useful to just make the units part of the variable name and this there isn’t any confusion as to what you are working with, and you aren’t creating more objects than you need to
WPILib does this in a few spots. It makes the user code super verbose and hard to read (for example, chassisSpeeds.vx vs chassisSpeeds.vxMetersPerSecond in various expressions). I’m not sure it’s worth it.
On a PR you once stated that Java’s type system is a potato.
I use that quote with my 3rd level Computer Science class that’s learning Java all of the time when discussing more advanced features.
Crazy benefit of being a CS teacher and programming mentor. Though my curriculum kind of requires one of the 3 languages somewhere. Thankfully I can pick and choose.
Definitely makes things verbose. On our team we like to use a shorthand suffix for all our variables. For example:
_mps = meters per second
_s = seconds
_V = volts
_radps2 = radians per second per second
Takes a little to get used to at the start, often requiring a legend. But eventually just becomes trivial after enough reps. Might not be the best solution in the world, but it’s something to try if you don’t want to use Units
For kP at least, it’s volts per unit. I usually start tuning this by saying “what’s the minimum error I want to send 12V” and then do the math. If the answer to that question is 100 rotations, I say 12V = 100R * kP. Which means kP is 12V/100R, or .12 volts per rotation.
This is why Units are so important. If your error is in inches, you’ll have a relatively small kP, where as if that same error is actually in meters, you’ll end up with a very large kP.
I feel compelled to point out these concerns can be proved real or imagined- “Go forth and do science!”. Tools like GCViewer can help profile how much work the garbage collector is actually doing in context, and lizzard for statically analyzing cyclomatic complexity. Lots of other tool possibilities too.
The proportional constant is just the ratio of the output effort to a given error in the measurement. For most FRC mechanisms, this looks something like the commanded voltage of a motor to a distance (for linear mechanisms like elevators and drivetrains), angle (for rotating mechanisms like arms and turrets), or a linear or angular velocity if you’re doing velocity control instead of position.
So you’d commonly see something like this (all these numbers are made up)
// Output 12 volts for every 4 inches of deviation from the setpoint
Per<VoltageUnit, DistanceUnit> kP = Volts.of(12).divide(Inches.of(4));
// Output an additional 0.04 volts for every accrued inch-second away from the setpoint
// kI is weird and doesn't really correspond to a physical property of the system like kP and kD
Per<VoltageUnit, MultUnit<DistanceUnit, TimeUnit>> kI = Volts.of(0.04).divide(Inches.mult(Seconds).of(10));
// To dampen overshoot, reduce output by 0.1 volt for every 8 inches per second of velocity
Per<VoltageUnit, LinearVelocity> kD = Volts.of(0.1).divide(InchesPerSecond.of(8));
Not quite: it relies on the reader inferring what the values mean from context clues in its usage sites. Using units would bake your meaning into the definition and leave no room for ambiguity.