Advertisement
Madwand

Spinner and engine identification lua code, version 3.0

Sep 15th, 2015
804
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.83 KB | None | 0 0
  1. --[[
  2. Spinner and engine index identification, version 3.0
  3. Created by Madwand 9/23/2015
  4. This code will help you discover the indices of spinners and
  5. propulsion on your aircraft, for use with the "VTSpinners",
  6. "VTOLSpinners", and "VTOLEngines" settings for the advanced
  7. aerial AI.
  8. Note that the potential pitch and roll engines identified
  9. do not include any on spin blocks, which must be identified
  10. with the "VTOLSpinners" setting.
  11. The potential spinner and engine reports are just there so you
  12. know which spinners/engines may end up used for what purpose.
  13. The engine/spinner index identified is what is important.
  14. --]]
  15.  
  16.  
  17. RollSpinners = {}
  18. PitchSpinners = {}
  19. YawSpinners = {}
  20. AllSpinners = {}
  21. RollEngines = {}
  22. PitchEngines = {}
  23. SpinnerStartRotations={}
  24. firstpass = true
  25.  
  26. function Update(I)
  27.   CoM = I:GetConstructCenterOfMass()
  28.   ForwardV = I:GetConstructForwardVector()
  29.   if firstpass then
  30.     firstpass = false
  31.     for p = 0, I:GetSpinnerCount() - 1 do
  32.       ClassifySpinner(I,p)
  33.     end
  34.     PrintList(I,'Potential roll spinners',RollSpinners)
  35.     PrintList(I,'Potential pitch spinners',PitchSpinners)
  36.     PrintList(I,'Potential yaw spinners',YawSpinners)
  37.     for p = 0, I:Component_GetCount(9) - 1 do
  38.       ClassifyEngine(I,p,false)
  39.     end
  40.     PrintList(I,"Potential roll engines",RollEngines)
  41.     PrintList(I,"Potential pitch engines",PitchEngines)
  42.   end
  43. end
  44.  
  45. function ClassifySpinner(I,p)
  46.   local info = I:GetSpinnerInfo(p)
  47.   local h,a,b = EulerAngles(info.LocalRotation)
  48.   local pos = info.LocalPositionRelativeToCom
  49.   SpinnerStartRotations[p]=info.LocalRotation
  50.   a=math.floor(a+.5)
  51.   b=math.floor(b+.5)
  52.   I:Log(string.format("Spinner index: %d Orientation: (%.2f, %.2f, %.2f) Position: (%.2f, %.2f, %.2f)", p, h, a, b, pos.x, pos.y, pos.z))
  53.   if (a==0 and b==0) then
  54.     tinsert(pos.z,YawSpinners,1,-1,p)
  55.     table.insert(AllSpinners,p)
  56.   elseif (a==0 and math.abs(b)>170) then
  57.     tinsert(pos.z,YawSpinners,-1,1,p)
  58.     table.insert(AllSpinners,p)
  59.   else
  60.     local h,a,b = EulerAngles(info.LocalRotation*Quaternion.Euler(0, 0, 90))
  61.     h=math.floor(h+.5)
  62.     a=math.floor(a+.5)
  63.     if (h==0 and a==0) then -- pointed right
  64.       tinsert(pos.z,PitchSpinners,1,-1,p)
  65.       if VTOLSpinners=='all' then tinsert(pos.z,DownSpinners,-1,-1,p) end
  66.       if pos.x<-1 then  -- on left
  67.         tinsert(pos.z,RollSpinners,-1,-1,p)
  68.       elseif pos.x>1 then -- on right
  69.         tinsert(pos.z,RollSpinners,1,1,p)
  70.       end
  71.       table.insert(AllSpinners,p)
  72.     elseif (a==0 and math.abs(h)>170) then -- pointed left
  73.       tinsert(pos.z,PitchSpinners,-1,1,p)
  74.       if VTOLSpinners=='all' then tinsert(pos.z,DownSpinners,1,1,p) end
  75.       if pos.x<-1 then -- on left
  76.         tinsert(pos.z,RollSpinners,1,1,p)
  77.       elseif pos.x>1 then -- on right
  78.         tinsert(pos.z,RollSpinners,-1,-1,p)
  79.       end
  80.       table.insert(AllSpinners,p)
  81.     end
  82.   end
  83. end
  84.  
  85. function GetPosRelativeToCoM(pos)
  86.   local rot = Quaternion.Inverse(Quaternion.LookRotation(ForwardV))
  87.   local rpos = rot*(pos-CoM)
  88.   for i, p in ipairs(rpos) do rpos[i]=math.floor(p*10+.5)/10 end
  89.   return rpos
  90. end
  91.  
  92. function ClassifyEngine(I,p,force)
  93.   local info = I:Component_GetBlockInfo(9,p)
  94.   local h,a,b = EulerAngles(info.LocalRotation)
  95.   local rot = Quaternion.Inverse(Quaternion.LookRotation(I:GetConstructForwardVector()))
  96.   local pos = GetPosRelativeToCoM(info.Position)
  97.   df = I:Component_GetFloatLogic(9,p)
  98.   I:Log(string.format("Engine index: %d  Drive fraction: %.02f Orientation: (%.2f, %.2f, %.2f) Position: (%f, %f, %f)", p, df, h, a, b, pos.x, pos.y, pos.z))
  99.   if (force or math.floor(b+.5)==-90) then
  100.     tinsert(pos.z,PitchEngines,1,-1,p)
  101.     if pos.x<-1.1 then  -- on left
  102.       tinsert(pos.z,RollEngines,-1,-1,p)
  103.     elseif pos.x>1.1 then -- on right
  104.       tinsert(pos.z,RollEngines,1,1,p)
  105.     end
  106.   end
  107. end
  108.  
  109. function tinsert(z,s,x,y,p)
  110.   s[p] = z>0 and x or y
  111. end
  112.  
  113. function PrintList(I, name, list)
  114.   str = name..': '
  115.   for i,v in pairs(list) do
  116.     str = str..string.format("%d ", i)
  117.   end
  118.   I:Log(str)
  119. end
  120.  
  121. function EulerAngles(q1)
  122.   local sqw = q1.w*q1.w
  123.   local sqx = q1.x*q1.x
  124.   local sqy = q1.y*q1.y
  125.   local sqz = q1.z*q1.z
  126.   local unit = sqx + sqy + sqz + sqw --if normalised is one, otherwise is correction factor
  127.   local test = q1.x*q1.y + q1.z*q1.w
  128.   local heading, attitude, bank
  129.   if (test > 0.499*unit) then --singularity at north pole
  130.     heading = 2 * math.atan2(q1.x,q1.w)
  131.     attitude = math.pi/2;
  132.     bank = 0
  133.   elseif (test < -0.499*unit) then --singularity at south pole
  134.     heading = -2 * math.atan2(q1.x,q1.w)
  135.     attitude = -math.pi/2
  136.     bank = 0
  137.   else
  138.     heading = math.atan2(2*q1.y*q1.w-2*q1.x*q1.z , sqx - sqy - sqz + sqw)
  139.     attitude = math.asin(2*test/unit)
  140.     bank = math.atan2(2*q1.x*q1.w-2*q1.y*q1.z , -sqx + sqy - sqz + sqw)
  141.   end
  142.   return math.deg(heading), math.deg(attitude), math.deg(bank)
  143. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement