SHOW:
|
|
- or go back to the newest paste.
1 | --Automated Train Control v1 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 | ||
12 | local RUNNING = true | |
13 | local MODE = 0 -- 0 SET, 1 RAMP, | |
14 | local sleep = 1 -- seconds | |
15 | local display = false | |
16 | local iteration = 1 | |
17 | local timer = nil | |
18 | ||
19 | local CONFIG_FILE = "/home/Waypoints.cfg" | |
20 | local CONFIG = nil | |
21 | local DEFAULT_CONFIG = { | |
22 | array = { | |
23 | { | |
24 | waypoint = "Station 1", | |
25 | speed = 0, | |
26 | radius = 10, | |
27 | x = 1180, | |
28 | z = -333, | |
29 | mode = "wait", | |
30 | data = 20 | |
31 | }, | |
32 | { | |
33 | waypoint = "Waypoint 2", | |
34 | speed = 10, | |
35 | radius = 10, | |
36 | x = 1180, | |
37 | z = -333, | |
38 | mode = nil, | |
39 | data = nil | |
40 | }, | |
41 | { | |
42 | waypoint = "Waypoint 3", | |
43 | speed = 5, | |
44 | radius = 10, | |
45 | x = 1136, | |
46 | z = -333, | |
47 | mode = nil, | |
48 | data = nil | |
49 | } | |
50 | } | |
51 | } | |
52 | ||
53 | local function saveConfig(file, cfg) -- Adapted from HandieAndy's code | |
54 | local f = io.open(file, "w") | |
55 | if f == nil then error("Couldn't open " .. file .. " to write config.") end | |
56 | f:write(serial.serialize(cfg, 100000)) | |
57 | f:close() | |
58 | print("Saved to file: ", CONFIG_FILE) | |
59 | end | |
60 | ||
61 | local function loadConfig() -- Adapted from HandieAndy's code | |
62 | local f = io.open(CONFIG_FILE, "r") | |
63 | if f == nil then | |
64 | print("Could not open " .. CONFIG_FILE .. ".") | |
65 | print("Loading default config") | |
66 | saveConfig(CONFIG_FILE, DEFAULT_CONFIG) | |
67 | return DEFAULT_CONFIG | |
68 | else | |
69 | local config = serial.unserialize(f:read("*a")) | |
70 | f:close() | |
71 | return config | |
72 | end | |
73 | end | |
74 | ||
75 | function helpdisplay() | |
76 | print("AutomaticTrainControl v1") | |
77 | print("Commands:") | |
78 | print("'Any number' - Changes set speed") | |
79 | print("'+' - Displays additional information") | |
80 | print("'-' - Hides additional information") | |
81 | print("'ramp' - Changes to ramp mode, requires further input") | |
82 | print("'idle' - Pauses train control") | |
83 | print("'save' - Saves config file") | |
84 | print("'stop' - Ends program") | |
85 | end | |
86 | ||
87 | function GetTrainPos() | |
88 | positions = entity.getLocation() | |
89 | xpos = positions.getX() | |
90 | ypos = positions.getY() | |
91 | zpos = positions.getZ() | |
92 | print("X: ", xpos) | |
93 | print("Z: ", zpos) | |
94 | end | |
95 | ||
96 | function GetTrainSpeed() | |
97 | speed = entity.getCurrentSpeed() | |
98 | return speed | |
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 == "ramp" then | |
135 | print("Start Speed (type 'x' for current setpoint):") | |
136 | c = io.read() | |
137 | if c == "x" then | |
138 | c = setpoint | |
139 | end | |
140 | print("End Speed:") | |
141 | rampStart = c | |
142 | c = io.read() | |
143 | print("Ramp Time (seconds):") | |
144 | rampEnd = c | |
145 | c = io.read() | |
146 | rampTime = c | |
147 | rampDiff = rampEnd - rampStart | |
148 | rampCount = math.floor(rampTime/sleep) | |
149 | rampInc = rampDiff / rampCount | |
150 | PID:SetPoint(rampStart) | |
151 | setpoint = rampStart | |
152 | MODE = 1 | |
153 | end | |
154 | if user == "+" then | |
155 | display = true | |
156 | term.clear() | |
157 | end | |
158 | if user == "save" then | |
159 | saveConfig(CONFIG_FILE, CONFIG) | |
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 | -- run through array | |
178 | function getDistance() | |
179 | --active = CONFIG.array[iteration] | |
180 | x1 = active.x | |
181 | z1 = active.z | |
182 | positions = entity.getLocation() | |
183 | y1 = positions.getY() | |
184 | x = positions.getDistanceToCoordinates(x1,y1,z1) | |
185 | return x | |
186 | end | |
187 | ||
188 | ||
189 | local function main() | |
190 | while RUNNING do | |
191 | array = CONFIG.array | |
192 | active = CONFIG.array[iteration] | |
193 | distance = getDistance() | |
194 | if distance < active.radius or timer ~= nil then | |
195 | setpoint = active.speed | |
196 | PID:SetPoint(setpoint) | |
197 | if active.mode == "wait" then | |
198 | if timer == nil then | |
199 | timer = active.data | |
200 | end | |
201 | if timer > 0 then | |
202 | timer = timer - 1 | |
203 | else | |
204 | timer = nil | |
205 | if iteration >= #array then | |
206 | iteration = 1 | |
207 | else | |
208 | iteration = iteration + 1 | |
209 | end | |
210 | end | |
211 | else | |
212 | if iteration >= #array then | |
213 | iteration = 1 | |
214 | else | |
215 | iteration = iteration + 1 | |
216 | end | |
217 | end | |
218 | end | |
219 | ||
220 | input = GetTrainSpeed() | |
221 | if MODE ~= 2 then | |
222 | if MODE == 1 then | |
223 | if rampCount > 0 then | |
224 | rampCount = rampCount - 1 | |
225 | setpoint = setpoint + rampInc | |
226 | PID:SetPoint(setpoint) | |
227 | if rampCount == 0 then | |
228 | setpoint = rampEnd | |
229 | PID:SetPoint(rampEnd) | |
230 | end | |
231 | else | |
232 | Mode = 0 | |
233 | end | |
234 | end | |
235 | PID:SetInput(input) | |
236 | PID:Compute() | |
237 | output = PID:GetOutput() | |
238 | BrakeOut = output * -1 | |
239 | setThrottle(output) | |
240 | setBrake(BrakeOut) | |
241 | end | |
242 | if display then | |
243 | print("CurrentSpeed: ", input) | |
244 | if MODE ~= 2 then | |
245 | print("SetPoint: ", setpoint) | |
246 | end | |
247 | print("Waypoint: ",active.waypoint) | |
248 | print("Distance: ",distance) | |
249 | print("Timer: ",timer) | |
250 | GetTrainPos() | |
251 | print("----") | |
252 | os.sleep(sleep) | |
253 | term.clear() | |
254 | else | |
255 | os.sleep(sleep) | |
256 | end | |
257 | ||
258 | end | |
259 | end | |
260 | ||
261 | function stop() | |
262 | RUNNING = false | |
263 | end | |
264 | ||
265 | ----------- Main loop ------------ | |
266 | ||
267 | term.clear() | |
268 | CONFIG = loadConfig() | |
269 | setpoint = 0 | |
270 | PID:new(0.01, 0.5, 0.0001, 0) | |
271 | PID:SetInput((GetTrainSpeed())) | |
272 | PID:SetOutput(0) | |
273 | PID:SetPoint(setpoint) | |
274 | PID:SetOutputLimits(-1, 1) | |
275 | PID:SetMode(1) | |
276 | ||
277 | helpdisplay() | |
278 | ||
279 | local tb = thread.create(main) | |
280 | local ta = thread.create(reads) | |
281 | tb:join() | |
282 | ta:join() | |
283 | term.clear() |