TIMAS_Bro

Untitled

May 3rd, 2026 (edited)
48
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.01 KB | None | 0 0
  1. local nav = peripheral.wrap("left")
  2. local vel = peripheral.wrap("right")
  3.  
  4. -- toggle TOP = stop LEFT rotor = ship turns LEFT (right rotor pushes)
  5. -- toggle FRONT = stop RIGHT rotor = ship turns RIGHT (left rotor pushes)
  6. local LEFT_STOP = "top"
  7. local RIGHT_STOP = "front"
  8.  
  9. local TURN_THRESHOLD = 10
  10. local STOP_DIST = 10
  11.  
  12. local sx, sz = 0, 0
  13. local tx, tz = 0, 0
  14. local heading = 0
  15. local speed = 0
  16. local forceMode = nil
  17. local statusText = "Flying"
  18. local arrived = false
  19. local angleLocked = false
  20. local logs = {}
  21. local fixedBearing = 0
  22. local totalDist = 0
  23. local elapsed = 0
  24.  
  25. local W, H = term.getSize()
  26. local MAX_LOGS = H - 11
  27.  
  28. local function turnLeft() rs.setOutput(LEFT_STOP, true) rs.setOutput(RIGHT_STOP, false) end
  29. local function turnRight() rs.setOutput(LEFT_STOP, false) rs.setOutput(RIGHT_STOP, true) end
  30. local function flyForward() rs.setOutput(LEFT_STOP, false) rs.setOutput(RIGHT_STOP, false) end
  31. local function stopAll() rs.setOutput(LEFT_STOP, true) rs.setOutput(RIGHT_STOP, true) end
  32.  
  33. local function normAngle(a)
  34. a = a % 360
  35. if a > 180 then a = a - 360 end
  36. return a
  37. end
  38.  
  39. -- compass: 0=South, 90=West, 180=North, 270=East
  40. local function calcBearing(x1, z1, x2, z2)
  41. local dx = x2 - x1
  42. local dz = z2 - z1
  43. return (math.deg(math.atan2(-dx, dz)) + 360) % 360
  44. end
  45.  
  46. local function dist(x1, z1, x2, z2)
  47. return math.sqrt((x2-x1)^2 + (z2-z1)^2)
  48. end
  49.  
  50. local function addLog(msg)
  51. table.insert(logs, os.date("%H:%M:%S") .. " " .. msg)
  52. if #logs > MAX_LOGS then table.remove(logs, 1) end
  53. end
  54.  
  55. local function drawUI()
  56. term.clear()
  57. term.setCursorPos(1, 1)
  58. term.setBackgroundColor(colors.blue)
  59. term.setTextColor(colors.white)
  60. term.clearLine()
  61. term.write(" Aeronautics Autopilot")
  62. term.setBackgroundColor(colors.black)
  63.  
  64. local progress = totalDist > 0 and math.min(1, elapsed / totalDist) or 0
  65. local barW = W - 12
  66. local filled = math.floor(progress * barW)
  67. local distLeft = math.max(0, totalDist - elapsed)
  68. local err = normAngle(fixedBearing - heading)
  69.  
  70. term.setTextColor(colors.white)
  71. term.setCursorPos(1, 2)
  72. term.write(string.format(" Elapsed %-8.1f blk Hdg: %-6.1f", elapsed, heading))
  73. term.setCursorPos(1, 3)
  74. term.write(string.format(" Remain %-8.1f blk Brg: %-6.1f", distLeft, fixedBearing))
  75. term.setCursorPos(1, 4)
  76. term.write(string.format(" Total %-8.1f blk Err: %-+6.1f", totalDist, err))
  77. term.setCursorPos(1, 5)
  78. term.write(string.format(" Speed %-8.2f b/s", speed))
  79.  
  80. term.setCursorPos(1, 6)
  81. term.setTextColor(colors.gray)
  82. term.write(" Prog [")
  83. term.setTextColor(colors.lime)
  84. term.write(string.rep("=", filled))
  85. term.setTextColor(colors.gray)
  86. term.write(string.rep("-", barW - filled))
  87. term.write("] ")
  88. term.setTextColor(colors.white)
  89. term.write(string.format("%.0f%%", progress * 100))
  90.  
  91. term.setCursorPos(1, 7)
  92. local modeStr, modeCol
  93. if forceMode then
  94. modeStr = "MANUAL: " .. forceMode
  95. modeCol = colors.orange
  96. elseif arrived then
  97. modeStr = "ARRIVED"
  98. modeCol = colors.lime
  99. elseif angleLocked then
  100. modeStr = "LOCKED: Flying straight"
  101. modeCol = colors.cyan
  102. else
  103. modeStr = "AUTO: " .. statusText
  104. modeCol = colors.green
  105. end
  106. term.setTextColor(modeCol)
  107. term.write(" " .. modeStr)
  108. term.setTextColor(colors.white)
  109.  
  110. term.setCursorPos(1, 8)
  111. term.setTextColor(colors.gray)
  112. term.write(string.rep("-", W))
  113.  
  114. term.setTextColor(colors.lightGray)
  115. for i, log in ipairs(logs) do
  116. term.setCursorPos(1, 8 + i)
  117. term.write((" " .. log):sub(1, W))
  118. end
  119.  
  120. term.setCursorPos(1, H - 1)
  121. term.setTextColor(colors.gray)
  122. term.write(string.rep("-", W))
  123. term.setCursorPos(1, H)
  124. term.setTextColor(colors.yellow)
  125. term.write("[F]wd [L]ft [R]ght [S]top [A]uto [K]lock [Q]uit")
  126. term.setTextColor(colors.white)
  127. end
  128.  
  129. local function correctHeading()
  130. local err = normAngle(fixedBearing - heading)
  131. if math.abs(err) < TURN_THRESHOLD then return end
  132.  
  133. local goRight = err > 0
  134. local dir = goRight and "Right" or "Left"
  135. addLog(string.format("Turning %s (hdg=%.1f err=%.1f)", dir, heading, err))
  136.  
  137. if goRight then turnRight() else turnLeft() end
  138.  
  139. while true do
  140. sleep(0.1)
  141. heading = nav.getRelativeAngle()
  142. speed = vel.getVelocity()
  143. elapsed = elapsed + speed * 0.1
  144. statusText = string.format("Turning %s hdg=%.1f", dir, heading)
  145. drawUI()
  146.  
  147. local newErr = normAngle(fixedBearing - heading)
  148.  
  149. -- Stop early — ship coasts ~25 degrees after motor cut
  150. local stopEarly = TURN_THRESHOLD + 25
  151. if math.abs(newErr) < stopEarly then
  152. stopAll()
  153. addLog(string.format("Motor cut at hdg=%.1f err=%.1f (coasting...)", heading, newErr))
  154. sleep(3.0)
  155. heading = nav.getRelativeAngle()
  156. local finalErr = normAngle(fixedBearing - heading)
  157. addLog(string.format("Coasted to hdg=%.1f err=%.1f", heading, finalErr))
  158. -- If still off after coasting, correctHeading will be called again by flightLoop
  159. return
  160. end
  161.  
  162. -- Overshot: sign flipped well past threshold
  163. local overshot = (goRight and newErr < -stopEarly) or
  164. (not goRight and newErr > stopEarly)
  165. if overshot then
  166. stopAll()
  167. addLog(string.format("Overshot! hdg=%.1f err=%.1f — correcting...", heading, newErr))
  168. sleep(3.0)
  169. heading = nav.getRelativeAngle()
  170. correctHeading()
  171. return
  172. end
  173. end
  174. end
  175.  
  176. local function inputLoop()
  177. while not arrived do
  178. local _, key = os.pullEvent("key")
  179. if key == keys.f then
  180. forceMode = "FORWARD"
  181. angleLocked = false
  182. flyForward()
  183. addLog("Manual: Forward")
  184. elseif key == keys.l then
  185. forceMode = "LEFT"
  186. angleLocked = false
  187. turnLeft()
  188. addLog("Manual: Turn Left")
  189. elseif key == keys.r then
  190. forceMode = "RIGHT"
  191. angleLocked = false
  192. turnRight()
  193. addLog("Manual: Turn Right")
  194. elseif key == keys.s then
  195. forceMode = "STOP"
  196. angleLocked = false
  197. stopAll()
  198. addLog("Manual: Stop")
  199. elseif key == keys.a then
  200. forceMode = nil
  201. angleLocked = false
  202. addLog("Resumed auto")
  203. elseif key == keys.k then
  204. forceMode = nil
  205. angleLocked = not angleLocked
  206. if angleLocked then
  207. flyForward()
  208. addLog(string.format("Angle locked at hdg=%.1f", heading))
  209. else
  210. addLog("Angle lock released, resuming auto")
  211. end
  212. elseif key == keys.q then
  213. stopAll()
  214. addLog("Aborted by user")
  215. arrived = true
  216. end
  217. drawUI()
  218. end
  219. end
  220.  
  221. local function flightLoop()
  222. local lastT = os.clock()
  223.  
  224. while not arrived do
  225. local now = os.clock()
  226. local dt = now - lastT
  227. lastT = now
  228.  
  229. heading = nav.getRelativeAngle()
  230. speed = vel.getVelocity()
  231. elapsed = elapsed + speed * dt
  232.  
  233. if elapsed >= totalDist - STOP_DIST then
  234. stopAll()
  235. statusText = "Arrived"
  236. addLog(string.format("Arrived! Flew %.1f blk", elapsed))
  237. arrived = true
  238. drawUI()
  239. break
  240. end
  241.  
  242. if not forceMode then
  243. if angleLocked then
  244. flyForward()
  245. statusText = "Locked"
  246. else
  247. local err = normAngle(fixedBearing - heading)
  248. if math.abs(err) < TURN_THRESHOLD then
  249. flyForward()
  250. statusText = "Forward"
  251. else
  252. stopAll()
  253. sleep(0.5)
  254. heading = nav.getRelativeAngle()
  255. correctHeading()
  256. end
  257. end
  258. end
  259.  
  260. drawUI()
  261. sleep(0.1)
  262. end
  263. end
  264.  
  265. -- Setup
  266. term.clear()
  267. term.setCursorPos(1, 1)
  268. print("=== Aeronautics Autopilot ===")
  269. print("Compass: 0=South 90=West 180=North 270=East")
  270. print("")
  271. io.write("Start X: ") sx = tonumber(io.read())
  272. io.write("Start Z: ") sz = tonumber(io.read())
  273. io.write("Target X: ") tx = tonumber(io.read())
  274. io.write("Target Z: ") tz = tonumber(io.read())
  275.  
  276. fixedBearing = calcBearing(sx, sz, tx, tz)
  277. totalDist = dist(sx, sz, tx, tz)
  278.  
  279. addLog(string.format("Route: (%d,%d) -> (%d,%d) %.1f blk", sx, sz, tx, tz, totalDist))
  280. addLog(string.format("Bearing: %.1f Current hdg: %.1f", fixedBearing, nav.getRelativeAngle()))
  281.  
  282. parallel.waitForAny(flightLoop, inputLoop)
  283.  
  284. sleep(2)
  285. term.clear()
  286. term.setCursorPos(1, 1)
  287. print("Autopilot ended.")
Advertisement
Add Comment
Please, Sign In to add comment