-
Notifications
You must be signed in to change notification settings - Fork 0
Control System Design Discussion #75
Comments
This paper is very relevant to our interests. |
Thanks for writing this up. I'll take a look at this in a bit. |
I've taken a read through a few resources (1, 2, 3, 4, and 5) and I think I have a basic understanding of the idea here. What I'm still unsure about how our controller will work. A "basic" PID controller for a thermostat is easy enough: double k_p = /* ??? */;
double k_i = /* ??? */;
double k_d = /* ??? */;
double startTime = System.currentTimeMillis();
double desiredOutput = 42;
double errorIntegral = 0; /* What does this start at? */
double lastError = 0; /* What does this start at? */
for (;;) {
double now = System.currentTimeMillis();
double dt = now - startTime;
double error = desiredOutput - read();
errorIntegral += (error * dt);
double errorDerivative = (error - lastError) / dt;
lastError = error;
startTime = now;
write((k_p * error) + (k_i * errorIntegral) + (k_d * errorDerivative));
TimeUnit.MILLISECONDS.sleep(16)
} Does that look correct? Assuming it is,
|
This reminds me of Fold (or a scan) as it's only ever looking at the previous values: |
I will comment more thoroughly on your code later, as well as looking at Folds, I've never heard of that before.
Euclidean is adequate for us given the short distances involved.
No, its a running integral of the last 'x' errors, so oldest values get pushed out.
If I understand your question correctly, I sort of touched on this in my OP where I said:
The mapping function between motion values for surge and yaw to speed and course will be the 'process' (our boat's dynamic model) which we don't know at the moment. You have to remember with control systems you're not controlling the output, you're controlling a device which affects an output indirectly. (You don't control temperature, you control a heater to affect temperature. In our case we control motors to affect our speed and course. By tuning the system we can get it to do what we want.
Signifcantly. Our control system Our timestep is likely going to be limited by the boat itself, as it is definitely going to be sluggish to respond to changes. We may have to wait for it to accelerate and change bearing/speed somewhat before calculating again. |
I had a go at a (generic) PID controller implementation and it doesn't seem to bad. It's not what this comment is about, but for the curious, this is pretty much what I've got (see #82 for all of it): class PIDController<in T>(
private val setpoint: T,
private val dt: Long,
private val gains: Gains,
private val e: (T, T) -> Double
) {
data class Gains(val kp: Double, val ki: Double, val kd: Double)
companion object {
const val BUFFER_SIZE = 4
}
private val errors = RingBuffer(BUFFER_SIZE)
fun add(value: T) = errors.add(e(setpoint, value))
fun nextOutput(): Double {
val (kp, ki, kd) = gains
val errors = errors.array
val integral = errors.map({ it * dt }).sum()
val de = errors[errors.lastIndex - 1] - errors[errors.lastIndex]
val derivative = de / dt
return (
(kp * errors.last())
+ (ki * integral)
+ (kd * derivative)
)
}
} I have a few questions about how we want to go about using this:
|
Yes, ms.
Start at 250 ms. We will need the ability to easily change this, however.
This is the correct method by which PIDs are implemented. You must not update your PID at a rate any faster than half that of your slowest input signal (related to Nyquist Frequency. Since our GPS update will be 10Hz (100 ms), 200 ms will be our minimum ∆t.
When any of the gains are changed, the new gains are applied at the next calculation of the controller. No stored values are cleared (such as the array holding previous error values). Since the gains are added at the end, we will see immediately the affect on each of the three terms and thus on the output.
Yes. It is a parameter used in tuning. This is called the integral timebase,
Yes. It is a parameter used in tuning. This is called the derivative timebase, |
We will need to be able to configure the following parameters for each PID controller (surge and yaw) on the fly (via a settings page on the GUI).
I envision the process for tuning the controller to be as follows:
|
Where and how are you expecting the waypoint distance to be displayed? |
In the 'mission information' box of the GUI would make the most sense. We could display distance and course to next waypoint. |
Fair enough, that works |
Stretch goal: |
No. |
Just kidding—I agree that a vector would be a good visualization to have. I'll see what I can do. (Let's move further ideas to LakeMaps/hangashore#50 where we can attach images and whatnot to further flesh out what it would look like.) |
The config file should be able to modify the |
I'd like to note that my above 6 steps for tuning are still a solid method to tune and I had forgotten about that plan. It should be the fastest method to tune once we know our instrumentation is accurate (via steps 1-4) |
As mentioned, for Rev 1.3 we need to come up with a control methodology. Here are some of the basics:
A control system is generally represented as a block diagram where each block is a self-contained series of transformations with inputs, outputs and parameters.
For us, the system is as follows:
Error = (waypoint) - (where we are)
. The result for us should be a vector comprised ofdistance to waypoint, bearing to waypoint
.where we are
as read by the GPS. It is then used as the feedback signal to the Error block.For Rev 1.3, it is appropriate for us to use PID control, as this is the simplest for us to implement due to its simple mathematical model and familiarity. Interestingly, PID theory was developed by observing helmsmen attempting to keep a vessel on course in varying wind and waves. PID control can be shown as follows:
A few notes:
The text was updated successfully, but these errors were encountered: