Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Change Flowgraph to be declarative rather than implicit #482

Open
jwmelto opened this issue Mar 2, 2021 · 0 comments
Open

Proposal: Change Flowgraph to be declarative rather than implicit #482

jwmelto opened this issue Mar 2, 2021 · 0 comments

Comments

@jwmelto
Copy link
Contributor

jwmelto commented Mar 2, 2021

This is a proposal for a destructive change to the way GNSS-SDR flowgraphs are composed. It would not (necessarily) be backwards compatible with existing config files. The purpose of this proposal is to generate discussion on the pros and cons to this approach.

Background

The GNSS-SDR relies upon core/receiver/gnss_flowgraph.cc to connect all the blocks together to create the GNSS application. Mostly.

In the config file, various classes of components (SignalSource, SignalConditioner, Channel, PVT, etc) may be specified with various implementations. However, the connection between these components is done in software, in the gnss_flowgraph source. In particular, the connection between SignalSource and SignalConditioner is particularly brittle.

Proposal

Since each component (adapter) derives from the common GNSSBlockInterface, I propose that each block declaratively specify its upstream (left-hand) connection in the config file. This is, I think, consistent with the GNU Radio philosophy of composable blocks being wired together. The output of each block in the config file would need a unique identifier. This would make it easier to support multi-channel sources, and would eliminate the need for PassThrough objects in the graph.

This type of loose coupling would also facilitate integration of additional algorithms. For example, the spoofing detection algorithm implemented in https://github.com/oscimp/gnss-sdr doesn't fit well into the existing paradigm, because it takes two inputs and produces two outputs. However, you would not want to feed both outputs into the Channel, because it would be redundant data. There is currently no way to specify a block that takes 2 inputs and produces 2 outputs, so the original author hard-coded the algorithm in the SignalSource.

Another consideration is having multiple instances of the Channel blocks. Suppose you had two independent antennas and you wanted to compare the solutions achieved between them. There is no good mechanism to do this. You could run two instances of GNSS-SDR, but to add a new algorithm that consumes the output of two instances is not supported.

Example

Here's a notional fragment of how this might be implemented:

[GNSS-SDR]

;######### GLOBAL OPTIONS ##################
GNSS-SDR.internal_fs_sps=2000000

;######### SIGNAL_SOURCE CONFIG ############
SignalSource0.implementation=File_Signal_Source
SignalSource0.RF_channels=1
SignalSource0.filename=../data/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat
SignalSource0.item_type=ishort
SignalSource0.sampling_frequency=4000000

;######### SIGNAL_CONDITIONER CONFIG ############
; the SignalConditioner is a composite object, consisting of DataTypeAdapter, InputFilter, and Resampler
; this composite is only required because the blocks can't be directly chained. It would be removed in this implementation

;######### DATA_TYPE_ADAPTER CONFIG ############
DataTypeAdapter0.implementation=Ishort_To_Complex
DataTypeAdapter0.input0=SignalSource0.output0 ; <- connect SignalSource0 output 0 to the input of the adapter

;######### INPUT_FILTER CONFIG ############
; no need for a pass-through filter

;######### RESAMPLER CONFIG ############
Resampler0.implementation=Direct_Resampler
Resampler0.input0=DataTypeAdapter0.output0 ; <- connect resampler to data type adapter
Resampler0.item_type=gr_complex ; <- ideally, this is derived from the input
Resampler0.sample_freq_in=4000000 ; <- ideally, this is derived from the input
Resampler0.sample_freq_out=2000000 ; <- we warn if this isn't GNSS-SDR.internal_fs_sps ... so does it need specifying?

; SampleCounter is explicitly constructed
SampleCounter0.implementation=SampleCounter
SampleCounter0.input0=Resampler0.output0 ; <- counter is explicitly attached

;######### CHANNELS GLOBAL CONFIG ############
Channels_1C.count=6
Channels_1B.count=0
Channels.in_acquisition=1

;######### SPECIFIC CHANNELS CONFIG ######
; The Channel is the core of the GNSS application. It makes sense for this complex algorithm to remain encapsulated
; behind this composite type

;######### CHANNEL 0 CONFIG ############
;Channel0.signal=1C
;Channel0.satellite=11
Channel0.input0=Resampler0.output0 ; <- channel 0 acquisition

;######### CHANNEL 1 CONFIG ############
;Channel1.signal=1C
;Channel1.satellite=18
Channel1.input0=Resampler0.output0 ; <- channel 1 acquisition


;######### OBSERVABLES CONFIG ############
Observables0.implementation=Hybrid_Observables
Observables0.input0=Channel0.output0 ; <- observables 0 is channel 0
Observables0.input1=Channel1.output0 ; <- observables 1 is channel 1
Observables0.input2=SampleCounter0.output0 ; <- observables N is sample counter ... made explicit
; note that this relies on the user to connect a sample counter explicitly
; an alternative is to get Channel0 input (left block) and connect that to a hidden sample counter
; the current reliance on SignalConditioner0 is brittle

; the rest of the file is elided for brevity

Consequences

Besides not being backwards-compatible with existing config files, this requires a central registry of GNSSBlockInterface objects, so that they can be found by their name.

Another thing I haven't thought through is the interdependence of objects. Today, the config file is not parsed sequentially, creating all the objects referenced; rather the flowgraph looks for specific classes of objects. The number of signal sources (for example) must be specified (if greater than 1). Now, since arbitrary objects can connect to other arbitrary objects, a way to ensure the existence of each object needs to be developed.

On the plus side, creating and attaching unique monitors becomes trivial. Additional algorithms can be integrated with minimal effort. Multiple input/multiple output signal sources and signal conditioners are trivially easy to connect. The directed acyclic graph of the application is explicitly asserted in the config file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant