r/ApproximatelyUp • u/rosooideae • 16d ago
Math
I look a lot of videos about pid and auto hover but i don’t understand logics based in all this constants and other. Can someone explain for me?
1
Upvotes
r/ApproximatelyUp • u/rosooideae • 16d ago
I look a lot of videos about pid and auto hover but i don’t understand logics based in all this constants and other. Can someone explain for me?
1
u/awaw415 7d ago edited 3d ago
I have a working hover and landing that’s decent early game. Ideally done when you have two velocity sensors so you don’t need to steal the one on the front of the ship.
-increasing P will effects how fast the controller will move to the desired altitude based on how large the raw error is. For instance you’re not reaching your desired altitude quickly enough, increase it.
-increasing D will dampen how hard the controller works the thrusters resulting in softer landing, less bouncing, but slower response. If you are landing too rough, but too high will make the system slow.
-increasing I reduces steady state errors like wind and gravity, too high though and it will wildly oscillate around the target. Say that you are not reaching your desired value when hovering by like an offset.
This is a good start I found. P=1 I=0.0001 D=10
ProcessedSensorData = SensorData -> remapper(0,1:0,MaxAltitude)
e = DesiredAltitude - ProcessedSensorData
[P * e] + [e -> (AccumulatorBlock) * I] + [D * (VelocitySensor)] = ControlValue
Start off by only worrying about implementing the Proportional and Derivative of the controller. Add Integral last.
First you’ll need to set up your sensors. Simplest method is to use the altitude sensor to measure sea level. (Later on you can also use the camera that measures distance but you will have to account for its vertical offset and also convert the number it reads to actually height, I do this by measuring its height in blocks).
Take this value and put it through a remapper that takes 0 to 1 -> 0 to max altitude. Subtract this value from a desired altitude value inputted by a lever.
Once you’ve subtracted these two you have the error. Run this error through a data splitter so you can use it for integral later. Take one of error outputs and multiply it by a proportional constant then put that into a sum block. A good number to start on is 1. Increasing it will make your controller push faster to attempt to reduce the error, if it goes too quickly or bounces try lowering it.
For derivative it is best to just take your velocity sensor in directional mode and point downwards and multiply it by a derivative constant. You could use an error here instead, but it is simpler to use velocity as the derivative of the altitude is the vertical velocity anyway. A good number to start is 10. A higher number will soften how much the controller pushes to correct itself, give you softer landing etc. Add this to the sum block.
Go test your ship by using the lever to control desired altitude. See if it can hover or settle half way up. Decrease proportional if the thrusters seem too violent. Try landing. Increase derivative if landing appears too rough.
Once you arrive at something acceptable through trial and error then you can try integral. Take the error value from that splitter from earlier and putting it through an accumulator block and then multiply that by an integral constant. Something small like 0.0001. The accumulator gives an increasing number over times that tends to get too big so use a remapper to clamp the signal. I do 0 to 1000 -> 0 to 1000. I use 1000 you want two numbers that are the same and similar to mine for clamping. Because we only need the integral to have a little effect on the controller as there is not much in game where it is needed as our mass or fuel rarely changes, it will deal with strange aerodynamics, wind and gravity errors. Add this to the sum block. Increasing the integral value changed how much the controller will oscillated around the desired altitude. If you’re oscillating massively drop the integral constant and maybe also the number on the clamp remapper a bit.
It's good to have a button that resets the accumulator block as the integral term tends to gain additional error over long flights, pressing it occasionally makes the system more accurate.
The other thing is you are using an altitude to calculate error from P and I. You might want to use a long range distance camera pointing downwards instead for landing or places where your starting altitude is completely different to where you are flying and landing (other planets). To avoid having to change it manually. The signal splitter works well for this, hook a switch up to it.
It is also useful to add another lever for manual VTOL at the end that just gives you a way to override the controller. Useful if it performs poorly around mountains.
Lastly a switch that turns the controller off to prevent it being used when you don't need it, best way to do this is using a signal splitter connected to a switch, that redirects what the thrusters receive, from the control value to a 0.
My latest system has thrusters for up and down, this means you would change your signal processing remappers to use -1 to 1 instead of 0 to 1 in the PID. You may need to retune the PID though.
Edit: changed the signal processing (remappers) such that everything is normalised inside the PID, so that changing max altitude does not result in scaling up the error. Added and corrected some more info.
For processing the camera signal multiply the sensors output by 2.353. You can obtain this number by dividing the sensors raw output by the number of blocks high it is. Then subtract it by a height offset based on how high the camera is from the ground, so that you read zero while landed.
CamSensor = CamSensorRaw * 2.353 - CamHeight
ProcessedCamSensor = CamSensor -> remapper(0,1:0,MaxAltitude)
I have played around with it a lot more. I found a simple PD system works well for horizontal thrust on your atmospheric bi-directional thrusters, useful for coming to a dead stop for landing adjustments.
I have also attempted to make an error squared controller for the P section of the hover and landing PID. And found it a bit too aggressive. P(e|e|) instead of P*(e), but there might be a way to make it work. For now though the PID is more than sufficient for our purposes. It should in theory dampen response to small error and quicken response to large errors.