View difference between Paste ID: 3us5SqG9 and RQVy8wj8
SHOW: | | - or go back to the newest paste.
1-
--Automated Train Control v1 by Gazer29
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
14
local ATC = false
15
local RUNNING = true
16
local MODE = 0 -- 0 SET, 1 RAMP,
17
local sleep = 1 -- seconds
18
local display = false
19
local iteration = 1
20
local timer = nil
21
22
local CONFIG_FILE = "/home/Waypoints.cfg"
23
local CONFIG = nil
24
local DEFAULT_CONFIG = {
25
  array = {
26
	{
27
	waypoint = "Station 1",
28
	speed = 0,
29
	radius = 10,
30
	x = 1180,
31
	z = -333,
32
	mode = "wait",
33
	data = 20
34
	},
35
	{
36
	waypoint = "Waypoint 2",
37
	speed = 10,
38
	radius = 10,
39
	x = 1180,
40
	z = -333,
41
	mode = nil,
42
	data = nil
43
	},
44
	{
45
	waypoint = "Waypoint 3",
46
	speed = 5,
47
	radius = 10,
48
	x = 1136,
49
	z = -333,
50
	mode = nil,
51
	data = nil
52
	}
53
  }
54
}
55
56
glassesTerminal.removeAll()
57
atext = glassesTerminal.addText2D()
58
atext.setText("ATC: OFF") -- no modifier!
59
atext.setFontSize(42)
60
atext.addColor(1, 0, 0, 1)
61
atext.setCondition(atext.addColor(0, 1, 0, 1), "OVERLAY_ACTIVE", true)
62
 
63
btext = glassesTerminal.addText2D()
64
btext.setText("+10")
65
btext.setFontSize(60)
66
btext.addColor(1,0,0,1)
67
btext.addTranslation(0, 10, 0)
68
btext.setCondition(btext.addColor(0, 1, 0, 1), "OVERLAY_ACTIVE", true)
69
 
70
ctext = glassesTerminal.addText2D()
71
ctext.setText("-10")
72
ctext.setFontSize(60)
73
ctext.addColor(1,0,0,1)
74
ctext.addTranslation(0,18,0)
75
ctext.setCondition(ctext.addColor(0, 1, 0, 1), "OVERLAY_ACTIVE", true)
76
77
local function saveConfig(file, cfg) -- Adapted from HandieAndy's code
78
  local f = io.open(file, "w")
79
  if f == nil then error("Couldn't open " .. file .. " to write config.") end
80
  f:write(serial.serialize(cfg, 100000))
81
  f:close()
82
  print("Saved to file: ", CONFIG_FILE)
83
end
84
85
local function loadConfig() -- Adapted from HandieAndy's code
86
  local f = io.open(CONFIG_FILE, "r")
87
  if f == nil then 
88
	print("Could not open " .. CONFIG_FILE .. ".")
89
	print("Loading default config")
90
	saveConfig(CONFIG_FILE, DEFAULT_CONFIG)
91
	return DEFAULT_CONFIG
92
	else
93
	local config = serial.unserialize(f:read("*a"))
94
	f:close()
95
	return config
96
	end
97
end
98
99
function helpdisplay()
100
	print("AutomaticTrainControl v1")
101
	print("Commands:")
102
	print("'Any number'    - Changes set speed")
103
	print("'+' 		- Displays additional information")
104
	print("'-' 		- Hides additional information")
105
	print("'ramp'		- Changes to ramp mode, requires further input")
106
	print("'idle'		- Pauses train control")
107
	print("'save'		- Saves config file")
108
	print("'stop' 		- Ends program")
109
end
110
	
111
function GetTrainPos()
112
	positions = entity.getLocation() 
113
	xpos = positions.getX()
114
	ypos = positions.getY()
115
	zpos = positions.getZ()
116
	print("X: 	", xpos)
117
	print("Z: 	", zpos)
118
end
119
120
function GetTrainSpeed()
121
	speed = entity.getCurrentSpeed()
122
	return speed
123
end
124
125
function setThrottle(x)
126
	if 0 >= x then x = 0 end
127
	if 1 <= x then x = 1 end
128
	entity.setThrottleLevel(x)
129
	if display then
130
		print("Throttle: ", x)
131
		end
132
end
133
134
function setBrake(x)
135
	if 0 >= x then x = 0 end
136
	if 1 <= x then x = 1 end
137
	entity.setAirBrakeLevel(x)
138
	if display then
139
		print("Brake:   ", x)
140
		end
141
end
142
143
local function reads()
144
  while RUNNING do
145
    user = nil
146
    user = io.read()
147
	if user == "stop" then	
148
		print("STOPPING...")
149
		os.sleep(1)
150
		stop()
151
		end
152
	if user == "." then
153
		term.clear()
154
		end
155
	if user == "idle" then
156
		MODE = 2
157
		end
158
	if user == "ramp" then
159
		print("Start Speed (type 'x' for current setpoint):")
160
		c = io.read()
161
		if c == "x" then
162
			c = setpoint
163
			end
164
		print("End Speed:")
165
		rampStart = c
166
		c = io.read()
167
		print("Ramp Time (seconds):")
168
		rampEnd = c
169
		c = io.read()
170
		rampTime = c
171
		rampDiff = rampEnd - rampStart
172
		rampCount = math.floor(rampTime/sleep)
173
		rampInc = rampDiff / rampCount
174
		PID:SetPoint(rampStart)
175
		setpoint = rampStart
176
		MODE = 1
177
		end
178
	if user == "+" then
179
		display = true
180
		term.clear()
181
		end
182
	if user == "save" then
183
		saveConfig(CONFIG_FILE, CONFIG)
184
		end
185
	if user == "-" then
186
		display = false
187
		term.clear()
188
		os.sleep(1)
189
		helpdisplay()
190
		end
191
	if nil ~= tonumber(user) then
192
		MODE = 0
193
		PID:SetPoint(user)
194
		setpoint = user
195
		print("Setting Speed: ", user)
196
		end
197
    os.sleep(1)
198
  end
199
end
200
201
-- run through array
202
function getDistance() 
203
	--active = CONFIG.array[iteration]
204
	x1 = active.x
205
	z1 = active.z
206
	positions = entity.getLocation()
207
	y1 = positions.getY()
208
	x = positions.getDistanceToCoordinates(x1,y1,z1)
209
	return x
210
	end
211
212
213
local function main()
214
	while RUNNING do
215
		array = CONFIG.array
216
		active = CONFIG.array[iteration]
217
		distance = getDistance()
218
		if distance < active.radius or timer ~= nil then
219
			setpoint = active.speed
220
			PID:SetPoint(setpoint)
221
			if active.mode == "wait" then
222
				if timer == nil then
223
					timer = active.data 
224
					end
225
				if timer > 0 then
226
					timer = timer - 1
227
					else
228
					timer = nil
229
					if iteration >= #array then
230
						iteration = 1
231
						else
232
						iteration = iteration + 1
233
						end
234
					end
235
				else
236
				if iteration >= #array then
237
					iteration = 1
238
					else
239
					iteration = iteration + 1
240
					end
241
				end
242
			end
243
		
244
		input = GetTrainSpeed()
245
		if MODE ~= 2 then
246
			if MODE == 1 then
247
				if rampCount > 0 then
248
				  rampCount = rampCount - 1
249
				  setpoint = setpoint + rampInc
250
				  PID:SetPoint(setpoint)
251
				  if rampCount == 0 then
252
					setpoint = rampEnd
253
					PID:SetPoint(rampEnd)
254
					end
255
				  else
256
				  Mode = 0
257
				  end
258
				end
259
			PID:SetInput(input)
260
			PID:Compute()
261
			output = PID:GetOutput()
262
			BrakeOut = output * -1
263
			setThrottle(output)
264
			setBrake(BrakeOut)
265
			end
266
		if display then
267
			print("CurrentSpeed: ", input)
268
			if MODE ~= 2 then
269
				print("SetPoint: ", setpoint)
270
				end
271
			print("Waypoint: ",active.waypoint)	
272
			print("Distance: ",distance)
273
			print("Timer: 	",timer)
274
			GetTrainPos()
275
			print("----")
276
			os.sleep(sleep)
277
			term.clear()
278
			else
279
			os.sleep(sleep)
280
			end
281
       	checkATC()
282
		end
283
  end
284
  
285
function stop()
286
  RUNNING = false
287
end
288
289
function checkATC()
290
  if MODE == 0 then
291
    atext.setText("ATC: "..setpoint.."	Speed: "..(math.floor(input * 1000)/1000))
292
    ATC = true
293
    end
294
  if MODE == 2 then
295
    atext.setText("ATC: OFF")
296
    ATC = false
297
    end
298
end
299
 
300
function inbounds(x0, y0, x1, y1, x2, y2) 
301
  local output = false
302
  if x0 > x1 then
303
    if y0 > y1 then
304
      if x0 < x2 then
305
        if y0 < y2 then
306
          output = true
307
          end
308
        end
309
      end
310
    end
311
  return output
312
end     
313
314
function pullOverlay()
315
while RUNNING do
316
  EVENT, ID, USER, X, Y, BUTTON = event.pull("interact_overlay")
317
  if inbounds(X,Y,0,0,41,7) then
318
	if ATC == true then
319
    	MODE = 2
320
        else
321
        MODE = 0
322
        PID:SetPoint(setpoint)
323
        end
324
  elseif inbounds(X,Y,0,11,20,16) then
325
    setpoint = setpoint + 10
326
    PID:SetPoint(setpoint)
327
  elseif inbounds(X,Y,0,19,20,24) then
328
    setpoint = setpoint - 10
329
    PID:SetPoint(setpoint)
330
    end
331
end
332
end
333
334
----------- Main loop ------------	
335
	
336
term.clear()
337
CONFIG = loadConfig()
338
setpoint = 0
339
PID:new(0.01, 0.5, 0.0001, 0)
340
PID:SetInput((GetTrainSpeed()))
341
PID:SetOutput(0)
342
PID:SetPoint(setpoint)
343
PID:SetOutputLimits(-1, 1)
344
PID:SetMode(1)
345
346
helpdisplay()
347
348
local tb = thread.create(main)
349
local ta = thread.create(reads)
350
local tc = thread.create(pullOverlay)
351
tb:join()
352
ta:join()
353
tc:join()
354
term.clear()