I am trying to build a sink block with FFT and Kurtosis capability using gr_modtool.
The code itself can be compiled without error.
But when I run the flow graph in GRC, it produces following error message.
Generating: '/home/nomo/gr-Kurtosis/kurtosis.py'
Executing: /usr/bin/python3 -u /home/nomo/gr-Kurtosis/kurtosis.py
Traceback (most recent call last):
File "/home/nomo/gr-Kurtosis/kurtosis.py", line 134, in <module>
main()
File "/home/nomo/gr-Kurtosis/kurtosis.py", line 112, in main
tb = top_block_cls()
File "/home/nomo/gr-Kurtosis/kurtosis.py", line 81, in __init__
self.Kurtosis_Kurtosis_c_0 = Kurtosis.Kurtosis_c(1024)
AttributeError: module 'Kurtosis' has no attribute 'Kurtosis_c'
Below is the implmentation source file:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "Kurtosis_c_impl.h"
namespace gr {
namespace Kurtosis {
Kurtosis_c::sptr
Kurtosis_c::make(int fftsize)
{
return gnuradio::get_initial_sptr
(new Kurtosis_c_impl(fftsize));
}
/*
* The private constructor
*/
Kurtosis_c_impl::Kurtosis_c_impl(int fftsize)
: gr::sync_block("Kurtosis_c",
gr::io_signature::make(1, 1, sizeof(gr_complex)),
gr::io_signature::make(0, 0, 0)),
d_N(fftsize)
{
d_input = (fftw_complex*)fftw_malloc(sizeof(gr_complex) * d_N);
K = (fftw_complex*)fftw_malloc(sizeof(gr_complex) * d_N);
d_plan = fftw_plan_dft_1d(d_N, d_input, d_input, FFTW_BACKWARD, FFTW_ESTIMATE);
}
/*
* Our virtual destructor.
*/
Kurtosis_c_impl::~Kurtosis_c_impl()
{
}
int
Kurtosis_c_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const gr_complex *in = (const gr_complex*) input_items[0];
for(int i = 0; i < noutput_items; i++)
{
d_input[i][0] = in[i].real();
d_input[i][1] = in[i].imag();
}
fftw_execute(d_plan);
for(int i = 0; i < noutput_items ;i++)
{
S1[i][0] = S1[i][0] + d_input[i][0];
S1[i][1] = S1[i][1] + d_input[i][1];
S2[i][0] = S2[i][0] + d_input[i][0] * d_input[i][0];
S2[i][1] = S2[i][1] + d_input[i][1] * d_input[i][1];
S3[i][0] = S3[i][0] + d_input[i][0] * d_input[i][0] * d_input[i][0];
S3[i][1] = S3[i][1] + d_input[i][1] * d_input[i][1] * d_input[i][1];
S4[i][0] = S4[i][0] + d_input[i][0] * d_input[i][0] * d_input[i][0] * d_input[i][0];
S4[i][1] = S4[i][1] + d_input[i][1] * d_input[i][1] * d_input[i][1] * d_input[i][1];
dc[i][0] = dc[i][0] + 1;
dc[i][1] = dc[i][1] + 1;
}
for(int i = 0; i < noutput_items; i++)
{
Myu1[i][0] = S1[i][0] / dc[i][0];
Myu1[i][1] = S1[i][1] / dc[i][1];
Myu2[i][0] = S2[i][0] / dc[i][0];
Myu2[i][1] = S2[i][1] / dc[i][1];
Myu3[i][0] = S3[i][0] / dc[i][0];
Myu3[i][1] = S3[i][1] / dc[i][1];
Myu4[i][0] = S4[i][0] / dc[i][0];
Myu4[i][1] = S4[i][1] / dc[i][1];
}
for(int i = 0; i < noutput_items; i++)
{
K[i][0] = (Myu4[i][0] - 4 * Myu3[i][0] * Myu1[i][0] + 6 * Myu2[i][0] * Myu1[i][0]
* Myu1[i][0] - 3 * Myu1[i][0] * Myu1[i][0] * Myu1[i][0] * Myu1[i][0]) /
((Myu2[i][0] - Myu1[i][0] * Myu1[i][0]) * (Myu2[i][0] - Myu1[i][0]
* Myu1[i][0]));
K[i][1] = (Myu4[i][1] - 4 * Myu3[i][1] * Myu1[i][1] + 6 * Myu2[i][1] * Myu1[i][1]
* Myu1[i][1] - 3 * Myu1[i][1] * Myu1[i][1] * Myu1[i][1] * Myu1[i][1]) /
((Myu2[i][1] - Myu1[i][1] * Myu1[i][1]) * (Myu2[i][1] - Myu1[i][1]
* Myu1[i][1]));
}
// Tell runtime system how many output items we produced.
return noutput_items;
}
} /* namespace Kurtosis1 */
} /* namespace gr */
The implementation header file is as below:
#ifndef INCLUDED_KURTOSIS1_KURTOSIS_C1_IMPL_H
#define INCLUDED_KURTOSIS1_KURTOSIS_C1_IMPL_H
#include <Kurtosis/Kurtosis_c.h>
#include <fftw3.h>
namespace gr {
namespace Kurtosis {
class Kurtosis_c_impl : public Kurtosis_c
{
private:
int d_N;
fftw_complex *K;
fftw_complex *S1;
fftw_complex *S2;
fftw_complex *S3;
fftw_complex *S4;
fftw_complex *Myu1;
fftw_complex *Myu2;
fftw_complex *Myu3;
fftw_complex *Myu4;
fftw_complex *dc;
fftw_complex *d_input;
fftw_plan d_plan;
public:
Kurtosis_c_impl(int fftsize);
~Kurtosis_c_impl();
// Where all the action really happens
int work(
int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items
);
};
} // namespace Kurtosis1
} // namespace gr
#endif /* INCLUDED_KURTOSIS1_KURTOSIS_C1_IMPL_H */
The following python code is generated when a flow graph is run in GRC
from distutils.version import StrictVersion
if __name__ == '__main__':
import ctypes
import sys
if sys.platform.startswith('linux'):
try:
x11 = ctypes.cdll.LoadLibrary('libX11.so')
x11.XInitThreads()
except:
print("Warning: failed to XInitThreads()")
from gnuradio import blocks
import pmt
from gnuradio import gr
from gnuradio.filter import firdes
import sys
import signal
from PyQt5 import Qt
from argparse import ArgumentParser
from gnuradio.eng_arg import eng_float, intx
from gnuradio import eng_notation
import Kurtosis
from gnuradio import qtgui
class kurtosis(gr.top_block, Qt.QWidget):
def __init__(self):
gr.top_block.__init__(self, "Not titled yet")
Qt.QWidget.__init__(self)
self.setWindowTitle("Not titled yet")
qtgui.util.check_set_qss()
try:
self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
except:
pass
self.top_scroll_layout = Qt.QVBoxLayout()
self.setLayout(self.top_scroll_layout)
self.top_scroll = Qt.QScrollArea()
self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
self.top_scroll_layout.addWidget(self.top_scroll)
self.top_scroll.setWidgetResizable(True)
self.top_widget = Qt.QWidget()
self.top_scroll.setWidget(self.top_widget)
self.top_layout = Qt.QVBoxLayout(self.top_widget)
self.top_grid_layout = Qt.QGridLayout()
self.top_layout.addLayout(self.top_grid_layout)
self.settings = Qt.QSettings("GNU Radio", "kurtosis")
try:
if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
self.restoreGeometry(self.settings.value("geometry").toByteArray())
else:
self.restoreGeometry(self.settings.value("geometry"))
except:
pass
##################################################
# Variables
##################################################
self.samp_rate = samp_rate = 32000
##################################################
# Blocks
##################################################
self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate,True)
self.blocks_file_source_0 = blocks.file_source(gr.sizeof_gr_complex*1, '/home/nomo/gr-Kurtosis/b200_220215_0718_30_40_6000_TEST.dat', True, 0, 0)
self.blocks_file_source_0.set_begin_tag(pmt.PMT_NIL)
self.Kurtosis_Kurtosis_c_0 = Kurtosis.Kurtosis_c(1024)
##################################################
# Connections
##################################################
self.connect((self.blocks_file_source_0, 0), (self.blocks_throttle_0, 0))
self.connect((self.blocks_throttle_0, 0), (self.Kurtosis_Kurtosis_c_0, 0))
def closeEvent(self, event):
self.settings = Qt.QSettings("GNU Radio", "kurtosis")
self.settings.setValue("geometry", self.saveGeometry())
event.accept()
def get_samp_rate(self):
return self.samp_rate
def set_samp_rate(self, samp_rate):
self.samp_rate = samp_rate
self.blocks_throttle_0.set_sample_rate(self.samp_rate)
def main(top_block_cls=kurtosis, options=None):
if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
style = gr.prefs().get_string('qtgui', 'style', 'raster')
Qt.QApplication.setGraphicsSystem(style)
qapp = Qt.QApplication(sys.argv)
tb = top_block_cls()
tb.start()
tb.show()
def sig_handler(sig=None, frame=None):
Qt.QApplication.quit()
signal.signal(signal.SIGINT, sig_handler)
signal.signal(signal.SIGTERM, sig_handler)
timer = Qt.QTimer()
timer.start(500)
timer.timeout.connect(lambda: None)
def quitting():
tb.stop()
tb.wait()
qapp.aboutToQuit.connect(quitting)
qapp.exec_()
if __name__ == '__main__':
main()
Question: How to solve this error?
Thank you in advance for any guidance you may be able to provide.
There are two probable reasons:
swig
installed on your system and the python binding does not get generated.#include <fftw3.h>
fftw3
in your case.Open your top-level CMakeLists.txt
and add
find_package(FFTW3)
then open lib/CMakeLists.txt
and add fftw3::fftw3
to target_link_libraries
list, something like
target_link_libraries(gnuradio-Kurtosis PUBLIC
gnuradio::gnuradio-runtime fftw3::fftw3
)
One more thing is to improve the error handling - open python/__init__.py
and change ImportError
to ModuleNotFoundError
After all these changes you need to reinstall your OOT module.