Advertisement
Whiplash141

Super Simple Missile Code v1

Jan 23rd, 2017
240
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 15.49 KB | None | 0 0
  1. /*
  2. //Whip's Super Simple Missile Code for Rexxar v1 - 1/23/17
  3.  
  4. ///SETUP///
  5. You need at least:
  6. * A timer set to run this program and trigger now itself
  7. * A antenna
  8. * A thruster pointed forward
  9. * A remote
  10. * A program
  11. * A gyro
  12.  
  13. ///FIRING INSTRUCTIONS///
  14. Plug in a Vector3D or GPS coordinate into the argument and it will fly to that spot.
  15. */
  16.  
  17.  
  18. //const string missileNameTag = "<Missile>";
  19. //add this name tag to all missile blocks :)
  20.  
  21. //Me magical PID constants (idk if they will even work lol)
  22. const double proportionalConstant = 5;
  23. const double derivativeConstant = 2;
  24.  
  25. bool driftCompensation = true;
  26. //set this to false if u want the missiles to drift like ass
  27.  
  28.  
  29. // No touchey below
  30. IMyRemoteControl missileReference = null;
  31.  
  32. bool fireMissile = false;
  33. bool firstGuidance = true;
  34.  
  35. Vector3D targetPos = new Vector3D();
  36. Vector3D missilePos = new Vector3D();
  37. Vector3D gravVec = new Vector3D();
  38.  
  39. double lastYawAngle = 0;
  40. double lastPitchAngle = 0;
  41. double lastRollAngle = 0;
  42.  
  43. List<IMyThrust> thrust = new List<IMyThrust>();
  44. List<IMyThrust> forwardThrust = new List<IMyThrust>();
  45. List<IMyThrust> otherThrust = new List<IMyThrust>();
  46. List<IMyGyro> gyros = new List<IMyGyro>();
  47. List<IMyRemoteControl> remotes = new List<IMyRemoteControl>();
  48. List<IMyRadioAntenna> antennas = new List<IMyRadioAntenna>();
  49. List<IMyTimerBlock> timers = new List<IMyTimerBlock>();
  50.  
  51. void Main(string arg)
  52. {
  53.     var vector = new Vector3D();
  54.     var gps = new Vector3D();
  55.    
  56.    
  57.     bool isGPS = TryParseGPS(arg, out gps);
  58.  
  59.     if (isGPS)
  60.     {
  61.         Echo("GPS position recieved");
  62.         targetPos = gps;
  63.         if (!fireMissile)
  64.             fireMissile = true;
  65.        
  66.         Echo(targetPos.ToString());
  67.     }
  68.     else
  69.     {        
  70.         bool isVector = TryParseVector3D(arg, out vector);
  71.         if (isVector)
  72.         {
  73.             Echo("Vector position recieved");
  74.             targetPos = vector;
  75.             if (!fireMissile)
  76.                 fireMissile = true;
  77.            
  78.             Echo(targetPos.ToString());
  79.         }
  80.     }
  81.     if (fireMissile)
  82.     {        
  83.         bool isSetup = GetBlocks();
  84.  
  85.         if (isSetup)
  86.         {
  87.             GuideMissile(targetPos);
  88.             timers[0].ApplyAction("TriggerNow");
  89.         }
  90.     }
  91. }
  92.  
  93. bool TryParseGPS(string gpsString, out Vector3D vector)
  94. {
  95.     vector = new Vector3D(0,0,0);
  96.  
  97.     var gpsStringSplit = gpsString.Split(':');
  98.  
  99.     double x, y, z;
  100.    
  101.     if (gpsStringSplit.Length < 5)
  102.         return false;
  103.  
  104.     bool passX = double.TryParse(gpsStringSplit[2], out x);
  105.     bool passY  = double.TryParse(gpsStringSplit[3], out y);
  106.     bool passZ = double.TryParse(gpsStringSplit[4], out z);
  107.    
  108.     Echo($"{x},{y},{z}");
  109.  
  110.     if (passX && passY && passZ)
  111.     {
  112.         vector = new Vector3D(x, y, z);
  113.         return true;
  114.     }
  115.     else
  116.         return false;
  117. }
  118.  
  119. bool TryParseVector3D(string vectorString, out Vector3D vector)
  120. {
  121.     vector = new Vector3D(0, 0, 0);
  122.  
  123.     vectorString = vectorString.Replace(" ", "").Replace("{", "").Replace("}", "").Replace("X", "").Replace("Y", "").Replace("Z", "");
  124.     var vectorStringSplit = vectorString.Split(':');
  125.  
  126.     double x, y, z;
  127.  
  128.     if (vectorStringSplit.Length < 4)
  129.         return false;
  130.  
  131.     bool passX = double.TryParse(vectorStringSplit[1], out x);
  132.     bool passY = double.TryParse(vectorStringSplit[2], out y);
  133.     bool passZ = double.TryParse(vectorStringSplit[3], out z);
  134.  
  135.     if (passX && passY && passZ)
  136.     {
  137.         vector = new Vector3D(x, y, z);
  138.         return true;
  139.     }
  140.     else
  141.         return false;
  142. }
  143.  
  144. bool GetBlocks()
  145. {
  146.     bool successfulSetup = true;
  147.  
  148.     forwardThrust.Clear();
  149.     otherThrust.Clear();
  150.  
  151.     GridTerminalSystem.GetBlocksOfType(gyros);
  152.     GridTerminalSystem.GetBlocksOfType(thrust);
  153.     GridTerminalSystem.GetBlocksOfType(remotes);
  154.     GridTerminalSystem.GetBlocksOfType(antennas);
  155.     GridTerminalSystem.GetBlocksOfType(timers);
  156.  
  157.     if (gyros.Count == 0)
  158.     {
  159.         Echo($"Error: No gyros");
  160.         successfulSetup = false;
  161.     }
  162.  
  163.     if (thrust.Count == 0)
  164.     {
  165.         Echo($"Error: No thrust");
  166.         successfulSetup = false;
  167.     }
  168.  
  169.     if (remotes.Count == 0)
  170.     {
  171.         Echo($"Error: No remotes");
  172.         successfulSetup = false;
  173.     }
  174.  
  175.     if (antennas.Count == 0)
  176.     {
  177.         Echo($"Error: No antenna");
  178.         successfulSetup = false;
  179.     }
  180.  
  181.     if (timers.Count == 0)
  182.     {
  183.         Echo($"Error: No timers");
  184.         successfulSetup = false;
  185.     }
  186.  
  187.     if (successfulSetup)
  188.     {
  189.         missileReference = remotes[0];
  190.         GetGyroOrientation(missileReference, gyros);
  191.         GetThrusterOrientation(missileReference, thrust, out forwardThrust, out otherThrust);
  192.  
  193.        
  194.         var myID = Me.EntityId;
  195.         foreach (IMyRadioAntenna thisAntenna in antennas)
  196.         {
  197.             thisAntenna.SetValue("PBList", myID);
  198.             thisAntenna.SetValue("Radius", float.MaxValue);
  199.             thisAntenna.SetValue("EnableBroadCast", true);
  200.             thisAntenna.ApplyAction("OnOff_On");
  201.         }
  202.  
  203.         foreach(IMyThrust thisThrust in otherThrust)
  204.         {
  205.             thisThrust.ApplyAction("OnOff_On");
  206.         }
  207.  
  208.         foreach (IMyThrust thisThrust in forwardThrust)
  209.         {
  210.             thisThrust.ApplyAction("OnOff_On");
  211.             thisThrust.SetValue("Override", float.MaxValue);
  212.         }
  213.        
  214.     }
  215.  
  216.     return successfulSetup;
  217. }
  218.  
  219. void GetThrusterOrientation(IMyRemoteControl refBlock, List<IMyThrust> thrusters, out List<IMyThrust> _forwardThrust, out List<IMyThrust> _otherThrust)
  220. {
  221.     var forwardDirn = refBlock.WorldMatrix.Forward;
  222.  
  223.     _forwardThrust = new List<IMyThrust>();
  224.     _otherThrust = new List<IMyThrust>();
  225.  
  226.     foreach (IMyThrust thisThrust in thrusters)
  227.     {
  228.         var thrustDirn = thisThrust.WorldMatrix.Backward;
  229.         bool sameDirn = thrustDirn == forwardDirn;
  230.  
  231.         if (sameDirn)
  232.         {
  233.             _forwardThrust.Add(thisThrust);
  234.         }
  235.         else
  236.         {
  237.             _otherThrust.Add(thisThrust);
  238.         }
  239.     }
  240. }
  241.  
  242. void GuideMissile(Vector3D targetPos)
  243. {
  244.     missilePos = missileReference.GetPosition();
  245.  
  246.     //---Get orientation vectors of our missile
  247.     Vector3D missileFrontVec = missileReference.WorldMatrix.Forward;
  248.     Vector3D missileLeftVec = missileReference.WorldMatrix.Left;
  249.     Vector3D missileUpVec = missileReference.WorldMatrix.Up;
  250.  
  251.     //---Check if we have gravity
  252.     double rollAngle = 0; double rollSpeed = 0;
  253.  
  254.     var remote = remotes[0] as IMyRemoteControl;
  255.     bool inGravity = false;
  256.  
  257.     gravVec = missileReference.GetNaturalGravity();
  258.     double gravMagSquared = gravVec.LengthSquared();
  259.     if (gravMagSquared != 0)
  260.     {
  261.         if (gravVec.Dot(missileUpVec) < 0)
  262.         {
  263.             rollAngle = Math.PI / 2 - Math.Acos(MathHelper.Clamp(gravVec.Dot(missileLeftVec) / gravVec.Length(), -1, 1));
  264.         }
  265.         else
  266.         {
  267.             rollAngle = Math.PI + Math.Acos(MathHelper.Clamp(gravVec.Dot(missileLeftVec) / gravVec.Length(), -1, 1));
  268.         }
  269.  
  270.         if (firstGuidance) lastRollAngle = rollAngle;
  271.  
  272.         rollSpeed = Math.Round(proportionalConstant * rollAngle + derivativeConstant * (rollAngle - lastRollAngle) * 60, 2);
  273.  
  274.         inGravity = true;
  275.     }
  276.     else
  277.     {
  278.         rollSpeed = 0;
  279.     }
  280.  
  281.     //---Find vector from missile to destinationVec    
  282.     var missileToTargetVec = targetPos - missilePos;                                                                                                                                                                                                                                                                                                     //w.H/i-P*L+a.s^H
  283.  
  284.     //---Get travel vector
  285.     var missileVelocityVec = missileReference.GetShipVelocities().LinearVelocity;
  286.  
  287.     //---Calc our new heading based upon our travel vector    
  288.  
  289.     var headingVec = CalculateHeadingVector(missileToTargetVec, missileVelocityVec, driftCompensation);
  290.    
  291.     //---Get pitch and yaw angles
  292.     double yawAngle; double pitchAngle;
  293.     GetRotationAngles(headingVec, missileFrontVec, missileLeftVec, missileUpVec, out yawAngle, out pitchAngle);
  294.  
  295.     if (firstGuidance)
  296.     {
  297.         lastPitchAngle = pitchAngle;
  298.         lastYawAngle = yawAngle;
  299.         firstGuidance = false;
  300.     }
  301.  
  302.     //---Angle controller
  303.     double yawSpeed = Math.Round(proportionalConstant * yawAngle + derivativeConstant * (yawAngle - lastYawAngle) * 60, 2);
  304.     double pitchSpeed = Math.Round(proportionalConstant * pitchAngle + derivativeConstant * (pitchAngle - lastPitchAngle) * 60, 2);
  305.  
  306.     //---Set appropriate gyro override
  307.     ApplyGyroOverride(pitchSpeed, yawSpeed, rollSpeed, gyros);
  308.  
  309.     //---Store previous values
  310.     lastYawAngle = yawAngle;
  311.     lastPitchAngle = pitchAngle;
  312.     lastRollAngle = rollAngle;
  313.  
  314. }
  315.  
  316. Vector3D CalculateHeadingVector(Vector3D targetVec, Vector3D velocityVec, bool driftComp)
  317. {
  318.     if (!driftComp)
  319.     {
  320.         return targetVec;
  321.     }
  322.  
  323.     if (velocityVec.LengthSquared() < 100)
  324.     {
  325.         return targetVec;
  326.     }
  327.  
  328.     if (targetVec.Dot(velocityVec) > 0)
  329.     {
  330.         return VectorReflection(velocityVec, targetVec);
  331.     }
  332.     else
  333.     {
  334.         return -velocityVec;
  335.     }
  336. }
  337.  
  338. Vector3D VectorProjection(Vector3D a, Vector3D b) //proj a on b    
  339. {
  340.     return a.Dot(b) / b.LengthSquared() * b;
  341. }
  342.  
  343. Vector3D VectorReflection(Vector3D a, Vector3D b) //reflect a over b    
  344. {
  345.     Vector3D project_a = VectorProjection(a, b);
  346.     Vector3D reject_a = a - project_a;
  347.     return project_a - reject_a;
  348. }
  349.  
  350. double VectorAngleBetween(Vector3D a, Vector3D b) //returns radians
  351. {
  352.     if (a.LengthSquared() == 0 || b.LengthSquared() == 0)
  353.         return 0;
  354.     else
  355.         return Math.Acos(MathHelper.Clamp(a.Dot(b) / a.Length() / b.Length(), -1, 1)); //avoids NAN errors
  356. }
  357.  
  358. //Whip's Get Rotation Angles Method v4
  359. void GetRotationAngles(Vector3D v_target, Vector3D v_front, Vector3D v_left, Vector3D v_up, out double yaw, out double pitch)
  360. {
  361.     //Dependencies: VectorProjection() | VectorAngleBetween()
  362.     //Keen uses a stupid left hand rule coordSystem, I dont.
  363.     var projTargetFront = VectorProjection(v_target, v_front);
  364.     var projTargetLeft = VectorProjection(v_target, v_left);
  365.     var projTargetUp = VectorProjection(v_target, v_up);
  366.     var projTargetFrontLeft = projTargetFront + projTargetLeft;
  367.     var projTargetFrontUp = projTargetFront + projTargetUp;
  368.  
  369.     yaw = VectorAngleBetween(v_front, projTargetFrontLeft);
  370.     pitch = VectorAngleBetween(v_front, projTargetFrontUp);
  371.  
  372.     //---Check if yaw angle is left or right  
  373.     //multiplied by -1 to convert from right hand rule to left hand rule
  374.     yaw = -1 * Math.Sign(v_left.Dot(projTargetLeft)) * yaw;
  375.  
  376.     //---Check if pitch angle is up or down    
  377.     pitch = Math.Sign(v_up.Dot(projTargetUp)) * pitch;
  378.  
  379.     //---Check if target vector is pointing opposite the front vector
  380.     if (pitch == 0 && yaw == 0 && v_target.Dot(v_front) < 0)
  381.     {
  382.         yaw = Math.PI;
  383.         pitch = Math.PI;
  384.     }
  385. }
  386.  
  387. //Whip's Gyro Orientation Method
  388. string[] gyroRelativeYaw;
  389. string[] gyroRelativePitch;
  390. string[] gyroRelativeRoll;
  391. int[] gyroYawSign;
  392. int[] gyroPitchSign;
  393. int[] gyroRollSign;
  394.  
  395. void GetGyroOrientation(IMyRemoteControl reference_block, List<IMyGyro> gyro_list)
  396. {
  397.     gyroRelativeYaw = new string[gyro_list.Count];
  398.     gyroRelativePitch = new string[gyro_list.Count];
  399.     gyroRelativeRoll = new string[gyro_list.Count];
  400.  
  401.     gyroYawSign = new int[gyro_list.Count];
  402.     gyroPitchSign = new int[gyro_list.Count];
  403.     gyroRollSign = new int[gyro_list.Count];
  404.  
  405.     var reference_up = reference_block.WorldMatrix.Up; //assuming rot right
  406.     var reference_right = reference_block.WorldMatrix.Right; //assuming rot up
  407.     var reference_forward = reference_block.WorldMatrix.Forward; //assuming rot up
  408.  
  409.     for (int i = 0; i < gyro_list.Count; i++)
  410.     {
  411.         var gyro_forward = gyro_list[i].WorldMatrix.Forward;
  412.         var gyro_backward = gyro_list[i].WorldMatrix.Backward;
  413.         var gyro_up = gyro_list[i].WorldMatrix.Up;
  414.         var gyro_down = gyro_list[i].WorldMatrix.Down;
  415.         var gyro_left = gyro_list[i].WorldMatrix.Left;
  416.         var gyro_right = gyro_list[i].WorldMatrix.Right;
  417.  
  418.         /// Pitch Fields ///    
  419.         if (reference_right == gyro_forward)
  420.         {
  421.             gyroRelativePitch[i] = "Roll";
  422.             gyroPitchSign[i] = 1;
  423.         }
  424.         else if (reference_right == gyro_backward)
  425.         {
  426.             gyroRelativePitch[i] = "Roll";
  427.             gyroPitchSign[i] = -1;
  428.         }
  429.         else if (reference_right == gyro_right)
  430.         {
  431.             gyroRelativePitch[i] = "Pitch";
  432.             gyroPitchSign[i] = 1;
  433.         }
  434.         else if (reference_right == gyro_left)
  435.         {
  436.             gyroRelativePitch[i] = "Pitch";
  437.             gyroPitchSign[i] = -1;
  438.         }
  439.         else if (reference_right == gyro_up)
  440.         {
  441.             gyroRelativePitch[i] = "Yaw";
  442.             gyroPitchSign[i] = -1;
  443.         }
  444.         else if (reference_right == gyro_down)
  445.         {
  446.             gyroRelativePitch[i] = "Yaw";
  447.             gyroPitchSign[i] = 1;
  448.         }
  449.  
  450.         /// Yaw Fields ///
  451.         if (reference_up == gyro_forward)
  452.         {
  453.             gyroRelativeYaw[i] = "Roll";
  454.             gyroYawSign[i] = -1;
  455.         }
  456.         else if (reference_up == gyro_backward)
  457.         {
  458.             gyroRelativeYaw[i] = "Roll";
  459.             gyroYawSign[i] = 1;
  460.         }
  461.         else if (reference_up == gyro_right)
  462.         {
  463.             gyroRelativeYaw[i] = "Pitch";
  464.             gyroYawSign[i] = -1;
  465.         }
  466.         else if (reference_up == gyro_left)
  467.         {
  468.             gyroRelativeYaw[i] = "Pitch";
  469.             gyroYawSign[i] = 1;
  470.         }
  471.         else if (reference_up == gyro_up)
  472.         {
  473.             gyroRelativeYaw[i] = "Yaw";
  474.             gyroYawSign[i] = 1;
  475.         }
  476.         else if (reference_up == gyro_down)
  477.         {
  478.             gyroRelativeYaw[i] = "Yaw";
  479.             gyroYawSign[i] = -1;
  480.         }
  481.  
  482.         /// Roll Fields ///
  483.         if (reference_forward == gyro_forward)
  484.         {
  485.             gyroRelativeRoll[i] = "Roll";
  486.             gyroRollSign[i] = 1;
  487.         }
  488.         else if (reference_forward == gyro_backward)
  489.         {
  490.             gyroRelativeRoll[i] = "Roll";
  491.             gyroRollSign[i] = -1;
  492.         }
  493.         else if (reference_forward == gyro_right)
  494.         {
  495.             gyroRelativeRoll[i] = "Pitch";
  496.             gyroRollSign[i] = 1;
  497.         }
  498.         else if (reference_forward == gyro_left)
  499.         {
  500.             gyroRelativeRoll[i] = "Pitch";
  501.             gyroRollSign[i] = -1;
  502.         }
  503.         else if (reference_forward == gyro_up)
  504.         {
  505.             gyroRelativeRoll[i] = "Yaw";
  506.             gyroRollSign[i] = -1;
  507.         }
  508.         else if (reference_forward == gyro_down)
  509.         {
  510.             gyroRelativeRoll[i] = "Yaw";
  511.             gyroRollSign[i] = 1;
  512.         }
  513.     }
  514. }
  515.  
  516. void ApplyGyroOverride(double pitch_speed, double yaw_speed, double roll_speed, List<IMyGyro> gyro_list)
  517. {
  518.     for (int i = 0; i < gyro_list.Count; i++)
  519.     {
  520.         var thisGyro = gyro_list[i];
  521.         if (thisGyro != null)
  522.         {
  523.             thisGyro.SetValue<float>(gyroRelativeYaw[i], (float)yaw_speed * gyroYawSign[i]);
  524.             thisGyro.SetValue<float>(gyroRelativePitch[i], (float)pitch_speed * gyroPitchSign[i]);
  525.             thisGyro.SetValue<float>(gyroRelativeRoll[i], (float)roll_speed * gyroRollSign[i]);
  526.             thisGyro.SetValue("Override", true);
  527.         }
  528.     }
  529. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement