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.