I’ve done PID in the past based on encoder sensor position, as well as velocity, for both Talon and Spark motor controllers, however, I’ve never done current based PID. I wanted to know if there is anything I should know before starting to try to do this. I want to do current PID because I want to directly control the torque output of the motor.
FWIW, I believe the TalonFX is releasing torque control as a part of their paid software package? I don’t remember the details but I remember reading it somewhere
Current control works exactly like you’d expect it to; it’s no different than any other PID controller. The catch is that you have to understand what it actually means to control the current instead of the position or velocity. If you don’t understand the motor mechanics, the behavior will surprise you.
What is your use-case?
For a drivetrain, a more advanced traction control algorithm. I can calculate the maximum amount of torque that can be applied by the wheels to the carpet without slipping, and by extension the maximum torque that the motor can apply. And just never request a larger torque than that value. Or maybe have a slightly higher tolerance for slip, since friction is usually maxmised at some small amount of wheel slip as far as I’ve read.
The difficulty here will probably be in transitioning in/out of current control, since torque control is not really an appropriate control strategy at steady-state.
Have you considered just setting the motor controller current limit to the current you would otherwise use as the setpoint of your current control loop?
Yeah I have just set a current limit before, this is just an interesting thing to do.
Have you thought about how current control will work if the wheels do start slipping?
Should be able to decelerate the wheels to the appropriate speed, with the acceleration variable in F = ma being the difference between the current speed and the desired speed.
You’re describing a cascaded controller with a current controller as the innermost loop.
Note that this still requires you to run a velocity control loop as your outer loop, and you will be limited by the dynamics of that loop. You will also need to figure out some sensible feedforward scheme or else you will have substantial steady state error.
I’m gonna go all old school road racer on you here - though I suspect the drag racers know this all as well - the general rule of thumb that I’d learned was about 10% slippage for maximum power transfer (any more and you’re turning power into heat, noise, and/or debris).
Not super-scientific but the point was that some slippage wasn’t bad - too much was a waste of whatever you’re trying to do but on a slightly different scale than FRC robots, you’re on the right track traction-wise from what I’ve learned. Drag racers at the top level spend an awful lot of effort running on that edge so I suspect for us more mortal sorts of folks, limiting to just past traction or staying on the non-slip side is probably pretty decent but I do dig what you are trying to do.
I guess that’s not the way I’m seeing it at the moment. The velocities are simply an input in order to calculate the correct torque to apply to the motor.
And for steady state I was thinking the actual speed will always tend to lag behind the desired speed somewhat due to the load on the motors of actually driving a 120lb robot, friction etc, so there’s always going to be a difference there to be an “acceleration” to calculate a small torque from, to maintain velocity. You’ll might end up being right and I’ll have to transition to velocity closed loop control once within a small delta of the desired speed. Then use current PID only for accelerations.
I’m gonna go all old school road racer on you here - though I suspect the drag racers know this all as well - the general rule of thumb that I’d learned was about 10% slippage for maximum power transfer (any more and you’re turning power into heat, noise, and/or debris).
I’m actually inspired by the racing world. I’ve created “throttle maps” and “steering maps” of sorts to tune the driving experience to exactly how the driver likes. And yeah, I’ve tended to use slip ratios of 7% or 8%. I did have a jank traction control working before where I just was constantly looking at the slip ratio, and if it exceeded what I set, I set the motor output so that the slip ratio would be what I set.
Also only doing traction control when going straight, doing it when turning is too hard right now…
I’d want to integrate it with the other gyro-based drive PID that I’m already doing for turning.
That’s a good point - as slippage goes up, I’d suspect that current draw goes down from the reduced friction (basically a “burnout” at that point) and it’s not clear how the algorithm would handle that. “Turning it up” to raise the current draw isn’t what you want or at least that’s how it seems to me.
Typical traction controls are based on RPM changes assuming you are “hooked up” (with rapid increases assuming lost traction aka “slip” - I’m betting the non-linear behavior when things get “loose” can make things interesting. I know what I want to do under those circumstances but explaining that to a motor control loop might be more challenging.
Nice stuff.
There is so much opportunity to combine what we know from other disciplines here.
This is a closed control loop, because you have to difference the current velocity and the measured velocity to get a corrective torque (and you need a gain to determine how big that torque is relative to the difference).
The difference I’m doing is between the driver requested velocity, and the currently measured velocity from the IMU. I’ve mapped the driver input control surface to correspond to -max_velocity to +max_velocity. I then use that difference like you said to get a corrective torque.
yeah but there’s no “natural” relationship between velocity difference and torque unless you pick an implicit timescale - that timescale is a proportional gain
Yeah, so at that point you’d need additional sensor data, like from the motor encoder, so you can tell that your motor is spinning faster than it should given the velocity reported by the IMU. Then you target the IMU velocity and use that acceleration (difference between encoder reported velocity and IMU velocity) to find the torque required. Then you clamp that torque with the maximum torque value that your robot can produce without slipping, given weight, gear ratio, number of wheels etc. That torque limit could be raised to allow for some slip.
At least that’s what’s in my head. Just some ramblings so far.
How do you relate torque to velocity difference?
You use that velocity difference as your “acceleration” and use F = ma. You have all the other bits of info to get the force and then translate that into a torque.