Skip to content

Commit

Permalink
refactor: save satellite state in dictionaries and simplify track
Browse files Browse the repository at this point in the history
Dictionaries.jl provides an efficient way to save satellite state
in dictionaries. It is a lot easier to merge / remove satellite state
with this commit while at the same time it is still efficient.
Moreover, state that's needed for doppler estimation or to
downconvert and correlate the signal is now directly saved into
SatState, which removes the difficulty to sync with the corresponding
hierarchic of satellite system -> satellite prn.
  • Loading branch information
Soeren Schoenbrod committed Jul 8, 2024
1 parent a243dac commit af0a8d3
Show file tree
Hide file tree
Showing 27 changed files with 1,349 additions and 1,086 deletions.
4 changes: 2 additions & 2 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ env:
SECRET_CODECOV_TOKEN: "Q3fuMdJjaQy9h/uk43rwSqz8M6ulvlCedU2Ir0S3QLP4t9F8cf7pzrTkX+nVhkGycZ/r5FRtTOwPr445R3wK5v9mEAsJN5GMOgI5w/L8m2XDwLmW3PN8RMno+fm2JVxZyPMNNmIQqbYEmmQcBS6Q3nywW3xi0Cl5umJuwDB+NdOFbpq3wc2wrnbOAbwlBJoCJmlH+F4ncuVY6EMmsgNKAf9RqUNWQxIthG616X1cNwuYEpL4dO/PWY2GMXWXTQ8ndO/713p4b5yIlzDP0mr2MrO+1A5fhgPc7Vr+f9mUlIAx+9AsWQYPrqPTkr2L5+mfaTodVE3u2Cop877WJZQD7w==;U2FsdGVkX1/wk2jzfWlRZ66IWgionQK/5Fu0pg3u0b26hhmmMjAjOklyi7QZKhJHjjt4KjK/dJzhd3eK28S0qQ=="

steps:
- label: "Julia v1.6"
- label: "Julia v1.8"
plugins:
- JuliaCI/julia#v1:
version: "1.6"
version: "1.8"
- JuliaCI/julia-test#v1: ~
- JuliaCI/julia-coverage#v1:
codecov: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
fail-fast: false
matrix:
version:
- '1.6' # Replace this with the minimum Julia version that your package supports. E.g. if your package requires Julia 1.5 or higher, change this to '1.5'.
- '1.8' # Replace this with the minimum Julia version that your package supports. E.g. if your package requires Julia 1.5 or higher, change this to '1.5'.
- '1' # Leave this line unchanged. '1' will automatically expand to the latest stable 1.x release of Julia.
- 'nightly'
os:
Expand Down
7 changes: 5 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ authors = ["Soeren Schoenbrod <[email protected]>", "Michael
version = "0.15.2"

[deps]
Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
Acquisition = "d4bbf60b-102b-5ffb-8f97-a7ea5817e69f"
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
Dictionaries = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4"
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
GNSSSignals = "52c80523-2a4e-5c38-8979-05588f836870"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Expand All @@ -18,12 +20,13 @@ Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"

[compat]
Acquisition = "0.1.1"
CUDA = "4.0"
CUDA = "5.0"
Dictionaries = "0.4.1"
DocStringExtensions = "0.6, 0.7, 0.8, 0.9"
GNSSSignals = "0.17.1"
LoopVectorization = "0.8, 0.9, 0.10, 0.11, 0.12"
StaticArrays = "0.9, 0.10, 0.11, 0.12, 1.0"
StructArrays = "0.4, 0.6.5"
TrackingLoopFilters = "0.1"
Unitful = "0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 1.0"
julia = "1.6"
julia = "1.8"
75 changes: 62 additions & 13 deletions src/Tracking.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ using LoopVectorization
using StaticArrays
using StructArrays
using TrackingLoopFilters
using Dictionaries
using Accessors

using Acquisition: AcquisitionResults
using Unitful: upreferred, Hz, dBHz, ms
Expand All @@ -30,6 +32,7 @@ export get_early,
get_bits,
get_accumulators,
get_early_late_sample_spacing,
get_system_sats_state,
track,
NumAnts,
NumAccumulators,
Expand All @@ -38,22 +41,31 @@ export get_early,
EarlyPromptLateCorrelator,
VeryEarlyPromptLateCorrelator,
SecondaryCodeOrBitDetector,
GainControlledSignal,
AbstractPostCorrFilter,
SatState,
SystemSatsState,
CPUDownconvertAndCorrelator,
GPUDownconvertAndCorrelator,
CPUSatDownconvertAndCorrelator,
CPUSystemDownconvertAndCorrelator,
GPUSatDownconvertAndCorrelator,
GPUSystemDownconvertAndCorrelator,
SystemConventionalPLLAndDLL,
TrackingConventionalPLLAndDLL,
NoSatPostProcess,
NoSystemPostProcess,
NoTrackingPostProcess,
ConventionalPLLAndDLL,
ConventionalPLLsAndDLLs,
DefaultPostCorrFilter,
TrackState,
add_sats!,
remove_sats!,
merge_sats,
filter_out_sats,
get_sat_states,
get_sat_state,
get_system,
estimate_cn0
estimate_cn0,
get_default_correlator,
convert_code_to_texture_memory

const Maybe{T} = Union{T,Nothing}

const StructVecOrMat{T} = Union{StructVector{T},StructArray{T,2}}

Expand All @@ -67,11 +79,23 @@ NumAccumulators(x) = NumAccumulators{x}()

TupleLike{T<:Tuple} = Union{T,NamedTuple{<:Any,T}}

struct DopplersAndFilteredPrompt
carrier_doppler::typeof(1.0Hz)
code_doppler::typeof(1.0Hz)
filtered_prompt::ComplexF64
end
abstract type AbstractSatDopplerEstimator end
abstract type AbstractSystemDopplerEstimator end
abstract type AbstractTrackingDopplerEstimator end

"""
$(SIGNATURES)
Abstract downconverter and correlator type. Structs for
downconversion and correlation must have this abstract type as a
parent.
"""
abstract type AbstractSatDownconvertAndCorrelator end
abstract type AbstractSystemDownconvertAndCorrelator end

abstract type AbstractSatPostProcess end
abstract type AbstractSystemPostProcess end
abstract type AbstractTrackingPostProcess end

"""
$(SIGNATURES)
Expand Down Expand Up @@ -99,12 +123,37 @@ include("gpsl1.jl")
include("gpsl5.jl")
include("galileo_e1b.jl")
include("sat_state.jl")

struct TrackState{
S<:MultipleSystemSatsState{
N,
<:AbstractGNSS,
<:SatState{
<:AbstractCorrelator,
<:AbstractSatDopplerEstimator,
<:AbstractSatDownconvertAndCorrelator,
<:AbstractSatPostProcess,
},
<:AbstractSystemDopplerEstimator,
<:AbstractSystemDownconvertAndCorrelator,
<:AbstractSystemPostProcess,
} where {N},
DE<:AbstractTrackingDopplerEstimator,
P<:AbstractTrackingPostProcess,
}
multiple_system_sats_state::S
doppler_estimator::DE
post_process::P
num_samples::Int
end

include("sample_parameters.jl")
include("update_sat_state.jl")
include("doppler_estimator.jl")
include("downconvert_and_correlate.jl")
include("downconvert_and_correlate_cpu.jl")
include("downconvert_and_correlate_gpu.jl")
include("conventional_pll_and_dll.jl")
include("tracking_state.jl")
include("post_process.jl")
include("track.jl")
end
175 changes: 82 additions & 93 deletions src/conventional_pll_and_dll.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
abstract type AbstractDopplerEstimator end
struct SystemConventionalPLLAndDLL <: AbstractSystemDopplerEstimator end
struct TrackingConventionalPLLAndDLL <: AbstractTrackingDopplerEstimator end

struct ConventionalPLLAndDLL{
CA<:AbstractLoopFilter,
CO<:AbstractLoopFilter,
F<:AbstractPostCorrFilter,
}
} <: AbstractSatDopplerEstimator
init_carrier_doppler::typeof(1.0Hz)
init_code_doppler::typeof(1.0Hz)
carrier_loop_filter::CA
Expand All @@ -15,16 +16,17 @@ struct ConventionalPLLAndDLL{
end

function ConventionalPLLAndDLL(
sat_state::SatState,
carrier_doppler,
code_doppler;
carrier_loop_filter = ThirdOrderBilinearLF(),
code_loop_filter = SecondOrderBilinearLF(),
carrier_loop_filter_bandwidth = 18Hz,
code_loop_filter_bandwidth = 1Hz,
post_corr_filter = DefaultPostCorrFilter(),
)
ConventionalPLLAndDLL(
sat_state.carrier_doppler,
sat_state.code_doppler,
float(carrier_doppler),
float(code_doppler),
carrier_loop_filter,
code_loop_filter,
float(carrier_loop_filter_bandwidth),
Expand All @@ -33,13 +35,6 @@ function ConventionalPLLAndDLL(
)
end

struct ConventionalPLLsAndDLLs{
N,
PD<:TupleLike{<:NTuple{N,Vector{<:ConventionalPLLAndDLL}}},
} <: AbstractDopplerEstimator
plls_and_dlls::PD
end

"""
$(SIGNATURES)
Expand Down Expand Up @@ -74,89 +69,83 @@ the incoming signal did not provide enough samples, it will return struct with
zeroed values.
"""
function estimate_dopplers_and_filter_prompt(
doppler_estimator::ConventionalPLLsAndDLLs,
system_sats_state::TupleLike{<:NTuple{N,SystemSatsState}},
sat_sample_params::TupleLike{<:NTuple{N,Vector{SampleParams}}},
track_state::TrackState{
<:MultipleSystemSatsState{
N,
<:AbstractGNSS,
<:SatState{<:AbstractCorrelator,<:ConventionalPLLAndDLL},
<:SystemConventionalPLLAndDLL,
},
<:TrackingConventionalPLLAndDLL,
},
sample_params::TupleLike{<:NTuple{N,Dictionary{I,SampleParams}}},
sampling_frequency,
min_integration_time,
) where {N}
results = map(
doppler_estimator.plls_and_dlls,
system_sats_state,
sat_sample_params,
) do estimator_per_system, system_sats, sat_sample_params_per_system
map(
estimator_per_system,
system_sats.states,
sat_sample_params_per_system,
) do estimator, state, sample_params
integration_time = state.integrated_samples / sampling_frequency
return if sample_params.signal_samples_to_integrate ==
sample_params.samples_to_integrate_until_code_end &&
integration_time >= min_integration_time
correlator = normalize(state.correlator, state.integrated_samples)
post_corr_filter =
update(estimator.post_corr_filter, get_prompt(correlator))
filtered_correlator = apply(post_corr_filter, correlator)
pll_discriminator = pll_disc(system_sats.system, filtered_correlator)
dll_discriminator = dll_disc(
system_sats.system,
filtered_correlator,
(state.code_doppler + get_code_frequency(system_sats.system)) /
sampling_frequency,
)
carrier_freq_update, carrier_loop_filter = filter_loop(
estimator.carrier_loop_filter,
pll_discriminator,
integration_time,
estimator.carrier_loop_filter_bandwidth,
)
code_freq_update, code_loop_filter = filter_loop(
estimator.code_loop_filter,
dll_discriminator,
integration_time,
estimator.code_loop_filter_bandwidth,
)
carrier_doppler, code_doppler = aid_dopplers(
system_sats.system,
estimator.init_carrier_doppler,
estimator.init_code_doppler,
carrier_freq_update,
code_freq_update,
)
dopplers_and_filtered_prompt = DopplersAndFilteredPrompt(
carrier_doppler,
code_doppler,
get_prompt(filtered_correlator),
)
new_estimator = ConventionalPLLAndDLL(
estimator.init_carrier_doppler,
estimator.init_code_doppler,
carrier_loop_filter,
code_loop_filter,
estimator.carrier_loop_filter_bandwidth,
estimator.code_loop_filter_bandwidth,
post_corr_filter,
)
(
estimator = new_estimator,
dopplers_and_filtered_prompt = dopplers_and_filtered_prompt,
)
else
(
estimator = estimator,
dopplers_and_filtered_prompt = DopplersAndFilteredPrompt(
0.0Hz,
0.0Hz,
complex(0.0, 0.0),
),
)
) where {I,N}
new_multiple_system_sats_state = map(
track_state.multiple_system_sats_state,
sample_params,
) do system_sats_state, system_sample_params
new_sat_states = map(
system_sats_state.states,
system_sample_params,
) do sat_state, sat_sample_params
integration_time = sat_state.integrated_samples / sampling_frequency
if sat_sample_params.signal_samples_to_integrate !=
sat_sample_params.samples_to_integrate_until_code_end ||
integration_time < min_integration_time
return sat_state
end
estimator = sat_state.doppler_estimator
correlator = normalize(sat_state.correlator, sat_state.integrated_samples)
post_corr_filter =
update(estimator.post_corr_filter, get_prompt(correlator))
filtered_correlator = apply(post_corr_filter, correlator)
pll_discriminator = pll_disc(system_sats_state.system, filtered_correlator)
dll_discriminator = dll_disc(
system_sats_state.system,
filtered_correlator,
(sat_state.code_doppler + get_code_frequency(system_sats_state.system)) / sampling_frequency,
)
carrier_freq_update, carrier_loop_filter = filter_loop(
estimator.carrier_loop_filter,
pll_discriminator,
integration_time,
estimator.carrier_loop_filter_bandwidth,
)
code_freq_update, code_loop_filter = filter_loop(
estimator.code_loop_filter,
dll_discriminator,
integration_time,
estimator.code_loop_filter_bandwidth,
)
carrier_doppler, code_doppler = aid_dopplers(
system_sats_state.system,
estimator.init_carrier_doppler,
estimator.init_code_doppler,
carrier_freq_update,
code_freq_update,
)
new_estimator = ConventionalPLLAndDLL(
estimator.init_carrier_doppler,
estimator.init_code_doppler,
carrier_loop_filter,
code_loop_filter,
estimator.carrier_loop_filter_bandwidth,
estimator.code_loop_filter_bandwidth,
post_corr_filter,
)
return update(
system_sats_state.system,
sat_state,
sat_sample_params,
carrier_doppler,
code_doppler,
get_prompt(filtered_correlator),
new_estimator,
)
end
return SystemSatsState(system_sats_state, new_sat_states)
end
new_doppler_estimator =
ConventionalPLLsAndDLLs(map(x -> map(y -> y.estimator, x), results))
new_dopplers_and_filtered_prompts =
map(x -> map(y -> y.dopplers_and_filtered_prompt, x), results)
new_doppler_estimator, new_dopplers_and_filtered_prompts
end
return TrackState(track_state, new_multiple_system_sats_state)
end
2 changes: 2 additions & 0 deletions src/correlator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -548,3 +548,5 @@ end
function zero_accumulators(accumulators::Vector{<:SVector{NA}}, signal) where {NA}
zeros(real(eltype(signal)), NA, length(accumulators))
end

get_shifts(c::AbstractCorrelator) = c.shifts
Loading

0 comments on commit af0a8d3

Please sign in to comment.