GNU Radio:如何在接收器块内定义 "get_*" 方法
GNU Radio: How to define a "get_*" method inside a sink block
我想用 C++ 为 GNU Radio 编写我自己的带有 1 个输入端口和 0 个输出端口的接收器块。我阅读并遵循了此处描述的步骤:
- http://gnuradio.org/redmine/projects/gnuradio/wiki/BlocksCodingGuide
- http://gnuradio.org/redmine/projects/gnuradio/wiki/OutOfTreeModules
- http://gnuradio.org/redmine/projects/gnuradio/wiki/OutOfTreeModulesConfig
- http://gnuradio.org/redmine/projects/gnuradio/wiki/Guided_Tutorial_GNU_Radio_in_C++
我正在使用
- Ubuntu 14.04.3 LTS
- 日食 4.5.1
- CDT 8.8.0.201509131935
- GNU 收音机 3.7.8
使用 gr_modtool 我创建了新模块 "jammertrap"。在其中,我创建了块 "bandpower"。这创建了三个文件
- bandpower.h 里面 /home/sdr/gnuradio/gr-jammertrap/include/jammertrap/
- bandpower_impl.h 里面 /home/sdr/gnuradio/gr-jammertrap/lib/
- bandpower_impl.cc 里面 /home/sdr/gnuradio/gr-jammertrap/lib/
bandpower.h:
#ifndef INCLUDED_JAMMERTRAP_BANDPOWER_H
#define INCLUDED_JAMMERTRAP_BANDPOWER_H
#include <jammertrap/api.h>
#include <gnuradio/block.h>
namespace gr
{
namespace jammertrap
{
class JAMMERTRAP_API bandpower : virtual public gr::block
{
public:
typedef boost::shared_ptr<bandpower> sptr;
// Return a shared_ptr to a new instance of jammertrap::bandpower.
// To avoid accidental use of raw pointers, jammertrap::bandpower's constructor is in a private implementation class.
// jammertrap::bandpower::make is the public interface for creating new instances.
static sptr make();
};
} // namespace jammertrap
} // namespace gr
#endif /* INCLUDED_JAMMERTRAP_BANDPOWER_H */
bandpower_impl.h:
#ifndef INCLUDED_JAMMERTRAP_BANDPOWER_IMPL_H
#define INCLUDED_JAMMERTRAP_BANDPOWER_IMPL_H
#include <jammertrap/bandpower.h>
namespace gr
{
namespace jammertrap
{
class bandpower_impl : public bandpower
{
private:
double d_bandpower_;
public:
bandpower_impl();
~bandpower_impl();
void forecast (int noutput_items, gr_vector_int &ninput_items_required);
// Where all the action really happens
int general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items);
// Returns the calculated RMS Bandpower
double get_bandpower();
};
} // namespace jammertrap
} // namespace gr
#endif /* INCLUDED_JAMMERTRAP_BANDPOWER_IMPL_H */
bandpower_impl.cc:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "bandpower_impl.h"
namespace gr
{
namespace jammertrap
{
bandpower::sptr
bandpower::make()
{
return gnuradio::get_initial_sptr (new bandpower_impl());
}
// The private constructor
bandpower_impl::bandpower_impl() : gr::block("bandpower", gr::io_signature::make(1, 1, sizeof(gr_complex)), gr::io_signature::make(0, 0, 0))
{
d_bandpower_ = 0;
}
// Our virtual destructor
bandpower_impl::~bandpower_impl()
{}
void bandpower_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required)
{
// ninput_items_required[0] = noutput_items;
}
int bandpower_impl::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items)
{
const gr_complex *in = (const gr_complex *) input_items[0];
d_bandpower_ = 0;
for(int i = 0; i < noutput_items; i++)
{
d_bandpower_ += (in[i].real() * in[i].real()) + (in[i].imag() * in[i].imag());
}
d_bandpower_ = sqrt(d_bandpower_ / noutput_items);
// Tell runtime system how many input items we consumed on each input stream.
consume_each (noutput_items);
// Tell runtime system how many output items we produced
return noutput_items;
}
double bandpower_impl::get_bandpower()
{
return d_bandpower_;
}
} /* namespace jammertrap */
} /* namespace gr */
为了制作和安装这个新块,我在 /home/sdr/gnuradio/gr-jammertrap/build 中输入了以下命令:
- cmake ../
- 制作
- make test // 结果:"test_jammertrap" and "qa_bandpower" passed successful
- 须藤安装
此接收器块 "bandpower" 应接收类型 gr_complex 的项目,计算平均接收功率并将此值存储在私有成员 "d_bandpower_" 中。
另外我定义了方法"get_bandpower()"来获取存储的值。
在另一个程序中,我用两个块
创建了一个流程图class
osmosdr::source:sptr osmosdr_source_;
gr::jammertrap::bandpower::sptr bandpower_measurement_;
并用
实例化它们
osmosdr_source_ = osmosdr::source::make(std::string());
bandpower_measurement_ = gr::jammertrap::bandpower::make();
启动流程图后,我想通过调用 get_bandpower() 来读取计算出的带宽,但 Eclipse 显示没有方法 "bandpower_measurement_->get_bandpower()"
我在bandpower.h、bandpower_impl.h或bandpower_impl.cc里面忘记写了什么?
普通OOT布局的publicAPI在bandpower.h
中,所以必须加一个
virtual double get_bandpower() = 0;
在该文件中。
然后,你 overload/implement 就像你一样,在 _impl.cc
/_impl.h
.
顺便说一句,我有点反对你实施背后的数学:如 noutput_items
,即。可用输入项的数量,根据缓冲区填充/运行时行为而变化,你的 "averaging length" 不是恒定的,这意味着如果你的流程图运行得很快,你的缓冲区通常会满,你的平均长度会很高,而在 "trickle" 的情况下,长度会小得多(在极端情况下会减少到 noutput_items==1
)。因此,功率估计器的方差将取决于计算方面。
这可不是什么好事。最好使用您平均计算的固定数量的项目。在你的情况下,你可以使用 set_output_multiple
(因为接收器也是一个同步块,这也会影响输入倍数)来保证你总是得到一个固定数字的倍数。
除此之外,已经有可以做你想做的事情的积木:
- Probe Avg Mag²:有一个方法
level()
与您的 get_bandpower
相同(除了 √(.) )
- 复数到 Mag ⟶ 抽取 FIR 滤波器 ⟶ 探测信号:√( Re²+Im²),然后将其传递给具有 123(这只是我的任意固定长度)抽头 1/长度的滤波器,并在每次平均时将其抽取为一个值。结果被发送到 Signal Probe,它有一个
signal()
方法,它做你的 get_bandpower
做的事情。 CPU 这个的负载相对较小——它实际上只是每个样本的量级发现,然后每 123 个样本进行 123 次实数乘法 + 123 次实数加法,在过滤器中,所有 SIMD 都增加了,所以基本上,不到 1每个样本的 FMAC。
- 复杂到 Mag⟶移动平均线⟶探测信号:名称说明了一切。这里没什么神奇的。
我想用 C++ 为 GNU Radio 编写我自己的带有 1 个输入端口和 0 个输出端口的接收器块。我阅读并遵循了此处描述的步骤:
- http://gnuradio.org/redmine/projects/gnuradio/wiki/BlocksCodingGuide
- http://gnuradio.org/redmine/projects/gnuradio/wiki/OutOfTreeModules
- http://gnuradio.org/redmine/projects/gnuradio/wiki/OutOfTreeModulesConfig
- http://gnuradio.org/redmine/projects/gnuradio/wiki/Guided_Tutorial_GNU_Radio_in_C++
我正在使用
- Ubuntu 14.04.3 LTS
- 日食 4.5.1
- CDT 8.8.0.201509131935
- GNU 收音机 3.7.8
使用 gr_modtool 我创建了新模块 "jammertrap"。在其中,我创建了块 "bandpower"。这创建了三个文件
- bandpower.h 里面 /home/sdr/gnuradio/gr-jammertrap/include/jammertrap/
- bandpower_impl.h 里面 /home/sdr/gnuradio/gr-jammertrap/lib/
- bandpower_impl.cc 里面 /home/sdr/gnuradio/gr-jammertrap/lib/
bandpower.h:
#ifndef INCLUDED_JAMMERTRAP_BANDPOWER_H
#define INCLUDED_JAMMERTRAP_BANDPOWER_H
#include <jammertrap/api.h>
#include <gnuradio/block.h>
namespace gr
{
namespace jammertrap
{
class JAMMERTRAP_API bandpower : virtual public gr::block
{
public:
typedef boost::shared_ptr<bandpower> sptr;
// Return a shared_ptr to a new instance of jammertrap::bandpower.
// To avoid accidental use of raw pointers, jammertrap::bandpower's constructor is in a private implementation class.
// jammertrap::bandpower::make is the public interface for creating new instances.
static sptr make();
};
} // namespace jammertrap
} // namespace gr
#endif /* INCLUDED_JAMMERTRAP_BANDPOWER_H */
bandpower_impl.h:
#ifndef INCLUDED_JAMMERTRAP_BANDPOWER_IMPL_H
#define INCLUDED_JAMMERTRAP_BANDPOWER_IMPL_H
#include <jammertrap/bandpower.h>
namespace gr
{
namespace jammertrap
{
class bandpower_impl : public bandpower
{
private:
double d_bandpower_;
public:
bandpower_impl();
~bandpower_impl();
void forecast (int noutput_items, gr_vector_int &ninput_items_required);
// Where all the action really happens
int general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items);
// Returns the calculated RMS Bandpower
double get_bandpower();
};
} // namespace jammertrap
} // namespace gr
#endif /* INCLUDED_JAMMERTRAP_BANDPOWER_IMPL_H */
bandpower_impl.cc:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "bandpower_impl.h"
namespace gr
{
namespace jammertrap
{
bandpower::sptr
bandpower::make()
{
return gnuradio::get_initial_sptr (new bandpower_impl());
}
// The private constructor
bandpower_impl::bandpower_impl() : gr::block("bandpower", gr::io_signature::make(1, 1, sizeof(gr_complex)), gr::io_signature::make(0, 0, 0))
{
d_bandpower_ = 0;
}
// Our virtual destructor
bandpower_impl::~bandpower_impl()
{}
void bandpower_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required)
{
// ninput_items_required[0] = noutput_items;
}
int bandpower_impl::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items)
{
const gr_complex *in = (const gr_complex *) input_items[0];
d_bandpower_ = 0;
for(int i = 0; i < noutput_items; i++)
{
d_bandpower_ += (in[i].real() * in[i].real()) + (in[i].imag() * in[i].imag());
}
d_bandpower_ = sqrt(d_bandpower_ / noutput_items);
// Tell runtime system how many input items we consumed on each input stream.
consume_each (noutput_items);
// Tell runtime system how many output items we produced
return noutput_items;
}
double bandpower_impl::get_bandpower()
{
return d_bandpower_;
}
} /* namespace jammertrap */
} /* namespace gr */
为了制作和安装这个新块,我在 /home/sdr/gnuradio/gr-jammertrap/build 中输入了以下命令:
- cmake ../
- 制作
- make test // 结果:"test_jammertrap" and "qa_bandpower" passed successful
- 须藤安装
此接收器块 "bandpower" 应接收类型 gr_complex 的项目,计算平均接收功率并将此值存储在私有成员 "d_bandpower_" 中。 另外我定义了方法"get_bandpower()"来获取存储的值。
在另一个程序中,我用两个块
创建了一个流程图classosmosdr::source:sptr osmosdr_source_;
gr::jammertrap::bandpower::sptr bandpower_measurement_;
并用
实例化它们osmosdr_source_ = osmosdr::source::make(std::string());
bandpower_measurement_ = gr::jammertrap::bandpower::make();
启动流程图后,我想通过调用 get_bandpower() 来读取计算出的带宽,但 Eclipse 显示没有方法 "bandpower_measurement_->get_bandpower()"
我在bandpower.h、bandpower_impl.h或bandpower_impl.cc里面忘记写了什么?
普通OOT布局的publicAPI在bandpower.h
中,所以必须加一个
virtual double get_bandpower() = 0;
在该文件中。
然后,你 overload/implement 就像你一样,在 _impl.cc
/_impl.h
.
顺便说一句,我有点反对你实施背后的数学:如 noutput_items
,即。可用输入项的数量,根据缓冲区填充/运行时行为而变化,你的 "averaging length" 不是恒定的,这意味着如果你的流程图运行得很快,你的缓冲区通常会满,你的平均长度会很高,而在 "trickle" 的情况下,长度会小得多(在极端情况下会减少到 noutput_items==1
)。因此,功率估计器的方差将取决于计算方面。
这可不是什么好事。最好使用您平均计算的固定数量的项目。在你的情况下,你可以使用 set_output_multiple
(因为接收器也是一个同步块,这也会影响输入倍数)来保证你总是得到一个固定数字的倍数。
除此之外,已经有可以做你想做的事情的积木:
- Probe Avg Mag²:有一个方法
level()
与您的get_bandpower
相同(除了 √(.) ) - 复数到 Mag ⟶ 抽取 FIR 滤波器 ⟶ 探测信号:√( Re²+Im²),然后将其传递给具有 123(这只是我的任意固定长度)抽头 1/长度的滤波器,并在每次平均时将其抽取为一个值。结果被发送到 Signal Probe,它有一个
signal()
方法,它做你的get_bandpower
做的事情。 CPU 这个的负载相对较小——它实际上只是每个样本的量级发现,然后每 123 个样本进行 123 次实数乘法 + 123 次实数加法,在过滤器中,所有 SIMD 都增加了,所以基本上,不到 1每个样本的 FMAC。 - 复杂到 Mag⟶移动平均线⟶探测信号:名称说明了一切。这里没什么神奇的。