![]() |
PID Control
SO we all know by now that not many people used the CMU cam with any success. Who here has used the default PID code given by first? We didn't because there wasn't enough time or need. I'm just curious.
|
Re: PID Control
Tried it. Didn't have enough time to calibrate it, so it wasn't successful. We'll be experimenting with it (or writing our own version of it) for next year's robot during the off-season. We're planning on an omni-drive bot though, so we'll be spending more time working on the drive code for that.
|
Re: PID Control
Quote:
It is pretty straight forward once you understand the basic concepts of a mass, spring and a velocity dependent damping force. Students have no problems understanding and implementing these things, with a little guidance. |
Re: PID Control
I am actually using the default PID algorithm given to us by FIRST. It has done its job well for me. I use the velocity controler for driver interface. I actually makes the driving much smoother and easy to control. I am also using the position controller for autonomous. I have had great succes with both.
One of our member's father is actually a professor of control algorithm at UC Davis so he went over all of the code with me. For calibration ease, he actually had me make the kD = 0. I've kept it that way and it catually seems to work just fine. So, in reality, I am using a PI algorithm. -Tony K |
Re: PID Control
Quote:
|
Re: PID Control
We are using PI control at low speeds, implemented using the hall-effects in the Kit.
It works quite smoothly, but somehow ours stops tracking at about 60% PWM output. However, at that point, PI has relatively few advantages. The tricky part was a smooth transition from closed loop to open loop drive at the 60% mark. |
Re: PID Control
We started with the PID code from FIRST, but had to fix many significant problems.
1. There is only one set of gains for all the motors. This is a problem if you're using the algorithm to control motors which are different (drive and arm) or have different loads (more friction or just motor differences between left and right sides). We generalized the code to include the gain constants in the per-motor structure. 2. The way they do the integral term is ludicrous. It computes a running sum of the error over all time, then divides that by pid_time (the count of loops). The sum never gets reset, so it grows without bound even when you are changing the target value. Even worse, when you change the target value (set_pos or set_vel), it resets pid_time to 1. This is horrible for two reasons. First, it doesn't reset the sum, so the integral term that was mollified by dividing by pid_time (sum = 2000, time = 1000, integral term is 2) is now blown sky high (2000/1 = 2000). Second, there's only one pid_time global, so changing the target value for ANY motor causes the integral term for ALL of the motors to go ballistic. 3. The PWM values are set up like they are for a different motor controller. PWM_ZERO is 132, but the Victor's zero point is 127. There's even code in there to take into account the motor controller's deadband, so that small signals actually do something, but since the zero point is wrong, it completely misses the mark. The MAX_PWM and MIN_PWM values were also centered on 132, so you also had to find that hidden error. 4. There was a hard-coded limit of two motors (or more correctly, two PID controllers) with no hint at what was required to control more motors. 5. The per-motor structure wastes a lot of space with duplicate values for both position and velocity modes, although only one set will be in play at any time. On a controller with only 1800 bytes of RAM, wasting 32 bytes per PID controller is not good coding. 6. While there were great comments about how to tune the PID (once you fixed the bugs), there was not much in the way of how to use the code. It wasn't too difficult to figure things out if you already had a good understanding of both PID and C, but I would think the idea behind this code was to make PID more accessible to teams without strong software experience. We did get it cleaned up and used it to control a total of six motors in four groups: left and right drive (2 CIMs each), arm elbow (van door) and arm wrist (globe). (Each pair of CIMs was controlled by one PID "motor," we just copied the same value to both PWMs.) I hope to clean up our version of the PID code and publish it on our web site. PM me if you want to see it before I have a chance to clean out our debugging junk. |
Re: PID Control
I spent a lot of time tweaking that code. I wanted to use it in manual drive mode, but it wasn't responsive enough (when you let go of the stick it kept going, for example). Our manual drive is back to open loop.
For auton, there is a fundamental problem with the code as is, and I have written about it elsewhere. The S_DRIVE thing sets the position target at the final goal and lets the PID system chase it. This leads to the motor drive values being pegged at their max, so small hanges can't get to the motors, so the loop is not closed -- it's open. This means that both motors will push as hard as they can, but if one goes faster than the other, there is nothing the PID system can do about it until it gets closer to the goal, so it tends to turn in a circle. I modified this so that I increment the PID target position a little bit each cycle, and not so much that the system ever pegs (clips). This keeps the loop closed and the robot driving straight. Well, sort of. To get it to really drive straight you need to have an integration term on the error, but that always made it unstable. I ended up calculating the heading error (difference between wheel counts) and running an outer loop to maintain a zero heading error. I used an integrator on this outer loop, and I got it to be fairly stable. Related subject: We have an arm that is driven by the van door motor, and a pot to measure its absolute position. I had hoped to just run the motor until the arm got to the desired position, but even though it is geared down twice from the output of the motor, when the arm is loaded it can still back drive the motor, even with the Victor set to "brake" mode. My solution was to make an always-on arm servo. It sagged when we loaded the arm up so I tried to add integration to that loop to compensate, but it always oscillated. I decided that I was measuring position and controlling the motor's speed, which are an integration apart (position is the speed integrated). Integration carries with it a 90 degree phase shift at all frequencies (integ(cos) = sin, for example). My additional integration added another 90 degrees for a total of 180 degrees which reverses the feedback at all frequencies: guaranteed oscillation. I got rid of the integrator and just increased the loop gain until the arm didn't sag as much. Works good! There was also an issue of stiction in the arm drive train: applying increasing amounts of voltage to the motor did not move the motor until the static friction (stiction) in the drive train was overcome, but then the voltage was too high for what we wanted. I thought about popping the motor with big, short pulses to break the stiction, but I never tried it. -norm |
Re: PID Control
Quote:
We had really good results using the PID code in position mode to control arm segments. We can command a position and have it hold pretty well even when adding or removing a tetra. It would sag a little, but not enough to drop the tetra if it started with some backwards tilt. The only problem we had was integration wind-up when we requested a large movement. I've since read about that issue - there are easy solutions like zeroing the integration term until the arm gets close to the target position. |
Re: PID Control
We used the 'kit' pid code for the first regional. Since then, we have migrated back to pid code written last year by our team. The switch is very easy as we have macroed 'KIT_PID.'
We only used the position loop during autonomous and we also split gains and max/min for rotate and drive. The pid code was quite easy to tune for linear distances but until we split gains, we had a heck of a time getting spins with the same gains. The reason we abandoned the kit pid code was eventually a robot will not drive straight (assuming it drove straight to begin with). Last year we had implemented 'go straight' code that would compensate for mechanical imperfections by engaging encoder counts and running it through pid. We tried implementing this into the new code but decided that since we already had code that works, it wasnt worth rewriting it and inserted the macros instead. |
| All times are GMT -5. The time now is 14:06. |
Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi