Direct posistion control

Hi,

I am trying to improve the speed and bandwidth of my control loop. I was thinking about removing the velocity control loop and feeding the position controller directly to the current controller. From what I have found about cascade controllers this should speed up the full loop by about 3 times. Is there any specific reason why you guys chose the cascaded loop? And do you know if anyone has tried something similar before so I have something to go off. I am pretty new at C++.

Thanks

Hi,

The cascaded PI velocity inside P position loop is mathematically identical to a parallel position → torque PID loop, but with different units for the gains. I.e. there should be no difference.

Can you give a link to where you read about this 3x improvement?

Hi,

I am having trouble finding an exact source for the 3x improvement, I’m not sure that is the right way to use it. What I have found on a few websites and in a textbook is just that the inner loops of any cascade controllers must be at least 3 times faster than their master controller to keep the controller stable. I thought it probably had something to do with the nyquist frequency of the inner loop, but as I said I can’t find any hard evidence, just rules of thumb. I understand that there are benefits to using the cascaded loop but for my application the velocity is not of much interest.

I thought this website was pretty nice, it only mentions the slave controller must be faster (not necessarily 3x)

Thanks

Why don’t you explain what problem you have with the implemented controller? I think that will be more productive.

So the problem I have is that when you are trying to position control your actuator, and you don’t care about velocity, you have to wait for your velocity controller. To make sure that interaction is stable you have to not feed that velocity controller faster than its Nyquist so, as far as I understand it, you have to buffer your position signal and you’re lowering your bandwidth by half. (But probably more because you want to stay away from your Nyquist). My thought is basically to skip the velocity loop because it isn’t very important to control velocity in my case (mostly just low speed stiff position control). The reason for the post is just to see whether this has been done before or considered by the designers so if there is a good reason for the cascade I don’t waste time implementing.

I think you misunderstand something here. You cannot change the position of something without changing the velocity. A motor controller can only control acceleration (with current control) directly. The resulting position is the result of double integration, according to Newtons law. No matter what control loop you implement, you always need to control the velocity to control the position.
The control loop in ODrive reflects this directly with a velocity controller, but as Oscar said, even if you implement a PID controller for the position directly, the math stays the same.
Also keep in mind that the position, velocity and current controllers in ODrive are just separate parts of the formula to calculate the current. It’s not like there are 3 loops that run in parallel where each loop adds a timedelay or something.
You can look into the implementation in controller.cpp

1 Like

Nice article.
And what @grahameth mentions is exactly right.

To reconcile them:
It’s true that in general that: if you don’t concurrently tune the system, then the inner loop must be faster (higher bandwidth) than the outer loop. But we’re generally fine with cascaded control because:

  • The innermost controller, the current controller, is very fast, and is indeed faster than the outer loop(s)
  • The Pos/vel cascade is tuned concurrently: you’ll tune the vel gain and pos gain together. If you were to tune just the vel controller, and yeild a particular control bandwidth, and then apply a pos control bandwidth at or faster, without any tuning, the compound controller would indeed be unstable. However this is nothing different than saying there are PID gains you could pick that are not a stable combination.

In summary: if you tune the loops separately, you need to be cautious about the bandwidth separation as mentioned in the article. If you tune the closed loop, you generally just tune it while checking stability as you go. And in the end, our cascaded loop is mathematically equivalent to the optimal state feedback control (the LQR regulator) but with some unit changes.

The actual way to get high performance is to use feed-forward. Use the pos-filter mode or trapezoidal trajectory mode. This will enable velocity feed-forward. You can additionally set the inertia, which will add torque feed forward.

1 Like

Thank you for the clear explanations, you have definitely dissuaded me from trying to change the vel controller hahaha. Instead it seems like a better idea to try to figure out my speed and acceleration. I did have one last question on the controllers. I saw in the manual that the pos controller only has P control. Do you think it might be off added benefit to add an I step in this loop?
And on the concurrent vel/cur controllers, why do they both have I gain, but no D gain?

Thanks again for the response.

I suspect D gain doesn’t help the current controller due to noise, but I’m not positive. All FOC controllers i can find on the internet use PI only.

As for D gain on velocity,

\tau = J\ddot{\theta} = Kt*I

In other words, torque is directly proportional to both the acceleration and current (assuming constant load of course). Therefore, since we have a current controller, we have an acceleration controller, and acceleration is of course the derivative of velocity, just as velocity is the derivative of position. So we actually do have a derivative control on velocity :slight_smile: