Advertisement
Whiplash141

Whip's Experimental Hover Script v5

Aug 8th, 2017
226
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.62 KB | None | 0 0
  1. //Whip's Hover Script v5 - 8/6/17
  2.  
  3. double hoverAltitude = 10;
  4. double descentSpeed = 10;
  5.  
  6. bool userDefinedPIDGains = false;
  7. double proportionalGain = 10;
  8. double integralGain = 0;
  9. double derivativeGain = 50;
  10. double integralLimit = 100;
  11.  
  12. PID altitudePID;
  13. PID velocityPID = new PID(5, 0, 2, -10, 10, 1d / 60d);
  14. bool PIDSet = true;
  15. bool isSetup = false;
  16.  
  17. List<IMyShipController> shipControllers = new List<IMyShipController>();
  18. List<IMyThrust> thrust = new List<IMyThrust>();
  19. List<IMyThrust> upThrust = new List<IMyThrust>();
  20.  
  21. Program()
  22. {
  23.     if (userDefinedPIDGains)
  24.         altitudePID = new PID(proportionalGain, integralGain, derivativeGain, -integralLimit, integralLimit, 1d / 60d);
  25.     else
  26.         PIDSet = false;
  27.  
  28.     isSetup = GrabBlocks();
  29. }
  30.  
  31. bool SetPIDController(IMyShipController reference)
  32. {
  33.     var mass = reference.CalculateShipMass().PhysicalMass;
  34.     altitudePID = new PID(mass / 250, 0, mass / 100, -100, 100, 1d / 60d);
  35.     //altitudePID = new PID(100, 0, 50, -100, 100, 1d / 60d);
  36.  
  37.     return true;
  38. }
  39.  
  40. void Main(string arg)
  41. {
  42.     if (!isSetup)
  43.         isSetup = GrabBlocks();
  44.  
  45.     var controller = GetControlledShipController(shipControllers);
  46.     var velocityVec = controller.GetShipVelocities().LinearVelocity;
  47.     var mass = controller.CalculateShipMass().PhysicalMass;
  48.    
  49.     var gravityVec = controller.GetNaturalGravity();
  50.     var gravityMagnitude = gravityVec.Length();
  51.    
  52.     if (Vector3D.IsZero(gravityVec))
  53.     {
  54.         Echo("Error: No natural gravity found");
  55.         return;
  56.     }
  57.    
  58.     if (!PIDSet)
  59.     {
  60.         PIDSet = SetPIDController(controller);
  61.     }
  62.    
  63.     double altitude = 0;
  64.     controller.TryGetPlanetElevation(MyPlanetElevation.Surface, out altitude);
  65.  
  66.     var upwardThrustMagnitude = CalculateUpThrust(thrust, controller, gravityVec);
  67.     var upwardAcceleration = upwardThrustMagnitude / mass;
  68.    
  69.     var downSpeed = velocityVec.Dot(Vector3D.Normalize(gravityVec));
  70.    
  71.     var equillibriumThrust = mass * gravityMagnitude / upwardThrustMagnitude * 100;
  72.  
  73.     altitudePID.Control(hoverAltitude - altitude);
  74.     velocityPID.Control(downSpeed - descentSpeed);
  75.    
  76.     double targetThrust = Math.Max(velocityPID.Value, altitudePID.Value);
  77.     /*if (altitude > hoverAltitude * 2)
  78.     {
  79.  
  80.         targetThrust = equillibriumThrust + velocityPID.Value;
  81.     }
  82.     else
  83.     {
  84.         targetThrust = equillibriumThrust + altitudePID.Value;
  85.     }*/
  86.  
  87.     foreach (var block in upThrust)
  88.     {
  89.         block.SetValue("Override", (float)Math.Max(targetThrust, 1.001));
  90.     }
  91. }
  92.  
  93. bool GrabBlocks()
  94. {
  95.     GridTerminalSystem.GetBlocksOfType(shipControllers);
  96.     if (shipControllers.Count == 0)
  97.     {
  98.         Echo("Error: No ship controllers found");
  99.         return false;
  100.     }
  101.  
  102.     GridTerminalSystem.GetBlocksOfType(thrust);
  103.     if (thrust.Count == 0)
  104.     {
  105.         Echo("Error: No thrusters found");
  106.         return false;
  107.     }
  108.  
  109.     return true;
  110. }
  111.  
  112. double CalculateStopAcceleration(double vf, double vi, double d)
  113. {
  114.     //Vf^2 = Vi^2 + 2*a*d
  115.     return Math.Abs(vf * vf - vi * vi) / (2 * d);
  116. }
  117.  
  118. double CalculateUpThrust(List<IMyThrust> thrust, IMyShipController reference, Vector3D gravityVec)
  119. {
  120.     upThrust.Clear();
  121.     double thrustSum = 0;
  122.     double gravityAlignmentCoeff = gravityVec.Dot(reference.WorldMatrix.Down);
  123.    
  124.     if (gravityAlignmentCoeff <= 0)
  125.         return -1;
  126.  
  127.     foreach (var block in thrust)
  128.     {
  129.         if (block.WorldMatrix.Backward == reference.WorldMatrix.Up)
  130.         {
  131.             upThrust.Add(block);
  132.             thrustSum += block.MaxEffectiveThrust;
  133.         }
  134.     }
  135.  
  136.     return thrustSum;
  137. }
  138.  
  139. IMyShipController GetControlledShipController(List<IMyShipController> SCs)
  140. {
  141.     foreach (IMyShipController thisController in SCs)
  142.     {
  143.         if (thisController.IsUnderControl && thisController.CanControlShip)
  144.             return thisController;
  145.     }
  146.  
  147.     return SCs[0];
  148. }
  149.  
  150. //Whip's PID controller class v3 - 8/4/17
  151. public class PID
  152. {
  153.     double _kP = 0;
  154.     double _kI = 0;
  155.     double _kD = 0;
  156.     double _lowerBound = 0;
  157.     double _upperBound = 0;
  158.     double _timeStep = 0;
  159.     double _errorSum = 0;
  160.     double _lastError = 0;
  161.     bool _firstRun = true;
  162.     public double Value {get; private set;}
  163.  
  164.     public PID(double kP, double kI, double kD, double lowerBound, double upperBound, double timeStep)
  165.     {
  166.         _kP = kP;
  167.         _kI = kI;
  168.         _kD = kD;
  169.         _lowerBound = lowerBound;
  170.         _upperBound = upperBound;
  171.         _timeStep = timeStep;
  172.     }
  173.  
  174.     public PID(float kP, float kI, float kD, float lowerBound, float upperBound, float timeStep)
  175.     {
  176.         _kP = kP;
  177.         _kI = kI;
  178.         _kD = kD;
  179.         _lowerBound = lowerBound;
  180.         _upperBound = upperBound;
  181.         _timeStep = timeStep;
  182.     }
  183.  
  184.     public double Control(double error)
  185.     {
  186.         //Compute derivative term
  187.         var errorDerivative = (error - _lastError) / _timeStep;
  188.        
  189.         if (_firstRun)
  190.         {
  191.             errorDerivative = 0;
  192.             _firstRun = false;
  193.         }
  194.  
  195.         //Compute integral term
  196.         _errorSum += error * _timeStep;
  197.  
  198.         //Clamp integral term
  199.         if (_errorSum > _upperBound)
  200.             _errorSum = _upperBound;
  201.         else if (_errorSum < _lowerBound)
  202.             _errorSum = _lowerBound;
  203.  
  204.         //Store this error as last error
  205.         _lastError = error;
  206.  
  207.         //Construct output
  208.         this.Value = _kP * error + _kI * _errorSum + _kD * errorDerivative;
  209.         return this.Value;
  210.     }
  211.  
  212.     public void Reset()
  213.     {
  214.         _errorSum = 0;
  215.         _lastError = 0;
  216.         _firstRun = true;
  217.     }
  218. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement