Embedded Python basic_block input buffer lengths
HI all, I am trying to debug a grc flowgraph containing an Embedded Python BASIC_BLOCK. The python block has two inputs and one output. The block makes sure (through FORECAST()) that both inputs have the SAME sample requirements. Also, the block ALWAYS uses CONSUME_EACH() so that both input buffers are cleared by the same amount of samples. I observe the following behavior: During normal operation (high SNR) the lengths of the two input buffers are the same. However, after some tinkering (I decrease the SNR using a QT Range and then increase it again) the two input buffers have different lengths! Is this even possible? Can the scheduler do that? I first suspected that the peak detector which is present in the flowgraph and feeds the first input of the python block is chewing up samples when it does not find a peak so my two streams become unsynchronized. However I verified that the peak detector is a sync_block so this is impossible either... Do you have any idea as to why this is happening? I attach the grc code (this is tested in 3.7 and 3.8). thanks in advance for any help, Achilleas test_input_buffers.grc Description: Binary data
PMT thoughts
I appreciate the effort that you guys have put into cleaning up gnuradio and making it easier to work with over the past few years (python2 - python3, swig to pybind11). I see that you are going to improve the logging as well which is great. I've recently been doing some message based processing, and been using PMTs. I think that PMTs could use an overhaul too. Here are some of my concerns: The interface is inconsistent. Here are a few examples: is_integer, but from/to_long is_dict, is_vector, not no is_list make_dict, make_vector, but list1, list2, etc Type safety doesn't really work in several cases: # apt install of gr 3.9 on ubuntu 20.04 a = pmt.make_dict() a = pmt.dict_add(a, pmt.intern("a"), pmt.intern("a")) pmt.is_dict(a) # True a = pmt.list_add(a, pmt.intern("b")) # I believe that this changes the dictionary to a list pmt.is_dict(b) # False I could come up with more examples, but they illustrate roughly the same point. I should note that something changed in GR3.9. It was even worse in 3.8. For example, on a list, pmt.is_dict() returns True. I can call some of the dict functions which return unexpected results, while others raise an error. The interface doesn't feel like modern C++. The pmt object doesn't really have any useful functions associated with it. You have to use the functions in pmt namespace to operate on any pmt. I believe that PMTs are using boost::any under the hood. I can get why some of the choices were made, but I think that there may be some alternatives available that could lead to an easier interface. I've been playing around with std::variant (in c++17, boost::variant prior to that). I have some ideas for how we could use it to wrap the scalar types as well as the vector and dynamic types. I would be happy to explore the idea if there is interest. We could also use variadic templates to avoid things like list1, ..., list6. Using std::variant, I would envision an interface like: pmt my_dict(); my_dict["abc"] = 4.0 // Automatically convert the string and the number to the proper type. std::get(my_dict["abc"])) pmt_list my_list(); my_list.append(pmt(my_dict)); for (auto& element : my_list) { // Do something } std::cout << my_list.type() << " " << my_list << std::endl; We should be able to deprecate, but maintain the current functions for dealing with PMTs. I believe that these changes could be made without breaking existing code. To be clear, I haven't implemented any of this. My goal right now is just to see if there is interest in doing something like this. If there is, I am happy to look into it and try to create a proof of concept. I'm also open to suggestions and feedback. Thanks, John
Re: (gnuradio3.8) module 'gnuradio.blocks' has no attribute 'message_sink'
Here is a solution using an asynchronous probe: In this application, there is a need to periodically send signals to a background task for non-realtime calculations. # connect the queue to the input signal msgq = gr.msg_queue(2) msg_sink = blocks.message_sink(gr.sizeof_float*num_bins, msgq, True) # dont block self.connect(self, msg_sink) # start the update thread update_thread( num_bins=num_bins, update_timeout=update_timeout, msgq=msgq, ) then in the background thread, the queue is read and processed # read from the queue and resize to have arrays of size num bins raw_samps = numpy.fromstring(self._msgq.delete_head().to_string(), numpy.float32) raw_samps.resize(len(raw_samps) / self._num_bins, self._num_bins) With the message_sink block no longer supported, the probe_signal_vf block works for me: # setup the probe and connect to input signal probe = blocks.probe_signal_vf(num_bins) self.connect(self, probe) # start the update thread update_thread( num_bins=num_bins, update_timeout=update_timeout, probe = probe, .. ) and in the background thread: # read from the probe and resize to have arrays of size num bins raw_samps = numpy.array(self._probe.level()) raw_samps.resize(1, self._num_bins) This will work if your application does not need every signal passed to the background task. Criss Swaim csw...@tpginc.net cell: 505.301.5701 On 1/15/2021 2:09 AM, Marcus Müller wrote: So, the old msg_queue infrastructure of GNU Radio has been removed, yes. A suitable replacement are the asynchronous message passing blocks. Depending on your use case, the conversion of your code should be relatively straightforward - the message debug sink might even do what you want. Best regards, Marcus On 07.01.21 04:46, Ting Wu wrote: Hi! I recently upgraded to gnuradio 3.8 and my old code threw the following error: module 'gnuradio.blocks' has no attribute 'message_sink' Is the 'message_sink' has been deprecated in the recent version of gnuradio? If so, what should I use now for the message source and sink? I really do not want to rewrite all the codes, so I would be really grateful if there is a simple way to make the following code work with the recent version of gnuradio. The code simply gets data stream from a USRP N200 (LFRX daughterboard). = class my_block(gr.top_block): def __init__(self): gr.top_block.__init__(self) self.source = uhd.usrp_source(device_addr="", stream_args=uhd.stream_args('sc16', 'sc16', args="scalar=1024")) self.source.set_samp_rate(samp_rate) self.source.set_gain(gain) self.source.set_center_freq(0) self.queue = gr.msg_queue() self.sink = blocks.message_sink(gr.sizeof_short*2, self.queue, False) #This line throws the error self.connect(self.source, self.sink) === Thanks in advance! Ting Wu