Gazer29

EngineControl

Apr 2nd, 2021 (edited)
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --Automated Cruise Control v2 by Gazer29
  2. --Uses Automation mod version: Beta 1
  3.  
  4. local component = require("component")
  5. local term = require ("term")
  6. local entity = component.entity_link.getAPI("immersiverailroading:locomotivediesel")
  7. local thread = require("thread")
  8. require("PIDController")
  9. local serial = require("serialization")
  10. local fs = require("filesystem")
  11. local glassesTerminal = require("component").glasses
  12. local event = require("event")
  13. local modem = component.modem
  14.  
  15. local ATC = false
  16. local RUNNING = true
  17. local MODE = 0 -- 0 SET, 1 RAMP,
  18. local sleep = 1 -- seconds
  19. local display = false
  20. local iteration = 1
  21. local timer = nil
  22.  
  23. local CONFIG_FILE = "/home/CMD.dat"
  24. local CONFIG = nil
  25. local DEFAULT_CONFIG = {}
  26.  
  27. glassesTerminal.removeAll()
  28. atext = glassesTerminal.addText2D()
  29. atext.setText("ATC: OFF") -- no modifier!
  30. atext.setFontSize(42)
  31. atext.addColor(1, 0, 0, 1)
  32. atext.setCondition(atext.addColor(0, 1, 0, 1), "OVERLAY_ACTIVE", true)
  33.  
  34. btext = glassesTerminal.addText2D()
  35. btext.setText("+10")
  36. btext.setFontSize(60)
  37. btext.addColor(1,0,0,1)
  38. btext.addTranslation(0, 10, 0)
  39. btext.setCondition(btext.addColor(0, 1, 0, 1), "OVERLAY_ACTIVE", true)
  40.  
  41. ctext = glassesTerminal.addText2D()
  42. ctext.setText("-10")
  43. ctext.setFontSize(60)
  44. ctext.addColor(1,0,0,1)
  45. ctext.addTranslation(0,18,0)
  46. ctext.setCondition(ctext.addColor(0, 1, 0, 1), "OVERLAY_ACTIVE", true)
  47.  
  48. local function saveConfig(file, cfg) -- Adapted from HandieAndy's code
  49.   local f = io.open(file, "w")
  50.   if f == nil then error("Couldn't open " .. file .. " to write config.") end
  51.   f:write(serial.serialize(cfg, 100000))
  52.   f:close()
  53.   print("Saved to file: ", CONFIG_FILE)
  54. end
  55.  
  56. local function loadConfig() -- Adapted from HandieAndy's code
  57.   local f = io.open(CONFIG_FILE, "r")
  58.   if f == nil then
  59.     --print("Could not open " .. CONFIG_FILE .. ".")
  60.     --print("Loading default config")
  61.     --saveConfig(CONFIG_FILE, DEFAULT_CONFIG)
  62.     return DEFAULT_CONFIG
  63.     else
  64.     local config = serial.unserialize(f:read("*a"))
  65.     f:close()
  66.     return config
  67.     end
  68. end
  69.  
  70. function helpdisplay()
  71.     print("AutomaticTrainControl v1")
  72.     print("Commands:")
  73.     print("'Any number'    - Changes set speed")
  74.     print("'+'      - Displays additional information")
  75.     print("'-'      - Hides additional information")
  76.     print("'ramp'       - Changes to ramp mode, requires further input")
  77.     print("'idle'       - Pauses train control")
  78.     print("'auto'       - Automatic control")
  79.     print("'stop'       - Ends program")
  80. end
  81.    
  82. function GetTrainPos()
  83.     positions = entity.getLocation()
  84.     xpos = positions.getX()
  85.     ypos = positions.getY()
  86.     zpos = positions.getZ()
  87.     print("X:   ", xpos)
  88.     print("Z:   ", zpos)
  89. end
  90.  
  91. function GetTrainSpeed()
  92.     speed = entity.getCurrentSpeed()
  93.     return speed
  94. end
  95.  
  96. function GetUUID()
  97.     uuid = entity.getUUID()
  98.     return uuid
  99. end
  100.  
  101. function setThrottle(x)
  102.     if 0 >= x then x = 0 end
  103.     if 1 <= x then x = 1 end
  104.     entity.setThrottleLevel(x)
  105.     if display then
  106.         print("Throttle: ", x)
  107.         end
  108. end
  109.  
  110. function setBrake(x)
  111.     if 0 >= x then x = 0 end
  112.     if 1 <= x then x = 1 end
  113.     entity.setAirBrakeLevel(x)
  114.     if display then
  115.         print("Brake:   ", x)
  116.         end
  117. end
  118.  
  119. local function reads()
  120.   while RUNNING do
  121.     user = nil
  122.     user = io.read()
  123.     if user == "stop" then 
  124.         print("STOPPING...")
  125.         os.sleep(1)
  126.         stop()
  127.         end
  128.     if user == "." then
  129.         term.clear()
  130.         end
  131.     if user == "idle" then
  132.         MODE = 2
  133.         end
  134.     if user == "auto" then
  135.         MODE = 3
  136.         end
  137.     if user == "ramp" then
  138.         print("Start Speed (type 'x' for current setpoint):")
  139.         c = io.read()
  140.         if c == "x" then
  141.             c = setpoint
  142.             end
  143.         print("End Speed:")
  144.         rampStart = c
  145.         c = io.read()
  146.         print("Ramp Time (seconds):")
  147.         rampEnd = c
  148.         c = io.read()
  149.         rampTime = c
  150.         rampDiff = rampEnd - rampStart
  151.         rampCount = math.floor(rampTime/sleep)
  152.         rampInc = rampDiff / rampCount
  153.         PID:SetPoint(rampStart)
  154.         setpoint = rampStart
  155.         MODE = 1
  156.         end
  157.     if user == "+" then
  158.         display = true
  159.         term.clear()
  160.         end
  161.     if user == "-" then
  162.         display = false
  163.         term.clear()
  164.         os.sleep(1)
  165.         helpdisplay()
  166.         end
  167.     if nil ~= tonumber(user) then
  168.         MODE = 0
  169.         PID:SetPoint(user)
  170.         setpoint = user
  171.         print("Setting Speed: ", user)
  172.         end
  173.     os.sleep(1)
  174.   end
  175. end
  176.  
  177.  
  178. local function main()
  179.     while RUNNING do
  180.         input = GetTrainSpeed()
  181.         if MODE ~= 2 then
  182.             if MODE == 1 then
  183.                 if rampCount > 0 then
  184.                   rampCount = rampCount - 1
  185.                   setpoint = setpoint + rampInc
  186.                   PID:SetPoint(setpoint)
  187.                   if rampCount == 0 then
  188.                     setpoint = rampEnd
  189.                     PID:SetPoint(rampEnd)
  190.                     end
  191.                   else
  192.                   Mode = 0
  193.                   end
  194.                 end
  195.             if MODE == 3 then
  196.                 CONFIG = loadConfig()
  197.                 if CONFIG[uuid] ~= nil then
  198.                     print(CONFIG[uuid].setspeed)
  199.                     setpoint = CONFIG[uuid].setspeed
  200.                     PID:SetPoint(setpoint)
  201.                     end
  202.                 end                
  203.             PID:SetInput(input)
  204.             PID:Compute()
  205.             output = PID:GetOutput()
  206.             BrakeOut = output * -1
  207.             setThrottle(output)
  208.             setBrake(BrakeOut)
  209.             end
  210.         if display then
  211.             print("CurrentSpeed: ", input)
  212.             if MODE ~= 2 then
  213.                 print("SetPoint: ", setpoint)
  214.                 end
  215.             GetTrainPos()
  216.             print("----")
  217.             os.sleep(sleep)
  218.             term.clear()
  219.             else
  220.             os.sleep(sleep)
  221.             end
  222.         checkATC()
  223.         end
  224.   end
  225.  
  226. function stop()
  227.   RUNNING = false
  228. end
  229.  
  230. function checkATC()
  231.   if MODE == 3 then
  232.     atext.setText("ATC: "..setpoint.."  Speed: "..(math.floor(input * 1000)/1000))
  233.     ATC = true
  234.     end
  235.   if MODE == 2 then
  236.     atext.setText("ATC: OFF")
  237.     ATC = false
  238.     end
  239. end
  240.  
  241. function inbounds(x0, y0, x1, y1, x2, y2)
  242.   local output = false
  243.   if x0 > x1 then
  244.     if y0 > y1 then
  245.       if x0 < x2 then
  246.         if y0 < y2 then
  247.           output = true
  248.           end
  249.         end
  250.       end
  251.     end
  252.   return output
  253. end    
  254.  
  255. function pullOverlay()
  256. while RUNNING do
  257.   EVENT, ID, USER, X, Y, BUTTON = event.pull("interact_overlay")
  258.   if inbounds(X,Y,0,0,41,7) then
  259.     if ATC == true then
  260.         MODE = 2
  261.         else
  262.         MODE = 3
  263.         PID:SetPoint(setpoint)
  264.         end
  265.   elseif inbounds(X,Y,0,11,20,16) then
  266.     setpoint = setpoint + 10
  267.     PID:SetPoint(setpoint)
  268.   elseif inbounds(X,Y,0,19,20,24) then
  269.     setpoint = setpoint - 10
  270.     PID:SetPoint(setpoint)
  271.     end
  272. end
  273. end
  274.      
  275. local function handleMessage(host, msg)
  276.   local packet = serial.unserialize(msg)
  277.   if packet == nil then
  278.     print("nil packet")
  279.     return
  280.   end
  281.   if packet.t == "STATUS" then
  282.         print(packet.v)
  283.         saveConfig(CONFIG_FILE, packet.v)
  284.   else
  285.     print("unknown command")
  286.   end
  287. end
  288.  
  289. function start()
  290.     modem.open(54421)
  291.     while RUNNING do
  292.       local eventName, p1, p2, p3, p4, p5 = event.pull()
  293.       if eventName == "modem_message" then
  294.         print("recv")
  295.         handleMessage(p2, p5)
  296.       end
  297.     end
  298.     modem.close(54421)
  299. end
  300.  
  301. ----------- Main loop ------------ 
  302.    
  303. term.clear()
  304. CONFIG = loadConfig()
  305. setpoint = 0
  306. PID:new(0.01, 0.5, 0.0001, 0)
  307. PID:SetInput((GetTrainSpeed()))
  308. PID:SetOutput(0)
  309. PID:SetPoint(setpoint)
  310. PID:SetOutputLimits(-1, 1)
  311. PID:SetMode(1)
  312.  
  313. helpdisplay()
  314. uuid = GetUUID()
  315.  
  316. local tb = thread.create(main)
  317. local ta = thread.create(reads)
  318. local tc = thread.create(pullOverlay)
  319. local td = thread.create(start)
  320. tb:join()
  321. ta:join()
  322. tc:join()
  323. td:join()
  324. term.clear()
Advertisement
Add Comment
Please, Sign In to add comment