水声相关公式C++实现

一、背景知识简介

声纳,由于水中声速较快(1500米每秒),而且传播距离远(最大能到200公里),所以声纳这种机械波远比雷达的电磁波在水中实用。

识别结果

类似于B超,靠回声得到一团团的亮斑,由于是径向,所以一般只能获得"相对距离与相对角度"

瀑布图

将360度展平而得到的图像

频率

高频比低频精度高,但是传播距离没有低频远(后面讲传播损失,频率会作为一个影响变量)

二、声纳方程

声纳分为主动(敲听反射)和被动(侦听)

主动声纳

SE = SL - 2 * TL + TS - (NL - AG)

被动声纳

SE = SL - TL - NL + DI - DT

其中的中间变量下面详细介绍

声纳还可分为船壳(舰载)声纳、拖曳声纳两种。(略)

三、中间变量相关因素与影响链条

1-基础概念介绍

简称 英文全称 中文名称 概念 单位
SL Source Level 发射声源级 主动声呐发射信号在 1 米处的声压强度,表征发射信号的初始能量 dB re 1 μPa·m
SL1 辐射噪声级 被探测目标自己辐射出的噪声强度
NL Noise Level 接收机背景噪声级 声呐接收机处的环境噪声强度,包含海洋环境噪声、自噪声等 dB re 1 μPa
DI Directivity Index 接收机指向性指数 描述声呐阵对特定方向信号的汇聚能力,值越高抗干扰能力越强 dB(相对量)
DT Detection Threshold 检测阈值 声呐满足指定检测概率和虚警率时,所需的最小信号相对噪声余量 dB(相对量)
TS Target Strength 目标强度 目标对入射声波的反射能力,表征目标反射声压相对于入射声压的比例 dB(相对量)
TL Transmission Loss 传播损失 声波从发射点到接收点的能量衰减量,包含扩展损失、吸收损失等 dB(相对量)
RL Reverberation Level 混响级 海洋中散射体反射形成的干扰声压强度,是主动声呐的主要干扰源 dB re 1 μPa
SE Signal Excess 信号余量/回声余量 声呐接收信号强度与检测所需强度的差值,SE≥0 表示可有效探测 dB(相对量)
Sen Receiver Sensitivity 接收灵敏度 接收机可分辨的最小输入声压强度,通常以 1 μPa 为参考基准 dB re 1 μPa

2-相关影响链条图

Mermaid 流程图代码

复制代码
---
config:
  layout: elk
---
flowchart LR
 subgraph EnvironmentEffects["环境基础属性"]
        A["温度 T"]
        B["盐度 S"]
        C["深度 D"]
        D1["频率 f"]
        E["带宽 B"]
  end
 subgraph s1["噪声与信号参数(中间层)"]
        N["环境噪声 NL (海洋环境)"]
        O["自噪声 NS (平台噪声)"]
        P1["干扰噪声 NJ (干扰源)"]
        Q["信号级 S (SL-2TL+TS)"]
        R["混响级 RL"]
  end
    A --> F["声速 c (T,S,D)"] & K["吸收系数 alpha (f,T,S,D)"]
    B --> G["密度 rho (T,S,D)"] & K
    C --> H["压强 P (D)"] & K
    D1 --> I["脉冲宽度 τ (1/B)"] & K & M["目标强度 TS (目标几何,f)"]
    E --> I
    F --> J["传播损失 TL (c,f,D)"]
    I --> L["混响级 RL (SL,TL,SS,V)"]
    N --> S["总噪声 NT (NL+NS+NJ+RL)"]
    O --> S
    P1 --> S
    R --> S
    Q --> T["信号余量 SE (S - NT + DI - DT)"]
    S --> T

四、C++实现

写代码时就是怕没有参照和对比,不知道自己找的公式是否正确,于是一般找个典型数值表,看看输出是否不离谱。

4-1 环境影响部分参数

1.吸收系数

直接影响传播损失TL的值(这里放了好几版,挑合适的用吧)

cpp 复制代码
// Thorp 吸收系数 α (dB/m) 吸收近似
inline double absorption(double f_Hz)
{
    double f_KHz = f_Hz / 1000.0;
    double alpha = 0.11 * std::pow(f_KHz, 2) /
                       (1 + std::pow(f_KHz, 2)) +
                   44.0 * std::pow(f_KHz, 2) /
                       (4100.0 + std::pow(f_KHz, 2)) +
                   2.75e-4 * std::pow(f_KHz, 2) + 0.003;
    return alpha / 1000.0; // dB/m
}


//吸收系数 α_bottom(f, 密度, 声速)
double bottomAbsorption()
{
    double f_kHz = m_env.dFreq / 1000.0;
    double rho_gcm3 = m_env.density;
    double c_mps = m_env.c;
    // 简:α ∝ f · (ρ/c)²
    return 0.5 * f_kHz * pow(rho_gcm3 / (c_mps / 1000.0), 2.0); // dB/m
}


    // 计算海水吸收系数(单位:dB/m)
    // 采用Ainslie-McColm简化模型(考虑硼酸、硫酸镁和纯水吸收)
    double computeAbsorptionCoeff(double freq_Hz) const {
        if (freq_Hz <= 0) return 0.0;

        double f = freq_Hz / 1000.0;  // 转换为kHz
        double T = m_env.tempC;       // 温度(℃)
        double S = m_env.sal;         // 盐度(‰)
        double P = m_env.P;           // 压强(atm)

        // 硼酸弛豫吸收(dB/km)
        double f1 = 0.78 * sqrt(S / 35.0) * exp(T / 26.0);
        double a1 = 0.106 * (f1 * f * f) / (f1*f1 + f*f) * exp((P - 1) / 0.4343 / f1);

        // 硫酸镁弛豫吸收(dB/km)
        double f2 = 42.0 * exp(T / 17.0);
        double a2 = 0.52 * (1 + T / 43.0) * (S / 35.0) * (f2 * f * f) / (f2*f2 + f*f) 
                  * exp(-(P - 1) / 0.8686 / f2);

        // 纯水吸收(dB/km)
        double a3 = 0.00049 * f * f * exp(-(T / 27.0 + P / 17.0));

        // 总吸收系数(转换为dB/m)
        double alpha_db_per_km = a1 + a2 + a3;
        return alpha_db_per_km / 1000.0;  // dB/km → dB/m
    }

2.静水压强

cpp 复制代码
inline double computeHydrostaticPressure_with_density(double depth_m,double salinity_ppt,
                                               double temp_C,
                                              double g = 9.80665,double atm_pa = 101325.0)
{
    /**
         综合计算压力(以 Pa 返回)
         depth_m            深度-米
         salinity_ppt       盐度-千分之一
         temp_C             摄氏温度
         g                  重力常数
         atm_pa             大气压强
     **/
    if (depth_m < 0.0) depth_m = -1 * depth_m;

    //计算密度,常见取值 rho0 ~1027 kg/m3 (取决于基准)
    const double rho0 = 1027.0; // 基准密度 kg/m3 (近似)
    const double a = 0.8;  // 每 ppt 盐度变化引起的密度变化 (approx)
    const double b = -0.2; // 每 °C 的近似密度变化 (approx)
    double rho = rho0 + a * (salinity_ppt - 35.0) + b * (temp_C - 10.0);

    double hydro_pa = rho * g * depth_m;//液体压强等于密度*重力加速度*深度


    double Pa = atm_pa + hydro_pa; //大气压强+液体压强
    Pa =  Pa / 98066.5 ;

    // Pa -> kgf/cm²: kgf_per_cm2 = Pa / 98066.5 (因为 1 kgf/cm² = 98,066.5 Pa)
    return Pa;
}



//简版
    // 公式:P = 1 + depth_m / 10.33(1atm≈10.33m水深)
    double computeHydrostaticPressure(double depth_m) const {
        return 1.0 + depth_m / 10.33;
    }

3.声速计算

cpp 复制代码
    // 采用Wilson经验公式
    double computeSoundSpeed(double tempC, double sal, double depth_m) const {
        // 温度项
        double c_temp = 1449.2 + 4.6 * tempC - 0.055 * tempC*tempC + 0.00029 * tempC*tempC*tempC;
        // 盐度项
        double c_sal = 1.34 * (sal - 35.0);
        // 深度项
        double c_depth = 0.0163 * depth_m;
        return c_temp + c_sal + c_depth;
    }

4-2 声纳方程部分参数

1.发射声源级SL【查表】

这部分主要是看(主动)声纳型号的属性查表,有根据功率进行转化的,但是不太准

水中声源级SL的求解应用举例-CSDN博客

1-1.辐射噪声级SL1

根据舰船自身属性,这里给一个根据质量估算的

cpp 复制代码
    inline double sourceLevel(double V_mps, double m_kg, double F_Hz)
    {
        double T = 0;

        // | 平台   | 质量区间 (t)    | 排水量 (t)    | 拟合 T   |
        // | ---- | -------------- | -------------- | ------ |
        // | 鱼雷   | 1--3            | 1--3            | 1      |
        // | 小型潜艇| 100--1 000      | 100--1 000      | 100    |
        // | 大型潜艇| 1 000--10 000   | 1 000--10 000   | 1000  |
        // | 商船/舰 | 10 000--100 000 | 10 000--100 000 | 10000 |

//        double mass_t = m / 1000.0;
//        double T = 0;
//        if (mass_t <= 0.0)
//            T = 1.0;
//        return std::pow(10.0, std::floor(std::log10(mass_t)));


        // SL = 60 log₁₀(V) + 9 log₁₀(T) − 20 log₁₀(F) + 35
        // 被动声呐领域最常用 的"机械+螺旋桨"辐射噪声级估算式
        //  V	目标航速	knot (Kn)	3--30 Kn
        //  T	目标类型系数	无因次	商船≈1000,潜艇≈100,鱼雷≈10
        //  F	工作频率	kHz	0.1--10 kHz

        double F_KHz = F_Hz / 1000.0;
        double V = V_mps * 3.6 / 1.852; //  m/s-> kont
        if(m_kg > 1000e3){
            T = 1000;
        }else if(m_kg > 100e3){
            T = 100;
        }else{
            T = 10;
        }

        if (V <= 0.0)
            V = 0.1; // 防 0
        if (T <= 0.0)
            T = 1.0; // 防 0
        if (F_KHz <= 0.0)
            F_KHz = 0.01; // 防 0

        return 60.0 * std::log10(V) +
               9.0 * std::log10(T) -
               20.0 * std::log10(F_KHz) +
               35.0;
    }

2.背景噪声级NL

这部分涉及海面噪声、环境噪声、自噪声(舰船自己发出的噪声),一般进行对数求和处理。

cpp 复制代码
   // 海面噪声-cq20251017
    double windNoise( )
    {
        EnvironmentInfo e = m_env;
        // | 场景 | 风速   | 对应海况 | NL/dB     | 状态    |
        // | --  | ------ | -------- | --------- | ----- |
        // | 无风 | 1 m/s  | 0        | **35 dB** | 极低噪声  |
        // | 微风 | 4 m/s  | 2        | **45 dB** | 典型低噪声 |
        // | 大风 | 12 m/s | 5        | **65 dB** | 高噪声   |
        // | 台风 | 25 m/s | 8        | **85 dB** | 极高噪声  |
        if (e.wind< 1)
        {
            e.seaState = 0;
        }
        else if (e.wind< 4)
        {
            e.seaState = 2;
        }
        else if (e.wind< 12)
        {
            e.seaState = 5;
        }
        else if (e.wind< 25)
        {
            e.seaState = 8;
        }
        else{
            e.seaState = 9;
        }

        // Knudsen 半经验:NL = 50 + 7.5·log10(wind) + 5·seaState
        return 50.0 + 7.5 * env_utils::log10(e.wind) + 5.0 * e.seaState;
    }

    // 总噪声
    double totalNoise(double env_dB, double self_dB, double jam_dB)
    {
        double env = pow(10.0, env_dB / 10.0);
        double self = pow(10.0, self_dB / 10.0);
        double jam = pow(10.0, jam_dB / 10.0);
        return 10.0 * log10(env + self +jam);
    };

3.接收机指向性指数DI【查表】

这部分需要根据具体型号查表得到

4.检测阈值DT

cpp 复制代码
//PassiveSonar
    inline double getDT(double d,     // 检测指数 (线性值)
                        double T_sec, // 积分时间 (s)
                        double W_Hz)  // 有效带宽 (Hz)
    {
        // 检测指数门限
        // DT = 5·log₁₀(d) − 5·log₁₀(T·W)
        if (d <= 0.0 || T_sec <= 0.0 || W_Hz <= 0.0)
            return 0.0;
        return 5.0 * std::log10(d) - 5.0 * std::log10(T_sec * W_Hz);
    }


//ActiveSonar
    inline double getDT(double B_Hz,     // 接收机带宽 (Hz)
                        double T_sec,    // 脉冲/积分时间 (s)
                        double SN = 1.0) // 信噪比 (线性值,默认 1)
    {
        // 匹配滤波器门限
        // DT = 10·log₁₀(2·B·T)  (当 S/N = 1 时)
        // 若给定 S/N,则 DT = 10·log₁₀(2·B·T·(S/N))

        if (B_Hz <= 0.0 || T_sec <= 0.0)
            return 999.0; // 物理保护:无限大阈值
        return 10.0 * std::log10(2.0 * B_Hz * T_sec * SN);
    }

5.目标强度TS【查表】

随着声波入射角而变化,常说的截面积也包含在内

具体计算就是 基准TS0 + 入射角修正

下面举一个例子

cpp 复制代码
    // 每 15° ACS 修正表(0--360° 全覆盖)
    inline double getTSinACS(double TS0, double theta_deg) {
        // 归一化到 0--360°
        while (theta_deg < 0) theta_deg += 360.0;
        while (theta_deg >= 360.0) theta_deg -= 360.0;

        //  每 15° ACS 修正表(公开经验拟合)
        static const double table[25] = {
            // 0°, 15°, 30°, 45°, 60°, 75°, 90°, 105°, 120°, 135°, 150°, 165°, 180°,
            +20.0, +15.0, +10.0, +5.0, 0.0, -5.0, -10.0, -5.0, 0.0, +5.0, +10.0, +15.0, +20.0,
            // 195°, 210°, 225°, 240°, 255°, 270°, 285°, 300°, 315°, 330°, 345°, 360°
            +15.0, +10.0, +5.0, 0.0, -5.0, -10.0, -5.0, 0.0, +5.0, +10.0, +15.0, +20.0
        };

        // 每 15° 插值
        double index = theta_deg / 15.0;
        int    idx0  = static_cast<int>(index);
        int    idx1  = (idx0 + 1) % 24;
        double t     = index - idx0;
        double TSoffset = table[idx0] + t * (table[idx1] - table[idx0]);
        return TS0 + TSoffset;
    }

6.传播损失TL

典型表格

声呐频率 吸收系数 α(dB/km) 1km 传播损失(球面扩展) 10km 传播损失(柱面扩展) 50km 传播损失(柱面扩展) 备注
100Hz 0.008dB/km 20.008dB 40.08dB 60.4dB 多为远程拖曳声呐频段,吸收损失极小
500Hz 0.03dB/km 20.03dB 40.3dB 61.5dB 低频段,适合远距离探测,干扰小
1kHz 0.068dB/km 20.068dB 40.68dB 63.4dB 中低频交界,常作为常规声呐基础频段
5kHz 0.35dB/km 20.35dB 43.5dB 77.5dB 中频段,兼顾探测距离与分辨率
10kHz 0.8dB/km 20.8dB 48dB 90dB 中高频,船壳声呐常用频段,吸收损失开始显著
20kHz 2.0dB/km 22.0dB 50dB 130dB 高频段,适用于中短距离精准探测
50kHz 7.0dB/km 27.0dB 77dB 380dB 高频,多用作近程成像声呐,远距离损耗剧增
100kHz 15.0dB/km 35.0dB 115dB 785dB 超高频,仅适配近距离目标检测,如避障声呐

对 Francois-Garrison 公式的一个简化工程版本

cpp 复制代码
// 计算海水吸收系数 alpha (dB/km)
// freq_hz: 频率 (Hz)
// temp_c: 温度 (°C)   [0, 30] 较合适
// salinity: 盐度 (‰) [30, 38] 较合适
// depth_m: 深度 (m)   [0, 1000] 较合适
double seaWaterAbsorption(double freq_hz,
                          double temp_c,
                          double salinity,
                          double depth_m)
{
    if (freq_hz <= 0.0)
        return 0.0;

    double f = freq_hz / 1000.0; // 转为 kHz
    double T = temp_c;
    double S = salinity;
    double z = depth_m;

    // 压强 (atm)
    double P = 1.0 + z / 10.33;  // 1 atm ≈ 10.33 m

    // ------------ Boric acid relaxation absorption (dB/km) ------------
    double f1 = 0.78 * sqrt(S / 35.0) * exp(T / 26.0);
    double a1 = 0.106 * (f1 * f * f) / (f * f + f1 * f1);

    // ------------ Magnesium sulfate relaxation absorption (dB/km) ------------
    double f2 = 42.0 * exp(T / 17.0);
    double a2 = 0.52 * (S / 35.0) * (T + 273.15) / 293.15
                * exp(-T / 12.0) * (f2 * f * f) / (f * f + f2 * f2);

    // ------------ Viscous (pure water) absorption (dB/km) ------------
    double a3 = 0.00049 * (T + 273.15) / 293.15 * exp(-T / 27.0) * f * f;

    // ------------ Pressure (depth) correction ------------
    double D = z / 1000.0; // 深度以 km 为单位
    double a = a1 + a2 + a3;

    // 经验修正:随深度增加略有减小(Francois-Garrison 建议的简化形式)
    a = a * (1.0 - 0.005 * D);

    return a;
}

7.混响RL

cpp 复制代码
    //反射损失 BL(θ, f, 底质) 参数:入射角
    double bottomLoss(double theta_deg)
    {
        int bottomType = m_env.landType;
        //----海底底质影响
        // 结论先行------海底质是声呐的"第四边界",
        // 它通过 反射损失、散射强度、吸收系数 三条路径,
        // 同时改变 传播损失 TL、混响级 RL、目标对比度 TS/RL,
        // 必须在任何 工程级声呐仿真 中显式建模。

        // | 效应        | 物理量                        | 典型量级         | 公开公式/数据                                          | 资料来源 |
        // | --------    | -------------------------- | ------------ | ------------------------------------------------ | ---- |
        // | **反射损失** | **BL** (Bottom Loss)       | 0--30 dB      | **朗伯散射**:$S_s = 10\log\mu + 10\log\sin^2\theta$  |      |
        // | **散射强度** | **BS** (Bottom Scattering) | −25 ~ −35 dB | **MIT 实测**:μ = −29 dB (砂砾)                       |      |
        // | **吸收系数** | **α\_bottom**              | 0.1--2 dB/m   | **分层模型**:α = f(密度, 声速, 粒径)                       |      |

        // 底质越硬、掠射角越小 → 反射越强、散射越强 → 混响级 RL ↑ 10--30 dB,直接掩盖目标回波。

        // 底质类型:0=泥, 1=砂, 2=砾, 3=岩
        double mu_dB[] = {-35, -29, -25, -20}; // MIT 实测 [^231^]
        double mu = mu_dB[bottomType];
        return mu + 10.0 * log10(sin(theta_deg * M_PI / 180.0) * sin(theta_deg * M_PI / 180.0));
    }

    // RL 混响级--仅在主动声纳中有用
    double RL(double r)
    {
        double freq = m_env.dFreq;
        double f_kHz = freq / 1000.0;
        EnvironmentInfo e = m_env;

        // 简化为体积+界面混响之和
        // 体积 RL = 10 log10(r^2) + Sv·r
        // 界面 RL = 10 log10(r) + Sb

        // RL(混响级)不是"背景噪声",而是"主动声呐自己的回声雾霾"。它直接影响 小目标探测、作用距离、识别置信度,而且 对小目标的影响远大于噪声。
        // 一、RL 对小/大目标的 公开实测影响(可直接引用)
        // 场景	        目标强度 TS	        有效作用距离	主要限制因素
        // 6 级海况,窄带	−10 dB(小鱼群)	250 m	    界面混响 RL
        // 6 级海况,窄带	+10 dB(大鱼群)	2550 m	    环境噪声 NL
        // 6 级海况,宽带	−10 dB	            2000 m	    噪声 NL(宽带抑制混响)
        // → TS < 0 dB 时,RL 是"硬上限";TS > 0 dB 时,NL 是"软上限"。

        //应该减去BL和RL
        // SE -= RL_bottom; // 混响级叠加到噪声
        // SE -= BL;        // 反射损失叠加到 TL
        const double Sv = -70.0 + 20.0 * env_utils::log10(f_kHz); // dB/m
        const double Sb = -40.0 + 10.0 * env_utils::log10(f_kHz) + bottomLoss(45);//~~~~~~~
        const double r_km = r / 1000.0;
        const double vol = 20.0 * env_utils::log10(r_km) + Sv * r_km;
        const double surf = 10.0 * env_utils::log10(r_km) + Sb;

		double res = (std::max)(vol, surf);
		if (res<0)
		{
			res = -1 * res;//~~~~~~~~~~~~~~
		}

        return res; // 取二者较大者
    }

8.信号余量(回声余量)SE

cpp 复制代码
//ActiveSonar
        SE = SL - (2 * TL) + TS - NL + DI - DT; // SE = SL - 2 * TL + TS - (NL - AG);

//PassiveSonar
        SE = SL - TL - NL + DI - DT;

9.灵敏度Sen【查表】

根据声纳型号查询属性

五、目标识别

这部分靠声音的特征、声谱来判断,本博客主要讲是否能探测到,这部分略。

https://www.bilibili.com/video/BV1Wi4y1L7oJ

如何解读声呐图像 | 声呐基础知识 | 古野科技 | 古野电气株式会社的产品网站

参考
声呐方程相关参数 - 知乎

上海海洋大学《水声学基础》课件--第2章 海洋的声学特性008.pdf-原创力文档

相关推荐
仰泳的熊猫2 小时前
1112 Stucked Keyboard
数据结构·c++·算法·pat考试
淼淼7632 小时前
QT表格与数据
开发语言·qt
smile_Iris2 小时前
Day 38 GPU训练及类的call方法
开发语言·python
三月微暖寻春笋2 小时前
【和春笋一起学C++】(五十一)复制构造函数
c++·复制构造函数·显式复制构造函数·隐式复制构造函数
认真敲代码的小火龙3 小时前
【JAVA项目】基于JAVA的养老院管理系统
java·开发语言·课程设计
AI科技星3 小时前
统一场论质量定义方程:数学验证与应用分析
开发语言·数据结构·经验分享·线性代数·算法
扶苏-su3 小时前
Java---事件处理机制
java·开发语言
小灰灰搞电子3 小时前
Qt 实现炫酷锁屏源码分享
开发语言·qt·命令模式
mahuifa3 小时前
(46)VTK C++开发示例 --- 加载CML文件
c++·3d·vtk·cml