ZZ-Cat / raildriver

Smart Locomotive Controller script for Garry's Mod Train Build Servers.
GNU Affero General Public License v3.0
2 stars 0 forks source link

Refactor Control Loop #71

Closed ZZ-Cat closed 2 weeks ago

ZZ-Cat commented 8 months ago

The existing implementation of the PIDF control loop is a bit of a janky mess and is in dire need of a clean-up.

Refactor existing feed-forward implementation

The existing feed-forward couples the set speed directly to the control loop's output and it barely contributes to anything at normal line speeds. At higher speeds, this feed-forward causes the control loop to keep accelerating uncontrollably.

A better solution would be to take the rate of change of the set point and use that as the feed-forward, effectively turning it into a pseudo-control derivative term.

Interpolate between set speeds

There currently is no interpolation between each speed you set the locomotive to.
RailDriver currently relies on the tune of the control loop to determine the acceleration and deceleration characteristics.
This leads to the control loop being either under-tuned or over-tuned for its main purpose.
In some cases, you can quite literally tune the control loop to make your locomotive almost instantly "jump" to your set speed... highly entertaining if you have other (be it freight or passenger) cars in tow.

A better solution is to have an interpolation between values and have this be the set point.
Then re-tune the control loop to closely track the set point.

The time scale and shape of the interpolation may be adjusted to control the acceleration and deceleration characteristics of the locomotive.

Scale P, I and D gains based on total train weight

This is a big one, especially when you are doing lengthy hauls. The more weight you have in tow, the more "sluggish" your train may seem. Also, the more likely you will see oscillations in the control loop.

Increase PID loop calculation speed

This may impact CPU usage and tick quota.
Currently, the control loop acts on every tick() which fires roughly every 10~15 milliseconds.
This heavily limits the control loop to a processing speed of 30~60 Hz. Even for a train, this isn't sufficient to provide stable performance.

A better solution may be to have the control loop execute at a fixed rate inside the governance of a while(perf(n)) statement.
This may need investigation to determine how it will be implemented and how much of an impact on performance it will have.

A possible scenario would be to have the control loop execute ten times at a fixed delay within that while(perf(n)) statement when the tick() fires. This could potentially increase the calculation speed of the control loop and allow the user to dial in the control loop calculation rate to favour performance at the expense of more intensive CPU usage and vice versa.

Refactor hillclimb/decent

This will effectively rename it to "Hill Compensation".
The concept will stay the same: Couple the locomotive's pitch angle directly to the control loop's output to assist with track grade changes.

Refactor I Term Decay

The I Term oscillates around zero while the I Term is being "bled off".
This can cause the locomotive to continue rolling in its current direction for quite some time before it comes to a complete stop.

Doing away with this oscillation will make the transition across the automatic brake system engaging a lot smoother than what it currently is.

Various housekeeping chores

ZZ-Cat commented 2 weeks ago

Closing this, because it's no longer relevant to Version 1.1.0.