I've been working on simulating drone flight in Gazebo (an open source robotics simulator).
Currently, I'm trying to control the drone's pitch / roll rotation using PIDs. It's important to remember that a drone moves linearly only by angular rotation (forward / backward requires pitch rotation, left / right requires roll).
Right now, I'm testing PID pitch control. The goal is to get the drone to rotate to a specified angle and hold that position - perfect job for a PID.
But the physics implementation complicates that. Essentially, the PID takes the setpoint - the desired pitch rotation angle (in radians), and the current pitch rotation angle (which I get directly form the simulation state).
The PID output is then used to calculate the resultant torque. The torque equation is t = I * a (torque = Intertia * angular acceleration). So, essentially, I'm using a PID to control the angular acceleration of the drone given the current and desired angles of rotation.
The problem, of course, is that a PID output scales linearly with time, so although it decreases to zero as the drone approaches the setpoint, it has been applying positive accelerations through the entire time. The result is that the drone has a lot of angular momentum, and so it naturally overshoots. Then, of course, the PID responds by reversing the rotation, but with the same problem.
In the end, what happens is that the drone starts with a horizontal attitude, rotates to the setpoint, then rotates back to horizontal, then back to the setpoint. If I add any I or D gain it becomes unstable.
The problem is really simple. It's like controlling a vehicle in space. Thrust is applied in pulses in order to give fine control over position / rotation. The PID however, provides a continuous output. Which means I need some sort of physical system that behaves as depicted here:
or I need to rewrite the physics so that the PID output scales appropriately to bring angular velocity to zero by the time it reaches the desired angle of rotation.
Solving this is proving more difficult than I thought - probably because I'm not a strong physics or controls guy.
I've posted this problem already in another forum. You can read the thread here:
where I get really specific. I'm afraid I wasn't able to articulate the problem well enough, partly because the guy who tried to help wasn't really familiar with PIDs (or C++).
Anyway, Any thoughts from someone who has dealt with this sort of thing (or thinks they know more about it than I do...) would be really welcome. :)
Edit: You can see the behavior in the following animated gif: