Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local component = require('component')
- if not component.isAvailable('eeprom') then
- print('Required eeprom component')
- os.exit()
- end
- local eeprom = component.eeprom
- local coords
- local ARGS = {...}
- if #ARGS == 3 then
- local c = 0
- for i = 1, 3 do
- if type(tonumber(ARGS[i])) == 'number' then
- c = c + 1
- end
- end
- if c == 3 then
- coords = 'X, Y, Z = '..table.concat(ARGS, ', ')
- end
- end
- local bios = [[local CHANNEL_GPS = 65534
- local modem = component.proxy(component.list('modem')())
- modem.open(CHANNEL_GPS)
- modem.setWakeMessage('PING')
- local function round(v, m)
- m = m or 1.0
- return {
- x = math.floor((v.x+(m*0.5))/m)*m,
- y = math.floor((v.y+(m*0.5))/m)*m,
- z = math.floor((v.z+(m*0.5))/m)*m
- }
- end
- local function len(v)
- return math.sqrt(v.x^2 + v.y^2 + v.z^2)
- end
- local function cross(v, b)
- return {x = v.y*b.z-v.z*b.y, y = v.z*b.x-v.x*b.z, z = v.x*b.y-v.y*b.x}
- end
- local function dot(v, b)
- return v.x*b.x + v.y*b.y + v.z*b.z
- end
- local function add(v, b)
- return {x = v.x+b.x, y = v.y+b.y, z = v.z+b.z}
- end
- local function sub(v, b)
- return {x = v.x-b.x, y = v.y-b.y, z = v.z-b.z}
- end
- local function mul(v, m)
- return {x = v.x*m, y = v.y*m, z = v.z*m}
- end
- local function norm(v)
- return mul(v, 1/len(v))
- end
- local function trilaterate(A, B, C)
- local a2b = {x = B.x-A.x, y = B.y-A.y, z = B.z-A.z}
- local a2c = {x = C.x-A.x, y = C.y-A.y, z = C.z-A.z}
- if abs(dot(norm(a2b), norm(a2c))) > 0.999 then
- return nil
- end
- local d = len(a2b)
- local ex = norm(a2b)
- local i = dot(ex, a2c)
- local ey = norm(sub(mul(ex, i), a2c))
- local j = dot(ey, a2c)
- local ez = cross(ex, ey)
- local r1 = A.d
- local r2 = B.d
- local r3 = C.d
- local x = (r1^2 - r2^2 + d^2) / (2*d)
- local y = (r1^2 - r3^2 - x^2 + (x-i)^2 + j^2) / (2*j)
- local result = add(A, add(mul(ex, x), mul(ey, y)))
- local zSquared = r1^2 - x^2 - y^2
- if zSquared > 0 then
- local z = sqrt( zSquared )
- local result1 = add(result, mul(ez, z))
- local result2 = add(result, mul(ez, z))
- local rounded1, rounded2 = round(result1, 0.01), round(result2, 0.01)
- if rounded1.x ~= rounded2.x or rounded1.y ~= rounded2.y or rounded1.z ~= rounded2.z then
- return rounded1, rounded2
- else
- return rounded1
- end
- end
- return round(result, 0.01)
- end
- local function narrow(p1, p2, fix)
- local dist1 = math.abs(len(sub(p1, fix)) - fix.d)
- local dist2 = math.abs(len(sub(p2, fix)) - fix.d)
- if math.abs(dist1 - dist2) < 0.01 then
- return p1, p2
- elseif dist1 < dist2 then
- return round(p1, 0.01)
- else
- return round(p2, 0.01)
- end
- end
- function locate()
- modem.open(CHANNEL_GPS)
- modem.broadcast(CHANNEL_GPS, 'PING')
- local tFixes = {}
- local pos1, pos2 = nil, nil
- local timeout = computer.uptime()+2
- while true do
- local e = {computer.pullSignal(1)}
- if e[1] == 'modem_message' and e[6] == 'GPS' then
- local tFix = {x = e[7], y = e[8], z = e[9], d = e[5]}
- if tFix.d == 0 then
- pos1, pos2 = {tFix.x, tFix.y, tFix.z}, nil
- else
- table.insert(tFixes, tFix)
- if #tFixes >= 3 then
- if not pos1 then
- pos1, pos2 = trilaterate(tFixes[1], tFixes[2], tFixes[#tFixes])
- else
- pos1, pos2 = narrow(pos1, pos2, tFixes[#tFixes])
- end
- end
- end
- if pos1 and not pos2 then
- break
- end
- end
- if computer.uptime() >= timeout then
- break
- end
- end
- if pos1 and pos2 then
- return nil
- elseif pos1 then
- X, Y, Z = pos1.x, pos1.y, pos1.z
- return true
- else
- return nil
- end
- end
- if not X and not locate() then
- computer.shutdown()
- end
- modem.broadcast(CHANNEL_GPS, 'GPS', X, Y, Z)
- computer.shutdown()]]
- if coords then
- bios = coords..'\n'..bios
- end
- eeprom.set(bios)
- eeprom.setLabel(table.concat(ARGS, ', '))
- print('GPS firmware installed')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement