Log in

View Full Version : Drivetrain PID tuning


ollien
21-12-2016, 23:25
Today, I was encouraging my rookie programmers to utilize the NavX to experiment with PID Control in order to make our robot drive straight. Given that we've never done this in a season, one of the things that crossed my mind is how we should deal with the differences in CoFs between our lab's carpet and that of a true to life field. What have other teams done to account for this? Have you guys just purchased carpet, and just calibrated it on that? What would you use to re-tune your loop at competition?

Thanks so much!

Jared Russell
21-12-2016, 23:36
Sensitivity to carpet variation is somewhat dependent on your drivetrain geometry and dynamics. A 6 wheel drive, dropped-center robot with a roughly central CoM and hard wheels is going to turn pretty similarly on a wide variety of floor surfaces. Meanwhile, a 4 wheel drive robot with a long wheelbase and pneumatic wheels may scrub quite differently depending on carpet.

Ideally your PID algorithm can be tuned to compensate for various types of floor conditions (after all, well-worn vs. brand new field carpet can be quite different in its own right!). If you are able to control your robot on a couple different types of surfaces at home (including whatever you have that is most similar to the field surface), you ought to be good when you get to competition.

beijing_strbow
22-12-2016, 12:28
We're able to get pretty good straight driving using only the P term with the navX, so that may be worth trying. As for carpet, a local store gave us a 5x12 foot square of the official carpet (different color though).

GeeTwo
22-12-2016, 15:33
We're able to get pretty good straight driving using only the P term with the navX, so that may be worth trying. As for carpet, a local store gave us a 5x12 foot square of the official carpet (different color though).

A P only loop makes sense in this application, because there is so much physical damping/resistance in the yaw of a robot; there is no need for a software dampening. The navX is likely much more dependable than the wheels for determining orientation, that I would not use drive train encoders in the navigation loop, but ONLY to to feed the wheel/motor PID loop.

As far as color, if you insist on the right color, you'd need a new piece (or two) of carpet each year.

Oblarg
22-12-2016, 17:25
Things to watch out for when doing this, based on personal experience:

1) It is very hard for a loop to keep you driving straight at max speed, because if your motors are saturated you can only slow down one side to adjust, rather than both slow down one side and speed up the other. If you give yourself some headroom, it will work much better.

2) Unless you are using cascading control (i.e. feeding the output of your heading loop to a wheel velocity loop), it is likely that you won't be able to make the p gain high enough on the heading loop to make steady state error acceptably small without introducing instability. A quick and dirty fix for this is to simply add or subtract some minimum output to/from the calculated heading loop output whenever it is outside of some tolerance around 0.

sspoldi
27-12-2016, 12:21
Today, I was encouraging my rookie programmers to utilize the NavX to experiment with PID Control in order to make our robot drive straight. Given that we've never done this in a season, one of the things that crossed my mind is how we should deal with the differences in CoFs between our lab's carpet and that of a true to life field. What have other teams done to account for this? Have you guys just purchased carpet, and just calibrated it on that? What would you use to re-tune your loop at competition?

Thanks so much!

We have never needed to re-tune for a change in carpet. Our typical heading stabilization is a PI controller for angular rate via gyro to stabilize heading. We tune via the following:

1.We do a quick system id on the yaw axis
a. Apply a moderate amplitude yaw step
(usually 1/2 max input on whatever yaw command input you have)
b. Model the angular rate output with the equation
rate = input*k*(1 - exp(-t/tau))

2. design a controller using the following architecture;
error = (yaw_cmd - yaw_rate)
motor_cmd = PID(error, Kp, Ki, Kd)
where:
Kp = gain/K*tau
Ki = gain/K
Kd = 0
gain = 5 to 10 (arbitrary, desired bandwith in rad/sec);

3. Vary gain to get the command response you want. We start at 10, and if it's too sluggish bump it up, if it oscillates or limit cycles (bounces back and forth due to backlash) we back it off.

Sorry for the terse explanation, but that's pretty much it. We do all our own code, so the PI controller is just written into the yaw service function. Sorry I don't have the code right now, but I can find it.

Cheers,
Steve.

SamcFuchs
28-12-2016, 10:38
Can anyone explain to me why so many teams use gyros for driving straight instead of encoders?

Ty Tremblay
28-12-2016, 10:46
Can anyone explain to me why so many teams use gyros for driving straight instead of encoders?

Wheel slip is not a factor and the sensor's value more directly represents robot angle*. That being said, there are downsides to both so it's really just team preference.

*aka "math"

GeeTwo
28-12-2016, 10:47
Can anyone explain to me why so many teams use gyros for driving straight instead of encoders?

short answer: wheels slip.

Once the wheels have slipped against the carpet/floor/obstacle and you don't know how much, you can't reliably use the encoders (by themselves) to determine orientation. Gyros have more drift, but are not subject to this sudden loss of calibration.

D.Allred
28-12-2016, 10:49
Can anyone explain to me why so many teams use gyros for driving straight instead of encoders?

I found it easy to implement with arcade drive. The heading loop replaces the rotate joystick.

David

SamcFuchs
28-12-2016, 10:58
short answer: wheels slip.

Once the wheels have slipped against the carpet/floor/obstacle and you don't know how much, you can't reliably use the encoders (by themselves) to determine orientation. Gyros have more drift, but are not subject to this sudden loss of calibration.

Good point. I'm used to encoders because we use them for motion profiling, which you couldn't really do with a gyro.

SamcFuchs
28-12-2016, 11:00
Wheel slip is not a factor and the sensor's value more directly represents robot angle*. That being said, there are downsides to both so it's really just team preference.

*aka "math"

Sure you get a number that represents your angle, but if you're trying to go a predetermined distance, encoders make corrections much easier.

ollien
28-12-2016, 13:20
I found it easy to implement with arcade drive. The heading loop replaces the rotate joystick.

David

How do you accomplish this? Do you just set your setpoint proportional to the position of the stick?

ahartnet
28-12-2016, 14:10
How do you accomplish this? Do you just set your setpoint proportional to the position of the stick?

Robot.drivetrain.arcadeDrive(DriveForwardSpeed, (Robot.drivetrain.getGyroAngle().getAngle()));

You might want/need to multiply the gyro angle by a Kp or -Kp. We actually ended up with the following:

Robot.drivetrain.arcadeDrive(-DriveForwardSpeed, (-(Robot.drivetrain.getGyroAngle().getAngle()) * Kp+.1));

Jared Russell
28-12-2016, 14:13
Good point. I'm used to encoders because we use them for motion profiling, which you couldn't really do with a gyro.

You can definitely do motion profiling with a gyro.

ollien
28-12-2016, 14:30
Robot.drivetrain.arcadeDrive(DriveForwardSpeed, (Robot.drivetrain.getGyroAngle().getAngle()));

You might want/need to multiply the gyro angle by a Kp or -Kp. We actually ended up with the following:

Robot.drivetrain.arcadeDrive(-DriveForwardSpeed, (-(Robot.drivetrain.getGyroAngle().getAngle()) * Kp+.1));

How are you allowing the driver to adjust the robot's angle?

D.Allred
28-12-2016, 14:44
How do you accomplish this? Do you just set your setpoint proportional to the position of the stick?

We did not use it to execute a turn or follow a path while driving. It was only used to make a stationary turn or maintain a heading for a "drive straight" mode similar to the example in your original post.

For tele-op drive straight, a button on the xBox controller sets the current heading as the desired heading value then replaces the driver's rotation joystick value with the output of the heading proportional controller. Essentially the driver is only controlling thrust at that point and the loop maintains heading.

For our use, a proportional only loop worked but you could set up PID and experiment with the tuning.

David

sspoldi
28-12-2016, 15:43
In 2015 we used Mecanum wheels and one thing we really noticed was that the robot would rotate and drive forward well, but generated a lot more random slipping when moving sideways. We ended up using encoders for forward and lateral positioning and the gyro for heading. We could have used the encoders (one on each wheel) to determine heading, but the slip was giving us problems.

It was worse when the wheels got worn out. we were using the 6" Vexpro wheels, very cost effective but had a very noticeable life span for the rollers. Replacement wheels altered our autonomous timing required for the 3 tote auto.

Cheers,
Steve.

Jared Russell
28-12-2016, 16:27
In 2015 we used Mecanum wheels and one thing we really noticed was that the robot would rotate and drive forward well, but generated a lot more random slipping when moving sideways. We ended up using encoders for forward and lateral positioning and the gyro for heading. We could have used the encoders (one on each wheel) to determine heading, but the slip was giving us problems.

It was worse when the wheels got worn out. we were using the 6" Vexpro wheels, very cost effective but had a very noticeable life span for the rollers. Replacement wheels altered our autonomous timing required for the 3 tote auto.

Cheers,
Steve.

This is very common for mecanum drives. The rollers don't need to spin for forward movement or turns in place (depending on your drivebase geometry), but do need to spin for sideways translation. The less your rollers spin freely, the more your strafing performance suffers.

SamcFuchs
28-12-2016, 16:31
You can definitely do motion profiling with a gyro.

Of course I'm going to defer to you on this, but how reliable is displacement with a gyro? I'm skeptical.

Jared Russell
28-12-2016, 16:46
Of course I'm going to defer to you on this, but how reliable is displacement with a gyro? I'm skeptical.

Do you mean angular displacement? (Gyros measure angular rate, which then must be integrated to obtain angular displacement). With commonly available FRC gyros based on an Invensense MPU-9250 (NavX, CTRE Pigeon) or Analog Devices ADXRS-450/451 (FIRST Choice gyro, WCP Spartan board) you can measure angular displacement *very* accurately...you will only drift a handful of degrees over an entire match under most conditions (e.g. level field). You can generate a turn-in-place motion profile just as you would using encoders.

A gyro can't help you measure translational motion, of course. If you use a multi-DOF IMU with gyros AND accelerometers, you can measure linear acceleration...but trying to obtain precise translational displacement from these is not going to work well (maybe this is what you were referring to). But you can combine a gyro with encoders to give you the "best of both worlds" and follow a profiled path while correcting for yaw errors. As long as the profile contains yaw information, you can use a PID controller (often a P controller is enough) to add a bit of velocity to one side and subtract it from the other to keep you on track.

For more details, see: https://github.com/Team254/FRC-2016-Public/blob/master/src/com/team254/frc2016/subsystems/Drive.java#L385 (our "drive straight" mode engaged by the driver by holding down a button)
and:
https://github.com/Team254/FRC-2016-Public/blob/master/src/com/team254/frc2016/subsystems/Drive.java#L396 (our path following mode used for autonomous mode)

SamcFuchs
28-12-2016, 17:53
Do you mean angular displacement? (Gyros measure angular rate, which then must be integrated to obtain angular displacement). With commonly available FRC gyros based on an Invensense MPU-9250 (NavX, CTRE Pigeon) or Analog Devices ADXRS-450/451 (FIRST Choice gyro, WCP Spartan board) you can measure angular displacement *very* accurately...you will only drift a handful of degrees over an entire match under most conditions (e.g. level field). You can generate a turn-in-place motion profile just as you would using encoders.

A gyro can't help you measure translational motion, of course. If you use a multi-DOF IMU with gyros AND accelerometers, you can measure linear acceleration...but trying to obtain precise translational displacement from these is not going to work well (maybe this is what you were referring to). But you can combine a gyro with encoders to give you the "best of both worlds" and follow a profiled path while correcting for yaw errors. As long as the profile contains yaw information, you can use a PID controller (often a P controller is enough) to add a bit of velocity to one side and subtract it from the other to keep you on track.

For more details, see: https://github.com/Team254/FRC-2016-Public/blob/master/src/com/team254/frc2016/subsystems/Drive.java#L385 (our "drive straight" mode engaged by the driver by holding down a button)
and:
https://github.com/Team254/FRC-2016-Public/blob/master/src/com/team254/frc2016/subsystems/Drive.java#L396 (our path following mode used for autonomous mode)

No, I mean linear displacement, which you would need for motion profiling with a gyro, no?

ollien
28-12-2016, 18:36
No, I mean linear displacement, which you would need for motion profiling with a gyro, no?

Gyros don't track linear displacement. As Jared said, they track the rate at which the angular displacement is changing.

SamcFuchs
29-12-2016, 13:32
Do you mean angular displacement? (Gyros measure angular rate, which then must be integrated to obtain angular displacement). With commonly available FRC gyros based on an Invensense MPU-9250 (NavX, CTRE Pigeon) or Analog Devices ADXRS-450/451 (FIRST Choice gyro, WCP Spartan board) you can measure angular displacement *very* accurately...you will only drift a handful of degrees over an entire match under most conditions (e.g. level field). You can generate a turn-in-place motion profile just as you would using encoders.

A gyro can't help you measure translational motion, of course. If you use a multi-DOF IMU with gyros AND accelerometers, you can measure linear acceleration...but trying to obtain precise translational displacement from these is not going to work well (maybe this is what you were referring to). But you can combine a gyro with encoders to give you the "best of both worlds" and follow a profiled path while correcting for yaw errors. As long as the profile contains yaw information, you can use a PID controller (often a P controller is enough) to add a bit of velocity to one side and subtract it from the other to keep you on track.

I think there was a misunderstanding here. I was talking about using a gyro/accelerometer (the navX in particular) to measure translational displacement, which we both agree is too inaccurate for motion profiling. However, I do have one concern with the alternative you suggest, using the PID loop together with your profile follower. Isn't there a concern that the PID loop could correct in such a way that you end up over/undershooting your goal for the profile?

Our system is to run an independent profile on each side of the robot, where each wheel follows the profile and corrects itself based on the error from the end point. This way, at the end of the loop, the setpoint for each side is the endpoint of the profile, so it ends up correcting itself to the right place.

I guess what I'm saying is that when you use the gyro to go straight (based on yaw) you're adding a new variable (yaw) instead of interpreting yaw as a difference of distances. How do you ensure that that doesn't become a problem?

Hope this makes some sense.

Jared Russell
29-12-2016, 19:12
However, I do have one concern with the alternative you suggest, using the PID loop together with your profile follower. Isn't there a concern that the PID loop could correct in such a way that you end up over/undershooting your goal for the profile?

Our system is to run an independent profile on each side of the robot, where each wheel follows the profile and corrects itself based on the error from the end point. This way, at the end of the loop, the setpoint for each side is the endpoint of the profile, so it ends up correcting itself to the right place.

I guess what I'm saying is that when you use the gyro to go straight (based on yaw) you're adding a new variable (yaw) instead of interpreting yaw as a difference of distances. How do you ensure that that doesn't become a problem?

Hope this makes some sense.

Yep this makes sense and is a problem if you have large errors that the gyro needs to correct (which would also be a problem if you didn't have a gyro present). Usually, though, your yaw errors will be fairly small and stem from the fact that your left and right profiles are executed independently and can encounter independent disturbances.

For example: Say we want to go in a straight line for 10 feet. You would generate left and right profiles that in this case would be identical. You begin following each profile. At some point, maybe there's a bunch in the carpet on the left side, so your left controller begins lagging a bit because of the disturbance...but the right controller keeps tracking accurately. If this happens, your robot is now veering off to the left.

The gyro's role in all of this being to coordinate the execution of your independent left and right profiles. If you are using a gyro to track your actual yaw angle compared to your profile, you'll see that you are now veering left, so your left side should try *extra* hard to get back on track, and the right side should ease up just a bit. With enough gain on the gyro term, the left side should recover very quickly and get synchronized with the right side before you've drifted too far from your intended path.

SamcFuchs
29-12-2016, 20:59
Yep this makes sense and is a problem if you have large errors that the gyro needs to correct (which would also be a problem if you didn't have a gyro present). Usually, though, your yaw errors will be fairly small and stem from the fact that your left and right profiles are executed independently and can encounter independent disturbances.

For example: Say we want to go in a straight line for 10 feet. You would generate left and right profiles that in this case would be identical. You begin following each profile. At some point, maybe there's a bunch in the carpet on the left side, so your left controller begins lagging a bit because of the disturbance...but the right controller keeps tracking accurately. If this happens, your robot is now veering off to the left.

The gyro's role in all of this being to coordinate the execution of your independent left and right profiles. If you are using a gyro to track your actual yaw angle compared to your profile, you'll see that you are now veering left, so your left side should try *extra* hard to get back on track, and the right side should ease up just a bit. With enough gain on the gyro term, the left side should recover very quickly and get synchronized with the right side before you've drifted too far from your intended path.

Ok, I can see how that would be effective...how does it compare to using encoders for correction?

AustinSchuh
30-12-2016, 12:39
Ok, I can see how that would be effective...how does it compare to using encoders for correction?

Jared probably has a slightly different way of looking at this, but I think there's a more fundamental change needed first to make sure you go straight. The encoder vs gyro problem becomes much easier to try. Instead of left, right profiles, I rewrite it as a distance, angle profile, and then use a distance PID loop and an angle PID loop.

angle = (right_distance - left_distance) / width
distance = (left_distance + right_distance) / 2

You can do a similar transform for your powers (pardon any sign errors) to get back to actual outputs you physically have.

left_voltage = distance_voltage - turn_voltage
right_voltage = distance_voltage + turn_voltage

This then lets you control what you care about.

In the presence of tire slip and tire wear, you won't always go straight with just encoders. A gyro has a different set of issues (noise), but isn't affected by those problems. So, we use the gyro for the angle of the robot instead of computing the angle as above.

Just re-phrasing your loops to be an angle, distance pair of loops has huge benefit. Unless your robot has all it's mass perfectly centered over the two drive wheels, your left, right PID loop won't be able to do good distance control and turn control without compromises. I tend to find that good distance control results in a small amount of turn chatter and oscillation. (You can work out the physics to show that the two sides are coupled in left, right, but not in angle, distance) A angle, distance loop doesn't make that assumption.

If you really want to do left, right with a gyro, you can reverse the equations above.

Jaci
30-12-2016, 13:09
Ok, I can see how that would be effective...how does it compare to using encoders for correction?

I think this question mostly stems from a misunderstanding.

The Motion Profiling you're describing, like most motion profiling, is based upon distance, velocity and acceleration. Something to note is that these all function in a single dimension. For devices like actuation arms or conveyors, this makes sense, as there is only one direction of motion. (there can still be issues here in tracking, but that is not related to a difference in distances)

If you want to start using this in a 2D sense (i.e. a drive base), these distances can be misread. For example, if a wheel (or track) on one side of your drive base slips (assuming 'tank' drive), it will mistakenly read a distance, even though it hadn't moved that far. To the code, your drive base is tracking properly, but in the real world it isn't. This is a common problem with drive bases. The most common way to fix this is to add an extra proportional gain based on the error between what you want your heading to be, and what your heading is reported to be by the gyroscope (per Austin's example). Let's say you have the following code:

float left_power = calc_power_left(time, profile_l, encoder_l);
float right_power = calc_power_right(time, profile_r, encoder_r);


The profile will have already generated the desired distance for each side of the drive base (the arc length along the curve of motion for each side), so in a perfect world, this would track just fine. However, we don't live in a perfect world, so we add something like the following:

float gyro_heading = ... your gyro code ...
float desired_heading = get_heading(time, profile);
float delta_angle = desired_heading - gyro_heading; // This is our error in alignment
float turn_power = 0.8 * (-1/80) * delta_angle; // Change these coefficients as required

setLeftMotors(left_power + turn_power);
setRightMotors(right_power - turn_power);


In the above example, get_heading returns the heading of the path at the given time (i.e. the 'tangent' if you were to plot the curve). This accounts for errors in the heading by 'nudging' the robot in the right direction.

The main point I'm trying to clear up here is that it isn't entirely possible to use encoders for correction, as they rely on continuous, perfect connection to the field floor. Adding in a gyroscope will account for any errors in heading that the encoders, wheels or field introduce.

I hope this clears up any misconceptions you have.

thatprogrammer
30-12-2016, 19:08
Jared probably has a slightly different way of looking at this, but I think there's a more fundamental change needed first to make sure you go straight. The encoder vs gyro problem becomes much easier to try. Instead of left, right profiles, I rewrite it as a distance, angle profile, and then use a distance PID loop and an angle PID loop.

angle = (right_distance - left_distance) / width
distance = (left_distance + right_distance) / 2

You can do a similar transform for your powers (pardon any sign errors) to get back to actual outputs you physically have.

left_voltage = distance_voltage - turn_voltage
right_voltage = distance_voltage + turn_voltage

This then lets you control what you care about.

In the presence of tire slip and tire wear, you won't always go straight with just encoders. A gyro has a different set of issues (noise), but isn't affected by those problems. So, we use the gyro for the angle of the robot instead of computing the angle as above.

Just re-phrasing your loops to be an angle, distance pair of loops has huge benefit. Unless your robot has all it's mass perfectly centered over the two drive wheels, your left, right PID loop won't be able to do good distance control and turn control without compromises. I tend to find that good distance control results in a small amount of turn chatter and oscillation. (You can work out the physics to show that the two sides are coupled in left, right, but not in angle, distance) A angle, distance loop doesn't make that assumption.

If you really want to do left, right with a gyro, you can reverse the equations above.

This post is very useful, but I had a few questions based on it.

1. Assuming that you use your gyro to calculate your angular offset rather than "angle = (right_distance - left_distance) / width." How would you calculate the turn voltage part of the bottom equation? "left_voltage = distance_voltage - turn_voltage"

Would you just use a full PID loop to calculate a voltage (and tune it) and then just add the result of that to your distance PID loop?

2. Do you have any tips for tuning PID loops in cases with lots of friction like turning PID loops? Jared (very kindly!) sent me some tips on tuning PID loops before, but I'm curious to see if there are other viewpoints on this in situations with lots of friction.

AustinSchuh
31-12-2016, 02:55
This post is very useful, but I had a few questions based on it.

1. Assuming that you use your gyro to calculate your angular offset rather than "angle = (right_distance - left_distance) / width." How would you calculate the turn voltage part of the bottom equation?
Would you just use a full PID loop to calculate a voltage (and tune it) and then just add the result of that to your distance PID loop?


Pick your favorite controller. P, PD, PID, LQR, Lead/Lag, MPC, YMMV ;) I try to start with what boils down to a PD loop before I pull out I or any other terms. The input to your controller is the angle, and the output is the voltage.


2. Do you have any tips for tuning PID loops in cases with lots of friction like turning PID loops? Jared (very kindly!) sent me some tips on tuning PID loops before, but I'm curious to see if there are other viewpoints on this in situations with lots of friction.

I've got a bit of a random pile of advice, but hopefully some of it is useful when the robot isn't working right. Sometimes you just need to try different things to figure out what's going wrong.

If you've got a bunch of friction, you end up needing to slow things down a bit. Friction is a pain to deal with. You also need to ask yourself really how accurate you need to be. If you can tolerate moderate steady state error, leave it as a PD loop. As the robot goes faster, it takes less energy to get it to steer, which works in your favor. If you really need good tracking, you are going to have to work at tuning I correctly.

Consider running in low gear if you have a transmission so friction is a smaller portion of your overall torque. The most annoying steering loop I tuned was 254's 2011 robot, geared for crazy speeds. We needed to run auto in high gear too, which meant we were close to saturation all the time.

The most annoying issue I've had tuning heading PID loops was where there was lag in the gyro angle reading. That phase lag meant I couldn't push the bandwidth of the loop up to anything useful. I had to fix that before I could get it to stabilize well. I debugged that by plotting the gyro and encoder headings.

Run your loops at 100 - 200 hz. You want to run your loops at 10x the frequency of the highest frequency you want to control. So, if you want to control at 10 hz, you need a 100 hz loop. The more reliable you can get your loop timing, the better. We go to great lengths to hit a 5 ms +- 5% loop timing, and it helps a lot.

The most important part here is to plot everything. Plot your error vs time, and watch it evolve. Plot the power due to P, I, D, FF. Plot the encoder based heading and the gyro based heading. It's possible but hard to tune these things by eye. Honestly, sometimes I think it's easier to rough tune them by listening to them and listening for the overshoot, and then reaching for the plots when I'm stuck. I also like to grab it and feel the loop, though you have to be very careful since robots can cause lots of damage fast.

We use more complicated controllers, which means I have less recent relevant robot experience than I'd like here. I should probably go grab a robot and tune a PID heading loop again just to have some more guidance.

SamcFuchs
31-12-2016, 08:30
The most important part here is to plot everything. Plot your error vs time, and watch it evolve. Plot the power due to P, I, D, FF. Plot the encoder based heading and the gyro based heading. It's possible but hard to tune these things by eye. Honestly, sometimes I think it's easier to rough tune them by listening to them and listening for the overshoot, and then reaching for the plots when I'm stuck. I also like to grab it and feel the loop, though you have to be very careful since robots can cause lots of damage fast.

This is a good point, and I feel it would probably solve a lot of out problems. However, I haven't found a good way to get real time plots from the robot. Do you just use the smartdashboard?

sspoldi
31-12-2016, 11:10
This is a good point, and I feel it would probably solve a lot of out problems. However, I haven't found a good way to get real time plots from the robot. Do you just use the smartdashboard?

We like to print to the console and either dump to an excel file or Octave script and do system ID on that.

We've gone almost exclusively to a PI controller for yaw rate for stabilization, since in teleop we're generally commanding yaw rate anyway. In autonomous we just program rate*time for heading changes, the integrator in the controller almost always gets us close enough. We've done heading control with feed forward for more bandwidth, but it was overkill for the particular application we tried it with. One of the first things we do in our gyro service function is to calculate (if necessary) and provide robot heading, and heading rate so that we don't need to derive it in a controller.

BTW, we generally run at 50 Hz, and target around 10 rad/sec for rate bandwith (a little less that 2 Hz). Our recent setups have been giving us around 30 millicesonds of delay between command and robot response, and 10 rad/s is about the point where we have to start to get more creative with a controller. We may try 100 Hz this year, depending on what we need to do.

Cheers,
Steve.

Ether
31-12-2016, 11:39
float gyro_heading = ... your gyro code ...
float desired_heading = get_heading(time, profile);
float delta_angle = desired_heading - gyro_heading; // This is our error in alignment
float turn_power = 0.8 * (-1/80) * delta_angle; // Change these coefficients as required...

It might be helpful to slightly modify one line of code:

float delta_angle = desired_heading - gyro_heading; // This is our error in alignment

float delta_angle = MATH.IEEEremainder(desired_heading - gyro_heading,360); // This is our error in alignment


https://www.chiefdelphi.com/forums/showpost.php?p=1440383&postcount=36
https://msdn.microsoft.com/en-us/library/system.math.ieeeremainder%28v=vs.110%29.aspx
http://en.cppreference.com/w/cpp/numeric/math/remainder

AustinSchuh
31-12-2016, 12:22
This is a good point, and I feel it would probably solve a lot of out problems. However, I haven't found a good way to get real time plots from the robot. Do you just use the smartdashboard?

This stuff happens so fast that it's not worth doing it in realtime. Each test is like 2 seconds, so we end up writing scripts to copy the data back and plot it.

This is almost a whole new thread, but it's actually hard to write code that is hard real-time on the roboRIO. Hard real-time means that 100% of the time, your code will finish in X us. That means all your algorithms need to run in constant bounded time, and they can't use any system calls which don't run in constant bounded time either.

This means you need to avoid
- Allocating memory (new, malloc, etc).
- file IO. (It can take an unbounded amount of time for your write system call to complete).
- algorithms which don't take constant execution time.
- Any other operations which aren't constant time.

https://rt.wiki.kernel.org/index.php/RT_PREEMPT_HOWTO has some good info on what real-time means. If you are interested in debugging real-time issues, I'm happy to post some more detailed information. I should really do a CD post some time on one of the ones I've found.

For us for logging, this means that we don't log data from our controls thread. We queue it up with a real-time bounded length queue, and write it to a USB stick mounted on the roboRIO from another process. This is a pain, but well worth it.

Another hack I'll use for debugging is to monitor the execution time of the syscalls I care about, (for example, the control loop execution time including logging), and re-run the test if there was a timing violation. This won't be real-time for running during a match where you can't replay if there was a timing violation, but lets you debug something quickly and know when you've affected your test results.

thatprogrammer
31-12-2016, 12:26
If you've got a bunch of friction, you end up needing to slow things down a bit. Friction is a pain to deal with. You also need to ask yourself really how accurate you need to be. If you can tolerate moderate steady state error, leave it as a PD loop. As the robot goes faster, it takes less energy to get it to steer, which works in your favor. If you really need good tracking, you are going to have to work at tuning I correctly.

Consider running in low gear if you have a transmission so friction is a smaller portion of your overall torque. The most annoying steering loop I tuned was 254's 2011 robot, geared for crazy speeds. We needed to run auto in high gear too, which meant we were close to saturation all the time
Thanks for this advice! I'll make sure to look into running robots in low gear for turning in auto if needed :D


Run your loops at 100 - 200 hz. You want to run your loops at 10x the frequency of the highest frequency you want to control. So, if you want to control at 10 hz, you need a 100 hz loop. The more reliable you can get your loop timing, the better. We go to great lengths to hit a 5 ms +- 5% loop timing, and it helps a lot.

On my old team, we used 254's looper code to run every loop we wanted to use closed control on at 5ms. We found this made our intake PD tuning much simpler (we originally couldn't get it to work at 20ms).

The most important part here is to plot everything. Plot your error vs time, and watch it evolve. Plot the power due to P, I, D, FF. Plot the encoder based heading and the gyro based heading. It's possible but hard to tune these things by eye. Honestly, sometimes I think it's easier to rough tune them by listening to them and listening for the overshoot, and then reaching for the plots when I'm stuck. I also like to grab it and feel the loop, though you have to be very careful since robots can cause lots of damage fast.

Considering how fast 971's robots and their mechanism tend to be geared, I hope you lower your gains a lot before you do that :p