Advertisement
Whiplash141

Whip's Missile Guidance Script

Oct 17th, 2015
537
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.57 KB | None | 0 0
  1. /*
  2. Whip's Rocket Guidance Script v10.0 - revised: 10/23/15
  3. By Joshua Banks
  4. */
  5. List<IMyTerminalBlock> remotes = new List<IMyTerminalBlock>();  
  6. List<IMyTerminalBlock> shooterRefrenceList = new List<IMyTerminalBlock>();  
  7. List<IMyTerminalBlock> missileRefrenceList = new List<IMyTerminalBlock>();  
  8. List<IMyTerminalBlock> gyroList = new List<IMyTerminalBlock>();
  9.  
  10. string shooterReferenceName = "[Shooter]";  
  11. string missileReferenceName = "[Missile 1]";  
  12. string gyroName = "[Control 1]";
  13. IMyRemoteControl shooterRefrence;  
  14. IMyRemoteControl missileRefrence;  
  15. bool hasRun = false;  
  16. double delta_origin;
  17. double max_rotation_degrees = 180; //in degrees per second (360 max for small ships, 180 max for large ships)
  18. double max_distance = 10000; //maximum guidance distance in meters  
  19. int tick_limit = 1; //change to higher for less precision
  20. int current_tick = 0;  
  21. int duration = 0;
  22.  
  23. void Main(string argument)  
  24. {  
  25.     Echo("Tick: " + current_tick.ToString());
  26.  
  27.     if (!hasRun)
  28.         GrabRemotes();
  29.      
  30.     if((current_tick % tick_limit) == 0)  
  31.     {  
  32.         if (duration < 180)
  33.         {
  34.             duration++;
  35.             return;
  36.         }
  37.         else
  38.         {
  39.             Echo("Guidance Active");  
  40.             GuideMissile();  
  41.             current_tick = 0;  
  42.         }    
  43.     }  
  44.     Echo("Has run?: " + hasRun.ToString());  
  45.     current_tick++;  
  46. }      
  47.  
  48. void GrabRemotes()
  49. {
  50.     GridTerminalSystem.SearchBlocksOfName(gyroName, gyroList);  
  51.     GridTerminalSystem.GetBlocksOfType<IMyRemoteControl>(remotes);
  52.     for(int i = 0 ; i < remotes.Count ; i++)  
  53.         {  
  54.             var thisRemote = remotes[i] as IMyRemoteControl;
  55.             if(thisRemote.CustomName.Contains(shooterReferenceName))  
  56.             {    
  57.                 shooterRefrenceList.Add(thisRemote as IMyRemoteControl);  
  58.                 Echo("Found Shooter");  
  59.             }  
  60.  
  61.             if(thisRemote.CustomName.Contains(missileReferenceName))  
  62.             {  
  63.                 missileRefrenceList.Add(thisRemote as IMyRemoteControl);  
  64.                 Echo("Found Missile");  
  65.             }  
  66.         }
  67.  
  68. //---Check if we do not have an shooter remote
  69.     if(shooterRefrenceList.Count == 0)  
  70.     {  
  71.         Echo("No shooter refrence block found");  
  72.         hasRun = false;  
  73.         return;  
  74.     }
  75. //---Check if we do not have a missile remote
  76.     else if(missileRefrenceList.Count == 0)  
  77.     {  
  78.         Echo("No missile refrence block found");  
  79.         hasRun = false;  
  80.         return;  
  81.     }  
  82.     else if(gyroList.Count == 0)
  83.     {
  84.         Echo("No control gyro found");
  85.         hasRun = false;
  86.         return;
  87.     }
  88.     else
  89.     {    
  90.         Echo("Ready to run");
  91.         shooterRefrence = shooterRefrenceList[0] as IMyRemoteControl;  
  92.         missileRefrence = missileRefrenceList[0] as IMyRemoteControl;  
  93.         hasRun = true;  
  94.     }
  95. }
  96.  
  97. void GuideMissile()  
  98. {  
  99. //---Get positions of our blocks with relation to world center
  100.     var originPos = shooterRefrence.GetPosition();  
  101.     var missilePos = missileRefrence.GetPosition();  
  102.  
  103. //---Find current distance from shooter to missile
  104.     delta_origin = Vector3D.Distance(originPos, missilePos);
  105.  
  106. //---Check if we are in range    
  107.     if(delta_origin < max_distance) //change this later to be larger
  108.     {
  109.     //---Get forward vector from our shooter vessel
  110.         var shooterForward = shooterRefrence.Position + Base6Directions.GetIntVector(shooterRefrence.Orientation.TransformDirection(Base6Directions.Direction.Forward));  
  111.         var targetVector = shooterRefrence.CubeGrid.GridIntegerToWorld(shooterForward);  
  112.         var targetVectorNorm = Vector3D.Normalize(targetVector - shooterRefrence.GetPosition());  
  113.  
  114.     //---Find vector from shooter to missile
  115.         var missileVector = Vector3D.Subtract(missilePos, originPos);
  116.  
  117.     //---Calculate angle between shooter vector and missile vector
  118.         double dotProduct; Vector3D.Dot(ref targetVectorNorm, ref missileVector, out dotProduct);
  119.         double x = dotProduct / missileVector.Length();      
  120.         double rawDevAngle = Math.Acos(x) * 180f / Math.PI; //angle between shooter vector and missile
  121.  
  122.     //---Calculate perpendicular distance from shooter vector
  123.         var projectionVector = dotProduct * targetVectorNorm;
  124.         double deviationDistance = Vector3D.Distance(projectionVector,missileVector);
  125.         Echo("Angular Dev: " + rawDevAngle.ToString());
  126.  
  127.     //---Determine scaling factor
  128.         double scalingFactor;
  129.         if(rawDevAngle < 90)
  130.         {
  131.             if(deviationDistance > 200)
  132.             {
  133.                 scalingFactor = delta_origin; //if we are too far from the beam, dont add any more distance till we are closer
  134.             }
  135.             else
  136.             {
  137.                 scalingFactor = (delta_origin + 200); //travel approx. 200m from current position in direction of target vector
  138.             }
  139.         }
  140.         else
  141.         {
  142.             scalingFactor = 200; //if missile is behind the shooter, goes 200m directly infront of shooter for better accuracy
  143.         }
  144.         var destination = shooterRefrence.GetPosition() + scalingFactor * targetVectorNorm;  
  145.         Echo(destination.ToString()); //debug
  146.  
  147.     //---Find front left and top vectors of our missileVector
  148.         var missileGridX = missileRefrence.Position + Base6Directions.GetIntVector(missileRefrence.Orientation.TransformDirection(Base6Directions.Direction.Forward));
  149.         var missileWorldX = missileRefrence.CubeGrid.GridIntegerToWorld(missileGridX) - missilePos;
  150.  
  151.         var missileGridY = missileRefrence.Position + Base6Directions.GetIntVector(missileRefrence.Orientation.TransformDirection(Base6Directions.Direction.Left));
  152.         var missileWorldY = missileRefrence.CubeGrid.GridIntegerToWorld(missileGridY) - missilePos;
  153.  
  154.         var missileGridZ = missileRefrence.Position + Base6Directions.GetIntVector(missileRefrence.Orientation.TransformDirection(Base6Directions.Direction.Up));
  155.         var missileWorldZ = missileRefrence.CubeGrid.GridIntegerToWorld(missileGridZ) - missilePos;
  156.  
  157.     //---Find vector from missile to destination
  158.         var shipToTarget = Vector3D.Subtract(destination, missilePos);
  159.  
  160.     //---Project target vector onto our top left and up vectors
  161.         double dotX; Vector3D.Dot(ref shipToTarget, ref missileWorldX, out dotX);
  162.         double dotY; Vector3D.Dot(ref shipToTarget, ref missileWorldY, out dotY);
  163.         double dotZ; Vector3D.Dot(ref shipToTarget, ref missileWorldZ, out dotZ);
  164.         var projTargetX = dotX / (missileWorldX.Length() * missileWorldX.Length()) * missileWorldX;
  165.         var projTargetY = dotY / (missileWorldY.Length() * missileWorldY.Length()) * missileWorldY;
  166.         var projTargetZ = dotZ / (missileWorldZ.Length() * missileWorldZ.Length()) * missileWorldZ;
  167.  
  168.     //---Get Yaw and Pitch Angles
  169.         double angleYaw = Math.Atan(projTargetY.Length() / projTargetX.Length());
  170.         double anglePitch = Math.Atan(projTargetZ.Length() / projTargetX.Length());
  171.  
  172.     //---Check if x is positive or negative
  173.         double checkPositiveX; Vector3D.Dot(ref missileWorldX, ref projTargetX, out checkPositiveX); Echo("check x:" + checkPositiveX.ToString());
  174.         if(checkPositiveX < 0)
  175.         {
  176.             angleYaw += Math.PI/2; //we only change one value so it doesnt spaz
  177.         }
  178.  
  179.     //---Check if yaw angle is left or right
  180.         double checkYaw; Vector3D.Dot(ref missileWorldY, ref projTargetY, out checkYaw); Echo("check yaw:" + checkYaw.ToString());
  181.         if(checkYaw > 0) //yaw is backwards for what ever reason
  182.             angleYaw = -angleYaw;
  183.         Echo("yaw angle:" + angleYaw.ToString());
  184.  
  185.     //---Check if pitch angle is up or down
  186.         double checkPitch; Vector3D.Dot(ref missileWorldZ, ref projTargetZ, out checkPitch); Echo("check pitch:" + checkPitch.ToString());
  187.         if(checkPitch < 0)
  188.             anglePitch = -anglePitch;
  189.         Echo("pitch angle:" + anglePitch.ToString());
  190.  
  191.     //---Angle controller
  192.         double max_rotation_radians = max_rotation_degrees * (Math.PI / 180);
  193.         double yawSpeed = max_rotation_radians * angleYaw / Math.Abs(angleYaw);
  194.         double pitchSpeed = max_rotation_radians * anglePitch / Math.Abs(anglePitch);
  195.         /*if (angleYaw < Math.PI/4)
  196.         {
  197.             yawSpeed = angleYaw * max_rotation_radians / (Math.PI/4);
  198.         }
  199.         else
  200.         {
  201.             yawSpeed = max_rotation_radians;
  202.         }
  203.          
  204.         if (anglePitch < Math.PI/4)
  205.         {
  206.             pitchSpeed = anglePitch * max_rotation_radians / (Math.PI/4);
  207.         }
  208.         else
  209.         {
  210.             pitchSpeed = max_rotation_radians;
  211.         }*/
  212.  
  213.         //double yawSpeed = angleYaw / Math.PI * max_rotation_radians;
  214.         //double pitchSpeed = anglePitch / Math.PI * max_rotation_radians;
  215.         for(int i = 0; i < gyroList.Count; i++)
  216.         {
  217.             var thisGyro = gyroList[i] as IMyGyro;
  218.             thisGyro.SetValue<float>("Yaw", (float)yawSpeed);
  219.             thisGyro.SetValue<float>("Pitch", (float)pitchSpeed);
  220.             thisGyro.SetValue("Override", true);
  221.         }
  222.     }
  223.     else
  224.     {
  225.         Echo("Out of range");
  226.         for(int i = 0; i < gyroList.Count; i++)
  227.         {
  228.             var thisGyro = gyroList[i] as IMyGyro;
  229.             thisGyro.SetValue<float>("Yaw", 0f);
  230.             thisGyro.SetValue<float>("Pitch", 0f);
  231.             thisGyro.SetValue("Override", true);
  232.         }
  233.     }
  234. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement