Using the MagNav Package with Simulated Data

This file is best viewed in a Pluto notebook. To run it this way, from the MagNav.jl directory, do:

julia> using Pluto
julia> Pluto.run() # select & open notebook

This is a reactive notebook, so feel free to change any parameters of interest.

Import packages and DataFrames

The DataFrames listed below provide useful information about the flight data collected by Sander Geophysics Ltd. (SGL) & magnetic anomaly maps.

DataframeDescription
df_mapmap files relevant for SGL flights
df_calSGL calibration flight lines
df_flightSGL flight files
df_allall flight lines
df_navall navigation-capable flight lines
df_eventpilot-recorded in-flight events
begin
    cd(@__DIR__)
    # uncomment line below to use local MagNav.jl (downloaded folder)
    # using Pkg; Pkg.activate("../"); Pkg.instantiate()
    using MagNav
    using CSV, DataFrames
    using Plots: plot, plot!
    using Random: seed!
    using Statistics: mean, median, std
    seed!(33); # for reproducibility
    include("dataframes_setup.jl"); # setup DataFrames
end;

Load map data and create flight data

The built-in NAMAD map is used to create flight data.

begin
    seed!(33)  # ensure create_XYZ0() reproducibility
    t    = 600 # flight time [s]
    mapS = get_map(MagNav.namad) # load map data
    xyz  = create_XYZ0(mapS;alt=mapS.alt,t=t) # create flight data
    traj = xyz.traj # trajectory (GPS) struct
    ins  = xyz.ins  # INS struct
    mapS = map_trim(mapS,traj;pad=10) # trim map for given trajectory (with padding)
    itp_mapS = map_interpolate(mapS)  # map interpolation function
end;

The xyz flight data struct is of type MagNav.XYZ0 (for the minimum dataset required for MagNav), which is a subtype of MagNav.XYZ (the abstract type for any flight data in MagNav.jl). There are 7 fields, which can be accessed using dot notation. These fields are described in the docs, which are easily accessed by searching MagNav.XYZ0 in the Live Docs in the lower right within Pluto.

typeof(xyz)
MagNav.XYZ0{Int64, Float64}
fieldnames(MagNav.XYZ0)
(:info, :traj, :ins, :flux_a, :flight, :line, :year, :doy, :diurnal, :igrf, :mag_1_c, :mag_1_uc)

Create a navigation filter model.

(P0,Qd,R) = create_model(traj.dt,traj.lat[1]);

Run the navigation filter (EKF), determine the Cramér–Rao lower bound (CRLB), & extract output data.

begin
    mag_use = xyz.mag_1_c # selected magnetometer (using compensated mag)
    (crlb_out,ins_out,filt_out) = run_filt(traj,ins,mag_use,itp_mapS,:ekf;P0,Qd,R)
end;

Plotting setup.

begin
    t0 = traj.tt[1]/60    # [min]
    tt = traj.tt/60 .- t0 # [min]
end;

Position (lat & lot) for trajectory (GPS), INS (after zeroing), & navigation filter.

begin
    p1 = plot_map(mapS;map_color=:gray); # map background
    plot_filt!(p1,traj,ins,filt_out;show_plot=false) # overlay GPS, INS, & filter
    plot!(p1,legend=:topleft) # move as needed
end

Northing & easting INS error (after zeroing).

begin
    p2 = plot(xlab="time [min]",ylab="error [m]",legend=:topright,dpi=200)
    plot!(p2,tt,ins_out.n_err,lab="northing")
    plot!(p2,tt,ins_out.e_err,lab="easting")
end
(p3,p4) = plot_filt_err(traj,filt_out,crlb_out;show_plot=false);

Northing navigation filter residuals.

p3

Easting navigation filter residuals.

p4

Display the map or flight paths in Google Earth by uncommenting below to generate a KMZ file (mapS) or KML files (traj, ins, filt_out), then open in Google Earth.

begin
    # map2kmz(mapS,"pluto_sim_map")
    # path2kml(traj,"pluto_sim_gps")
    # path2kml(ins,"pluto_sim_ins")
    # path2kml(filt_out,"pluto_sim_filt")
end;