Advertisement
Feliiiiip

CBC Pitch Calculator

May 7th, 2024 (edited)
752
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.14 KB | Source Code | 0 0
  1. --[[
  2.     Create: Big Cannons pitch calculation code using Newton's Method
  3.     Author: Lugia831999
  4.  ]]
  5.  
  6. -- Variables
  7. local pitch_range = { min = -30, max = 60 }
  8. local num_charges = 4 -- Number of charges
  9. local length = 8      -- Length of cannon
  10. local step_size = 75  -- Step size for Newton's Method
  11.  
  12. -- Constants
  13. local D = 0.99
  14. local G = -0.05
  15. local K = 0.5 * (D + 1)
  16. local L = 0.5 * G * D
  17. local M = (G * D) / (D - 1)
  18. local vel = 2 * num_charges
  19.  
  20.  
  21. --[[
  22.     Function to calculate the cannon's target pitch using Newton's Method
  23.  
  24.     raw_dx - Horizontal distance between cannon pivot point and target point
  25.     raw_dy - Vertical distance between cannon pivot and target point
  26.  ]]
  27. function calculate_pitch(raw_dx, raw_dy)
  28.     local pitch, new_pitch, F_val
  29.     local pitch_limit = math.deg(math.acos( raw_dx / ( K*vel*(D / (1 - D) + 1) + length ) )) - 0.001
  30.     local min_pitch = math.max(pitch_range.min, -pitch_limit)
  31.     local max_pitch = math.min(pitch_range.max, pitch_limit)
  32.  
  33.     local best = { pitch = 0, diff = math.huge }
  34.    
  35.     -- Try max pitch first
  36.     pitch = max_pitch
  37.     F_val, new_pitch = F(pitch, raw_dx, raw_dy, min_pitch, max_pitch)
  38.     if math.abs(F_val) < best.diff then best.pitch = pitch; best.diff = math.abs(F_val) end
  39.  
  40.     -- If too high, try min pitch next
  41.     if F_val > 0 then
  42.         pitch = min_pitch
  43.         F_val, new_pitch = F(pitch, raw_dx, raw_dy, min_pitch, max_pitch)
  44.         if math.abs(F_val) < best.diff then best.pitch = pitch; best.diff = math.abs(F_val) end
  45.  
  46.         -- If still not good, then return the pitch with best diff
  47.         if F_val > 0 then
  48.             return best.pitch
  49.         end
  50.     end
  51.  
  52.     -- Execute Newton's Method iterations
  53.     for i = 1, 50 do
  54.         pitch = new_pitch
  55.         F_val, new_pitch = F(pitch, raw_dx, raw_dy, min_pitch, max_pitch)
  56.         if math.abs(F_val) < best.diff then best.pitch = pitch; best.diff = math.abs(F_val) end
  57.  
  58.         if math.abs(pitch - new_pitch) < 1e-6 then break end
  59.     end
  60.  
  61.     return best.pitch
  62. end
  63.  
  64.  
  65. --[[
  66.     The meat and potatoes of the pitch calculation.
  67.     Calculates the vertical difference between the target point and the projectile given the pitch `pitch_deg`.
  68.     Refer to this Desmos graph for a clearer view of the function and more details: https://www.desmos.com/calculator/1xzyp2f2bp
  69.  ]]
  70. function F(pitch_deg, raw_dx, raw_dy, min_pitch, max_pitch)
  71.     local pitch = math.rad(pitch_deg)
  72.     local sin_p = math.sin(pitch)
  73.     local cos_p = math.cos(pitch)
  74.     local dx = raw_dx - length * cos_p
  75.     local dy = raw_dy - length * sin_p
  76.  
  77.     local inner_log = ((D - 1) / D) * ((dx / (K*vel*cos_p)) - 1) + 1
  78.     local t = math.log( inner_log, D ) + 1
  79.     local F_val = (L - K*M)*t + ( sin_p + M/vel )*( dx/cos_p ) - dy
  80.     local dF = ( ( -G / (K * inner_log * math.log(D)) + M) * (sin_p / vel) + 1 ) * raw_dx / cos_p^2
  81.  
  82.     local new_pitch = pitch_deg - step_size * (F_val / dF)
  83.     new_pitch = math.min(math.max(new_pitch, min_pitch), max_pitch)
  84.  
  85.     return F_val, new_pitch
  86. end
  87.  
  88.  
  89. local args = {...}
  90. if #args == 2 then
  91.     local pitch = calculate_pitch(args[1], args[2])
  92.     print("Target pitch:", pitch)
  93. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement