Advertisement
montana_1

getGPSCoordinates

Aug 15th, 2015
228
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.75 KB | None | 0 0
  1. function round(num, bounds)
  2.     if(num > 0) then
  3.         if(num + bounds >= math.ceil(num)) then
  4.             return math.ceil(num)
  5.         elseif(num - bounds <= math.floor(num)) then
  6.             return math.floor(num)
  7.         end
  8.     elseif(num < 0) then
  9.         if(num - bounds <= math.floor(num)) then
  10.             return math.floor(num)
  11.         elseif(num + bounds >= math.ceil(num)) then
  12.             return math.ceil(num)
  13.         end
  14.     end
  15.     return num
  16. end
  17.  
  18. function testPointEquality(p1,p2)
  19.     if(p1[2] == p2[2] and p1[3] == p2[3] and p1[4] == p2[4]) then
  20.     return true
  21.     else return false
  22.     end
  23. end
  24.  
  25. function getGPSCoordinates(timeOut)
  26.     local timeOut = timeOut or 2
  27.     local computer = require("computer")
  28.     local event = require("event")
  29.     local timer = computer.uptime()
  30.     local points = {}
  31.     while(computer.uptime() - timer < timeOut*4 and #points<4) do
  32.         --print("Timer: "..computer.uptime() - timer)
  33.        
  34.         --[[    Data i assumed to be meaningful!
  35.             This could be a huge problem, but will usually work if this
  36.             port is only used for gps, a fix should be inplemented
  37.         ]]--
  38.  
  39.         local eventType, recieverAddress, senderAddress, port, distance, x,y,z = event.pull(timeOut, "modem_message")
  40.         if(distance ~= nil and x ~= nil and y ~= nil and z ~= nil) then
  41.             local tmp = {distance, x,y,z}
  42.             tmp = tonumberVector(tmp)
  43.             local same = false
  44.             for i=1, #points do
  45.                 if(testPointEquality(points[i], tmp)) then
  46.                     same = true
  47.                     --print("Same point!")
  48.                     break
  49.                 end
  50.             end
  51.             if(not same) then
  52.                 if(#points<3) then
  53.                     points[#points+1] = tmp
  54.                     --print("Point added:"..tostring(tmp[1]))
  55.                     --print(#points)
  56.                 else
  57.                     local normPlane = getPlane(points[1],points[2],points[3])
  58.                     --print(tostringVector(normPlane))
  59.                     if(isInPlane(tmp,points[1],normPlane)) then
  60.                         --print("Point in plane!")
  61.                     else
  62.                         --print("Point not in plane, adding point")
  63.                         points[#points+1] = tmp
  64.                         --print(#points)
  65.                     end
  66.                 end
  67.             end
  68.         else
  69.             print("Nil event type")
  70.         end
  71.     end
  72.     --print(#points)
  73.     if(#points >3) then
  74.         return points
  75.     else
  76.         return nil
  77.     end
  78. end
  79.  
  80. function split(inputstr, sep)
  81.     if(inputstr == nil or inputstr == "") then
  82.                 return nil
  83.         end
  84.         if sep == nil then
  85.                 sep = ","
  86.         end
  87.         local t={} ; i=1
  88.         for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
  89.                 t[i] = str
  90.                 i = i + 1
  91.         end
  92.         return t
  93. end
  94.  
  95. function addVector(p1,p2)
  96.     --p1 + p2
  97.     return {p1[1]+p2[1], p1[2]+p2[2], p1[3]+p2[3]}
  98. end
  99.  
  100. function subtractVector(p1,p2)
  101.     --p1 - p2
  102.     return {p1[1]-p2[1], p1[2]-p2[2], p1[3]-p2[3]}
  103. end
  104.  
  105. function scaleVector(p1, scalar)
  106.     --p1 * scalar
  107.     return {p1[1]*scalar, p1[2]*scalar, p1[3]*scalar}
  108. end
  109.  
  110. function dotVector(p1,p2)
  111.     return p1[1]*p2[1] + p1[2]*p2[2] + p1[3]*p2[3]
  112. end
  113.  
  114. function crossVector(p1,p2)
  115.     return {p1[2]*p2[3] - p1[3]*p2[2], p1[3]*p2[1] - p1[1]*p2[3], p1[1]*p2[2] - p1[2]*p2[1]}
  116. end
  117.  
  118. function magnitudeVector(p1)
  119.     return math.sqrt(math.pow(p1[1], 2) + math.pow(p1[2], 2) + math.pow(p1[3], 2))
  120. end
  121.  
  122. function normalizeVector(p1)
  123.     return p1/magnitudeVector(p1)
  124. end
  125.  
  126. function getPlane(p1,p2,p3)
  127.     --find the equation of the plane
  128.     local p12 = subtractVector(p2,p1)
  129.     local p13 = subtractVector(p3,p1)
  130.     local plane = crossVector(p12,p13)
  131.     return plane
  132. end
  133.  
  134. function isInPlane(p1,p2,p3)
  135.     local bounds= 0.000001
  136.     --[[
  137.         where:
  138.         p1 is the point in question,
  139.         p2 is a point known to exist on plane p3,
  140.         and p3 is the plane in question
  141.     ]]--
  142.     if(dotVector(subtractVector(p1,p2),p3) < bounds and dotVector(subtractVector(p1,p2),p3) > -bounds) then
  143.         return true
  144.     else
  145.         return false
  146.     end
  147. end
  148.  
  149. function rotateVectorZAxis(p1,theta)
  150.     return {p1[1]*math.cos(theta) - p1[2]*math.sin(theta), p1[1]*math.sin(theta) + p1[2]*math.cos(theta), p1[3]}
  151. end
  152.  
  153. function rotateVectorXAxis(p1,theta)
  154.     return {p1[1], p1[2]*math.cos(theta) - p1[3]*math.sin(theta), p1[2]*math.sin(theta) + p1[3]*math.cos(theta)}
  155. end
  156.  
  157. function rotateVectorYAxis(p1,theta)
  158.     return {p1[1]*math.cos(theta) + p1[3]*math.sin(theta), p1[2], p1[3]*math.cos(theta) - p1[1]*math.sin(theta)}
  159. end
  160.  
  161. function tostringVector(p1)
  162.     return tostring(p1[1]) .. "," .. tostring(p1[2]) .. "," .. tostring(p1[3])
  163. end
  164.  
  165. function tonumberVector(p1)
  166.     local tmp = {}
  167.     for i=1, #p1 do
  168.         tmp[i] = tonumber(p1[i])
  169.     end
  170.     return tmp
  171. end
  172.  
  173. function roundVector(p1)
  174.     local bounds = 0.000001
  175.     local tmp = {}
  176.     --[[
  177.     for i=1, #p1 do
  178.         if(p1[i] < bounds and p1[i] > -bounds) then
  179.             tmp[i] = 0
  180.         else
  181.             tmp[i] = p1[i]
  182.         end
  183.     end
  184.     ]]--
  185.     for i=1, #p1 do
  186.         tmp[i] = round(p1[i],bounds)
  187.     end
  188.     return tmp
  189. end
  190.  
  191. function distanceBetweenPoints(p1,p2)
  192.     return math.sqrt(math.pow(p1[1]-p2[1],2) + math.pow(p1[2]-p2[2],2) + math.pow(p1[3]-p2[3],2))
  193. end
  194.  
  195. function findPossiblePoints2D(d1,p1,d2,p2)
  196.     local distance = distanceBetweenPoints(p1,p2)
  197.     local a = (math.pow(d1, 2) - math.pow(d2, 2) + math.pow(distance, 2)) / (2 * distance)
  198.     --print(a)
  199.     local intersect = addVector(p1,scaleVector(scaleVector(subtractVector(p2,p1), a), (1/distance)))
  200.     --print(tostringVector(intersect))
  201.     local h = math.sqrt(math.pow(d1, 2) - math.pow(a, 2))
  202.     --print(h)
  203.     local x_plus = intersect[1] + ((h*(p2[2]-p1[2]))/distance)
  204.     local x_minus = intersect[1] - ((h*(p2[2]-p1[2]))/distance)
  205.     local y_plus = intersect[2] + ((h*(p2[1]-p1[1]))/distance)
  206.     local y_minus = intersect[2] - ((h*(p2[1]-p1[1]))/distance)
  207.     return {x_plus,y_minus,0}, {x_minus,y_plus,0}
  208. end
  209.  
  210. function findPossiblePoints3D(d1,p1,d2,p2,d3,p3)
  211.    
  212.     print("Trilateration points: "..d1..","..tostringVector(p1)..";"..d2..","..tostringVector(p2)..";"..d3..","..tostringVector(p3))
  213.    
  214.     --offset vectors such that p1 is at 0,0,0
  215.     local offset = scaleVector(p1, -1)
  216.     --print("Offset: "..tostringVector(offset))
  217.     local p1p = addVector(p1, offset)
  218.     --print("p1p: "..tostringVector(p1p))
  219.     local p2p = addVector(p2, offset)
  220.     --print("p2p: "..tostringVector(p2p))
  221.     local p3p = addVector(p3, offset)
  222.     --print("p3p: "..tostringVector(p3p))
  223.    
  224.     print("Offset vectors: "..tostringVector(p1p).."; "..tostringVector(p2p).."; "..tostringVector(p3p))
  225.  
  226.  
  227.     --find the equation of the plane
  228.     local plane = roundVector(getPlane(p1p,p2p,p3p))
  229.     print("Plane: "..tostringVector(plane))
  230.  
  231.     -- checked up to here --
  232.    
  233.     --rotate first about the y axis such that p2 is at z = 0
  234.     local angle1
  235.     if(p2p[1] ~= 0)then
  236.         angle1 = math.atan(p2p[3]/p2p[1])
  237.     elseif(p2p[3] > 0) then
  238.         --  90 degrees
  239.         angle1 = 1.57079633
  240.     elseif(p2p[3] < 0) then
  241.         --  -90 degrees
  242.         angle1 = -1.57079633
  243.     end
  244.     print("Angle1: "..angle1)
  245.     local plane_ry = roundVector(rotateVectorYAxis(plane, angle1))
  246.     print("plane_ry: "..tostringVector(plane_ry))
  247.     local p1p_ry = roundVector(rotateVectorYAxis(p1p, angle1))
  248.     print("p1p_ry: "..tostringVector(p1p_ry))
  249.     local p2p_ry = roundVector(rotateVectorYAxis(p2p, angle1))
  250.     print("p2p_ry: "..tostringVector(p2p_ry))
  251.     local p3p_ry = roundVector(rotateVectorYAxis(p3p, angle1))
  252.     print("p3p_ry: "..tostringVector(p3p_ry))
  253.    
  254.     --rotate second about the z axis such that p2 is at y = 0 and the line from p1 to p2 is at z=0 y=0, and is hence on the x axis
  255.     local angle2
  256.     if(p2p_ry[1] ~= 0)then
  257.         angle2 = (-1) * math.atan(p2p_ry[2]/p2p_ry[1])
  258.     elseif(p2p_ry[2] > 0) then
  259.         --  -90 degrees
  260.         angle2 = -1.57079633
  261.     elseif(p2p_ry[2] < 0) then
  262.         --  90 degrees
  263.         angle2 = 1.57079633
  264.     end
  265.     print("Angle2: "..angle2)
  266.     local plane_ryz = roundVector(rotateVectorZAxis(plane_ry, angle2))
  267.     print("plane_ryz: "..tostringVector(plane_ryz))
  268.     local p1p_ryz = roundVector(rotateVectorZAxis(p1p_ry, angle2))
  269.     print("p1p_ryz: "..tostringVector(p1p_ryz))
  270.     local p2p_ryz = roundVector(rotateVectorZAxis(p2p_ry, angle2))
  271.     print("p2p_ryz: "..tostringVector(p2p_ryz))
  272.     local p3p_ryz = roundVector(rotateVectorZAxis(p3p_ry, angle2))
  273.     print("p3p_ryz: "..tostringVector(p3p_ryz))
  274.    
  275.     --rotate plane about the x axis such that p3 is at z = 0
  276.     local angle3
  277.     if(p3p_ryz[2] ~= 0)then
  278.         angle3 = (-1) * math.atan(p3p_ryz[3]/p3p_ryz[2])
  279.     elseif(p3p_ry[3] > 0) then
  280.         --  -90 degrees
  281.         angle3 = -1.57079633
  282.     elseif(p3p_ry[3] < 0) then
  283.         --  90 degrees
  284.         angle3 = 1.57079633
  285.     end
  286.     print("Angle3: "..angle3)
  287.     local plane_ryzx = roundVector(rotateVectorXAxis(plane_ryz, angle3))
  288.     print("plane_ryzx: "..tostringVector(plane_ryzx))
  289.     local p1p_ryzx = roundVector(rotateVectorXAxis(p1p_ryz, angle3))
  290.     print("p1p_ryzx: "..tostringVector(p1p_ryzx))
  291.     local p2p_ryzx = roundVector(rotateVectorXAxis(p2p_ryz, angle3))
  292.     print("p2p_ryzx : "..tostringVector(p2p_ryzx ))
  293.     local p3p_ryzx = roundVector(rotateVectorXAxis(p3p_ryz, angle3))
  294.     print("p3p_ryzx : "..tostringVector(p3p_ryzx ))
  295.  
  296.     --at this point, p1 should be at 0,0,0; p2 x,0,0; and p3 should be at x,y,0
  297.    
  298.     --calculations for finding rotated, offset points  
  299.     local xp_ryzx = (math.pow(d1,2) - math.pow(d2,2) + math.pow(p2p_ryzx[1],2))/(2*p2p_ryzx[1])
  300.  
  301.  
  302.  
  303.     local yp_ryzx = ((math.pow(d1,2) - math.pow(d3,2) + math.pow(p3p_ryzx[1],2) + math.pow(p3p_ryzx[2],2))/(2*p3p_ryzx[2])) - ((p3p_ryzx[1]/p3p_ryzx[2])*xp_ryzx)
  304.  
  305.  
  306.     local z1p_ryzx = math.sqrt(math.pow(d1,2)-math.pow(xp_ryzx,2)-math.pow(yp_ryzx,2))
  307.     local z2p_ryzx = (-1) * math.sqrt(math.pow(d1,2)-math.pow(xp_ryzx,2)-math.pow(yp_ryzx,2))
  308.    
  309.     --possible rotated, offset points
  310.     local point1p_ryzx = {xp_ryzx, yp_ryzx, z1p_ryzx}
  311.     local point2p_ryzx = {xp_ryzx, yp_ryzx, z2p_ryzx}
  312.    
  313.     --rotate back around the x axis
  314.     plane_ryx = rotateVectorXAxis(plane_ryzx, (-1)*angle3)
  315.     local point1p_ryz = rotateVectorXAxis(point1p_ryzx, (-1)*angle3)
  316.     local point2p_ryz = rotateVectorXAxis(point2p_ryzx, (-1)*angle3)
  317.  
  318.     --rotate back around the z axis
  319.     plane_ry = rotateVectorZAxis(plane_ryz, (-1)*angle2)
  320.     local point1p_ry = rotateVectorZAxis(point1p_ryz, (-1)*angle2)
  321.     local point2p_ry = rotateVectorZAxis(point2p_ryz, (-1)*angle2)
  322.  
  323.     --rotate back around the y axis
  324.     plane = rotateVectorYAxis(plane_ry, (-1)*angle1)
  325.     local point1p = rotateVectorYAxis(point1p_ry, (-1)*angle1)
  326.     local point2p = rotateVectorYAxis(point2p_ry, (-1)*angle1)
  327.     --print(tostringVector(plane))
  328.  
  329.     --remove offset
  330.     local point1 = addVector(point1p, scaleVector(offset,-1))
  331.     local point2 = addVector(point2p, scaleVector(offset,-1))
  332.    
  333.     --print("Possible points are either: "..tostringVector(point1).." or "..tostringVector(point2))
  334.     return roundVector(point1), roundVector(point2)
  335.  
  336. end
  337.  
  338. function narrow(p1,p2,d4,p4)
  339.     local bounds = 0.00001
  340.     local distance1 = distanceBetweenPoints(p1,p4)
  341.     local error1 = distance1 - d4
  342.     print(error1)
  343.     if(error1 < bounds and error1 > -bounds) then
  344.         return p1
  345.     end
  346.     local distance2 = distanceBetweenPoints(p2,p4)
  347.     local error2 = distance2 - d4
  348.     print(error2)
  349.     if(error2 < bounds and error2 > -bounds) then
  350.         return p2
  351.     end
  352.     print("Narrowing function could not obtain a meaningful answer")
  353.     return nil
  354. end
  355.  
  356. function getLocation(timeout)
  357.     local timeout = timeout or 2
  358.     local coords = getGPSCoordinates(timeout)
  359.     if(coords == nil) then
  360.         print("Coordinate table could not be obtained")
  361.         return nil
  362.     end
  363.     if(#coords < 4) then
  364.         print("Insufficient points")
  365.         return nil
  366.     end
  367.     local d1 = coords[1][1]
  368.     local p1 = {coords[1][2],coords[1][3],coords[1][4]}
  369.     local d2 = coords[2][1]
  370.     local p2 = {coords[2][2],coords[2][3],coords[2][4]}
  371.     local d3 = coords[3][1]
  372.     local p3 = {coords[3][2],coords[3][3],coords[3][4]}
  373.     local d4 = coords[4][1]
  374.     local p4 = {coords[4][2],coords[4][3],coords[4][4]}
  375.     local point1, point2 = findPossiblePoints3D(d1,p1,d2,p2,d3,p3)
  376.     print("Possible point 1: "..tostringVector(point1))
  377.     print("Possible point 2: "..tostringVector(point2))
  378.     local location = narrow(point1,point2,d4,p4)
  379.     if(location ~= nil) then
  380.         print(tostringVector(location))
  381.         return location
  382.     else
  383.         print("Location could not be narrowed")
  384.         return nil
  385.     end
  386. end
  387.  
  388. local term = require("term")
  389. local component = require("component")
  390. local event = require("event")
  391.  
  392. component.modem.open(3665)
  393.  
  394. --getGPSCoordinates(.5)
  395. getLocation()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement