Stormworks: Build and Rescue

Stormworks: Build and Rescue

Not enough ratings
*LUA* Radio Radar (Signal Trilateration)
   
Award
Favorite
Favorited
Unfavorite
File Size
Posted
Updated
74.660 KB
15 May, 2019 @ 11:25am
17 May, 2019 @ 2:27am
2 Change Notes ( view )

Subscribe to download
*LUA* Radio Radar (Signal Trilateration)

Description
Signal trilateration system as seen on the steam update announcement:
https://steamhost.cn/steamcommunity_com/games/573090/announcements/detail/1606007962356266695
and here:
http://rising.at/Stormworks/trilaterate2.gif

- - - Description - - -
The system uses a total of 4 antennas. The middle one goes though a specified range of frequencies (mc settings) and then lists every discovered signal. The other 3 antennas go through the list of discovered signals and update their position via trilateration.

- - -

The important thing here is that in order to accurately measure the distance to a signal, you need to know the antenna types on both end and preferably also the battery level.

This is where the MC settings come in:
By default, the system uses 4 medium antennas. You can switch those to bigger ones if you want but then you'll also have to change the setting for that in the MC.

Furthermore, the MC by default expects every signal it discovers to be sent from a medium antenna. (Change that default setting on the MC to whatever antenna type you use most)
For best precision, I recommend to set up all your antennas to transmit both their antenna type and their current battery level. The scanner can then use that information instead of the default values.

Composite Channel 31: Antenna type (1=small, 2=medium, 3=large, 4=huge)
Composite Channel 32: Battery level

- - - - - -

The system is optimized for use with a 9x5 or 5x3 monitor hooked up as touchscreen.
You can hook up additional, smaller monitors but they will only display the radar circle.

On the left hand side of your main monitor you'll see the list of all discovered frequencies. You can click to select one of them. The selected signal is then highlighted on the radar and the MC will also send the calculated coordinates of that signal to composite output 1 and 2 (x/y).


- - - - - - -


Since the code in this thing is minified (due to 4kb size restriction), I'll also post it here:

-- Frequency scanner varnames = {"screenW","screenH","touchX1","touchY1","touchX2","touchY2","defRadio","s_Radio","t_Radio","s_Start","s_End","s_Current","s_SS","t_Current","ra","rb","rc","gpsX","gpsY","compass","LPower","RRadio","RPower"} v = {} senders = {100,1000,4000,20000} receivers = {0,1000,4000,20000} freq = -1 tra = -1 found = {} foundnew = {} dist = {} distnew = {} tset = {} tx = {} ty = {} rsel = 3 rrange = {10,50,100,200,500,1000,5000,10000,40000} off = 0 selected = 0 selx = 0 sely = 0 xa = -1 xb = 1 xc = 0 ya = 0 yb = 0 yc = -1 function onTick() --Init input variables-- for i=1,#varnames do v[varnames[i]] = input.getNumber(i) end if v.defRadio < 1 then return true end --Radio range settings-- if v.LPower == 0 then v.LPower = 1 end if v.RPower == 0 then v.RPower = 1 end if v.RRadio == 0 then v.RRadio = v.defRadio end s_range = (senders[v.RRadio] + receivers[v.s_Radio]) *v.LPower *v.RPower t_range = (senders[v.RRadio] + receivers[v.t_Radio]) *v.LPower *v.RPower --scan frequencies-- if freq == -1 or freq == v.s_End then freq = v.s_Start else freq = freq +1 end output.setNumber(6,freq) v.s_Current = math.floor(v.s_Current) if v.s_Current == v.s_Start then found = foundnew dist = distnew foundnew = {} distnew = {} end if v.s_Current >= v.s_Start and v.s_Current <= v.s_End then if v.s_SS > 0 then foundnew[#foundnew+1] = v.s_Current distnew[#distnew+1] = math.floor((1 -v.s_SS) *s_range *10)/10 end end --track known frequencies if #found > 0 then if tra == -1 or tra >= #found then tra = 1 else tra = tra +1 end --cycle tracking output.setNumber(7,found[tra]) --trilateration v.t_Current = math.floor(v.t_Current) if v.t_Current >= v.s_Start and v.t_Current <= v.s_End then ra = (1 -v.ra) *t_range rb = (1 -v.rb) *t_range rc = (1 -v.rc) *t_range S = (xc^2 - xb^2 + yc^2 - yb^2 + rb^2 - rc^2) / 2.0; T = (xa^2 - xb^2 + ya^2 - yb^2 + rb^2 - ra^2) / 2.0; try = ((T * (xb - xc)) - (S * (xb - xa))) / (((ya - yb) * (xb - xc)) - ((yc - yb) * (xb - xa))) trx = ((try * (ya - yb)) - T) / (xb - xa) ty["f"..v.t_Current] = try tx["f"..v.t_Current] = trx end end --List interaction maxlines = math.floor((v.screenH-22)/6) if input.getBool(1) then if v.touchX1 < (v.screenW -v.screenH) then if v.touchY1 <= 6 then off = off -0.25 if off < 0 then off = 0 end elseif v.touchY1 >= (v.screenH-6) then off = off +0.25 if off > (#found-maxlines) then off = (#found-maxlines) end else try = off+math.floor((v.touchY1-14)/6)+1 if try > 0 and try <= #found then selected = found[try] end end elseif v.touchX1 > (v.screenW - 25) then if v.touchY1 < 25 then rsel = rsel -0.25 if rsel < 1 then rsel = 1 end elseif v.touchY1 > (v.screenH - 25) then rsel = rsel +0.25 if rsel > #rrange then rsel = #rrange end end end end --selected if tx["f"..selected] ~= nil then selx = tx["f"..selected] sely = ty["f"..selected] selx = v.gpsX + selx * math.cos(v.compass*math.pi*2) - sely * math.sin(v.compass*math.pi*2) sely = v.gpsY + selx * math.sin(v.compass*math.pi*2) + sely * math.cos(v.compass*math.pi*2) output.setNumber(1, selx) output.setNumber(2, sely) end end function onDraw() if maxlines == nil then return true end sw = screen.getWidth() sh = screen.getHeight() sx = sw /2 sy = sh /2 --screenlayout screen.setColor(0,200,0) screen.drawText(sw-sh+1,2,rrange[math.floor(rsel)].."m") if sw >= 160 then screen.drawRectF(sw-16,8, 11, 3) screen.drawRectF(sw-12,4, 3,11) screen.drawRectF(sw-16,sh-10,11,3) screen.drawRect(1,0,sw-sh-2,sh-1) screen.drawRectF(1,1,sw-sh-2,6) screen.drawRectF(1,sh-7,sw-sh-2,6) screen.drawText(4, 8, (sw>160 and "Freq: Dist:" or "F: Dist:")) screen.setColor(0,0,0) if off > 0 then screen.drawTriangleF((sw-sh)/2-4, 6, (sw-sh)/2+5, 6, (sw-sh)/2, 1) end if (off+maxlines) < #found then screen.drawTriangleF((sw-sh)/2-5, sh-6, (sw-sh)/2+5, sh-6, (sw-sh)/2, sh) end end screen.setColor(0,200,0,25) cy = sh/2 cx = sw-cy screen.drawCircleF(cx,cy,cy-3) screen.setColor(0,200,0,150) screen.drawCircle(cx,cy,cy-1) screen.drawTriangleF(cx-3, sy, cx+4, sy, cx, sy-4) scale = cy /rrange[math.floor(rsel)] --list frequencies j = 0 for i=1, #found do fr = found
if found~=nil then
if selected == fr then
screen.setColor(255,0,0)
else
screen.setColor(255,150,0)
end
if i>off and i<=#found and j<maxlines and sw >= 160 then
screen.drawText(4, 14+j*6, string.sub(" "..fr,-3).."|"..string.sub(" "..dist,-7) )
j= j +1
end
if dist <= rrange[math.floor(rsel)] and tx["f"..fr] ~= nil then
xx = math.floor(cx +tx["f"..fr] *scale)
yy = math.floor(cy -ty["f"..fr] *scale)
if selected == fr then screen.drawRectF(xx-1,yy-1,4,4) else screen.drawRectF(xx,yy,2,2) end
end
end
end
end
25 Comments
Abgad Klishal 7 Feb, 2024 @ 6:06pm 
ive spent 2 days figuring out that you dont need to do that much big math if you do it using a lot of triangles in weird ways
Shillelagh 7 Mar, 2021 @ 10:27am 
How are you calculating distance with the antennas?
tdel 20 Dec, 2019 @ 1:19pm 
I can't seem to load this in. Stormworks claims it's too big. When I spawn it in with a mission it looks like maybe one of the "test target" antennas escaped out of bounds?
ThatMacBookGamer 18 Sep, 2019 @ 8:07am 
I'm not that good at lua, so I'll just make my ship bigger.
Tajin  [author] 18 Sep, 2019 @ 12:28am 
You can move the antennas but then you have to update their relative positions inside the script:

[code]xa = -1
xb = 1
xc = 0
ya = 0
yb = 0
yc = -1[/code]

These coordinates are in meters, relative to the antenna in the middle.
ThatMacBookGamer 17 Sep, 2019 @ 6:25pm 
Can I move one of the antenna, because my boat's not quite that wide.
Aljon 29 Aug, 2019 @ 6:43pm 
He might be a programmer in real life :O
Sqnty 29 Aug, 2019 @ 5:34pm 
how did you get soo good with logic?
Tajin  [author] 20 May, 2019 @ 12:43pm 
Certainly but then you can only track objects that actually transmit their gps-coordinates.
This however can track any radio signal.
Aljon 20 May, 2019 @ 9:31am 
hmmm where can I use this. cant I just like send gps to the antenna so it will show on screen map