Friday, October 17, 2025

Re: Detection of drones

Hi Pedro,

"detecing drones" feels like an overall complicated problem, and we can't know what you
mean by "nothing is working", I'm afraid!

I see you have multiple out-of-tree blocks (some or all of which you have written
yourself?) in your flow graph – cool!

So, go ahead and make sure they work individually. Especially, build something that allows
you to test your "Energy Detector" block without an SDR, in pure software!

I haven't done an intense reading of your Python code, but there's definitely a syntax
error in there – so you really need to make sure all things work in isolation before
plugging them together.

Best,
Marcus


On 10/16/25 4:13 PM, Pedro Tapia wrote:
> hi everyone, i am trying to use gnuradio for drone detection but nothing is working, if
> anyone can help import numpy as np
> from gnuradio import gr
> import pmt
> from threading import Timer, Lock
>
> class freq_scanner(gr.sync_block):
>     def __init__(self, start_freq=2.4e9, stop_freq=2.5e9, step_freq=5e6, dwell_time=0.5):
>         gr.sync_block.__init__(self,
>             name="Frequency Scanner",
>             in_sig=None,
>             out_sig=None) # Não precisamos mais da saída de sinal
>
>         self.message_port_register_out(pmt.intern("cmd"))
>
>         self._start_freq = float(start_freq)
>         self._stop_freq = float(stop_freq)
>         self._step_freq = float(step_freq)
>         self._dwell_time = float(dwell_time)
>         self.current_freq = self._start_freq
>         # --- A "Caixa de Correio" agora guarda apenas um número (float) ---
>         self.freq_to_send = None
>         self.lock = Lock()
>
>         # Iniciamos o timer
>         self.timer = Timer(self._dwell_time, self.prepare_next_freq)
>         self.timer.start()
>
>     def prepare_next_freq(self):
>         """Esta função é chamada pelo timer e APENAS CALCULA a frequência."""
>         next_freq = self.current_freq + self._step_freq
>         if next_freq > self._stop_freq:
>             next_freq = self._start_freq
>         self.current_freq = next_freq
>         print(f"Timer preparou! Próxima Freq: {self.current_freq / 1e6:.2f} MHz", flush=True)
>         # Coloca APENAS o número float na caixa de correio
>         with self.lock:
>             self.freq_to_send = self.current_freq
>
>         # Reinicia o timer
>         self.timer = Timer(self._dwell_time, self.prepare_next_freq)
>         self.timer.start()
>
>     def stop(self):
>         self.timer.cancel()
>         return True
>
>     def work(self, input_items, output_items):
>         """A função work agora faz TODO o trabalho de PMT e publicação."""
>         local_freq_to_send = None
>         # Pega o número da caixa de correio
>         with self.lock:
>             if self.freq_to_send is not None:
>                 local_freq_to_send = self.freq_to_send
>                 self.freq_to_send = None # Esvazia a caixa
>
>         # Se havia um número para enviar...
>         if local_freq_to_send is not None:
>             # ...Cria o dicionário PMT AQUI, no thread principal...
>             msg_dict = pmt.make_dict()
>             msg_dict = pmt.dict_add(msg_dict, pmt.intern("freq"),
> pmt.from_double(local_freq_to_send))
>             # ...e publica AQUI, no thread principal.
>             self.message_port_pub(pmt.intern("cmd"), msg_dict)
>         return 0  import numpy as np
> from gnuradio import gr
> import pmt
> import scipy.special as scs
> from threading import Lock
>
> class Energy_Detector(gr.basic_block):
>     def __init__(self, samples=1024, Pfa=0.01):
>         self.samples = int(samples)
>         self.Pfa = float(Pfa)
>
>         gr.basic_block.__init__(self,
>             name="Energy_Detector",
>             in_sig=[(np.float32, self.samples), (np.float32, self.samples)],
>             out_sig=None)
>
>         self.message_port_register_out(pmt.intern("detection_in"))
>         self.message_port_register_in(pmt.intern("freq_in"))
>         # CORREÇÃO 1: Nome da função corrigido
>         self.set_msg_handler(pmt.intern("freq_in"), self.handle_freq_msg)
>         self.current_center_freq = 0.0 # Inicializa a frequência
>         self.lock = Lock()
>
>     def handle_freq_msg(self, msg):
>         if pmt.is_dict(msg):
>             freq_val = pmt.dict_ref(msg, pmt.intern("freq"), pmt.PMT_NIL)
>             if not pmt.is_nil(freq_val):
>                 with self.lock:
>                     self.current_center_freq = pmt.to_double(freq_val)
>
>     def general_work(self, input_items, output_items):
>         signal_energy_vector = input_items[0][0]
>         noise_vector = input_items[1][0]
>
>         signalAvg = np.mean(signal_energy_vector)
>         NoisePower = noise_vector ** 2
>         NoiseAvg = np.mean(NoisePower)
>         var = np.var(NoisePower)
>         stdev = np.sqrt(var)
>
>         Qinv = np.sqrt(2) * scs.erfinv(1 - 2 * self.Pfa)
>         Threshold = NoiseAvg + Qinv * stdev
>
>         # CORREÇÃO 3: Lógica de detecção corrigida
>         if signalAvg > Threshold:
>             local_center_freq = 0.0
>             with self.lock:
>                 local_center_freq = self.current_center_freq
>             # Só envia a mensagem se a frequência for válida (maior que zero)
>             if local_center_freq > 0:
>                 msg_tuple = pmt.make_tuple(
>                     pmt.from_float(float(signalAvg)),
>                     pmt.from_float(1.0),
>                     pmt.from_double(local_center_freq)
>                 )
>                 self.message_port_pub(pmt.intern("detection_in"), msg_tuple)
>
>         # CORREÇÃO 2: Consumo explícito das portas
>         self.consume(0, 1)
>         self.consume(1, 1)
>         return 0     freq_hz = pmt.to_double(pmt.tuple_ref(msg, 2))
>                 freq_mhz = freq_hz / 1e6
>
>                 # Imprime o alerta formatado no terminal
>                 print("="*40)
>                 print("!!! ALERTA: SINAL DE DRONE DETECTADO !!!")
>                 print(f"    Frequência: {freq_mhz:.2f} MHz")
>                 print(f"    Energia do Sinal: {energy:.4f}")
>                 print("="*40, flush=True) # flush=True para garantir a impressão imediata
>
>         except Exception as e:
>             print(f"Alert Formatter - Erro ao processar mensagem: {e}")
>             print(f"Mensagem recebida: {msg}")
>
>     def work(self, input_items, output_items):
>         # Este bloco não processa sinais de streaming, apenas mensagens.
>         # Portanto, a função work não faz nada.
>         return 0

Thursday, October 16, 2025

Detection of drones

hi everyone, i am trying to use gnuradio for drone detection but nothing is working, if anyone can help import numpy as np
from gnuradio import gr
import pmt
from threading import Timer, Lock

class freq_scanner(gr.sync_block):
    def __init__(self, start_freq=2.4e9, stop_freq=2.5e9, step_freq=5e6, dwell_time=0.5):
        gr.sync_block.__init__(self,
            name="Frequency Scanner",
            in_sig=None,
            out_sig=None) # Não precisamos mais da saída de sinal

        self.message_port_register_out(pmt.intern("cmd"))

        self._start_freq = float(start_freq)
        self._stop_freq = float(stop_freq)
        self._step_freq = float(step_freq)
        self._dwell_time = float(dwell_time)
        
        self.current_freq = self._start_freq
        
        # --- A "Caixa de Correio" agora guarda apenas um número (float) ---
        self.freq_to_send = None
        self.lock = Lock()

        # Iniciamos o timer
        self.timer = Timer(self._dwell_time, self.prepare_next_freq)
        self.timer.start()

    def prepare_next_freq(self):
        """Esta função é chamada pelo timer e APENAS CALCULA a frequência."""
        
        next_freq = self.current_freq + self._step_freq
        if next_freq > self._stop_freq:
            next_freq = self._start_freq
        
        self.current_freq = next_freq
        
        print(f"Timer preparou! Próxima Freq: {self.current_freq / 1e6:.2f} MHz", flush=True)
        
        # Coloca APENAS o número float na caixa de correio
        with self.lock:
            self.freq_to_send = self.current_freq

        # Reinicia o timer
        self.timer = Timer(self._dwell_time, self.prepare_next_freq)
        self.timer.start()

    def stop(self):
        self.timer.cancel()
        return True

    def work(self, input_items, output_items):
        """A função work agora faz TODO o trabalho de PMT e publicação."""
        
        local_freq_to_send = None
        # Pega o número da caixa de correio
        with self.lock:
            if self.freq_to_send is not None:
                local_freq_to_send = self.freq_to_send
                self.freq_to_send = None # Esvazia a caixa

        # Se havia um número para enviar...
        if local_freq_to_send is not None:
            # ...Cria o dicionário PMT AQUI, no thread principal...
            msg_dict = pmt.make_dict()
            msg_dict = pmt.dict_add(msg_dict, pmt.intern("freq"), pmt.from_double(local_freq_to_send))
            
            # ...e publica AQUI, no thread principal.
            self.message_port_pub(pmt.intern("cmd"), msg_dict)
        
        return 0  import numpy as np
from gnuradio import gr
import pmt
import scipy.special as scs
from threading import Lock

class Energy_Detector(gr.basic_block):
    def __init__(self, samples=1024, Pfa=0.01):
        self.samples = int(samples)
        self.Pfa = float(Pfa)

        gr.basic_block.__init__(self,
            name="Energy_Detector",
            in_sig=[(np.float32, self.samples), (np.float32, self.samples)],
            out_sig=None)

        self.message_port_register_out(pmt.intern("detection_in"))
        self.message_port_register_in(pmt.intern("freq_in"))
        # CORREÇÃO 1: Nome da função corrigido
        self.set_msg_handler(pmt.intern("freq_in"), self.handle_freq_msg)
        
        self.current_center_freq = 0.0 # Inicializa a frequência
        self.lock = Lock()

    def handle_freq_msg(self, msg):
        if pmt.is_dict(msg):
            freq_val = pmt.dict_ref(msg, pmt.intern("freq"), pmt.PMT_NIL)
            if not pmt.is_nil(freq_val):
                with self.lock:
                    self.current_center_freq = pmt.to_double(freq_val)

    def general_work(self, input_items, output_items):
        signal_energy_vector = input_items[0][0]
        noise_vector = input_items[1][0]

        signalAvg = np.mean(signal_energy_vector)
        
        NoisePower = noise_vector ** 2
        NoiseAvg = np.mean(NoisePower)
        var = np.var(NoisePower)
        stdev = np.sqrt(var)

        Qinv = np.sqrt(2) * scs.erfinv(1 - 2 * self.Pfa)
        Threshold = NoiseAvg + Qinv * stdev

        # CORREÇÃO 3: Lógica de detecção corrigida
        if signalAvg > Threshold:
            local_center_freq = 0.0
            with self.lock:
                local_center_freq = self.current_center_freq
            
            # Só envia a mensagem se a frequência for válida (maior que zero)
            if local_center_freq > 0:
                msg_tuple = pmt.make_tuple(
                    pmt.from_float(float(signalAvg)),
                    pmt.from_float(1.0),
                    pmt.from_double(local_center_freq)
                )
                self.message_port_pub(pmt.intern("detection_in"), msg_tuple)

        # CORREÇÃO 2: Consumo explícito das portas
        self.consume(0, 1)
        self.consume(1, 1)
        return 0     freq_hz = pmt.to_double(pmt.tuple_ref(msg, 2))
                freq_mhz = freq_hz / 1e6

                # Imprime o alerta formatado no terminal
                print("="*40)
                print("!!! ALERTA: SINAL DE DRONE DETECTADO !!!")
                print(f"    Frequência: {freq_mhz:.2f} MHz")
                print(f"    Energia do Sinal: {energy:.4f}")
                print("="*40, flush=True) # flush=True para garantir a impressão imediata

        except Exception as e:
            print(f"Alert Formatter - Erro ao processar mensagem: {e}")
            print(f"Mensagem recebida: {msg}")

    def work(self, input_items, output_items):
        # Este bloco não processa sinais de streaming, apenas mensagens.
        # Portanto, a função work não faz nada.
        return 0   

Thursday, October 9, 2025

Adding Signalhound sink/source oot module to gr core

Hello,

 

I’m a software engineer for signalhound. We are a big fan of gr over here. We already have a signalhound out of tree module on github for customers of SH to access. I was wondering it it would be possible to get our module added to the gr core and if so what that process would look like?

 

Thank you,

Nathan Snyder | Software Engineer

Signal Hound, Inc.

1502 SE Commerce Ave, Suite 101

Battle Ground, WA 98604

(360) 787-2144

nathan@signalhound.com

www.signalhound.com

 

Thursday, September 25, 2025

Capture the Flag @ Ingeniería deMuestra

Hi everyone,

Just like last year (and since 2020), we're organizing a little CTF very much like GRCon's during an exposition event at our University (https://idm.uy/). Since it is completely online, we encourage people from all over to join and play. The only caveat is that it is in Spanish, but many English-speaking people have played it in the past. 

If you're interested, you may read all the details at our webpage https://ctf.idm.uy/ (or directly at https://eva.fing.edu.uy/course/view.php?id=1557&section=1#tabs-tree-start). You may register with a group of up to three people by sending us a mail to ctf@fing.edu.uy.

The deadline to register is next Thursday, and the CTF begins next Friday!

best
Federico

Monday, September 15, 2025

[GR-UHD] Announcing GNURadio 3 binary installers with UHD 4.9

Hi All,
 
Together with the latest UHD 4.9 release new GNURadio 3 binary installers with UHD 4.9 support are now available for Ubuntu and Windows.
 
Ubuntu Noble (24.04), Plucky (25.04):
- GNURadio 3.10.12
 
Windows 10/11:
Note:   The Windows installer bundle uses cmake changes not yet available in gnuradio main and has received limited testing outside of using grc with gr-uhd required features. Please refer to https://files.ettus.com/binaries/gnuradio/latest_stable/gnuradio_installer_README.txt for other known limitations.
 
Thanks,
Marian Koop
 
 

Friday, September 12, 2025

Re: Simple BPSK Constellation?

Ralph,

It's because the Constellation Modulator includes a root-raised cosine filter. If you just want bare constellation points, you can use the Chunks to Symbols block.

Ron

On 9/12/25 03:29, Ralph Ewig wrote:

Hi Everyone,

I've been trying to make a simple DBPSK transmitter for a random data (bit) source in GRC. My flowgraph just uses:

                        Constellation Object
Random Uniform Source > Constellation Modulator > Throttle > QT GUI Sink

However, in the constellation plot I see clusters around -1,1 and a point at 0,0 instead of the expected tight grouping just around -1,1. I've confirmed the source produces a stream of 0,1 (bytes) so there should be no errand points being mapped to 0 etc. Can someone point me in the right direction?

Thanks,
Ralph

Simple BPSK Constellation?

Hi Everyone,

I've been trying to make a simple DBPSK transmitter for a random data (bit) source in GRC. My flowgraph just uses:

                        Constellation Object
Random Uniform Source > Constellation Modulator > Throttle > QT GUI Sink

However, in the constellation plot I see clusters around -1,1 and a point at 0,0 instead of the expected tight grouping just around -1,1. I've confirmed the source produces a stream of 0,1 (bytes) so there should be no errand points being mapped to 0 etc. Can someone point me in the right direction?

Thanks,
Ralph