使用Rust原生实现小波卡尔曼滤波算法

一、算法原理概述

  1. 小波变换(Wavelet Transform)

    • 通过多尺度分解将信号分为高频(细节)和低频(近似)部分,高频通常包含噪声,低频保留主体信息。
    • 使用Haar小波(计算高效)进行快速分解与重构:
      // Haar小波分解公式
      approx = (x[2i] + x[2i+1]) / 2.0;
      detail = (x[2i] - x[2i+1]) / 2.0;
      
  2. 卡尔曼滤波(Kalman Filter)

    • 预测-更新两阶段递归估计[citation:5][citation:6]:
      • 预测:基于状态方程预估当前状态和误差协方差

        Xpred=A⋅Xprev+B⋅uPpred=A⋅Pprev⋅AT+QXpred​=A⋅Xprev​+B⋅uPpred​=A⋅Pprev​⋅AT+Q

      • 更新:结合观测值修正预测值,计算卡尔曼增益K

        K=Ppred⋅HT/(H⋅Ppred⋅HT+R)Xnew=Xpred+K⋅(z−H⋅Xpred)Pnew=(I−K⋅H)⋅PpredK=Ppred​⋅HT/(H⋅Ppred​⋅HT+R)Xnew​=Xpred​+K⋅(z−H⋅Xpred​)Pnew​=(I−K⋅H)⋅Ppred​

  3. 小波卡尔曼融合

    • 先对原始信号小波分解,对不同频段独立应用卡尔曼滤波,最后重构信号
    • 高频部分使用更高测量噪声协方差R(抑制噪声),低频部分使用更低R(保留主体)。

二、Rust实现代码

cargo.toml

[package]
name = "wavelet-kalman-filter"
version = "0.1.0"
edition = "2021"

[dependencies]
plotters = "0.3.5"
rand = "0.8.5"
log = "0.4.17"
simple_logger = "5.0.0"

main.rs

use log::{info};
use log::LevelFilter;
use simple_logger::SimpleLogger;

// 初始化日志记录,将日志保存到文件
fn init_logger() {
    SimpleLogger::new()
        .with_level(LevelFilter::Info)
        .with_utc_timestamps()
        .init()
        .expect("Failed to initialize logger");
    info!("日志系统初始化完成");
}

// 主结构体
pub struct WaveletKalmanFilter {
    pub a: f64,      // 状态转移系数(如匀速运动时A=1)
    pub q: f64,      // 过程噪声协方差
    pub r_low: f64,  // 低频观测噪声协方差
    pub r_high: f64, // 高频观测噪声协方差
    pub state: f64,  // 当前状态估计
    pub cov: f64,    // 当前误差协方差
}

// 一维Haar小波分解(返回低频近似 + 高频细节)
pub fn haar_decompose(signal: &[f64]) -> (Vec<f64>, Vec<f64>) {
    info!("开始Haar小波分解,输入信号长度: {}", signal.len());
    // 对信号进行对称延拓,以缓解小波分析的边界问题
    fn symmetric_extend(signal: &[f64]) -> Vec<f64> {
        if signal.len() <= 1 {
            info!("信号长度小于等于1,直接返回原信号");
            return signal.to_vec();
        }
        let mut extended = Vec::new();
        // 左侧对称部分
        for i in (1..=signal.len() - 1).rev() {
            extended.push(signal[i]);
        }
        // 原始信号部分
        extended.extend_from_slice(signal);
        // 右侧对称部分
        for i in 1..signal.len() {
            extended.push(signal[signal.len() - 1 - i]);
        }
        info!("对称延拓后信号长度: {} 信号内容: {:?}", extended.len(), extended);
        extended
    }

    // 对延拓后的信号进行Haar小波分解
    pub fn haar_decompose(signal: &[f64]) -> (Vec<f64>, Vec<f64>) {
        let extended = symmetric_extend(signal);
        let mut approx = Vec::new();
        let mut detail = Vec::new();
        for i in (0..extended.len()).step_by(2) {
            let sum = extended[i] + extended.get(i + 1).unwrap_or(&0.0);
            let diff = extended[i] - extended.get(i + 1).unwrap_or(&0.0);
            approx.push(sum / 2.0);
            detail.push(diff / 2.0);
        }
        // 截取与原始信号分解后相同长度的结果
        let half_len = (signal.len() + 1) / 2;
        let approx = approx[extended.len() / 4..extended.len() / 4 + half_len].to_vec();
        let detail = detail[extended.len() / 4..extended.len() / 4 + half_len].to_vec();
        info!(
            "延拓后Haar分解完成,近似分量长度: {}, 细节分量长度: {}",
            approx.len(),
            detail.len()
        );
        (approx, detail)
    }
    let mut approx = Vec::new();
    let mut detail = Vec::new();
    for i in (0..signal.len()).step_by(2) {
        let sum = signal[i] + signal.get(i + 1).unwrap_or(&0.0);
        let diff = signal[i] - signal.get(i + 1).unwrap_or(&0.0);
        approx.push(sum / 2.0);
        detail.push(diff / 2.0);
    }
    info!(
        "直接Haar分解完成,近似分量长度: {}, 细节分量长度: {}",
        approx.len(),
        detail.len()
    );
    (approx, detail)
}

// 一维Haar小波重构
pub fn haar_recompose(approx: &[f64], detail: &[f64]) -> Vec<f64> {
    info!(
        "开始Haar小波重构,近似分量长度: {}, 细节分量长度: {}",
        approx.len(),
        detail.len()
    );
    let mut output = Vec::with_capacity(approx.len() * 2);
    for i in 0..approx.len() {
        output.push(approx[i] + detail[i]);
        output.push(approx[i] - detail[i]);
    }
    info!("Haar小波重构完成,输出信号长度: {}", output.len());
    output
}

impl WaveletKalmanFilter {
    // 初始化滤波器
    pub fn new(a: f64, q: f64, r_low: f64, r_high: f64) -> Self {
        info!(
            "创建新的WaveletKalmanFilter,a: {}, q: {}, r_low: {}, r_high: {}",
            a, q, r_low, r_high
        );
        WaveletKalmanFilter {
            a,
            q,
            r_low,
            r_high,
            state: 0.0,
            cov: 1.0, // 初始协方差设为较大值(表示不确定性高)
        }
    }

    // 单步预测
    pub fn predict(&mut self) {
        info!("执行单步预测前,状态: {}, 协方差: {}", self.state, self.cov);
        self.state = self.a * self.state; // X_pred = A * X_prev
        self.cov = self.a * self.cov * self.a + self.q; // P_pred = A*P*A^T + Q
        info!("执行单步预测后,状态: {}, 协方差: {}", self.state, self.cov);
    }

    // 单步更新(根据频段选择R)
    pub fn update(&mut self, measurement: f64, is_low_freq: bool) {
        // info!(
        //     "执行单步更新前,测量值: {}, 是否低频: {}",
        //     measurement, is_low_freq
        // );
        let r = if is_low_freq { self.r_low } else { self.r_high };
        let k = self.cov / (self.cov + r); // 卡尔曼增益K
        self.state += k * (measurement - self.state); // X_new = X_pred + K*(z - H*X_pred)
        self.cov = (1.0 - k) * self.cov; // P_new = (I - K*H)*P_pred
        info!("执行单步更新后,状态: {}, 协方差: {}", self.state, self.cov);
    }
}

pub fn wavelet_kalman_filter(
    signal: &[f64],
    levels: usize, // 小波分解层数
    a: f64,        // 状态转移系数
    q: f64,        // 过程噪声
    r_low: f64,    // 低频观测噪声
    r_high: f64,   // 高频观测噪声
) -> Vec<f64> {
    info!(
        "开始小波卡尔曼滤波,输入信号长度: {}, 分解层数: {}",
        signal.len(),
        levels
    );
    // 1. 递归小波分解(多尺度)
    let mut approx = signal.to_vec();
    let mut details = Vec::new();
    for level in 0..levels {
        info!("第 {} 层小波分解", level + 1);
        let (a, d) = haar_decompose(&approx);
        details.push(d);
        approx = a;
    }

    // 2. 对各频段独立应用卡尔曼滤波
    let mut kalman = WaveletKalmanFilter::new(a, q, r_low, r_high);
    kalman.state = approx[0]; // 初始化状态

    // 低频滤波(R较小,信任观测值)
    info!("开始低频滤波,近似分量长度: {}", approx.len());
    for i in 0..approx.len() {
        info!("低频滤波第 {} 步", i + 1);
        kalman.predict();
        kalman.update(approx[i], true); // 标记为低频
        approx[i] = kalman.state;
    }

    // 高频滤波(R较大,抑制噪声)
    info!("开始高频滤波,细节分量数量: {}", details.len());
    for (level, d) in details.iter_mut().enumerate() {
        info!("第 {} 层细节分量滤波,长度: {}", level + 1, d.len());
        kalman = WaveletKalmanFilter::new(a, q, r_low, r_high); // 重置滤波器
        kalman.state = d[0];
        for i in 0..d.len() {
            info!("第 {} 层细节分量第 {} 步滤波", level + 1, i + 1);
            kalman.predict();
            kalman.update(d[i], false); // 标记为高频
            d[i] = kalman.state;
        }
    }

    // 3. 小波重构
    info!("开始小波重构,分解层数: {}", levels);
    for _ in 0..levels {
        approx = haar_recompose(&approx, &details.pop().unwrap());
    }
    info!("小波卡尔曼滤波完成,输出信号长度: {}", approx.len());
    approx
}

// 绘图函数实现
fn draw_signals(
    clean: &[f64],
    noisy: &[f64],
    filtered: &[f64],
) -> Result<(), Box<dyn std::error::Error>> {
    info!(
        "开始绘制信号图,原始信号长度: {}, 含噪信号长度: {}, 滤波信号长度: {}",
        clean.len(),
        noisy.len(),
        filtered.len()
    );
    use plotters::prelude::*;

    let root = BitMapBackend::new("signals.png", (1024, 768)).into_drawing_area();
    root.fill(&WHITE)?;

    let mut chart = ChartBuilder::on(&root)
        .caption("信号处理结果", ("sans-serif", 50).into_font())
        .margin(10)
        .x_label_area_size(30)
        .y_label_area_size(30)
        .build_cartesian_2d(0f64..clean.len() as f64, -2f64..2f64)?;

    chart.configure_mesh().draw()?;

    chart
        .draw_series(LineSeries::new(
            clean.iter().enumerate().map(|(i, &y)| (i as f64, y)),
            &RED,
        ))?
        .label("原始信号")
        .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED));

    chart
        .draw_series(LineSeries::new(
            noisy.iter().enumerate().map(|(i, &y)| (i as f64, y)),
            &BLUE,
        ))?
        .label("含噪信号")
        .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE));

    chart
        .draw_series(LineSeries::new(
            filtered.iter().enumerate().map(|(i, &y)| (i as f64, y)),
            &GREEN,
        ))?
        .label("滤波信号")
        .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &GREEN));

    chart
        .configure_series_labels()
        .background_style(&WHITE.mix(0.8))
        .border_style(&BLACK)
        .draw()?;
    info!("信号图绘制完成,保存至 signals.png");
    Ok(())
}

// 测试函数:添加高斯噪声的信号滤波
fn test_noisy_sine() {
    info!("开始测试含噪正弦信号滤波");
    let clean_signal: Vec<_> = (0..1000).map(|i| (i as f64 * 0.1).sin()).collect();
    let noisy_signal: Vec<_> = clean_signal
        .iter()
        .map(|x| x + rand::random::<f64>())
        .collect();

    let filtered = wavelet_kalman_filter(&noisy_signal, 3, 1.0, 0.01, 0.1, 2.0);

    // 绘图比较(使用plotters库)
    draw_signals(&clean_signal, &noisy_signal, &filtered);
    info!("含噪正弦信号滤波测试完成");
}

// 主函数
fn main() {
    init_logger();
    info!("程序启动");
    test_noisy_sine();
    info!("程序结束");
}

实时小波卡尔曼滤波

// 引入 nalgebra 库中的矩阵、向量和标量类型
use nalgebra::{DMatrix, DVector, Scalar};
// 引入标准库中的 π 常量
use std::f64::consts::PI;
// 引入标准库中的双端队列
use std::collections::VecDeque;

// 定义实时小波卡尔曼滤波器结构体
pub struct RealTimeWaveletKalmanFilter {
    // 当前状态向量
    state: DVector<f64>,
    // 状态协方差矩阵
    covariance: DMatrix<f64>,
    // 状态转移矩阵
    transition: DMatrix<f64>,
    // 观测矩阵
    observation: DMatrix<f64>,
    // 过程噪声协方差矩阵
    process_noise: DMatrix<f64>,
    // 测量噪声协方差矩阵
    measurement_noise: DMatrix<f64>,
    // 小波类型
    wavelet_type: WaveletType,
    // 小波分解的层数
    decomposition_level: usize,
    // 小波系数阈值
    threshold: f64,
    // 数据缓冲区,用于存储待处理的数据点
    buffer: VecDeque<f64>,
    // 缓冲区的最小大小,取决于小波类型
    min_buffer_size: usize,
    // 缓冲区的大小
    buffer_size: usize,
    // 已处理的数据点数量
    processed_count: usize,
    // 存储各层近似系数的缓冲区
    approx_buffers: Vec<Vec<f64>>,
    // 存储各层细节系数的缓冲区
    detail_buffers: Vec<Vec<f64>>,
}

// 定义小波类型枚举,支持 Haar 和 Daubechies4 两种小波
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum WaveletType {
    Haar,
    Daubechies4,
}

// 实现实时小波卡尔曼滤波器的方法
impl RealTimeWaveletKalmanFilter {
    // 构造函数,初始化实时小波卡尔曼滤波器
    pub fn new(
        initial_state: DVector<f64>,
        initial_covariance: DMatrix<f64>,
        transition: DMatrix<f64>,
        observation: DMatrix<f64>,
        process_noise: DMatrix<f64>,
        measurement_noise: DMatrix<f64>,
        wavelet_type: WaveletType,
        decomposition_level: usize,
        threshold: f64,
    ) -> Self {
        // 根据小波类型确定最小缓冲区大小
        let min_buffer_size = match wavelet_type {
            WaveletType::Haar => 2,
            WaveletType::Daubechies4 => 4,
        };
        // 计算缓冲区大小,通过 2 的 decomposition_level 次幂得到
        let buffer_size = 1 << decomposition_level;
        // 初始化各层近似系数缓冲区
        let approx_buffers = vec![vec![]; decomposition_level];
        // 初始化各层细节系数缓冲区
        let detail_buffers = vec![vec![]; decomposition_level];
        // 返回初始化后的实时小波卡尔曼滤波器实例
        RealTimeWaveletKalmanFilter {
            state: initial_state,
            covariance: initial_covariance,
            transition,
            observation,
            process_noise,
            measurement_noise,
            wavelet_type,
            decomposition_level,
            threshold,
            buffer: VecDeque::with_capacity(buffer_size * 2),
            min_buffer_size,
            buffer_size,
            processed_count: 0,
            approx_buffers,
            detail_buffers,
        }
    }
    // 添加一个新的数据点到滤波器,并尝试进行处理
    pub fn add_data_point(&mut self, measurement: f64) -> Option<f64> {
        // 将新的数据点添加到缓冲区
        self.buffer.push_back(measurement);
        // 检查缓冲区中的数据量是否达到最小缓冲区大小
        if self.buffer.len() >= self.min_buffer_size {
            // 尝试进行小波处理,得到去噪后的数据
            if let Some(denoised) = self.process_wavelets() {
                // 进行卡尔曼预测
                self.predict();
                // 进行卡尔曼更新
                self.update(denoised);
                // 返回更新后的状态向量的第一个元素
                return Some(self.state[0]);
            }
        }
        // 如果无法处理,返回 None
        None
    }
    // 处理小波变换,包括分解、阈值处理和重构
    fn process_wavelets(&mut self) -> Option<f64> {
        // 计算当前处理的小波分解层数
        let level = (self.processed_count % self.decomposition_level) + 1;
        // 确保层数不超过最大分解层数
        let level = level.min(self.decomposition_level);
        // 获取数据块的大小
        let block_size = self.buffer_size;
        // 检查缓冲区中的数据量是否足够一个数据块
        if self.buffer.len() < block_size {
            return None;
        }
        // 从缓冲区中取出一个数据块
        let mut block: Vec<f64> = self.buffer.drain(..block_size).collect();
        // 初始化去噪后的数据块(此处变量未使用)
        let _denoised_block: Vec<f64> = Vec::with_capacity(block_size);
        // 进行小波分解
        for _ in 0..level {
            // 检查数据块的大小是否足够进行小波分解
            if block.len() < self.min_buffer_size {
                break;
            }
            // 根据小波类型进行分解,得到近似系数和细节系数
            let (approx, detail) = match self.wavelet_type {
                WaveletType::Haar => self.haar_decompose(&block),
                WaveletType::Daubechies4 => self.daubechies4_decompose(&block),
            };
            // 将近似系数添加到对应的缓冲区
            self.approx_buffers[level - 1].extend_from_slice(&approx);
            // 将细节系数添加到对应的缓冲区
            self.detail_buffers[level - 1].extend_from_slice(&detail);
            // 更新数据块为近似系数,以便进行下一层分解
            block = approx;
        }
        // 对各层的近似系数和细节系数进行阈值处理
        for i in 0..level {
            self.approx_buffers[i] = self.threshold_coefficients(self.approx_buffers[i].clone());
            self.detail_buffers[i] = self.threshold_coefficients(self.detail_buffers[i].clone());
        }
        // 从最高层的近似系数开始重构
        let mut reconstructed = self.approx_buffers[level - 1].clone();
        // 逐层进行小波重构
        for i in (0..level).rev() {
            reconstructed = match self.wavelet_type {
                WaveletType::Haar => self.haar_reconstruct(&reconstructed, &self.detail_buffers[i]),
                WaveletType::Daubechies4 => self.daubechies4_reconstruct(&reconstructed, &self.detail_buffers[i]),
            };
            // 计算需要保留的系数数量
            let keep_count = (self.buffer_size >> i).max(self.min_buffer_size);
            // 获取近似系数缓冲区的长度
            let approx_len = self.approx_buffers[i].len();
            // 获取细节系数缓冲区的长度
            let detail_len = self.detail_buffers[i].len();
            // 复制近似系数缓冲区
            let mut approx_copy = self.approx_buffers[i].clone();
            // 复制细节系数缓冲区
            let mut detail_copy = self.detail_buffers[i].clone();
            // 保留近似系数缓冲区的最后 keep_count 个元素
            self.approx_buffers[i] = approx_copy.split_off(approx_len.saturating_sub(keep_count));
            // 保留细节系数缓冲区的最后 keep_count 个元素
            self.detail_buffers[i] = detail_copy.split_off(detail_len.saturating_sub(keep_count));
        }
        // 如果重构后的数据存在,更新已处理数据点数量并返回最后一个元素
        if let Some(last_value) = reconstructed.last() {
            self.processed_count += 1;
            return Some(*last_value);
        }
        // 如果重构失败,返回 None
        None
    }
    // 卡尔曼滤波器的预测步骤
    pub fn predict(&mut self) {
        // 根据状态转移矩阵更新状态向量
        self.state = &self.transition * &self.state;
        // 更新状态协方差矩阵
        self.covariance = &self.transition * &self.covariance * self.transition.transpose() + &self.process_noise;
    }
    // 卡尔曼滤波器的更新步骤
    pub fn update(&mut self, measurement: f64) {
        // 将测量值转换为向量
        let measurement_vector = DVector::from_vec(vec![measurement]);
        // 计算测量残差
        let innovation = &measurement_vector - &self.observation * &self.state;
        // 计算测量残差的协方差矩阵
        let innovation_covariance = &self.observation * &self.covariance * self.observation.transpose() + &self.measurement_noise;
        // 计算卡尔曼增益
        if let Some(kalman_gain) = self.compute_kalman_gain(&innovation_covariance) {
            // 根据卡尔曼增益更新状态向量
            self.state = &self.state + &kalman_gain * innovation;
            // 生成单位矩阵
            let identity = DMatrix::identity(self.covariance.nrows(), self.covariance.ncols());
            // 更新状态协方差矩阵
            self.covariance = (identity - &kalman_gain * &self.observation) * &self.covariance;
        }
    }
    // 计算卡尔曼增益
    fn compute_kalman_gain(&self, innovation_covariance: &DMatrix<f64>) -> Option<DMatrix<f64>> {
        // 尝试直接求逆计算卡尔曼增益
        if let Some(inv) = innovation_covariance.clone().try_inverse() {
            Some(&self.covariance * self.observation.transpose() * inv)
        } else {
            // 如果直接求逆失败,使用奇异值分解计算伪逆
            let svd = innovation_covariance.clone().svd(true, true);
            svd.pseudo_inverse(1e-12)
                .ok()
                .map(|inv| &self.covariance * self.observation.transpose() * inv)
        }
    }
    // Haar 小波分解
    fn haar_decompose(&self, signal: &[f64]) -> (Vec<f64>, Vec<f64>) {
        // 获取信号长度
        let n = signal.len();
        // 如果信号长度小于 2,直接返回原信号和全 0 的细节系数
        if n < 2 {
            return (signal.to_vec(), vec![0.0; n]);
        }
        // 初始化近似系数缓冲区
        let mut approx = Vec::with_capacity(n / 2);
        // 初始化细节系数缓冲区
        let mut detail = Vec::with_capacity(n / 2);
        // 对信号进行两两分组,计算近似系数和细节系数
        for i in (0..n).step_by(2) {
            // 左边界(未使用)
            let _left_boundary = if i == 0 { i + 1 } else { i - 1 };
            // 右边界
            let right_boundary = if i + 1 >= n { n - 2 } else { i + 1 };
            // 获取当前信号点
            let s0 = if i < n { signal[i] } else { signal[n - (i - n) % (n - 1) - 1] };
            // 获取下一个信号点
            let s1 = if i + 1 < n { signal[i + 1] } else { signal[right_boundary] };
            // 计算近似系数
            approx.push((s0 + s1) / 2.0);
            // 计算细节系数
            detail.push((s0 - s1) / 2.0);
        }
        // 返回近似系数和细节系数
        (approx, detail)
    }
    // Daubechies4 小波分解
    fn daubechies4_decompose(&self, signal: &[f64]) -> (Vec<f64>, Vec<f64>) {
        // Daubechies4 小波分解的低通滤波器系数
        const H0: f64 = 0.4829629131445341;
        const H1: f64 = 0.8365163037378079;
        const H2: f64 = 0.2241438680420134;
        const H3: f64 = -0.1294095225512604;
        // 获取信号长度
        let n = signal.len();
        // 如果信号长度小于 4,直接返回原信号和全 0 的细节系数
        if n < 4 {
            return (signal.to_vec(), vec![0.0; n]);
        }
        // 初始化近似系数缓冲区
        let mut approx = Vec::with_capacity(n / 2);
        // 初始化细节系数缓冲区
        let mut detail = Vec::with_capacity(n / 2);
        // 定义对称延拓函数,用于处理边界情况
        let symmetric_extend = |idx: isize, signal: &[f64]| {
            let n = signal.len();
            if idx < 0 {
                let symmetric_idx = (-idx - 1) as usize;
                if symmetric_idx < n { signal[symmetric_idx] } else { *signal.last().unwrap() }
            } else if idx >= n as isize {
                let symmetric_idx = 2 * n as isize - 2 - idx;
                if symmetric_idx < 0 {
                    signal[0]
                } else {
                    let idx_usize = symmetric_idx as usize;
                    if idx_usize < n { signal[idx_usize] } else { *signal.last().unwrap() }
                }
            } else {
                signal[idx as usize]
            }
        };
        // 对信号进行两两分组,计算近似系数和细节系数
        for i in (0..n).step_by(2) {
            let idx_minus2 = i as isize - 2;
            let idx_minus1 = i as isize - 1;
            let idx_0 = i as isize;
            let idx_plus1 = i as isize + 1;
            let s_minus2 = symmetric_extend(idx_minus2, signal);
            let s_minus1 = symmetric_extend(idx_minus1, signal);
            let s0 = symmetric_extend(idx_0, signal);
            let s1 = symmetric_extend(idx_plus1, signal);
            // 计算近似系数
            let a = s_minus2 * H0 +
                    s_minus1 * H1 +
                    s0 * H2 +
                    s1 * H3;
            // 计算细节系数
            let d = s_minus2 * (-H3) +
                    s_minus1 * H2 +
                    s0 * (-H1) +
                    s1 * H0;
            approx.push(a);
            detail.push(d);
        }
        // 返回近似系数和细节系数
        (approx, detail)
    }
    // Haar 小波重构
    fn haar_reconstruct(&self, approx: &[f64], detail: &[f64]) -> Vec<f64> {
        // 计算重构后信号的长度
        let n = approx.len().max(detail.len()) * 2;
        // 初始化重构后的信号
        let mut signal = vec![0.0; n];
        // 定义对称延拓函数,用于处理边界情况
        let extend = |arr: &[f64], idx: isize| {
            if idx < 0 {
                let symmetric_idx = (-idx - 1) as usize;
                if symmetric_idx < arr.len() { arr[symmetric_idx] } else { *arr.last().unwrap() }
            } else if idx >= arr.len() as isize {
                let symmetric_idx = 2 * arr.len() as isize - 2 - idx;
                if symmetric_idx < 0 {
                    arr[0]
                } else {
                    let idx_usize = symmetric_idx as usize;
                    if idx_usize < arr.len() { arr[idx_usize] } else { *arr.last().unwrap() }
                }
            } else {
                arr[idx as usize]
            }
        };
        // 根据近似系数和细节系数重构信号
        for i in 0..n {
            if i % 2 == 0 {
                let a = extend(approx, (i / 2) as isize);
                let d = extend(detail, (i / 2) as isize);
                signal[i] = a + d;
            } else {
                let a = extend(approx, (i / 2) as isize);
                let d = extend(detail, (i / 2) as isize);
                signal[i] = a - d;
            }
        }
        // 返回重构后的信号
        signal
    }
    // Daubechies4 小波重构
    fn daubechies4_reconstruct(&self, approx: &[f64], detail: &[f64]) -> Vec<f64> {
        // Daubechies4 小波重构的低通滤波器系数
        const G0: f64 = -0.1294095225512604;
        const G1: f64 = 0.2241438680420134;
        const G2: f64 = 0.8365163037378079;
        const G3: f64 = 0.4829629131445341;
        // 计算重构后信号的长度
        let n = approx.len().max(detail.len()) * 2;
        // 初始化重构后的信号
        let mut signal = vec![0.0; n];
        // 定义对称延拓函数,用于处理边界情况
        let extend = |arr: &[f64], idx: isize| {
            if idx < 0 {
                let symmetric_idx = (-idx - 1) as usize;
                if symmetric_idx < arr.len() { arr[symmetric_idx] } else { *arr.last().unwrap() }
            } else if idx >= arr.len() as isize {
                let symmetric_idx = 2 * arr.len() as isize - 2 - idx;
                if symmetric_idx < 0 {
                    arr[0]
                } else {
                    let idx_usize = symmetric_idx as usize;
                    if idx_usize < arr.len() { arr[idx_usize] } else { *arr.last().unwrap() }
                }
            } else {
                arr[idx as usize]
            }
        };
        // 根据近似系数和细节系数重构信号
        for i in 0..n {
            let half_i = i as f64 / 2.0;
            let base_idx = half_i.floor() as isize;
            let a_idx = base_idx - 1;
            let a_idx1 = base_idx;
            let a0 = extend(approx, a_idx);
            let d0 = extend(detail, a_idx);
            let a1 = extend(approx, a_idx1);
            let d1 = extend(detail, a_idx1);
            let value = 
                a0 * G2 + 
                d0 * G3 + 
                a1 * G0 + 
                d1 * G1;
            signal[i] = value;
        }
        // 返回重构后的信号
        signal
    }
    // 对小波系数进行阈值处理
    fn threshold_coefficients(&self, mut coefficients: Vec<f64>) -> Vec<f64> {
        // 对每个系数进行阈值处理
        coefficients.iter_mut().for_each(|c| {
            if *c > self.threshold {
                *c -= self.threshold;
            } else if *c < -self.threshold {
                *c += self.threshold;
            } else {
                *c = 0.0;
            }
        });
        // 返回处理后的系数
        coefficients
    }
    // 获取当前状态向量
    pub fn get_state(&self) -> &DVector<f64> {
        &self.state
    }
    // 获取当前状态协方差矩阵
    pub fn get_covariance(&self) -> &DMatrix<f64> {
        &self.covariance
    }
}

// 测试模块
#[cfg(test)]
mod tests {
    use super::*;
    use approx::assert_relative_eq;
    use rand::Rng;
    // 生成带噪声的正弦信号
    fn generate_sine_with_noise(length: usize, noise_level: f64) -> Vec<f64> {
        let mut rng = rand::thread_rng();
        (0..length)
            .map(|i| {
                let t = i as f64 * 0.1;
                t.sin() + noise_level * (rng.gen_range(-0.5..0.5))
            })
            .collect()
    }
    // 测试对称边界处理
    #[test]
    fn test_symmetric_boundary() {
        let signal = vec![1.0, 2.0, 3.0, 4.0];
        let mut filter = RealTimeWaveletKalmanFilter::new(
            DVector::from_vec(vec![0.0]),
            DMatrix::from_diagonal(&DVector::from_vec(vec![1.0])),
            DMatrix::from_row_slice(1, 1, &[1.0]),
            DMatrix::from_row_slice(1, 1, &[1.0]),
            DMatrix::from_diagonal(&DVector::from_vec(vec![0.001])),
            DMatrix::from_element(1, 1, 0.1),
            WaveletType::Daubechies4,
            2,
            0.2,
        );
        // 验证 Daubechies4 分解后的近似系数长度
        assert_eq!(filter.daubechies4_decompose(&signal).0.len(), 2);
        let short_signal = vec![1.0];
        // 验证 Haar 分解后的近似系数长度
        assert_eq!(filter.haar_decompose(&short_signal).0.len(), 1);
        let decomposed = filter.daubechies4_decompose(&signal);
        // 验证分解后的近似系数长度大于 0
        assert!(decomposed.0.len() > 0);
    }
    // 测试带边界的实时信号处理性能
    #[test]
    fn test_realtime_boundary_performance() {
        let mut filter = RealTimeWaveletKalmanFilter::new(
            DVector::from_vec(vec![0.0]),
            DMatrix::from_diagonal(&DVector::from_vec(vec![1.0])),
            DMatrix::from_row_slice(1, 1, &[1.0]),
            DMatrix::from_row_slice(1, 1, &[1.0]),
            DMatrix::from_diagonal(&DVector::from_vec(vec![0.001])),
            DMatrix::from_element(1, 1, 0.1),
            WaveletType::Daubechies4,
            3,
            0.2,
        );
        // 生成测试数据
        let measurements: Vec<f64> = (0..500)
            .map(|i| {
                if i < 100 {
                    1.0
                } else if i < 300 {
                    5.0
                } else {
                    2.0
                }
            })
            .collect();
        let mut count = 0;
        let start = std::time::Instant::now();
        // 处理测试数据
        for m in &measurements {
            if filter.add_data_point(*m).is_some() {
                count += 1;
            }
        }
        let duration = start.elapsed();
        println!("带边界的信号处理耗时: {:?} ({}点/毫秒)", 
                 duration, 
                 measurements.len() as f64 / duration.as_millis() as f64);
        // 验证处理后产生的估计值数量
        assert!(count > 450, "应产生大部分估计值");
        // 验证处理时间是否符合要求
        assert!(duration.as_millis() < 20, "处理过慢");
    }
    // 测试带边界的实时信号处理
    #[test]
    fn test_realtime_processing_with_boundary() {
        let initial_state = DVector::from_vec(vec![0.0]);
        let initial_covariance = DMatrix::from_diagonal(&DVector::from_vec(vec![1.0]));
        let transition = DMatrix::from_row_slice(1, 1, &[0.95]);
        let observation = DMatrix::from_row_slice(1, 1, &[1.0]);
        let process_noise = DMatrix::from_diagonal(&DVector::from_vec(vec![0.001]));
        let measurement_noise = DMatrix::from_element(1, 1, 0.1);
        let mut filter = RealTimeWaveletKalmanFilter::new(
            initial_state,
            initial_covariance,
            transition,
            observation,
            process_noise,
            measurement_noise,
            WaveletType::Daubechies4,
            3,
            0.3,
        );
        let n = 128;
        // 生成带噪声的正弦信号
        let mut measurements = generate_sine_with_noise(n, 0.5);
        // 在边界点添加干扰
        for i in 0..n {
            if i == 0 || i == n - 1 {
                measurements[i] += 1.0;
            }
        }
        // 验证前几个数据点是否无法处理
        assert!(filter.add_data_point(measurements[0]).is_none());
        assert!(filter.add_data_point(measurements[1]).is_none());
        assert!(filter.add_data_point(measurements[2]).is_none());
        let mut estimates = Vec::with_capacity(n);
        // 处理数据并记录估计值
        for (i, &m) in measurements.iter().enumerate() {
            if let Some(est) = filter.add_data_point(m) {
                estimates.push(est);
                if i > n - 5 {
                    println!("Boundary estimate at {}: {:.4} (measured {:.4})", i, est, m);
                }
            }
        }
        // 验证处理后产生的估计值数量
        assert!(estimates.len() > n - 10, "应产生几乎与输入相同数量的估计值");
        // 生成原始正弦信号
        let original_signal: Vec<f64> = (0..n).map(|i| (i as f64 * 0.1).sin()).collect();
        let mut mse = 0.0;
        // 计算均方误差
        for (est, orig) in estimates.iter().zip(&original_signal[original_signal.len() - estimates.len()..]) {
            mse += (est - orig).powi(2);
        }
        mse /= estimates.len() as f64;
        println!("带边界延拓的实时处理MSE: {:.6}", mse);
        // 验证均方误差是否符合要求
        assert!(mse < 0.1, "去噪后MSE应较低");
        // 计算开始边界失真
        let boundary_distortion_start = (estimates[0] - original_signal[original_signal.len() - estimates.len()]).abs();
        // 计算结束边界失真
        let boundary_distortion_end = (estimates[estimates.len()-1] - *original_signal.last().unwrap()).abs();
        println!("开始边界失真: {:.4}, 结束边界失真: {:.4}", boundary_distortion_start, boundary_distortion_end);
        // 验证开始边界失真是否符合要求
        assert!(boundary_distortion_start < 0.5, "开始边界失真过大");
        // 验证结束边界失真是否符合要求
        assert!(boundary_distortion_end < 0.5, "结束边界失真过大");
    }
    // 测试实时 Haar 小波处理
    #[test]
    fn test_realtime_haar_processing() {
        let initial_state = DVector::from_vec(vec![0.0]);
        let initial_covariance = DMatrix::from_diagonal(&DVector::from_vec(vec![1.0]));
        let transition = DMatrix::from_row_slice(1, 1, &[0.98]);
        let observation = DMatrix::from_row_slice(1, 1, &[1.0]);
        let process_noise = DMatrix::from_diagonal(&DVector::from_vec(vec![0.001]));
        let measurement_noise = DMatrix::from_element(1, 1, 0.15);
        let mut filter = RealTimeWaveletKalmanFilter::new(
            initial_state,
            initial_covariance,
            transition,
            observation,
            process_noise,
            measurement_noise,
            WaveletType::Haar,
            4,
            0.4,
        );
        let mut measurements = vec![];
        // 生成测试数据
        for i in 0..100 {
            if i < 30 {
                measurements.push(1.0 + rand::thread_rng().gen_range(-0.5..0.5));
            } else if i < 70 {
                measurements.push(-1.0 + rand::thread_rng().gen_range(-0.5..0.5));
            } else {
                measurements.push(2.0 + rand::thread_rng().gen_range(-0.5..0.5));
            }
        }
        // 在边界点添加干扰
        measurements[0] += 1.0;
        measurements[99] += 1.0;
        let mut estimates = Vec::with_capacity(measurements.len());
        // 处理数据并记录估计值
        for (i, &m) in measurements.iter().enumerate() {
            if let Some(est) = filter.add_data_point(m) {
                estimates.push(est);
                if i == 0 || i == 99 {
                    println!("边界点 {}: 测量值={:.4}, 估计值={:.4}", i, m, est);
                }
            }
        }
        // 获取第一个阶跃点的估计值
        let step1 = estimates[35].abs();
        // 获取第二个阶跃点的估计值
        let step2 = estimates[75].abs();
        // 验证是否检测到第一个阶跃
        assert!(step1 > 0.8, "未检测到第一个阶跃");
        // 验证是否检测到第二个阶跃
        assert!(step2 > 1.5, "未检测到第二个阶跃");
        // 验证阶跃过渡是否清晰
        assert!(step2 - step1 > 1.0, "阶跃过渡不清晰");
        // 计算开始边界失真
        let start_distortion = (estimates[0] - 2.0).abs();
        // 计算结束边界失真
        let end_distortion = (estimates[99] - 3.0).abs();
        println!("开始边界失真: {:.4}, 结束边界失真: {:.4}", start_distortion, end_distortion);
        // 验证开始边界失真是否符合要求
        assert!(start_distortion < 1.0, "开始边界失真过大");
        // 验证结束边界失真是否符合要求
        assert!(end_distortion < 1.0, "结束边界失真过大");
    }
}

// 主函数,演示实时小波卡尔曼滤波器的使用
fn main() {
    // 初始化状态向量
    let initial_state = DVector::from_vec(vec![0.0]);
    // 初始化状态协方差矩阵
    let initial_covariance = DMatrix::from_diagonal(&DVector::from_vec(vec![1.0]));
    // 初始化状态转移矩阵
    let transition = DMatrix::from_row_slice(1, 1, &[0.95]);
    // 初始化观测矩阵
    let observation = DMatrix::from_row_slice(1, 1, &[1.0]);
    // 初始化过程噪声协方差矩阵
    let process_noise = DMatrix::from_diagonal(&DVector::from_vec(vec![0.001]));
    // 初始化测量噪声协方差矩阵
    let measurement_noise = DMatrix::from_element(1, 1, 0.1);
    // 创建实时小波卡尔曼滤波器实例
    let mut filter = RealTimeWaveletKalmanFilter::new(
        initial_state,
        initial_covariance,
        transition,
        observation,
        process_noise,
        measurement_noise,
        WaveletType::Daubechies4,
        3,
        0.2,
    );
    // 定义测试数据
    let measurements = vec![1.0, 1.1, 0.9, 1.2, 0.8, 1.3, 0.7];
    // 处理测试数据并输出去噪后的估计值
    for m in measurements {
        if let Some(estimate) = filter.add_data_point(m) {
            println!("去噪后的估计值: {}", estimate);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值