21、高性能数字滤波器与C++实用工具

高性能数字滤波器与C++实用工具

高性能数字滤波器

17阶低通FIR滤波器

有一个17阶低通FIR滤波器,也被称为18抽头滤波器,因为它有18个滤波器系数。其系数总和为128,分辨率比例为64。该滤波器使用 std::uint32_t 来表示内部算法值,因为这些值并不总是能适应 std::uint16_t 。它可以过滤 std::uint16_t 整个范围内的输入值。

以下是该滤波器的定义和使用示例:

typedef fir_order_n<17U,
64U,
std::uint16_t,
std::uint32_t> filter_type;
filter_type f(4U);
void do_something()
{
    f.new_sample<-2, -2, -2, -1, 3, 9, 15, 20, 24,
    24, 20, 15, 9, 3, -1, -2, -2, -2>(100U);
}

这个17阶滤波器比之前的5阶滤波器需要更多的代码和运行时间。这不仅是因为它有更多的系数,还因为延迟线值是32位宽而不是16位。对于8位或16位目标,这个17阶滤波器明显过大,更适合32位目标。不过,可以使用两个或更多级联的低阶滤波器以更少的代码和运行时间成本获得相同的滤波质量。

滤波器设计示例

考虑一个未滤波的原始信号,其主要成分是频率为60Hz、振幅为150、偏移为250的正弦波,还添加了一个强异步噪声成分,噪声频率为600Hz,振幅为30,偏移为0.317ms。该信号的数学表示为:
$S = 250 + 150 \cdot \sin(0.12\pi t) + \frac{1}{5} \sin(0.317 + 1.2\pi t)$

我们将使用一个N阶低通FIR滤波器对该信号进行滤波,使600Hz的噪声成分得到强烈抑制,60Hz的主要成分尽可能少地衰减。

设计步骤
  1. 确定采样频率 :假设每个噪声半波应采集约3 - 4个样本,噪声频率为600Hz,若每个噪声半波采集3.5个样本,则采样频率$T_s$为:
    $T_s = 3.5 \cdot (2 \cdot 600 Hz) = 4200 Hz \approx 4000 Hz$
    相应的采样周期为250μs。
  2. 选择滤波器参数 :选择通带上限频率为200Hz,阻带下限频率为600Hz,阻带衰减为40dB,通带允许1dB的波纹。
  3. 生成滤波器系数 :将这些滤波器参数提供给滤波器设计工具,计算出18个双精度系数,对应于18抽头、17阶滤波器的缩放整数系数。
测试数据

使用一个单独的程序以4kHz的采样频率从上述信号方程生成101个数字化点作为测试数据:

#include <cstdint>
#include <array>
const std::array<std::uint16_t, 101U> data =
{
    {
        250U, 288U, 306U, 301U, 287U, 288U, 312U, 351U,
        381U, 386U, 371U, 354U, 357U, 381U, 412U, 428U,
        417U, 390U, 370U, 372U, 392U, 411U, 409U, 383U,
        347U, 326U, 328U, 343U, 350U, 333U, 296U, 258U,
        241U, 246U, 258U, 256U, 231U, 190U, 158U, 150U,
        162U, 176U, 170U, 141U, 106U,
        87U,
        93U, 116U,
        132U, 125U, 100U,
        77U,
        75U,
        97U, 129U, 147U,
        141U, 123U, 113U, 127U, 162U, 198U, 215U, 209U,
        195U, 197U, 224U, 264U, 297U, 306U, 296U, 285U,
        293U, 325U, 363U, 386U, 383U, 364U, 352U, 363U,
        392U, 420U, 427U, 409U, 381U, 368U, 377U, 400U,
        414U, 403U, 371U, 338U, 324U, 332U, 348U, 348U,
        322U, 282U, 250U, 240U, 250U
    }
};
滤波操作

使用17阶滤波器对测试数据进行滤波:

#include <iostream>
#include <math/filters/fir_order_n.h>
typedef fir_order_n<17U,
64U,
std::uint16_t,
std::uint32_t> filter_type;
void do_something()
{
    filter_type f(data[0U]);
    std::cout << f.get_result() << "\n";
    std::for_each(
        data.begin() + 1U,
        data.end(),
        [&f](const std::uint16_t& s)
        {
            f.new_sample
            <-2, -2, -2, -1, 3, 9, 15, 20, 24,
            24, 20, 15, 9, 3, -1, -2, -2, -2>(s);
            std::cout << f.get_result() << "\n";
        });
}

滤波结果显示,滤波器质量非常好,60Hz的主要成分基本无衰减通过,600Hz的噪声基本被消除。该滤波器在32位目标上运行快速,在8位目标上运行时间较长,CPU负载过高。

级联低阶滤波器

可以使用两个级联的16位5阶滤波器来替代17阶滤波器,以降低8位目标的CPU负载。5阶滤波器的系数为(5, 5, 6, 6, 5, 5)。

#include <iostream>
typedef fir_order_n<5U> filter_type;
void do_something()
{
    filter_type f1(data[0U]);
    filter_type f2(f1.get_result());
    std::cout << f2.get_result() << std::endl;
    std::for_each(
        data.begin() + 1U,
        data.end(),
        [&f1, &f2](const std::uint16_t& s)
        {
            f1.new_sample<5, 5, 6, 6, 5, 5>(s);
            filter_type::result_type r = f1.get_result();
            f2.new_sample<5, 5, 6, 6, 5, 5>(r);
            std::cout << f2.get_result() << std::endl;
        });
}

级联滤波器的滤波质量与17阶滤波器相当,但CPU负载显著降低。

高通滤波器

使用高通滤波器对测试数据进行滤波,选择阻带上限频率为80Hz,衰减为40dB,通带下限频率为600Hz,通带波纹为1dB。得到一个10阶、11抽头的高通滤波器,系数为(1, 2, 4, 6, 8, -40, 8, 6, 4, 2, 1)。

滤波器测试结果对比

滤波器类型 滤波效果 运行时间(8位目标) CPU负载(8位目标,4kHz采样率)
17阶低通 噪声基本消除,60Hz成分无衰减 约56μs 约22%
级联5阶低通 滤波质量与17阶相当 约22μs 约9%
10阶高通 衰减60Hz成分,保留600Hz波纹 - -

滤波器设计流程mermaid图

graph LR
    A[确定信号特征] --> B[选择滤波器类型]
    B --> C[确定采样频率]
    C --> D[选择滤波器参数]
    D --> E[生成滤波器系数]
    E --> F[滤波测试]
    F --> G{是否满足要求}
    G -- 是 --> H[应用滤波器]
    G -- 否 --> D

C++实用工具

nothing结构

nothing 结构不包含任何成员,也没有任何功能,但它可以作为其他函数和模板参数的占位符。

示例:固定点类
// A simplified Q7.8 fixed-point representation.
class fixed_point
{
public:
    // Construct from integer with left-shift.
    fixed_point(std::uint16_t u) : value(u << 8) { }
    // Create pi with the special constructor.
    static fixed_point value_pi()
    {
        return fixed_point(nothing(), 0x0324U);
    }
private:
    std::uint16_t value;
    // Constructor from integer without left-shift.
    fixed_point(const nothing&,
    std::uint16_t u) : value(u) { }
};

nothing 结构用于区分从 std::uint16_t 进行左移的普通构造函数和不进行左移的私有构造函数。

示例:triple类
struct nothing {};
template <typename first_type
= nothing,
typename second_type = nothing,
typename third_type
= nothing>
class triple
{
public:
    // Constructor with default values.
    triple(const first_type&
    t1_ = first_type(),
    const second_type& t2_ = second_type(),
    const third_type&
    t3_ = third_type())
    : t1(t1_),
    t2(t2_),
    t3(t3_)
    {
    }
    // Element access.
    first_type&
    first()
    { return t1; }
    second_type& second() { return t2; }
    third_type&
    third()
    { return t3; }
private:
    first_type
    t1;
    second_type t2;
    third_type
    t3;
};

triple 类类似于标准库中的 std::pair 类,但有三个元素。

noncopyable类

noncopyable 类用于禁止类对象的有意和无意复制。

class noncopyable
{
protected:
    noncopyable() {}
    ~noncopyable() {}
    // Emphasize: The following members are private.
private:
    noncopyable(const noncopyable&) = delete;
    const noncopyable& operator=(const noncopyable&)
    = delete;
};
示例:LED类
class led : private noncopyable
{
    // ...
};

通过私有继承 noncopyable 类, led 类变得不可复制,简化了代码编写和维护。

模板timer类

模板 timer 类可用于实时C++中的各种定时应用。

template<typename unsigned_tick>
class timer
{
public:
    // A class-specific tick type.
    typedef unsigned_tick tick_type;
    // Utility functions for creating timespans.
    template<typename other>
    static tick_type microseconds(const other&);
    template<typename other>
    static tick_type milliseconds(const other&);
    template<typename other>
    static tick_type seconds(const other&);
    template<typename other>
    static tick_type minutes(const other&);
    template<typename other>
    static tick_type hours(const other&);
    // Constructors.
    timer();
    explicit timer(const tick_type&);
    timer(const timer&);
    // Copy assignment operator.
    timer& operator=(const timer&);
    // Interval and relative timeout functions.
    void start_interval(const tick_type&);
    void start_relative(const tick_type&);
    // The timeout, now, and delay functions.
    bool timeout() const;
    static tick_type now();
    static void blocking_delay(const tick_type&);
};

该类提供了以下操作:
- 使用 now() 查询当前时间点。
- 使用 start_relative() 设置相对超时。
- 使用 start_interval() 设置间隔超时。
- 使用 blocking_delay() 进行阻塞延迟。

timer类使用流程mermaid图

graph LR
    A[创建timer对象] --> B[设置时间间隔或相对时间]
    B --> C{是否超时}
    C -- 否 --> B
    C -- 是 --> D[执行操作]
    D --> E{是否继续计时}
    E -- 是 --> B
    E -- 否 --> F[结束]

滤波器设计与应用总结

在滤波器设计与应用中,我们需要根据具体的应用场景和硬件平台来选择合适的滤波器。对于不同的信号特征和滤波要求,我们可以通过以下步骤进行滤波器的设计和应用:
1. 分析信号特征 :确定信号的主要成分和噪声成分,包括频率、振幅和偏移等参数。
2. 选择滤波器类型 :根据滤波要求,选择低通、高通或其他类型的滤波器。
3. 确定采样频率 :根据信号的频率特征,确定合适的采样频率,以保证信号的有效采集。
4. 选择滤波器参数 :如通带频率、阻带频率、衰减和波纹等参数,以满足滤波要求。
5. 生成滤波器系数 :使用滤波器设计工具,根据选择的参数生成滤波器系数。
6. 滤波测试 :使用生成的滤波器系数对测试数据进行滤波,评估滤波效果。
7. 优化调整 :如果滤波效果不满足要求,返回步骤4进行参数调整,直到满足要求为止。

不同滤波器的应用场景

滤波器类型 应用场景
17阶低通 对32位目标系统,需要高精度滤波,且对CPU负载要求不高的场景
级联5阶低通 8位或16位目标系统,对CPU负载敏感,同时需要较好滤波效果的场景
10阶高通 需要去除低频信号,保留高频信号的场景,如信号的高频特征提取

C++实用工具的综合应用

在实际的C++编程中, nothing 结构、 noncopyable 类和模板 timer 类可以结合使用,以提高代码的可读性、可维护性和性能。

示例:结合使用的代码
#include <iostream>
#include <array>

// nothing结构
struct nothing {};

// noncopyable类
class noncopyable
{
protected:
    noncopyable() {}
    ~noncopyable() {}
private:
    noncopyable(const noncopyable&) = delete;
    const noncopyable& operator=(const noncopyable&) = delete;
};

// 简化的固定点类
class fixed_point
{
public:
    fixed_point(std::uint16_t u) : value(u << 8) { }
    static fixed_point value_pi()
    {
        return fixed_point(nothing(), 0x0324U);
    }
private:
    std::uint16_t value;
    fixed_point(const nothing&, std::uint16_t u) : value(u) { }
};

// triple类
template <typename first_type = nothing, typename second_type = nothing, typename third_type = nothing>
class triple
{
public:
    triple(const first_type& t1_ = first_type(), const second_type& t2_ = second_type(), const third_type& t3_ = third_type())
        : t1(t1_), t2(t2_), t3(t3_)
    {
    }
    first_type& first() { return t1; }
    second_type& second() { return t2; }
    third_type& third() { return t3; }
private:
    first_type t1;
    second_type t2;
    third_type t3;
};

// 模板timer类
template<typename unsigned_tick>
class timer
{
public:
    typedef unsigned_tick tick_type;
    template<typename other>
    static tick_type microseconds(const other&);
    template<typename other>
    static tick_type milliseconds(const other&);
    template<typename other>
    static tick_type seconds(const other&);
    template<typename other>
    static tick_type minutes(const other&);
    template<typename other>
    static tick_type hours(const other&);
    timer();
    explicit timer(const tick_type&);
    timer(const timer&);
    timer& operator=(const timer&);
    void start_interval(const tick_type&);
    void start_relative(const tick_type&);
    bool timeout() const;
    static tick_type now();
    static void blocking_delay(const tick_type&);
};

// 不可复制的LED类
class led : private noncopyable
{
public:
    led() {}
    void toggle() const
    {
        std::cout << "LED toggled." << std::endl;
    }
};

int main()
{
    // 使用triple类
    triple<char, int, led> things('a', 123, led());

    // 使用timer类
    timer<std::uint32_t> t;
    t.start_interval(t.milliseconds(1000));

    while (!t.timeout())
    {
        // 等待超时
    }

    things.third().toggle();

    return 0;
}

代码解释

  1. nothing 结构 :作为固定点类构造函数的区分标志,避免构造函数的歧义。
  2. noncopyable :使 led 类不可复制,防止不必要的对象复制。
  3. triple :类似于 std::pair ,但包含三个元素,方便数据的组织。
  4. 模板 timer :用于定时操作,设置时间间隔并等待超时。

综合应用流程mermaid图

graph LR
    A[定义实用工具类] --> B[创建对象]
    B --> C[使用对象功能]
    C --> D{是否完成任务}
    D -- 否 --> C
    D -- 是 --> E[结束]

总结

通过对高性能数字滤波器和C++实用工具的介绍,我们了解了不同类型滤波器的设计、应用和性能特点,以及如何使用 nothing 结构、 noncopyable 类和模板 timer 类来提高C++代码的质量和效率。在实际应用中,我们可以根据具体需求选择合适的滤波器和实用工具,以实现高效、可靠的系统设计。

注意事项

  • 在滤波器设计中,要根据硬件平台的特点选择合适的滤波器阶数和类型,避免资源浪费和性能瓶颈。
  • 在使用C++实用工具时,要注意类的继承和成员函数的使用,确保代码的正确性和可维护性。
这个是完整源码 python实现 Django 【python毕业设计】基于Python的天气预报(天气预测分析)(Django+sklearn机器学习+selenium爬虫)可视化系统.zip 源码+论文+sql脚本 完整版 数据库是mysql 本研究旨在开发一个基于Python的天气预报可视化系统,该系统结合了Django框架、sklearn机器学习库和Selenium爬虫技术,实现对天气数据的收集、分析和可视化。首先,我们使用Selenium爬虫技术从多个天气数据网站实时抓取气象数据,包括温度、湿度、气压、风速等多项指标。这些数据经过清洗和预处理后本研究旨在开发一个基于Python的天气预报可视化系统,该系统结合了Django框架、sklearn机器学习库和Selenium爬虫技术,实现对天气数据的收集、分析和可视化。首先,我们使用Selenium爬虫技术从多个天气数据网站实时抓取气象数据,包括温度、湿度、气压、风速等多项指标。这些数据经过清洗和预处理后,将其存储在后端数据库中,以供后续分析。 其次,采用s,将其存储在后端数据库中,以供后续分析。 其次,采用sklearn机器学习库构建预测模型,通过时间序列分析和回归方法,对未来天气情况进行预测。我们利用以往的数据训练模型,以提高预测的准确性。通过交叉验证和超参数优化等技术手段,我们优化了模型性能,确保其在实际应用中的有效性和可靠性。 最后,基于Django框架开发前端展示系统,实现天气预报的可视化。用户可以通过友好的界面查询实时天气信息和未来几天内的天气预测。系统还提供多种图表类型,包括折线图和柱状图,帮助用户直观理解天气变化趋势。 本研究的成果为天气预报领域提供了一种新的技术解决方案,不仅增强了数据获取和处理的效率,还提升了用户体验。未来,该系统能够扩展至其他气象相关的应用场景,为大众提供更加准确和及时的气象服务。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值