GPS Widget voor FrSky Horus

Moet je niet bij update ook de andere routines laten uitvoeren?

Hier bedoel ik.
local function update(thisWidget, options) thisWidget.options = optionsend

Het gekke is, de basis die jij toen geschreven hebt die werkt prima met 3 maps.

Het enige wat ik heb toegevoegd is het volgende:
Code:
    --add one bitmap per map size and set current map size
  map.bmp={}
  map.bmp.xsmall  = Bitmap.open("/widgets/GPSMap/maps/map"..LoadMap.."xsmall.png")
  map.bmp.small   = Bitmap.open("/widgets/GPSMap/maps/map"..LoadMap.."small.png")
  map.bmp.medium  = Bitmap.open("/widgets/GPSMap/maps/map"..LoadMap.."medium.png")
  map.bmp.large   = Bitmap.open("/widgets/GPSMap/maps/map"..LoadMap.."large.png")
  map.bmp.xlarge  = Bitmap.open("/widgets/GPSMap/maps/map"..LoadMap.."xlarge.png")

en

Code:
  ------ Checks if Plane is visible in any map, otherwise disable plane view ------
  if thisWidget.gpsLat < North.xsmall and thisWidget.gpsLat > South.xsmall and thisWidget.gpsLong < East.xsmall and thisWidget.gpsLong > West.xsmall then
    thisWidget.map.current = "xsmall"
    PlaneVisible  = 1
    Zoomlevel     = 1
  elseif thisWidget.gpsLat < North.small and thisWidget.gpsLat > South.small and thisWidget.gpsLong < East.small and thisWidget.gpsLong > West.small then
    thisWidget.map.current = "small"
    PlaneVisible  = 1
    Zoomlevel     = 2
  elseif thisWidget.gpsLat < North.medium and thisWidget.gpsLat > South.medium and thisWidget.gpsLong < East.medium and thisWidget.gpsLong > West.medium then   
    thisWidget.map.current = "medium"
    PlaneVisible  = 1
    Zoomlevel     = 3
  elseif thisWidget.gpsLat < North.large and thisWidget.gpsLat > South.large and thisWidget.gpsLong < East.large and thisWidget.gpsLong > West.large then   
    thisWidget.map.current = "large"
    PlaneVisible  = 1
    Zoomlevel     = 4
  elseif thisWidget.gpsLat < North.xlarge and thisWidget.gpsLat > South.xlarge and thisWidget.gpsLong < East.xlarge and thisWidget.gpsLong > West.xlarge then   
    thisWidget.map.current = "xlarge"
    PlaneVisible  = 1   
    Zoomlevel     = 5
  else
    thisWidget.map.current = "xlarge"
    PlaneVisible = 0
    Zoomlevel    = 5
  end

Even door mijn toevoegingen heen kijken :-)
 
Kleine noot..

Als je een model ingeladen hebt met de Map Widget, en schakeld daarna over naar een model zonder de Map Widget, en daarna direct weer overschakeld naar een ander model met Map Widget dan gaat het wel goed.

Het gebeurd alleen als je schakeld tussen 2 modellen die de Map Widget gebruiken.
 
Ik ga er mee aan de slag, maar het lijkt alsof je iets in de widget generiek zit te doen. Meestal een probleem met variabelen per ongeluk globaal hebben.
 
Björn,

ik heb je script eens doorgenomen.
Er ziiten een aantal fundamentele fouten in. Dat is niet erg, en widgets zijn erg onhandig opgezet, dus dat is niet zo raar.

Ik stel voor dat we even bellen via whatsapp of zoiets, dan licht ik de fouten toe. Je moet er zelf maar mee doen wat je nodig vind.

Stuur maar een PB met hoe ik je kan bereiken.
 
Hallo Björn,

ik ontdekte heel recent dit draadje en je script, en ik moet zeggen dat ik dit een fantastisch idee vind. Op ons terrein hebben we ook enkele beperkingen (no-fly), en dit script kan me daarbij enorm helpen. Dank!
Ik heb de maps voor ons terrein gegenereerd met behulp van je tooltje, maar dan kwam het volgende probleem: de coordinaten van de no-fly zone lijn bepalen.
Om dat wat te vereenvoudigen, heb ik een kleine update van het script gedaan (zie gedeelte TEST DEBUG, later te verwijderen), om zo door alle zoomlevels heen de no-fly coordinaten te testen via de Companion simulatie:

Debug GPS map LUA.png


Misschien kan dit anderen helpen...

Mijn volgende stap is om te doorgronden hoe er in de code een no-fly zone conditie wordt gedetecteerd...en of dit aan te passen is naar een complexere vorm (meerdere lijnen ter afbakening)
 
Na effe wat zoeken naar de LUA syntax, heb ik al een eerste stap kunnen zetten om een polygoon te gebruiken om de (no-)fly zone af te bakenen. Nu het algoritme nog toevoegen om te verifiëren of de huidige positie van het model wel of niet binnen die polygoon ligt. Komt goed.
GPS polygon.png
 
Dat ging vlotter dan ik dacht....
Als ik test-coordinaten invoer en het algoritme erop loslaat, en tekst op het scherm toon of het systeem denkt of het vliegtuig binnen of buiten de polygoon zit, krijg ik dit:
inside.png

not inside.png


Nu de code nog integreren, en we kunnen echt gaan testen.
 
Ik weet niet wat je met de cursor van de vliegtuigpositie hebt gedaan, maar het lijkt nu net of je een begraafplaats aanduid. [emoji12]
 
Ik zal voor de web generator eens kijken hoe ik die "border" punten kan omzetten met markers in google maps.. naar X.Y punten van het plaatje tov het zoomlevel.

Er zitten nog wat klein quircks in de code..
  • Als je een model hebt waarbij je de Widget gebruikt, en overschakeld naar een model die ook de widget gebruikt wordt de boel niet goed ingeladen. Hier moet nog aandacht aan besteerd worden om dit te fixen. tijdelijke oplossingen zijn:
    1. Eerst naar een model overschakelen die geen gebruik maakt van de widget, daarna weer overschakelen naar het uiteindelijke model wat je wilt gebruiken met de widget.
    2. Het model selecteren die je wilt gebruiken, dan zender herstarten.
  • Map selectie.
    • Map selectie is pas actief na herstart van de zender, of even ander model kiezen en weer terug naar het model.
  • Tevens had ik gisteren een emergency alarm tijdens een Reset van de widget.. mijn model stond aan de rand van het scherm.Vermoedelijk werd er iets buiten de 479x271 geschreven.
 
Laatst bewerkt:
Ik zal voor de web generator eens kijken hoe ik die "border" punten kan omzetten met markers in google maps.. naar X.Y punten van het plaatje tov het zoomlevel.

Dat zou heel handig zijn idd.
Intussen is het me gelukt om het algoritme voor no-flyzone detectie met een polygoon aan de praat te krijgen. Ik heb aan de array Map een array "poly" toegevoegd, waarin ik een set hoekpunten toevoeg per zoomlevel per kaart.
In de testversie toon ik tekst op het scherm met de indicatie of het model binnen of buiten de polygoon zit, dat kan nog verwijderd worden later.

Let nog niet teveel op de kleine details van mijn code...het is echt een testversie

Ik heb mijn wijzigingen gemarkeerd met
-- ********************************************
-- polygon no-fly update
-- ********************************************

Dit is mijn versie van main.lua:


Code:
---- ##########################################################################################################
---- #                                                                                                        #
---- # GPS Widget for FrSky Horus                                                                                  #
-----#                                                                                                        #
---- # License GPLv3: http://www.gnu.org/licenses/gpl-3.0.html                                                #
---- #                                                                                                        #
---- # This program is free software; you can redistribute it and/or modify                                   #
---- # it under the terms of the GNU General Public License version 3 as                                      #
---- # published by the Free Software Foundation.                                                             #
---- #                                                                                                        #
---- # Original idea and credits goes to Tonnie Oostbeek (Tonnie78)                                             #
---- #                                                                                                        #
---- # Revised by Björn Pasteuning / Hobby4life 2019                                                          #
---- #                                                                                                        #
---- # Changelog:                                                                                             #
---- #                                                                                                        #
---- # v1.6 - Added RSSI detect for noFlyzone alarm function                                                  #
---- # v1.7 - Added posibility to select maps with GV8                                                        #
---- # v1.8 - Added posibolity to select Heading/Bearing input with GV7                                       #
---- #        0 = Calculate, 1 = Use Sensor input                                                             #
---- # v1.9 - Added Reset function from a Source to reset all max values                                      #
---- # v1.9a- Small fix in reset function                                                                     #
---- # v2.0 - Added Satellite indicator                                                                       #
---- # v2.1 - 1) HomePoint indicator / will show after a sat fix...                                           #
---- #        2) Line of sight line added, can be turned on and off in widget settings                        #
---- #        3) NoFlyZone line color is fixed to RED                                                         #
---- #        4) PlaneColor is fixed to YELLOW                                                                #
---- #        5) Map now selectable from Widget Settings page                                                 #
---- # v2.3 - Cleaned up code, fixed NIL issue in LCD draw routines                                           #
---- # v2.4 - Added LoS distance in middle of LoSLine, and added bearing indicator from home to plane         #
---- # v2.5 - Distance is now calculated from 2 coordinates                                                   #
---- # v2.6 - Heading is now only calculated from 2 upfollowing coordinates                                   #
---- # v2.7 - Automatic detection of Altitude sensor, Vario Altimeter or GPS Altimeter                        #
---- #        Vario Altimeter has priority over GPS Altimeter                                                 #
---- # v2.8 - 1) If Plane is outside view of maps, "OUT OF RANGE" Message will appear                         #
---- #        2) If HomePoint is outside zoom level, HomePoint is not visible (fix)                           #
---- # v2.9   Changed Layout and masked bottom area due new map download function                             #
---- #        Maps can now be generated and downloaded from: https://www.hobby4life.nl/mapgen.htm             #
---- # v3.0   Now creating maps is much easier, 5 maps are now used                                           #
---- #        File structure changed!, remove GPSmap widget, and reinstall widget..                           #
---- #        Sometimes it looks like no map is loaded.                                                       #
---- #        Go to widget settings -> MapSelect and toggle between 0 and another map and back to 0           #
---- #        then close widget and restart radio to take effect.                                             #
---- ##########################################################################################################

Version     = "v3.0"  -- Current version
 
TotalMaps   = 1       -- Enter the amount of maps loaded, starts with 0 !!!!


local options = {
  { "ResetAll"  , SOURCE  , 1     },  --Define a source for trigger a reset of al max values
  { "Imperial"  , VALUE   , 0,0,1 },  --Toggle between Metric or Imperial notation, note that correct settings have to be set on the sensor page too!
  { "LosLine"   , VALUE   , 0,0,1 },  --Enable / Disable line of sight line between Home point and plane. 0 = off, 1 = on
  { "MapSelect" , VALUE   , 0,0,TotalMaps },  --Selects Map to load, needs model change or power cycle to take effect, 0 correnspondents to map0small.png, map0medium.png and map0large.png etc...
}


-- in the create function you add all shared variables to the array containing the widget data ('thisWidget')
local function create(zone, options)
 
  local thisWidget  = {zone=zone, options=options}
  local LoadMap     = thisWidget.options.MapSelect or 0

-- Declaration and preset of Global Widget Variables used in the entire scope --
  HomeLat     = 0
  HomeLong    = 0
  HomeSet     = 1
  DrawSock    = 0
  MaxDistance = 0
  MaxSpeed    = 0
  MaxAltitude = 0
  LoSDistance = 0
  MaxLoS      = 0
  TempLat     = 0
  TempLong    = 0
  HomePosx    = 0
  HomePosy    = 0
  HomeVisible = 1
 
  PlaneVisible= 0
 
  --create array containing all sensor ID's used for quicker retrieval
  local ID = {}
  ID.GPS        = getFieldInfo("GPS")  and getFieldInfo("GPS").id    or 0
  ID.GSpd       = getFieldInfo("GSpd") and getFieldInfo("GSpd").id or 0
  ID.Altimeter  = (getFieldInfo("Alt") and getFieldInfo("Alt").id) or (getFieldInfo("GAlt") and getFieldInfo("GAlt").id) or 0  -- Vario Altimeter has priority over GPS Altimeter
  ID.RSSI       = getFieldInfo("RSSI") and getFieldInfo("RSSI").id or 0
  ID.Tmp1       = getFieldInfo("Tmp1") and getFieldInfo("Tmp1").id or 0 -- used with OpenXsenor or sallites in view indicator

 
  --add ID to thisWidget
  thisWidget.ID = ID

  --create array containing all map info per map size
-- ********************************************
-- polygon no-fly update
-- ********************************************
  local map = {North={},South={},West={},East={},wx={},wy={},zx={},zy={}, poly={}}
--  local map = {North={},South={},West={},East={},wx={},wy={},zx={},zy={}}
-- ********************************************
-- END OF polygon no-fly update
-- ********************************************

if LoadMap == 0 then
 
-- LAC Lier

-- coordinates for the extra small map.
map.North.xsmall = 51.114654
map.South.xsmall = 51.113738
map.West.xsmall = 4.561133
map.East.xsmall = 4.563707
-- No Fly Zone screen coordinates for extra small map--
map.wx.xsmall = 0
map.wy.xsmall = 100
map.zx.xsmall = 90
map.zy.xsmall = 0

-- ********************************************
-- polygon no-fly update
-- ********************************************
map.poly.xsmall = {{90,0}, {478,0}, {478,235}, {220,235}, {20,70}}
-- ********************************************
-- END OF polygon no-fly update
-- ********************************************

-- coordinates for the small map.
map.North.small = 51.115112
map.South.small = 51.11328
map.West.small = 4.559845
map.East.small = 4.564995
-- No Fly Zone screen coordinates for small map--
map.wx.small = 0
map.wy.small = 230
map.zx.small = 270
map.zy.small = 0

map.poly.small = {{250,0}, {478,0}, {478,235}, {290,235}, {150,110}}

-- coordinates for the medium map.
map.North.medium = 51.116028
map.South.medium = 51.112364
map.West.medium = 4.55727
map.East.medium = 4.56757
-- No Fly Zone screen coordinates for medium map--
map.wx.medium = 40
map.wy.medium = 240
map.zx.medium = 330
map.zy.medium = 0

map.poly.medium = {{280,0}, {478,0}, {478,235}, {320,235}, {195,125}}

-- coordinates for the large map.
map.North.large = 51.11786
map.South.large = 51.110532
map.West.large = 4.55212
map.East.large = 4.57272
-- No Fly Zone screen coordinates for large map--
map.wx.large = 20
map.wy.large = 240
map.zx.large = 420
map.zy.large = 0

map.poly.large = {{300,0}, {478,0}, {478,235}, {340,235}, {210,120}}


-- coordinates for the extra large map.
map.North.xlarge = 51.121524
map.South.xlarge = 51.106868
map.West.xlarge = 4.541821
map.East.xlarge = 4.583019
-- No Fly Zone screen coordinates for extra large map--
map.wx.xlarge = 20
map.wy.xlarge = 240
map.zx.xlarge = 420
map.zy.xlarge = 0

map.poly.xlarge = {{300,0}, {478,0}, {478,235}, {345,235}, {225,130}}


elseif LoadMap == 1 then
......

end

    --add one bitmap per map size and set current map size
  map.bmp={}
  map.bmp.xsmall  = Bitmap.open("/widgets/GPSMap/maps/map"..LoadMap.."xsmall.png")
  map.bmp.small   = Bitmap.open("/widgets/GPSMap/maps/map"..LoadMap.."small.png")
  map.bmp.medium  = Bitmap.open("/widgets/GPSMap/maps/map"..LoadMap.."medium.png")
  map.bmp.large   = Bitmap.open("/widgets/GPSMap/maps/map"..LoadMap.."large.png")
  map.bmp.xlarge  = Bitmap.open("/widgets/GPSMap/maps/map"..LoadMap.."xlarge.png")

  WindSock = Bitmap.open("/widgets/GPSMap/icons/windsock.png")
  --HomeIcon = Bitmap.open("/widgets/GPSMap/home.png")
 
  --set current size
  map.current = "large"

  --add the map array to thisWidget
  thisWidget.map = map
 
  --return the thisWidget array to the opentx API, containing all data to be shared across functions
  return thisWidget
 
end

-- ********************************************
-- polygon no-fly update
-- ********************************************

--***********************************************************************
--*                           NO-FLY DETECTION FUNCTION                          *
--***********************************************************************
local function insidePolygon(polygon, planex, planey)
--  local polygon = thisWidget.map.poly[thisWidget.map.current]
    local oddNodes = false
    local j = #polygon
    for i = 1, #polygon do
        if (polygon[2] < planey and polygon[j][2] >= planey or polygon[j][2] < planey and polygon[2] >= planey) then
            if (polygon[1] + ( planey - polygon[2] ) / (polygon[j][2] - polygon[2]) * (polygon[j][1] - polygon[1]) < planex) then
                oddNodes = not oddNodes;
            end
        end
        j = i;
    end
 
   if (oddNodes) then
       lcd.drawText( 20, 136, "is inside", SMLSIZE + CUSTOM_COLOR)
   else
       lcd.drawText( 20, 136, "NOT inside", SMLSIZE + CUSTOM_COLOR)
   end
   return oddNodes
end


-- ********************************************
-- END OF polygon no-fly update
-- ********************************************



--***********************************************************************
--*                        BACKGROUND FUNCTION                          *
--***********************************************************************
local function background(thisWidget)
 
  ImperialSet = thisWidget.options.Imperial or 0
  --ExtHeadingSensor = thisWidget.options.ExtHdg or 0
  LosLineSet = thisWidget.options.LosLine or 0

 
  thisWidget.gpsLatLong = getValue(thisWidget.ID.GPS)
  if  (type(thisWidget.gpsLatLong) ~= "table") then
    thisWidget.ID.GPS       = getFieldInfo("GPS")  and getFieldInfo("GPS").id    or 0
    thisWidget.ID.GSpd      = getFieldInfo("GSpd") and getFieldInfo("GSpd").id or 0
    thisWidget.ID.Altimeter = (getFieldInfo("Alt") and getFieldInfo("Alt").id) or (getFieldInfo("GAlt") and getFieldInfo("GAlt").id) or 0
    thisWidget.ID.RSSI      = getFieldInfo("RSSI") and getFieldInfo("RSSI").id or 0
    thisWidget.ID.Tmp1      = getFieldInfo("Tmp1") and getFieldInfo("Tmp1").id or 0
    model.setGlobalVariable(8,0,0)
    return
  end
 
  thisWidget.Speed      = getValue(thisWidget.ID.GSpd)
  thisWidget.Altitude   = getValue(thisWidget.ID.Altimeter)
  thisWidget.Rssi       = getValue(thisWidget.ID.RSSI)
  thisWidget.Sats       = getValue(thisWidget.ID.Tmp1)

 
  thisWidget.gpsLat     = thisWidget.gpsLatLong.lat
  thisWidget.gpsLong    = thisWidget.gpsLatLong.lon
 
  -- Part for loading the correct zoomlevel of the map

-- coordinates for the smallest map. These can be found by placing the image back into Google Earth and looking at the overlay
-- parameters

  local North = thisWidget.map.North
  local South = thisWidget.map.South
  local East  = thisWidget.map.East
  local West  = thisWidget.map.West
 
  ------ Checks if Plane is visible in any map, otherwise disable plane view ------
  if thisWidget.gpsLat < North.xsmall and thisWidget.gpsLat > South.xsmall and thisWidget.gpsLong < East.xsmall and thisWidget.gpsLong > West.xsmall then
    thisWidget.map.current = "xsmall"
    PlaneVisible = 1
  elseif thisWidget.gpsLat < North.small and thisWidget.gpsLat > South.small and thisWidget.gpsLong < East.small and thisWidget.gpsLong > West.small then
    thisWidget.map.current = "small"
    PlaneVisible = 1
  elseif thisWidget.gpsLat < North.medium and thisWidget.gpsLat > South.medium and thisWidget.gpsLong < East.medium and thisWidget.gpsLong > West.medium then
    thisWidget.map.current = "medium"
    PlaneVisible = 1
  elseif thisWidget.gpsLat < North.large and thisWidget.gpsLat > South.large and thisWidget.gpsLong < East.large and thisWidget.gpsLong > West.large then
    thisWidget.map.current = "large"
    PlaneVisible = 1
  elseif thisWidget.gpsLat < North.xlarge and thisWidget.gpsLat > South.xlarge and thisWidget.gpsLong < East.xlarge and thisWidget.gpsLong > West.xlarge then
    thisWidget.map.current = "xlarge"
    PlaneVisible = 1
  else
    thisWidget.map.current = "large"
    PlaneVisible = 0
  end

-- Part for setting the correct zoomlevel ends here.
  North = North[thisWidget.map.current]
  South = South[thisWidget.map.current]
  East  = East[thisWidget.map.current]
  West  = West[thisWidget.map.current]

  thisWidget.x  = math.floor(480*((thisWidget.gpsLong - West)/(East - West)))
  thisWidget.y  = math.floor(272*((North - thisWidget.gpsLat)/(North - South)))
  thisWidget.x  = math.max(10,thisWidget.x)
  thisWidget.x  = math.min(thisWidget.x,470)
  thisWidget.y  = math.max(10,thisWidget.y)
  thisWidget.y  = math.min(thisWidget.y,262)

-- Calculate  home position in relation to map.
  if thisWidget.gpsLat ~= 0 and thisWidget.gpsLong ~= 0 then
    if HomeSet == 1 then
        HomeLat = thisWidget.gpsLat
        HomeLong = thisWidget.gpsLong
        HomeSet = 0
        DrawSock = 1
    end
      HomePosx = math.floor(480*((HomeLong - West)/(East - West)))
      HomePosy = math.floor(272*((North - HomeLat)/(North - South)))
      HomePosx = math.max(10,HomePosx)
      HomePosx = math.min(HomePosx,470)
      HomePosy = math.max(10,HomePosy)
      HomePosy = math.min(HomePosy,262)
  end

------ Checks if Homepoint is visible on the map otherwise disable view -------
  if HomeLat < North and HomeLat > South and HomeLong < East and HomeLong > West then
    HomeVisible = 1
  else
    HomeVisible = 0
  end

-------------------- Checks if plane crossed the nofly zone line and toggles GV9 Variable --------------
  local wx = thisWidget.map.wx[thisWidget.map.current]
  local wy = thisWidget.map.wy[thisWidget.map.current]
  local zx = thisWidget.map.zx[thisWidget.map.current]
  local zy = thisWidget.map.zy[thisWidget.map.current]

-- ********************************************
-- no-fly polygon update
-- ********************************************
  local testpolygon = thisWidget.map.poly[thisWidget.map.current]

  if (insidePolygon(testpolygon,thisWidget.x,thisWidget.y) and (thisWidget.Rssi > 0)) then
    model.setGlobalVariable(8,0,0)
  else
    model.setGlobalVariable(8,0,1)
  end



--  if (((thisWidget.x - wx)*(zy-wy))-((thisWidget.y - wy)*(zx-wx)) < 0) and (thisWidget.Rssi > 0) then
--    model.setGlobalVariable(8,0,0)
--  else
--    model.setGlobalVariable(8,0,1)
--  end
-- ********************************************
-- END OF no-fly polygon update
-- ********************************************

end
---------------------------------------------------------------------------------------------------------

--***********************************************************************
--*                          SPECIAL FUNCTIONS                          *
--***********************************************************************

----------------------- Function to calculated bearing angle between 2 coordinates ----------------------
function CalcBearing(PrevLat,PrevLong,NewLat,NewLong)
  local yCalc = math.sin(math.rad(NewLong)-math.rad(PrevLong)) * math.cos(math.rad(NewLat))
  local xCalc = math.cos(math.rad(PrevLat)) * math.sin(math.rad(NewLat)) - math.sin(math.rad(PrevLat)) * math.cos(math.rad(NewLat)) * math.cos(math.rad(NewLat) - math.rad(PrevLat))
  local Bearing = math.deg(math.atan2(yCalc,xCalc))
  if Bearing < 0 then
    Bearing = 360 + Bearing
  end
  return Bearing
end

----------------------- Function to calculate distance between 2 coordinates -----------------------------
function CalcDistance(PrevLat,PrevLong,NewLat,NewLong)
  local earthRadius = 0
  if ImperialSet == 1 then
    earthRadius = 20902000  --feet  --3958.8 miles
  else
    earthRadius = 6371000   --meters
  end
  local dLat = math.rad(NewLat-PrevLat)
  local dLon = math.rad(NewLong-PrevLong)
  PrevLat = math.rad(PrevLat)
  NewLat = math.rad(NewLat)
  local a = math.sin(dLat/2) * math.sin(dLat/2) + math.sin(dLon/2) * math.sin(dLon/2) * math.cos(PrevLat) * math.cos(NewLat)
  local c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
  return (earthRadius * c)
end

--***********************************************************************
--*                            UPDATE FUNCTION                          *
--***********************************************************************
local function update(thisWidget, options)
  thisWidget.options = options
end




--***********************************************************************
--*                           REFRESH FUNCTION                          *
--***********************************************************************
local function refresh(thisWidget)
 
  local NS        = ""
  local EW        = ""
  local FM        = ""
  local SPD       = ""
  local LCD_Lat   = thisWidget.gpsLat or 0
  local LCD_Long  = thisWidget.gpsLong or 0
  local LCD_Speed = thisWidget.Speed or 0
  local LCD_Alt   = thisWidget.Altitude or 0
  local LCD_Sats  = thisWidget.Sats or 0
  local xvalues   = { }
  local yvalues   = { }
  local x         = thisWidget.x or 0
  local y         = thisWidget.y or 0
 
   background(thisWidget)
 
  ------------------------------------------------------------------------------------------------------------
  RstAll = getValue(thisWidget.options.ResetAll) or 0
 
  if RstAll > 1000 then
    MaxDistance   = 0
    MaxSpeed      = 0
    MaxAltitude   = 0
    MaxLoS        = 0
    HomeSet       = 1
    DrawSock      = 0
    HomeLat       = thisWidget.gpsLat or 0
    HomeLong      = thisWidget.gpsLong or 0
  end
 
   ------------ Calculates Heading and Distance from Home to Plane position -------------------------------------------
  local HomeToPlaneBearing = CalcBearing(HomeLat,HomeLong,LCD_Lat,LCD_Long) or 0
  local HomeToPlaneDistance = CalcDistance(HomeLat,HomeLong,LCD_Lat,LCD_Long) or 0
  --- Temporary fix for overflow HomeToPlaneDistance variable.. on Reset it sometimes overflows
  if HomeToPlaneDistance > 100000 then -- When overflowing with 100
    HomeToPlaneDistance = 0
  end
----------------------------------------- Calculates max Ground Distance ----------------------------------
   if (HomeToPlaneDistance > MaxDistance) then
           MaxDistance = HomeToPlaneDistance
  end
-----------------------------------------------------------------------------------------------------------

------------------------------------------- Calculates max Speed ------------------------------------------
   if (LCD_Speed > MaxSpeed) then
       MaxSpeed = LCD_Speed
   end
----------------------------------------------------------------------------------------------------------

---------------------------------------- Calculates max Altitude -----------------------------------------
   if (LCD_Alt > MaxAltitude) then
       MaxAltitude = LCD_Alt
   end
-------------------------------------------------------------------------------------------------------------

-------------------------------- Calculates (max) Line Of Sight Distance ---------------------------------
   local a = math.floor(LCD_Alt)
   local b = math.floor(HomeToPlaneDistance)
   LoSDistance = math.floor(math.sqrt((a * a) + (b * b)))
   if LoSDistance > MaxLoS then
       MaxLoS = LoSDistance
   end

------------------------------ Checks if valid GPS data is received -------------------------------------
 if  (type(thisWidget.gpsLatLong) ~= "table") then
       lcd.drawBitmap(thisWidget.map.bmp.xlarge, thisWidget.zone.x -10, thisWidget.zone.y -10)
       lcd.setColor(CUSTOM_COLOR, lcd.RGB(255,0,0))
    lcd.drawFilledRectangle(0, 239, 480, 33, SOLID)
       lcd.drawText( 120, 236, "No GPS SIGNAL", DBLSIZE + CUSTOM_COLOR + SHADOWED)
       return
   end

------------ Calculates Heading Bearing from previous and new location of the plane ----------------------
  if (LCD_Lat ~= TempLat) and (LCD_Long ~= TempLong) then
    Bearing = CalcBearing(TempLat,TempLong,LCD_Lat,LCD_Long)
    TempLat = LCD_Lat
    TempLong = LCD_Long
  end
  headingDeg = Bearing or 0



-----------------------------------------LCD ROUTINES --------------------------------------------------
--                     A
--                     |
--                     |
-- C   _________________|___________________  D
--                     |
--                     |
--                     |
--                     |
--                     |
--                     |
--                     |
--                E ---|--- F
--                     B

  xvalues.ax = x + (4 * math.sin(math.rad(headingDeg)))                            -- front of fuselage x position
  yvalues.ay = y - (4 * math.cos(math.rad(headingDeg)))                            -- front of fuselage y position
  xvalues.bx = x - (7 * math.sin(math.rad(headingDeg)))                            -- rear of fuselage x position
  yvalues.by = y + (7 * math.cos(math.rad(headingDeg)))                            -- rear of fuselage y position
  xvalues.cx = x + (10 * math.cos(math.rad(headingDeg)))                            -- left wingtip x position
  yvalues.cy = y + (10 * math.sin(math.rad(headingDeg)))                           -- left wingtip y position
  xvalues.dx = x - (10 * math.cos(math.rad(headingDeg)))                           -- right wingtip x position
  yvalues.dy = y - (10 * math.sin(math.rad(headingDeg)))                           -- right wingtip y position
  xvalues.ex = x - ((7 * math.sin(math.rad(headingDeg))) + (3 * math.cos(math.rad(headingDeg))))   -- left tailwing tip x position
  yvalues.ey = y + ((7 * math.cos(math.rad(headingDeg))) - (3 * math.sin(math.rad(headingDeg))))   -- left tailwing tip y position
  xvalues.fx = x - ((7 * math.sin(math.rad(headingDeg))) - (3 * math.cos(math.rad(headingDeg))))   -- right tailwing tip x position
  yvalues.fy = y + ((7 * math.cos(math.rad(headingDeg))) + (3 * math.sin(math.rad(headingDeg))))   -- right tailwing tip y position
 
 
-- Preset info
   if LCD_Lat > 0 then
       NS = "N"
   else
       NS = "S"
   end

   if LCD_Long > 0 then
       EW = "E"
   else
       EW = "W"
   end
 
   if ImperialSet == 1 then
       FM  = "ft"
       SPD = "mph"
   else
       FM  = "m"
       SPD = "km/h"
   end
 
 
--draw background
  lcd.drawBitmap(thisWidget.map.bmp[thisWidget.map.current], thisWidget.zone.x -10, thisWidget.zone.y -10)
 

-- Draw nofly zone line --
  lcd.setColor(CUSTOM_COLOR, lcd.RGB(248,0,0))
-- ********************************************
-- polygon no-fly update
-- ********************************************
--  disable no-fly line drawing
--  lcd.drawLine(thisWidget.map.wx[thisWidget.map.current], thisWidget.map.wy[thisWidget.map.current], thisWidget.map.zx[thisWidget.map.current], thisWidget.map.zy[thisWidget.map.current], SOLID, CUSTOM_COLOR)
-- draw polygon--
   local tmp = thisWidget.map.poly[thisWidget.map.current]
   for i = 1, #thisWidget.map.poly[thisWidget.map.current]-1  do
       lcd.drawLine(tmp[1],tmp[2],tmp[i+1][1],tmp[i+1][2], SOLID, CUSTOM_COLOR)
   end
   local k = #thisWidget.map.poly[thisWidget.map.current]
   lcd.drawLine(tmp[k][1],tmp[k][2],tmp[1][1],tmp[1][2], SOLID, CUSTOM_COLOR)
-- ********************************************
-- END OF polygon no-fly update
-- ********************************************
 
 
  if PlaneVisible == 1 then
  -- Draws plane --
    lcd.setColor(CUSTOM_COLOR, lcd.RGB(248,252,0))
    lcd.drawLine(xvalues.ax, yvalues.ay, xvalues.bx, yvalues.by, SOLID, CUSTOM_COLOR)
    lcd.drawLine(xvalues.cx, yvalues.cy, xvalues.dx, yvalues.dy, SOLID, CUSTOM_COLOR)
    lcd.drawLine(xvalues.ex, yvalues.ey, xvalues.fx, yvalues.fy, SOLID, CUSTOM_COLOR)
  end

-- Draws the Windsock as Homepoint & display Plane direction angle from Homepoint
  if HomeVisible == 1 then
    if DrawSock == 1 then
      lcd.drawBitmap(WindSock, HomePosx-16, HomePosy-16, 50)
      lcd.setColor(CUSTOM_COLOR, lcd.RGB(248,0,248))
      local SockFlags = CUSTOM_COLOR + SMLSIZE + SHADOWED
      local SockX = HomePosx
      local SockY = HomePosy
      if SockX > 470 then
        SockFlags = SockFlags + RIGHT
      end
      if SockY < 10 then
        SockY = SockY + 10
      elseif SockY > 256 then
        SockY = SockY - 10
      end
      lcd.drawText(SockX, SockY, math.floor(HomeToPlaneBearing).."deg", SockFlags)
    end
  end

  if PlaneVisible == 1 and HomeVisible == 1 then
  -- Enables a Line of Sight line when homeposition has been set, and enabled in Widget config menu
    if (HomeSet == 0) and (LosLineSet == 1) then
      lcd.setColor(CUSTOM_COLOR, lcd.RGB(0, 252, 0))
      lcd.drawLine(x,y,HomePosx,HomePosy, DOTTED, CUSTOM_COLOR)
      local MidLosLineX = ((x + HomePosx)/2)
      local MidLosLineY = ((y + HomePosy)/2)
      local LosFlags = CUSTOM_COLOR + SMLSIZE + SHADOWED
      if MidLosLineX > 470 then
        LosFlags = LosFlags + RIGHT
      end
      if MidLosLineY < 10 then
        MidLosLineY = MidLosLineY + 10
      elseif MidLosLineY > 256 then
        MidLosLineY = MidLosLineY - 10
      end
      lcd.setColor(CUSTOM_COLOR, WHITE)
      lcd.drawText(MidLosLineX, MidLosLineY, math.floor(HomeToPlaneDistance)..FM , LosFlags)
    end
  else
    if PlaneVisible == 0 then
      lcd.setColor(CUSTOM_COLOR, lcd.RGB(255,0,0))
      lcd.drawText( 120, 120, "OUT OF RANGE", DBLSIZE + CUSTOM_COLOR + SHADOWED)
    end
  end
 
 
  lcd.drawFilledRectangle(0, 239, 480, 33, SOLID)



-- Draws all flight information on screen --
 lcd.setColor(CUSTOM_COLOR, WHITE)

  lcd.drawText(10, 239, "Speed: "..math.floor(LCD_Speed)..SPD, CUSTOM_COLOR + SMLSIZE + SHADOWED)
  lcd.drawText(10, 255, "Max: "..math.floor(MaxSpeed)..SPD , CUSTOM_COLOR + SMLSIZE + SHADOWED)
 
  lcd.drawText(130, 239, "Alt: "..math.floor(LCD_Alt)..FM, CUSTOM_COLOR + SMLSIZE + SHADOWED)
  lcd.drawText(130, 255, "Max: "..math.floor(MaxAltitude)..FM , CUSTOM_COLOR + SMLSIZE + SHADOWED)
 
  lcd.drawText(240, 239, "Dist: "..math.floor(HomeToPlaneDistance)..FM, CUSTOM_COLOR + SMLSIZE + SHADOWED)
  lcd.drawText(240, 255, "Max: "..math.floor(MaxDistance)..FM , CUSTOM_COLOR + SMLSIZE + SHADOWED)
 
  lcd.drawText(360, 239, "LoS: "..math.floor(LoSDistance)..FM, CUSTOM_COLOR + SMLSIZE + SHADOWED)
  lcd.drawText(360, 255, "Max: "..math.floor(MaxLoS)..FM , CUSTOM_COLOR + SMLSIZE + SHADOWED)

  if LCD_Sats > 0  then
    lcd.drawText(10, 32, "Satellites: "..math.floor(LCD_Sats), CUSTOM_COLOR + SMLSIZE + SHADOWED)
  end

  lcd.drawText(10, 16, "Heading: "..math.floor(headingDeg).."deg" , CUSTOM_COLOR + SMLSIZE + SHADOWED)
  lcd.drawText(10, 0, "Lat: "..NS..math.abs(LCD_Lat).." / Lon: "..EW..math.abs(LCD_Long), CUSTOM_COLOR + SMLSIZE +SHADOWED)
 
  lcd.drawText(470, 0, Version , CUSTOM_COLOR + SMLSIZE + RIGHT + SHADOWED)

end
return { name="Map", options=options, create=create, update=update, background=background, refresh=refresh }
 
Laatst bewerkt:
Tof project!
Phaedra, hoe krijg ik je versie gedownload? Ik vind je versie top omdat we ook met een beperking zitten langs 4 zijden.
 
Bedankt N.P.S. Ik probeer het dit WE. Zat momenteel te proberen met mijn Ipad vanuit Praag maar dat lukte niet.
 
Als je mijn versie gebruikt, kan je best nog even volgende lijnen uit de functie insidePolygon weghalen:

Code:
if (oddNodes) then
       lcd.drawText( 20, 136, "is inside", SMLSIZE + CUSTOM_COLOR)
   else
       lcd.drawText( 20, 136, "NOT inside", SMLSIZE + CUSTOM_COLOR)
   end

Dat was ik nog vergeten te doen voor ik de code hier postte....
 
OK , kopiëren was eenvoudig met Windows.
Heb ook de lijnen uit de functie insidePolygon gehaald op advies van Phaedra.
Nu nog de kaartjes aanmaken.
Ik laat nog iets weten. Dit is mijn eerste widget, kan wat tijd nemen.
Alvast bedankt.
 
Ik heb nog een paar kleinere wijzigingen aangebracht.
  • Bij het buiten de polygoon vliegen werd het alarm nooit getriggerd (L14 triggert als GV9 >0; bij L14 audio melding en haptic). Dit kwam voort uit het feit dat ik GV9 alleen in flight mode 0 aanpaste. Ik voegde extra regels toe voor de andere flight modes.
  • Eens dat in orde was, kreeg ik het alarm constant tot ik een geldige GPS positie had. Ik voegde enkele condities toe om dat op te vangen (zie code hieronder).


Code:
-- ********************************************
-- no-fly polygon update
-- ********************************************
  local testpolygon = thisWidget.map.poly[thisWidget.map.current]

  if ((insidePolygon(testpolygon,thisWidget.x,thisWidget.y) == false) and (thisWidget.Rssi > 0) and
      (type(thisWidget.gpsLatLong) == "table") and (PlaneVisible == 1)) then
    -- if a valid GPS position is received, and RSSI is valid, and position is inside polygon, set GVAR 9 to 1
    model.setGlobalVariable(8,0,1)
    model.setGlobalVariable(8,1,1)
    model.setGlobalVariable(8,2,1)
  else
    model.setGlobalVariable(8,0,0)
    model.setGlobalVariable(8,1,0)
    model.setGlobalVariable(8,2,0)
  end
 
Back
Top