Advertisement
Whiplash141

My Missile Guidance Script - Dev Version

Nov 3rd, 2015
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 15.05 KB | None | 0 0
  1. /*
  2. Whip's GASP Missile Guidance Script v15 - revised: 11/2/15
  3. /// PROPRIETARY VERSION ///
  4.     Torpedo 1
  5. ___________________________________________________________________
  6. Description:
  7.          
  8. This script handles the launch of the GASP Torpedo for the WMI Komodo Destroyer        
  9.            
  10. - Whiplash141 :)  
  11. */
  12.  
  13. /*
  14. ___________________________________________________________________
  15.  
  16. ========== You can edit these variables to your liking ============
  17. ___________________________________________________________________
  18. */
  19.     static string torpedo_no = "1";        
  20.     string forwardThrustName = "Forward Thrust - Torpedo - " + torpedo_no; //name tag of forward thrust on the missile
  21.     string maneuveringThrustersName = "Thruster - Maneuvering - " + torpedo_no; //name tag of manevering thrusters on the missile
  22.     string mergeName = "Merge - Missile Main - " + torpedo_no; //name tag of missile merge          
  23.     string artMassName = "Artificial Mass - Detach - " + torpedo_no; //name tag of missile mass
  24.     string batteryName = "Battery - Torpedo - " + torpedo_no; //name tag of missile battery
  25.     string shooterReferenceName = "[Shooter]"; //name tag of shooter's remote
  26.     string missileReferenceName = "[Missile " + torpedo_no + "]"; //name tag of missile's remote
  27.     string gyroName = "[Control " + torpedo_no + "]"; //name of missile gyro    
  28.     double guidance_delay = 2; //time (in seconds) that the missile will delay guidance activation by
  29.     double max_rotation_degrees = 180; //in degrees per second (360 max for small ships, 180 max for large ships)
  30.     double max_distance = 10000; //maximum guidance distance in meters; don't enlarge it lol, 10km is super far
  31.     int tick_limit = 1; //change to higher for less precision
  32.  
  33. /*
  34. ___________________________________________________________________
  35.  
  36. ============= Don't touch anything below this :) ==================
  37. ___________________________________________________________________
  38. */
  39. //---So many lists...  
  40.     List<IMyTerminalBlock> forwardThrusters = new List<IMyTerminalBlock>();          
  41.     List<IMyTerminalBlock> artMasses = new List<IMyTerminalBlock>();        
  42.     List<IMyTerminalBlock> mergeBlocks = new List<IMyTerminalBlock>();        
  43.     List<IMyTerminalBlock> maneuveringThrusters = new List<IMyTerminalBlock>();      
  44.     List<IMyTerminalBlock> batteries = new List<IMyTerminalBlock>();
  45.     List<IMyTerminalBlock> remotes = new List<IMyTerminalBlock>();  
  46.     List<IMyTerminalBlock> shooterRefrenceList = new List<IMyTerminalBlock>();  
  47.     List<IMyTerminalBlock> missileRefrenceList = new List<IMyTerminalBlock>();  
  48.     List<IMyTerminalBlock> gyroList = new List<IMyTerminalBlock>();
  49.    
  50.     IMyRemoteControl shooterRefrence;  
  51.     IMyRemoteControl missileRefrence;  
  52.     bool hasRun = false;
  53.     double delta_origin;
  54.     int current_tick = 0;  
  55.     int duration = 0;      
  56.     int timeElapsed = 0;      
  57.  
  58. void Main()  
  59. {  
  60.     Echo("Tick: " + current_tick.ToString());
  61.    
  62.     if (!hasRun)
  63.     {
  64.         GrabRemotes();
  65.     }        
  66.     else //will not run or release missile until has run setup succesfully
  67.     {
  68.         MissileSystems();
  69.        
  70.         if (duration < Math.Ceiling(guidance_delay * 60))
  71.         {
  72.             duration++;
  73.             return;
  74.         }
  75.         else
  76.         {
  77.             if((current_tick % tick_limit) == 0)
  78.             {
  79.                 Echo("Guidance Active");  
  80.                 GuideMissile();  
  81.                 current_tick = 0;  
  82.             }
  83.         }      
  84.         current_tick++;    
  85.     }
  86.    
  87.     Echo("Has run?: " + hasRun);
  88. }      
  89.  
  90. void GrabRemotes()
  91. {
  92.     GridTerminalSystem.SearchBlocksOfName(gyroName, gyroList);
  93.     GridTerminalSystem.GetBlocksOfType<IMyRemoteControl>(remotes);
  94.     for(int i = 0 ; i < remotes.Count ; i++)  
  95.         {  
  96.             var thisRemote = remotes[i] as IMyRemoteControl;
  97.             if(thisRemote.CustomName.Contains(shooterReferenceName))  
  98.             {    
  99.                 shooterRefrenceList.Add(thisRemote as IMyRemoteControl);  
  100.                 Echo("Found Shooter");  
  101.             }  
  102.  
  103.             if(thisRemote.CustomName.Contains(missileReferenceName))  
  104.             {  
  105.                 missileRefrenceList.Add(thisRemote as IMyRemoteControl);  
  106.                 Echo("Found Missile");  
  107.             }  
  108.         }
  109.  
  110. //---Check if we do not have an shooter remote
  111.     if(shooterRefrenceList.Count == 0)  
  112.     {  
  113.         Echo("No shooter refrence block found");  
  114.         hasRun = false;  
  115.         return;  
  116.     }
  117. //---Check if we do not have a missile remote
  118.     else if(missileRefrenceList.Count == 0)  
  119.     {  
  120.         Echo("No missile refrence block found");  
  121.         hasRun = false;  
  122.         return;  
  123.     }  
  124.     else if(gyroList.Count == 0)
  125.     {
  126.         Echo("No control gyro found");
  127.         hasRun = false;
  128.         return;
  129.     }
  130.     else
  131.     {    
  132.         Echo("Ready to run");
  133.         shooterRefrence = shooterRefrenceList[0] as IMyRemoteControl;  
  134.         missileRefrence = missileRefrenceList[0] as IMyRemoteControl;  
  135.         hasRun = true;  
  136.     }
  137. }
  138.  
  139. void GuideMissile()  
  140. {  
  141. //---Get positions of our blocks with relation to world center
  142.     var originPos = shooterRefrence.GetPosition();  
  143.     var missilePos = missileRefrence.GetPosition();  
  144.  
  145. //---Find current distance from shooter to missile
  146.     delta_origin = Vector3D.Distance(originPos, missilePos);
  147.  
  148. //---Check if we are in range    
  149.     if(delta_origin < max_distance) //change this later to be larger
  150.     {
  151.     //---Get forward vector from our shooter vessel
  152.         var shooterForward = shooterRefrence.Position + Base6Directions.GetIntVector(shooterRefrence.Orientation.TransformDirection(Base6Directions.Direction.Forward));  
  153.         var targetVector = shooterRefrence.CubeGrid.GridIntegerToWorld(shooterForward);  
  154.         var targetVectorNorm = Vector3D.Normalize(targetVector - shooterRefrence.GetPosition());  
  155.  
  156.     //---Find vector from shooter to missile
  157.         var missileVector = Vector3D.Subtract(missilePos, originPos);
  158.  
  159.     //---Calculate angle between shooter vector and missile vector
  160.         double dotProduct; Vector3D.Dot(ref targetVectorNorm, ref missileVector, out dotProduct);
  161.         double x = dotProduct / missileVector.Length();      
  162.         double rawDevAngle = Math.Acos(x) * 180f / Math.PI; //angle between shooter vector and missile
  163.  
  164.     //---Calculate perpendicular distance from shooter vector
  165.         var projectionVector = dotProduct * targetVectorNorm;
  166.         double deviationDistance = Vector3D.Distance(projectionVector,missileVector);
  167.         Echo("Angular Dev: " + rawDevAngle.ToString());
  168.  
  169.     //---Determine scaling factor
  170.         double scalingFactor;
  171.         if(rawDevAngle < 90)
  172.         {
  173.             if(deviationDistance > 100)
  174.             {
  175.                 scalingFactor = delta_origin; //if we are too far from the beam, dont add any more distance till we are closer
  176.             }
  177.             else
  178.             {
  179.                 scalingFactor = (delta_origin + 100); //travel approx. 100m from current position in direction of target vector
  180.             }
  181.         }
  182.         else
  183.         {
  184.             scalingFactor = 200; //if missile is behind the shooter, goes 200m directly infront of shooter for better accuracy
  185.         }
  186.         var destination = shooterRefrence.GetPosition() + scalingFactor * targetVectorNorm;  
  187.         Echo(destination.ToString()); //debug
  188.  
  189.     //---Find front left and top vectors of our missile
  190.         var missileGridX = missileRefrence.Position + Base6Directions.GetIntVector(missileRefrence.Orientation.TransformDirection(Base6Directions.Direction.Forward));
  191.         var missileWorldX = missileRefrence.CubeGrid.GridIntegerToWorld(missileGridX) - missilePos;
  192.  
  193.         var missileGridY = missileRefrence.Position + Base6Directions.GetIntVector(missileRefrence.Orientation.TransformDirection(Base6Directions.Direction.Left));
  194.         var missileWorldY = missileRefrence.CubeGrid.GridIntegerToWorld(missileGridY) - missilePos;
  195.  
  196.         var missileGridZ = missileRefrence.Position + Base6Directions.GetIntVector(missileRefrence.Orientation.TransformDirection(Base6Directions.Direction.Up));
  197.         var missileWorldZ = missileRefrence.CubeGrid.GridIntegerToWorld(missileGridZ) - missilePos;
  198.  
  199.     //---Find vector from missile to destination
  200.         var shipToTarget = Vector3D.Subtract(destination, missilePos);
  201.  
  202.     //---Project target vector onto our top left and up vectors
  203.         double dotX; Vector3D.Dot(ref shipToTarget, ref missileWorldX, out dotX);
  204.         double dotY; Vector3D.Dot(ref shipToTarget, ref missileWorldY, out dotY);
  205.         double dotZ; Vector3D.Dot(ref shipToTarget, ref missileWorldZ, out dotZ);
  206.         var projTargetX = dotX / (missileWorldX.Length() * missileWorldX.Length()) * missileWorldX;
  207.         var projTargetY = dotY / (missileWorldY.Length() * missileWorldY.Length()) * missileWorldY;
  208.         var projTargetZ = dotZ / (missileWorldZ.Length() * missileWorldZ.Length()) * missileWorldZ;
  209.         var projTargetXYplane = projTargetX + projTargetY;
  210.  
  211.     //---Get Yaw and Pitch Angles
  212.         double angleYaw = Math.Atan(projTargetY.Length() / projTargetX.Length());
  213.         double anglePitch = Math.Atan(projTargetZ.Length() / projTargetXYplane.Length());
  214.  
  215.     //---Check if x is positive or negative
  216.         double checkPositiveX; Vector3D.Dot(ref missileWorldX, ref projTargetX, out checkPositiveX); Echo("check x:" + checkPositiveX.ToString());
  217.         if(checkPositiveX < 0)
  218.         {
  219.             angleYaw += Math.PI/2; //we only change one value so it doesnt spaz
  220.         }
  221.  
  222.     //---Check if yaw angle is left or right
  223.         double checkYaw; Vector3D.Dot(ref missileWorldY, ref projTargetY, out checkYaw); Echo("check yaw:" + checkYaw.ToString());
  224.         if(checkYaw > 0) //yaw is backwards for what ever reason
  225.             angleYaw = -angleYaw;
  226.         Echo("yaw angle:" + angleYaw.ToString());
  227.  
  228.     //---Check if pitch angle is up or down
  229.         double checkPitch; Vector3D.Dot(ref missileWorldZ, ref projTargetZ, out checkPitch); Echo("check pitch:" + checkPitch.ToString());
  230.         if(checkPitch < 0)
  231.             anglePitch = -anglePitch;
  232.         Echo("pitch angle:" + anglePitch.ToString());
  233.  
  234.     //---Angle controller
  235.         double max_rotation_radians = max_rotation_degrees * (Math.PI / 180);
  236.         double yawSpeed = max_rotation_radians * angleYaw / Math.Abs(angleYaw);
  237.         double pitchSpeed = max_rotation_radians * anglePitch / Math.Abs(anglePitch);
  238.  
  239.         //Alt method 1: Proportional Control
  240.         //(small ship gyros too weak for this to be effective)
  241.         /*
  242.             double yawSpeed = angleYaw / Math.PI * max_rotation_radians;
  243.             double pitchSpeed = anglePitch / Math.PI * max_rotation_radians;
  244.         */
  245.        
  246.         //Alt method 2: Proportional Control with bounds
  247.         //(Small gyros still too weak :/)
  248.             /*if (angleYaw < Math.PI/4)
  249.             {
  250.                 yawSpeed = angleYaw * max_rotation_radians / (Math.PI/4);
  251.             }
  252.             else
  253.             {
  254.                 yawSpeed = max_rotation_radians;
  255.             }
  256.              
  257.             if (anglePitch < Math.PI/4)
  258.             {
  259.                 pitchSpeed = anglePitch * max_rotation_radians / (Math.PI/4);
  260.             }
  261.             else
  262.             {
  263.                 pitchSpeed = max_rotation_radians;
  264.             }*/
  265.  
  266.     //---Set appropriate gyro override
  267.         for(int i = 0; i < gyroList.Count; i++)
  268.         {
  269.             var thisGyro = gyroList[i] as IMyGyro;
  270.             thisGyro.SetValue<float>("Yaw", (float)yawSpeed);
  271.             thisGyro.SetValue<float>("Pitch", (float)pitchSpeed);
  272.             thisGyro.SetValue("Override", true);
  273.         }
  274.     }
  275.     else
  276.     {
  277.         Echo("Out of range");
  278.         for(int i = 0; i < gyroList.Count; i++)
  279.         {
  280.             var thisGyro = gyroList[i] as IMyGyro;
  281.             thisGyro.SetValue<float>("Yaw", 0f);
  282.             thisGyro.SetValue<float>("Pitch", 0f);
  283.             thisGyro.SetValue("Override", true);
  284.         }
  285.     }
  286. }
  287.  
  288. void MissileSystems()              
  289. {            
  290.     GridTerminalSystem.SearchBlocksOfName(artMassName,artMasses);  
  291.     GridTerminalSystem.SearchBlocksOfName(mergeName,mergeBlocks);    
  292.     GridTerminalSystem.SearchBlocksOfName(batteryName,batteries);
  293.  
  294. //---Check for the required launch components
  295.     if(mergeBlocks.Count == 0)
  296.     {
  297.         Echo("No merges found");
  298.     }  
  299.     else if(artMasses.Count == 0)
  300.     {
  301.         Echo("No masses found");
  302.     }
  303.     else if(batteries.Count == 0)
  304.     {
  305.         Echo("No batteries found");
  306.     }
  307.  
  308.     if (timeElapsed == 0)        
  309.     {        
  310.         for(int i = 0 ; i < batteries.Count ; i++)  
  311.         {  
  312.             var thisBattery = batteries[i] as IMyBatteryBlock;
  313.             thisBattery.ApplyAction("OnOff_On"); //make sure our battery is on
  314.             thisBattery.SetValue("Recharge", false);    
  315.         }  
  316.    
  317.     }  
  318.     else if(timeElapsed == 60)  
  319.     {  
  320.         for(int i = 0 ; i < artMasses.Count ; i++)      
  321.         {      
  322.             var thisMass = artMasses[i] as IMyVirtualMass;      
  323.             thisMass.ApplyAction("OnOff_On");      
  324.         }          
  325.         Echo("Detach Thrust On");  
  326.          
  327.         for(int i = 0 ; i < mergeBlocks.Count ; i++)  
  328.         {  
  329.             var thisMerge = mergeBlocks[i] as IMyShipMergeBlock;  
  330.             thisMerge.ApplyAction("OnOff_Off");  
  331.         }  
  332.     }  
  333.     else if(timeElapsed == 180)  
  334.     {        
  335.         for(int i = 0 ; i < artMasses.Count ; i++)      
  336.         {      
  337.             var thisMass = artMasses[i] as IMyVirtualMass;      
  338.             thisMass.ApplyAction("OnOff_Off");      
  339.         }          
  340.         ThrusterOverride();        
  341.         ManeuveringThrust();        
  342.         Echo("Detach Thrust Off");        
  343.         Echo("Thruster Override On");          
  344.     }                  
  345.  
  346.     if (timeElapsed < 180)
  347.         timeElapsed++;        
  348. }
  349.  
  350. void ManeuveringThrust()        
  351. {        
  352.     if(maneuveringThrusters.Count == 0)
  353.         Echo("No maneivering thrust found");
  354.    
  355.     GridTerminalSystem.SearchBlocksOfName(maneuveringThrustersName,maneuveringThrusters);        
  356.     for(int i = 0 ; i < maneuveringThrusters.Count ; i++)        
  357.     {        
  358.         IMyThrust Thrust = maneuveringThrusters[i] as IMyThrust;
  359.         Thrust.ApplyAction("OnOff_On");        
  360.     }        
  361. }        
  362.              
  363. void ThrusterOverride()        
  364. {        
  365.     if(forwardThrusters.Count == 0)
  366.         Echo("No main thrust found");
  367.    
  368.     GridTerminalSystem.SearchBlocksOfName(forwardThrustName,forwardThrusters);              
  369.     for(int i = 0; i < forwardThrusters.Count;i++)              
  370.     {              
  371.         IMyThrust Thrust = forwardThrusters[i] as IMyThrust;
  372.         Thrust.ApplyAction("OnOff_On");
  373.         Thrust.SetValue<float>("Override", float.MaxValue);              
  374.     }          
  375. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement