一、背景知识简介
声纳,由于水中声速较快(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【查表】
这部分主要是看(主动)声纳型号的属性查表,有根据功率进行转化的,但是不太准
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