GPS Widget voor FrSky Horus

Discussie in 'Model elektronica' gestart door toostbeek, 12 apr 2019.

  1. Hobby4Life

    Hobby4Life

    Lid geworden:
    20 nov 2009
    Berichten:
    1.329
    Locatie:
    Avenhorn, NL
    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 :)
     
  2. Hobby4Life

    Hobby4Life

    Lid geworden:
    20 nov 2009
    Berichten:
    1.329
    Locatie:
    Avenhorn, NL
    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.
     
  3. l shems

    l shems

    Lid geworden:
    27 jan 2015
    Berichten:
    1.045
    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.
     
  4. l shems

    l shems

    Lid geworden:
    27 jan 2015
    Berichten:
    1.045
    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.
     
  5. Hobby4Life

    Hobby4Life

    Lid geworden:
    20 nov 2009
    Berichten:
    1.329
    Locatie:
    Avenhorn, NL
    Okidoki ik ben erg benieuwd.. ik heb je een pb gestuurd
     
  6. Phaedra

    Phaedra

    Lid geworden:
    20 aug 2011
    Berichten:
    505
    Locatie:
    omgeving Antwerpen
    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)
     
    toostbeek vindt dit leuk.
  7. toostbeek

    toostbeek

    Lid geworden:
    6 dec 2014
    Berichten:
    1.415
    Het is zeker mogelijk om complexere gebieden als nofly zone te creëren.
     
  8. Phaedra

    Phaedra

    Lid geworden:
    20 aug 2011
    Berichten:
    505
    Locatie:
    omgeving Antwerpen
    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
     
  9. Phaedra

    Phaedra

    Lid geworden:
    20 aug 2011
    Berichten:
    505
    Locatie:
    omgeving Antwerpen
    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.
     
    Hobby4Life vindt dit leuk.
  10. toostbeek

    toostbeek

    Lid geworden:
    6 dec 2014
    Berichten:
    1.415
    Ik weet niet wat je met de cursor van de vliegtuigpositie hebt gedaan, maar het lijkt nu net of je een begraafplaats aanduid.
     
  11. Hobby4Life

    Hobby4Life

    Lid geworden:
    20 nov 2009
    Berichten:
    1.329
    Locatie:
    Avenhorn, NL
    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: 31 okt 2019
  12. Phaedra

    Phaedra

    Lid geworden:
    20 aug 2011
    Berichten:
    505
    Locatie:
    omgeving Antwerpen
    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: 31 okt 2019
  13. Phaedra

    Phaedra

    Lid geworden:
    20 aug 2011
    Berichten:
    505
    Locatie:
    omgeving Antwerpen
    Tja, 't is de tijd van het jaar he....
     
    toostbeek vindt dit leuk.
  14. gie

    gie

    Lid geworden:
    17 apr 2017
    Berichten:
    25
    Locatie:
    Belgie
    Tof project!
    Phaedra, hoe krijg ik je versie gedownload? Ik vind je versie top omdat we ook met een beperking zitten langs 4 zijden.
     
  15. N.P.S.

    N.P.S. Forum veteraan

    Lid geworden:
    17 jun 2007
    Berichten:
    9.115
  16. gie

    gie

    Lid geworden:
    17 apr 2017
    Berichten:
    25
    Locatie:
    Belgie
    Bedankt N.P.S. Ik probeer het dit WE. Zat momenteel te proberen met mijn Ipad vanuit Praag maar dat lukte niet.
     
  17. Phaedra

    Phaedra

    Lid geworden:
    20 aug 2011
    Berichten:
    505
    Locatie:
    omgeving Antwerpen
    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....
     
  18. gie

    gie

    Lid geworden:
    17 apr 2017
    Berichten:
    25
    Locatie:
    Belgie
    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.
     
  19. Phaedra

    Phaedra

    Lid geworden:
    20 aug 2011
    Berichten:
    505
    Locatie:
    omgeving Antwerpen
    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
     
    Hobby4Life vindt dit leuk.
  20. Hobby4Life

    Hobby4Life

    Lid geworden:
    20 nov 2009
    Berichten:
    1.329
    Locatie:
    Avenhorn, NL
    Lekker bezig! :)
     

Deel Deze Pagina