Advertisement
plaYer2k

Space Engineers - Ackermann Steering - Suspension Controller

Nov 9th, 2015
6,546
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.04 KB | None | 0 0
  1. WheelController wheelController;
  2. static MyGridProgram GP;
  3.  
  4. const bool debug = true;
  5.  
  6. void Main(string arg)
  7. {
  8.     if(wheelController == null || arg == "reset")
  9.     {
  10.         if(debug)
  11.             GP = this;
  12.         List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>();
  13.         GridTerminalSystem.GetBlocksOfType<IMyRemoteControl>(blocks);
  14.         List<IMyTerminalBlock> wheels = new List<IMyTerminalBlock>();
  15.         GridTerminalSystem.GetBlocksOfType<IMyMotorSuspension>(wheels);
  16.  
  17.         // Lets initialize an example wheel controller
  18.         wheelController = new WheelController(
  19.                 blocks.Count == 0 ? Me : blocks[0],
  20.                 wheels,
  21.                 3f,
  22.                 1f,
  23.                 new Vector3D(0, 0, 0)
  24.             );
  25.     }
  26.     wheelController.Update();
  27. }
  28.  
  29. public class WheelController
  30. {
  31.     static readonly Dictionary<string, Vector3D> WheelOffsetLookup = new Dictionary<string, Vector3D>
  32.         {
  33.             { "Large", new Vector3D(0, 0, -3.1) },
  34.             { "Small", new Vector3D(0, 0, -0.6) }
  35.         };
  36.  
  37.     List<Wheel> Wheels = new List<Wheel>();
  38.     IMyTerminalBlock Anchor;
  39.     Vector3D AnchorOffset;
  40.     float SteerSpeedFactor;
  41.     float ReturnSpeedFactor;
  42.  
  43.     /*
  44.         @anchor - The anchor block which gets used as reference for position and orientation.
  45.         @wheels - The list of wheels with which we have to work.
  46.         @steerSpeedFactor - This is a proportional factor for total steer speed over the max angle.
  47.         @returnSpeedFactor - This is a proportional factor for total return speed over the max angle.
  48.         @offset - The additional offset in forward and right direction.
  49.     */
  50.     public WheelController(IMyTerminalBlock anchor, List<IMyTerminalBlock> wheels, float steerSpeedFactor, float steerReturnFactor, Vector3D offset)
  51.     {
  52.         Wheels.Clear();
  53.         Anchor = anchor;
  54.         AnchorOffset = offset;
  55.         Vector3D center = Anchor.GetPosition();
  56.         MatrixD anchorMatrixInv = MatrixD.Invert(Anchor.WorldMatrix);
  57.  
  58.         SteerSpeedFactor = steerSpeedFactor;
  59.         ReturnSpeedFactor = steerReturnFactor;
  60.  
  61.         double FocusLeft = double.MaxValue;
  62.         double FocusRight = double.MinValue;
  63.  
  64.         bool hasDestoryedWheels = false;
  65.  
  66.         for(int i = 0; i < wheels.Count; i++)
  67.         {
  68.             // Check if the wheel actually is a suspension wheel.
  69.             IMyMotorSuspension wheel = wheels[i] as IMyMotorSuspension;
  70.             if(wheel == null)
  71.                 continue;
  72.  
  73.             // Get the transformed local matrix in respect to the new anchor with offset.
  74.             MatrixD wheelMatrix = wheel.WorldMatrix * anchorMatrixInv;
  75.             wheelMatrix.Translation += AnchorOffset;
  76.  
  77.             MatrixD wheelMatrixInv = wheelMatrix;
  78.             wheelMatrixInv.Translation = new Vector3D(0,0,0);
  79.             wheelMatrixInv = MatrixD.Invert(wheelMatrixInv);
  80.             Vector3D wheelOffset = WheelOffsetLookup.ContainsKey(wheel.BlockDefinition.SubtypeId) ?
  81.                 WheelOffsetLookup[wheel.BlockDefinition.SubtypeId] : WheelOffsetLookup[wheel.CubeGrid.GridSizeEnum.ToString()];
  82.             wheelOffset = Vector3D.Transform(wheelOffset, wheelMatrixInv);
  83.             wheelMatrix.Translation += wheelOffset;
  84.  
  85.             float maxSteerAngle = wheel.GetMaximum<float>("MaxSteerAngle");
  86.             if(wheel.CustomName.Contains("MaxSteerAngle="))
  87.             {
  88.                 string[] split = wheel.CustomName.Split(' ');
  89.                 for(int j = 0; j < split.Length; j++)
  90.                 {
  91.                     if(!split[j].StartsWith("MaxSteerAngle="))
  92.                         continue;
  93.                     string angleString = split[j].Replace("MaxSteerAngle=","");
  94.                     float angle = 0;
  95.                     bool isDegree = split[j].EndsWith("°");
  96.                     if(isDegree)
  97.                         split[j] = split[j].Replace("°","");
  98.                     if(!float.TryParse(angleString, out angle))
  99.                         continue;
  100.                     if(isDegree)
  101.                         angle = VRageMath.MathHelper.ToRadians(angle);
  102.                     if(angle < 0)
  103.                         angle *= -1;
  104.                     if(angle < maxSteerAngle)
  105.                         maxSteerAngle = angle;
  106.                 }
  107.             }
  108.             double Z = wheelMatrix.Translation.GetDim(2);
  109.             double tan = Math.Tan(maxSteerAngle);
  110.             double deltaX = Math.Abs(Z / tan);
  111.             double X = wheelMatrix.Translation.GetDim(0);
  112.             double CurrentFocusLeft = X - deltaX;
  113.             double CurrentFocusRight = X + deltaX;
  114.             //DEBUG
  115.             if(false && debug)
  116.                 GP.Echo(string.Format("> {0}\nX:{1:0.00} - Z:{2:0.00}", wheel.CustomName, wheelMatrix.Translation.GetDim(0),wheelMatrix.Translation.GetDim(2)));
  117.                 //GP.Echo(string.Format("> {0}\nX:{3} - Z\nangle: {4:0.000} - tan: {5:0.000}\n{1}:{2}",wheel.CustomName, CurrentFocusLeft, CurrentFocusRight,X,Z,maxSteerAngle,tan));
  118.             if(CurrentFocusLeft < FocusLeft)
  119.                 FocusLeft = CurrentFocusLeft;
  120.             if(CurrentFocusRight > FocusRight)
  121.                 FocusRight = CurrentFocusRight;
  122.  
  123.             // Add the new wheel with parameters to the list of wheels.
  124.             Wheels.Add(new Wheel(
  125.                     wheel,
  126.                     wheelMatrix,
  127.                     maxSteerAngle
  128.                 ));
  129.         }
  130.         for(int i = 0; i < Wheels.Count; i++)
  131.         {
  132.             Wheels[i].SetFocus((float)FocusLeft, (float)FocusRight, SteerSpeedFactor, ReturnSpeedFactor);
  133.         }
  134.     }
  135.  
  136.     public void Update()
  137.     {
  138.         Wheels.RemoveAll(x => !x.IsFunctional());
  139.         for(int i = 0; i < Wheels.Count; i++)
  140.         {
  141.             Wheels[i].Update();
  142.         }
  143.     }
  144.    
  145.     public class Wheel
  146.     {
  147.         IMyMotorSuspension Block;
  148.         float AngleLeft;
  149.         float AngleRight;
  150.         float AngleMax;
  151.         MatrixD MatrixLocal;
  152.         MatrixD MatrixLocalInv;
  153.         float SteerSpeedLeft, SteerSpeedRight;
  154.         float ReturnSpeedLeft, ReturnSpeedRight;
  155.         float LastAngle;
  156.         float LastDirection;
  157.  
  158.         public Wheel(IMyMotorSuspension block, MatrixD matrix, float angleMax)
  159.         {
  160.             Block = block;
  161.             MatrixLocal = matrix;
  162.             AngleMax = angleMax;
  163.         }
  164.  
  165.         public bool BlockExists()
  166.         {
  167.             return Block != null;
  168.         }
  169.  
  170.         public bool IsFunctional()
  171.         {
  172.             return Block.IsFunctional;
  173.         }
  174.  
  175.         public bool IsWorking()
  176.         {
  177.             return Block.IsWorking;
  178.         }
  179.  
  180.         public bool Update()
  181.         {
  182.             if(!Block.IsWorking)
  183.                 return false;
  184.  
  185.             if(Block.SteerAngle < -0.001f)
  186.             {
  187.                 if(Block.MaxSteerAngle != AngleLeft)
  188.                     Block.SetValue<float>("MaxSteerAngle", AngleLeft);
  189.                 if(Block.SteerSpeed != SteerSpeedLeft)
  190.                     Block.SetValue<float>("SteerSpeed", SteerSpeedLeft);
  191.                 if(Block.SteerReturnSpeed != ReturnSpeedLeft)
  192.                     Block.SetValue<float>("SteerReturnSpeed", ReturnSpeedLeft);
  193.             }
  194.             else if(Block.SteerAngle > 0.001f)
  195.             {
  196.                 if(Block.MaxSteerAngle != AngleRight)
  197.                     Block.SetValue<float>("MaxSteerAngle", AngleRight);
  198.                 if(Block.SteerSpeed != SteerSpeedRight)
  199.                     Block.SetValue<float>("SteerSpeed", SteerSpeedRight);
  200.                 if(Block.SteerReturnSpeed != ReturnSpeedRight)
  201.                     Block.SetValue<float>("SteerReturnSpeed", ReturnSpeedRight);
  202.             }
  203.             float CurrentAngle = Block.SteerAngle;
  204.             float CurrentDirection = CurrentAngle - LastAngle;
  205.  
  206.             // Final sets for the next run.
  207.             LastAngle = CurrentAngle;
  208.             LastDirection = CurrentDirection;
  209.             return true;
  210.         }
  211.  
  212.         public void SetFocus(float focusLeft, float focusRight, float steerSpeedFactor, float returnSpeedFactor)
  213.         {
  214.             float X = (float)MatrixLocal.Translation.GetDim(0);
  215.             float Z = (float)MatrixLocal.Translation.GetDim(2);
  216.             AngleLeft = (float)Math.Abs(Math.Atan(Z/((Z > 0 ? focusLeft : focusRight ) - X)));
  217.             AngleRight = (float)Math.Abs(Math.Atan(Z/((Z > 0 ? focusRight : focusLeft ) - X)));
  218.             SteerSpeedLeft = AngleLeft * steerSpeedFactor;
  219.             SteerSpeedRight = AngleRight * steerSpeedFactor;
  220.             ReturnSpeedLeft = AngleLeft * returnSpeedFactor;
  221.             ReturnSpeedRight = AngleRight * returnSpeedFactor;
  222.         }
  223.     }
  224. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement