GNU Radio is a free and open-source software development toolkit that provides signal processing blocks to implement software radios. It is used with readily-available low-cost external RF (radio frequency) hardware to create software-defined radios, or without hardware in a simulation-like environment.
GNU Radio is widely used in education, research, industry, and amateur radio communities for rapid prototyping, experimentation, and signal analysis without expensive hardware.
sudo apt-get update
sudo apt-get install gnuradio gnuradio-dev
sudo apt-get install libuhd-dev uhd-host # For USRP hardware support
sudo apt-get install gr-osmosdr # For RTL-SDR and other SDRs
git clone https://github.com/gnuradio/gnuradio.git
cd gnuradio
mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make install
sudo ldconfig
pip install gnuradio
pip install gnuradio-osmosdr # RTL-SDR support
The graphical tool for building radio applications.
gnuradio-companion
# or shorter
grcc
- Open GNU Radio Companion
- Drag and drop signal processing blocks
- Connect input/output ports
- Configure block parameters
- Generate Python code or run directly
- Test and refine
| Command | Purpose |
|---|
gnuradio-companion | Launch GUI block editor |
grcc file.grc | Compile GRC file to Python script |
python3 file.py | Run generated flowgraph |
gr_filter_design | GUI filter design tool |
gr_plot_qt | Plot signal data with Qt |
gr_plot_fft | FFT visualization tool |
import gnuradio
from gnuradio import gr, blocks, analog, filter
import math
# Create a top-level block
class SimpleFlowgraph(gr.top_block):
def __init__(self):
gr.top_block.__init__(self, "Simple FM Example")
# Signal source: 440 Hz sine wave
self.signal_source = analog.sig_source_f(
sample_rate=48000,
waveform=analog.GR_SIN_WAVE,
frequency=440,
amplitude=1
)
# Sink to print samples
self.null_sink = blocks.null_sink(gr.sizeof_float)
# Connect source to sink
self.connect(self.signal_source, self.null_sink)
if __name__ == '__main__':
tb = SimpleFlowgraph()
tb.start()
input('Press Enter to quit')
tb.stop()
tb.wait()
import numpy as np
from gnuradio import gr, blocks, fft
class FFTFlowgraph(gr.top_block):
def __init__(self):
gr.top_block.__init__(self, "FFT Example")
# Create test signal
sample_rate = 1e6
freq = 10e3 # 10 kHz
duration = 1 # 1 second
samples = int(sample_rate * duration)
t = np.arange(samples) / sample_rate
signal = np.exp(2j * np.pi * freq * t).astype(np.complex64)
# Vector source with signal
self.vector_source = blocks.vector_source_c(signal)
# FFT block
self.fft = fft.fft_vcc(1024, True, ())
# Null sink
self.null_sink = blocks.null_sink(gr.sizeof_gr_complex * 1024)
self.connect(self.vector_source, self.fft, self.null_sink)
if __name__ == '__main__':
tb = FFTFlowgraph()
tb.start()
tb.wait()
| Block | Description |
|---|
analog.sig_source_* | Generate sine, cosine, square, sawtooth waveforms |
blocks.vector_source_* | Provide pre-defined data samples |
blocks.file_source | Read samples from file |
blocks.udp_source | Receive samples via UDP |
osmosdr.source | Receive from RTL-SDR or USRP |
| Block | Description |
|---|
filter.fir_filter_* | FIR filtering |
filter.iir_filter_* | IIR filtering |
fft.fft_vcc | FFT computation |
analog.nbfm_rx | Narrow-band FM demodulation |
analog.fm_deemph | FM de-emphasis filter |
digital.gmsk_mod | GMSK modulation |
| Block | Description |
|---|
blocks.null_sink | Discard samples |
blocks.file_sink | Write to file |
blocks.udp_sink | Send via UDP |
osmosdr.sink | Transmit via USRP/SDR |
qtgui.time_sink_f | Time-domain plot |
qtgui.freq_sink_c | Frequency-domain plot |
from gnuradio import gr, blocks, analog, filter, digital
import osmosdr
class FMDemod(gr.top_block):
def __init__(self, freq=99.5e6, sample_rate=1e6):
gr.top_block.__init__(self, "FM Demodulation")
# SDR source
self.sdr = osmosdr.source(args="numchan=1")
self.sdr.set_sample_rate(sample_rate)
self.sdr.set_center_freq(freq)
self.sdr.set_freq_corr(0)
self.sdr.set_gain(25)
# Low-pass filter
self.lpf = filter.fir_filter_ccf(
1, filter.firdes.low_pass(1, sample_rate, 75e3, 25e3)
)
# Decimate by 10
self.decim = digital.rational_resampler_ccf(1, 10)
# FM demodulator
self.demod = analog.fm_demod_cf(
channel_rate=sample_rate/10,
audio_decim=1,
deviation=75e3,
audio_pass=15e3,
audio_stop=16e3,
gain=1,
tau=75e-6
)
# Audio sink
self.audio_sink = blocks.null_sink(gr.sizeof_float)
# Connect
self.connect(self.sdr, self.lpf, self.decim, self.demod, self.audio_sink)
if __name__ == '__main__':
tb = FMDemod()
tb.start()
try:
input("Press Ctrl+C to stop")
except KeyboardInterrupt:
pass
tb.stop()
tb.wait()
from gnuradio import gr, blocks
import numpy as np
# Create and save test signal
sample_rate = 1e6
num_samples = 1000000
duration = num_samples / sample_rate
# Generate complex sine
t = np.arange(num_samples) / sample_rate
freq = 100e3
signal = np.exp(2j * np.pi * freq * t).astype(np.complex64)
# Save to file
signal.tofile('test_signal.cfile')
# Read from file in GNU Radio
class FileReadFlowgraph(gr.top_block):
def __init__(self):
gr.top_block.__init__(self)
# Read from file
self.file_source = blocks.file_source(
gr.sizeof_gr_complex, 'test_signal.cfile', False
)
# Analysis sink
self.null_sink = blocks.null_sink(gr.sizeof_gr_complex)
self.connect(self.file_source, self.null_sink)
gr_filter_design
Then in Python, apply the generated filter:
from gnuradio import filter
# Low-pass filter at 100 kHz cutoff, 25 kHz transition
taps = filter.firdes.low_pass(
gain=1.0,
sample_rate=1e6,
cutoff_freq=100e3,
transition_width=25e3,
window=filter.firdes.WIN_HAMMING
)
lpf = filter.fir_filter_ccf(1, taps)
# Band-pass filter
taps = filter.firdes.band_pass(
gain=1.0,
sample_rate=1e6,
low_cutoff_freq=100e3,
high_cutoff_freq=200e3,
transition_width=10e3
)
# Band-stop (notch)
taps = filter.firdes.band_reject(
gain=1.0,
sample_rate=1e6,
low_cutoff_freq=100e3,
high_cutoff_freq=200e3,
transition_width=10e3
)
# High-pass
taps = filter.firdes.high_pass(
gain=1.0,
sample_rate=1e6,
cutoff_freq=100e3,
transition_width=10e3
)
# Install RTL-SDR drivers
sudo apt-get install rtl-sdr
sudo apt-get install gr-osmosdr
# Check device
rtl_test -t
from gnuradio import gr, blocks, qtgui
import osmosdr
import sys
class RTLSDRReceiver(gr.top_block):
def __init__(self):
gr.top_block.__init__(self, "RTL-SDR Receiver")
# Create SDR source
self.rtl = osmosdr.source(args="numchan=1 rtl=0")
self.rtl.set_sample_rate(2.4e6)
self.rtl.set_center_freq(100e6) # 100 MHz
self.rtl.set_gain(40)
# Time sink for visualization
self.ts = qtgui.time_sink_c(
1024, # size
2.4e6, # sample rate
"RTL-SDR Time", # title
1 # number of channels
)
# Frequency sink
self.fs = qtgui.freq_sink_c(
1024,
2.4e6,
"RTL-SDR Frequency",
1
)
# Connect
self.connect(self.rtl, self.ts)
self.connect(self.rtl, self.fs)
if __name__ == '__main__':
tb = RTLSDRReceiver()
tb.start()
try:
input("Press Ctrl+C to stop")
except KeyboardInterrupt:
pass
tb.stop()
tb.wait()
# 1. Use decimation to reduce sample rate
decimation = 10 # Reduce rate by factor of 10
# 2. Use integer arithmetic where possible
# 3. Minimize copying with in-place operations
# 4. Profile code with gr-perf-monitorx
# 4. Use hardware acceleration (SIMD) when available
| Problem | Solution |
|---|
| Segmentation fault | Update GNU Radio: pip install --upgrade gnuradio |
| Module not found | Install missing module: sudo apt-get install gr-<module> |
| SDR not detected | Check USB connection, run rtl_test |
| Poor performance | Reduce sample rate, increase decimation |
| No audio output | Check sink configuration and volume settings |
# Enable verbose logging
grcc -v flowgraph.grc
# Run with GDB
gdb --args python3 flowgraph.py