MV

MV

Sunday, September 9, 2012

Free Aviation GPS for Android (How to make a moving map GPS)

I am ready to upload my latest application on Android Play store and it is free. There are no po-up ads, and no hidden charges. Similar applications charge $50 to begin with. This is a thank you gift from me to the open source community whose tools I have used throughout my career, and whose tools I used to prepare the sectional maps for the GPS.

I name it Avare. Here is a Video showing Avare use.

Not only that Avare is free, I will give sources, maps, databases, and scripts I used to design and make it.

The application works on any Android device with a GPS. Most of the testing was performed on a first generation Android device running Cyanogen Mod Android 2.2, although I recommend using an external Bluetooth GPS for better accuracy, and at least a tablet device for larger screen area.

Total application size is about 350 MB which includes all 48 state sectional charts, an airport AFD database, fonts, and the application itself. I did not buy the maps, I prepared them using scripts run on free FAA sectional charts raster images. Features include ground track bearing, speed, altitude; distance, bearing, and ETA to the destination, destination AFD, and distance, bearing to any point on the map. Maps can be zoomed, and panned just like pictures using two fingers on the touch screen.

It was mostly an exercise in trigonometry, projections, Geo-tagging, and GPS coordinate systems, more than it was an Android programming experience.

Following are some technical details related to the maps and databases preparations. You can email me at governer@gmail.com if you have technical questions on this topic. I will cover Android application programming technical details with code snippets in next few blogs to keep this blog entry manageable.

---- Technical details for preparing maps

The raster maps are available on FAA website at http://aeronav.faa.gov/index.asp?xml=aeronav/applications/VFR/chartlist_sect.

There are 37 sectionals for 48 states, each one divided into 2 parts, North and South. File format is TIFF with Lambert-Conformal-Conic-2 "projection". Total combined data size of these maps is about 10 Gigabyte. The maps are typically updated every 6 months on a per sectional basis.

I needed a script that could automatically download the 37 zip files, unzip them, re-project them to WGS84 (GPS longitude, latitude), burn the borders and legends, combine the 74 TIFF files to generate a master map for the 48 states, then cut this master map to tiles of 512x512 pixels, convert each tile to JPEG while storing the longitude, and latitude of each tile in a Sqlite database, appending the airport facilities directory (also downloaded from FAA) to this database, then zipping the entire structure into one big zip file that will be used the application.

Since Google store does not allow application sizes of greater than 50 MB, I had to split the maps from the application. The maps also get uploaded to the Play store, and my application downloads them when installing on the devices. Android allows loading resources from a ZIP file so I do not unzip the 16000+ JPEG tiles and some databases because that doubles the storage requirement.

The script is a combination of perl, bash, make, C, and uses GDAL python, and TIFF tools. I had to recompile GDAL with BigTIFF support because the master map is 10 GB large TIFF picture, and TIFF files cannot be bigger than 4GB unless BigTIFF is enabled.

Why did I divide the master map into 16000 tiles? This is because even a PC cannot display such a large map, so I have to have tiles on the phone device which I can load from a particular section of the map under the GPS location.

This is  (100th the area) scaled image of the New York North Sectional. 
74 such maps are combined to generate the master map. The legends on the left (and on South for South maps) need to be burnt.

This shows the considerably smaller version of the 100000 pixel  by 40000 pixel master map. 
You can see some seams along sectional boundaries which are due to scanning seams in the individual maps themselves

And this is Alaska


This is the actual size 512 pixel by 512 pixel tile generated by cutting the master image (above) into 16000 equal area pieces. 15 such tiles will be loaded from the area under the aircraft by the app. I store the longitude and latitude of each tile in a Sqlite database.
As you can see there are some black tiles in the master images. I detect and throw away these black tiles by doing a simple Unix diff with a reference zero energy JPEG as part on my automated script.

Everything is done automatically. I just run the script on a fast machine at night, and the maps/database zip file for the application is ready in the morning. Downloading takes an hour on a fast connection, processing the maps takes about 7 hours. The scripts are easy to write once you figure out the technical details with projections, and all technology related to Geo-Tagging. Can I be called a Cartographer after exploring these details?


FAA raster maps can be downloaded using a modified Perl script of http://www.mikealeonetti.com/wiki/index.php/Download_all_files_on_a_website_perl_script (Thank you  Mike A. Leonetti).

So a simple make rule will be:

download:
        mkdir charts
        cd charts && \
        rm -rf *.zip && \
        perl ../reapfiles.pl -f zip http://aeronav.faa.gov/index.asp?xml=aeronav/applications/VFR/chartlist_sect

Then unzip rule is:

unzip:
        cd charts && \
        rm -f *.tif && \
        unzip \*.zip \*.tif && \
        for file in *\ *; do \
                mv "$$file" `echo $$file | sed 's/ //g'`;\
        done

Then I wrote a simple C program that I call stage. This program uses GDAL to stage the 74 charts for combining into a master image. stage.c is attached at the end of the blog.

stage:
        cc stage.c -o stage
        rm -rf merge
        mkdir merge
        ./stage


Maps need to be merged, projected/warped, converted to RGB,  and legends removed. This is done with the stage.c program which uses GDAL (gdal.org).

This is New York North/South joined, and projected to WGS84 ( EPSG:4326). Legends on left and bottom need to be removed.

Side legends removed. This map is ready to be integrated with 36 others to create the master map. Note that circles appear as ovals in projected maps. I have a solution for this when displaying them.

Next, all 37 staged maps are combined to one master image. The master image, matser.tif is 10 GB large.

oneimage:
        rm -f master.tif master.jpeg
        gdal_merge.py merge/*_c.tif -o master.tif
        gdal_translate -outsize 2% 2% -of JPEG master.tif master_small.jpeg

Then split to 512x512 tiles.

split:
        rm -rf tiles
        mkdir tiles
        gdal_retile.py -targetDir tiles -ps 512 512 -useDirForEachRow master.tif


And then the rule for database preparation (see the import of AFD data in the end):

finalize:
        rm -f maps.db
        sqlite3 maps.db 'create table files(name varchar(64),lonul float,latul float,lonll float,latll float,lonur float,latur float,lonlr float,latlr float,lonc float,latc float);'
        for file in `find tiles -name "*.tif" -print | sed 's/.tif'// | sort`; do \
                echo $$file ; \
                gdal_translate -of jpeg -co QUALITY=50 $$file.tif $$file.jpeg; \
                rm -f $$file.jpeg.aux.xml ; \
                cmp -s $$file.jpeg black_tile.jpeg ; \
                RETVAL=$$?; \
                if [ $$RETVAL -eq 0 ]; then \
                        echo removing $$file.jpeg because it has no info ; \
                        rm $$file.jpeg ; \
                else \
                        sqlite3 maps.db "insert into files values(\"$$file\",`gdalinfo $$file.tif | grep "Upper Left" | sed 's/Upper Left\s*(\s*//' | sed 's/).*//'`, `gdalinfo $$file.tif | grep "Lower Left" | sed 's/Lower Left\s*(\s*//' | sed 's/).*//'`, `gdalinfo $$file.tif | grep "Upper Right" | sed 's/Upper Right\s*(\s*//' | sed 's/).*//'`, `gdalinfo $$file.tif | grep "Lower Right" | sed 's/Lower Right\s*(\s*//' | sed 's/).*//'`, `gdalinfo $$file.tif | grep "Center" | sed 's/Center\s*(\s*//' | sed 's/).*//'`);" ; \
                fi ; \
        done
        sqlite3 maps.db < import.sql

And in the end, generate the zip file for use by the Android app:

zip:
        rm -f tiles.zip
        zip -r -i \*.jpeg -i \*.db -1 -T -q tiles.zip tiles maps.db


Application details coming up in next Blog, at the launch of the application.


If you use my application, or you find this information helpful, I request you to donate some money to keep my PC generating maps when there are FAA updates:

18 comments:

  1. Wow. I'm impressed. I don't have an android, but have been playing with the same ideas on a laptop, win7. Thank you for the insights.

    Any Mouse

    ReplyDelete
  2. Zubair, I'm playing with a Raspberry Pi application (Raspbian) that acts as an AHRS, GPS and budget EFIS. I've got the maps but I'm having a hard time figuring out how to trim off the collar (the white info section on the left-hand side of the charts) and the black banding that the re-projection leaves on the top and bottom. Any pointers? Thanks in advance. -S

    ReplyDelete
  3. Steve,
    To trim the left corner or right, you will have to manually read the coordinates where to trim.
    For black banding, you will have to trim the corners for a squarer chart, which will loose info on the chart, but the adjoining chart makes up the lost info as it overlaps.
    For doing the two above steps together first warp then,
    gdal_translate -q -projwin tl bl tr br warped.tif cut.tif
    You will need to read the tl bl tr br coordinated from the chart.

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. Hello,

    I would be happy to donate if you would provide a link to the project files.

    Thanks,
    Steve

    ReplyDelete
  6. Zubair, its very nice program. How are you displaying maps by using Java code or WebView component. I can see you mixed two implementations. By the way why you are not simply using tif files? Thanks,
    David

    ReplyDelete
  7. David... Android does not support tif format. Each picture occupies a region of lat/long hence it does not need geo ref, but just a proper name.

    ReplyDelete
  8. David... Android does not support tif format. Each picture occupies a region of lat/long hence it does not need geo ref, but just a proper name.

    ReplyDelete
  9. But I can see you are calling GDAL in your library https://github.com/apps4av/avare/search?utf8=%E2%9C%93&q=GDAL

    ReplyDelete
  10. GDAL is used for merging charts. Its re-projected to a display friendly projection like Google projection.

    ReplyDelete
  11. This comment has been removed by the author.

    ReplyDelete
  12. Hey Zubair, can I use the process you explain here to have Sectional Charts on web google maps??

    ReplyDelete
  13. Really a great addition. I have read this marvelous post. Thanks for sharing information about it. I really like that. Thanks so lot for your convene. Cheat engine for ios

    ReplyDelete
  14. Awesome article, it was exceptionally helpful! I simply began in this and I'm becoming more acquainted with it better! Cheers, keep doing awesome! spotify premium apk download

    ReplyDelete
  15. Wow, What an Outstanding post. I found this too much informatics. It is what I was seeking for. I would like to recommend you that please keep sharing such type of info.If possible, Thanks.
    Cellcare92

    ReplyDelete
  16. To play Nintendo Entertainment System games without console, Visit RomsArena

    ReplyDelete
  17. nice blog !!!! thanks to share very useful information ... so thanks crzhondaprice

    ReplyDelete