ThreatSourceLibaray/ThreatSource/src/Sensor/QuadrantDetector.cs

372 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using ThreatSource.Utils;
using System.Diagnostics;
namespace ThreatSource.Sensor
{
/// <summary>
/// 四象限探测器类,实现了激光半主动导弹光学导引头中的核心组件
/// </summary>
/// <remarks>
/// 该类提供了四象限探测器的核心功能:
/// - 四个独立光敏元件的信号处理
/// - 光斑中心位置计算
/// - 目标方向误差计算
/// - 实时状态更新
/// 用于激光半主动导弹的精确制导
/// </remarks>
public class QuadrantDetector
{
/// <summary>
/// 四个象限的光敏元件接收到的信号强度
/// </summary>
/// <remarks>
/// 按照右上、左上、左下、右下的顺序排列
/// 用于计算光斑中心位置
/// </remarks>
private double[] quadrantSignals = new double[4];
/// <summary>
/// 获取或设置探测器直径,单位:米
/// </summary>
/// <remarks>
/// 定义了四象限传感器的物理尺寸
/// 影响系统的探测精度
/// 典型值为0.03米
/// </remarks>
public double DetectorDiameter { get; set; }
/// <summary>
/// 获取或设置聚焦后光斑直径,单位:米
/// </summary>
/// <remarks>
/// 定义了光学系统聚焦后的光斑大小
/// 影响系统的探测灵敏度
/// 典型值为0.006米
/// </remarks>
public double FocusedSpotDiameter { get; set; }
/// <summary>
/// 获取或设置最小可检测功率,单位:瓦特
/// </summary>
/// <remarks>
/// 定义了探测器的灵敏度阈值
/// 低于此值时无法有效探测
/// 典型值为1e-12瓦特
/// </remarks>
public double MinDetectablePower { get; set; }
/// <summary>
/// 获取水平方向误差
/// </summary>
/// <remarks>
/// 范围:[-1, 1]
/// 正值表示光斑中心在探测器中心右侧
/// 负值表示光斑中心在探测器中心左侧
/// </remarks>
public double HorizontalError { get; private set; }
/// <summary>
/// 获取垂直方向误差
/// </summary>
/// <remarks>
/// 范围:[-1, 1]
/// 正值表示光斑中心在探测器中心上方
/// 负值表示光斑中心在探测器中心下方
/// </remarks>
public double VerticalError { get; private set; }
/// <summary>
/// 滤波后的水平方向误差
/// </summary>
/// <remarks>
/// 对原始水平误差进行滤波后的值
/// 用于减少误差信号的噪声和快速变化
/// </remarks>
private double filteredHorizontalError = 0;
/// <summary>
/// 滤波后的垂直方向误差
/// </summary>
/// <remarks>
/// 对原始垂直误差进行滤波后的值
/// 用于减少误差信号的噪声和快速变化
/// </remarks>
private double filteredVerticalError = 0;
/// <summary>
/// 误差滤波系数
/// </summary>
/// <remarks>
/// 控制滤波的强度,值越小滤波越强
/// 范围:(0,1]
/// 值为1时无滤波效果
/// </remarks>
private const double errorFilterFactor = 0.15;
/// <summary>
/// 误差死区阈值
/// </summary>
/// <remarks>
/// 小于此值的误差将被视为零
/// 用于避免对微小误差的过度响应
/// </remarks>
private const double errorDeadZone = 0.01;
/// <summary>
/// 获取总接收功率,单位:瓦特
/// </summary>
/// <remarks>
/// 四个象限接收到的总功率
/// 用于判断是否锁定目标
/// </remarks>
public double TotalReceivedPower { get; private set; }
/// <summary>
/// 获取是否锁定目标
/// </summary>
/// <remarks>
/// true表示接收到足够的信号强度可以锁定目标
/// false表示信号强度不足无法锁定目标
/// </remarks>
public bool IsTargetLocked { get; private set; }
/// <summary>
/// 初始化四象限探测器的新实例
/// </summary>
/// <param name="detectorDiameter">传感器直径,单位:米</param>
/// <param name="focusedSpotDiameter">聚焦后光斑直径,单位:米</param>
/// <param name="minDetectablePower">最小可检测功率,单位:瓦特</param>
/// <remarks>
/// 构造过程:
/// - 设置传感器参数
/// - 初始化信号强度
/// - 初始化误差值
/// </remarks>
public QuadrantDetector(double detectorDiameter, double focusedSpotDiameter, double minDetectablePower)
{
DetectorDiameter = detectorDiameter;
FocusedSpotDiameter = focusedSpotDiameter;
MinDetectablePower = minDetectablePower;
// 初始化信号强度和误差值
for (int i = 0; i < 4; i++)
{
quadrantSignals[i] = 0;
}
HorizontalError = 0;
VerticalError = 0;
filteredHorizontalError = 0;
filteredVerticalError = 0;
TotalReceivedPower = 0;
IsTargetLocked = false;
}
/// <summary>
/// 处理接收到的激光信号
/// </summary>
/// <param name="receivedPower">接收到的总功率,单位:瓦特</param>
/// <param name="spotOffset">光斑中心相对于探测器中心的偏移量,单位:米</param>
/// <remarks>
/// 处理过程:
/// - 计算每个象限接收到的功率
/// - 更新误差值
/// - 判断是否锁定目标
/// </remarks>
public void ProcessLaserSignal(double receivedPower, Vector2D spotOffset)
{
// 更新总接收功率
TotalReceivedPower = receivedPower;
// 判断是否锁定目标
IsTargetLocked = receivedPower >= MinDetectablePower;
// 如果功率不足,清空信号并返回
if (!IsTargetLocked)
{
for (int i = 0; i < 4; i++)
{
quadrantSignals[i] = 0;
}
HorizontalError = 0;
VerticalError = 0;
filteredHorizontalError = 0;
filteredVerticalError = 0;
return;
}
// 计算光斑在每个象限的覆盖情况
CalculateQuadrantSignals(spotOffset);
// 计算误差值
CalculateErrors();
}
/// <summary>
/// 计算每个象限接收到的信号强度
/// </summary>
/// <param name="spotOffset">光斑中心相对于探测器中心的偏移量,单位:米</param>
/// <remarks>
/// 计算过程:
/// - 根据光斑位置和大小计算与每个象限的重叠面积
/// - 根据重叠面积分配总功率
/// </remarks>
private void CalculateQuadrantSignals(Vector2D spotOffset)
{
// 探测器半径
double detectorRadius = DetectorDiameter / 2;
// 光斑半径
double spotRadius = FocusedSpotDiameter / 2;
// 光斑中心坐标
double spotX = spotOffset.X;
double spotY = spotOffset.Y;
// 简化模型:根据光斑中心到各象限中心的距离计算信号强度
// 象限中心坐标
double quadrantRadius = detectorRadius / 2;
Vector2D[] quadrantCenters = new Vector2D[4]
{
new Vector2D(quadrantRadius, quadrantRadius), // 右上
new Vector2D(-quadrantRadius, quadrantRadius), // 左上
new Vector2D(-quadrantRadius, -quadrantRadius), // 左下
new Vector2D(quadrantRadius, -quadrantRadius) // 右下
};
// 计算每个象限接收到的信号强度
double totalWeight = 0;
double[] weights = new double[4];
for (int i = 0; i < 4; i++)
{
// 计算光斑中心到象限中心的距离
double distance = Math.Sqrt(
Math.Pow(spotX - quadrantCenters[i].X, 2) +
Math.Pow(spotY - quadrantCenters[i].Y, 2)
);
// 使用高斯分布模型计算权重
weights[i] = Math.Exp(-Math.Pow(distance, 2) / (2 * Math.Pow(spotRadius, 2)));
totalWeight += weights[i];
}
// 分配总功率
for (int i = 0; i < 4; i++)
{
quadrantSignals[i] = totalWeight > 0 ?
TotalReceivedPower * weights[i] / totalWeight : 0;
}
}
/// <summary>
/// 计算水平和垂直方向误差
/// </summary>
/// <remarks>
/// 计算公式:
/// - 水平误差 = ((A+D) - (B+C)) / (A+B+C+D)
/// - 垂直误差 = ((A+B) - (C+D)) / (A+B+C+D)
/// 其中A、B、C、D分别为右上、左上、左下、右下象限的信号强度
/// </remarks>
private void CalculateErrors()
{
// 确保总功率不为零
if (TotalReceivedPower > 0)
{
// 计算水平误差
double rawHorizontalError = ((quadrantSignals[0] + quadrantSignals[3]) -
(quadrantSignals[1] + quadrantSignals[2])) /
TotalReceivedPower;
// 计算垂直误差
double rawVerticalError = ((quadrantSignals[0] + quadrantSignals[1]) -
(quadrantSignals[2] + quadrantSignals[3])) /
TotalReceivedPower;
// 限制误差范围在[-1, 1]之间
HorizontalError = Math.Max(-1, Math.Min(1, rawHorizontalError));
VerticalError = Math.Max(-1, Math.Min(1, rawVerticalError));
// 应用误差滤波
filteredHorizontalError = filteredHorizontalError * (1 - errorFilterFactor) +
HorizontalError * errorFilterFactor;
filteredVerticalError = filteredVerticalError * (1 - errorFilterFactor) +
VerticalError * errorFilterFactor;
// 应用误差死区
if (Math.Abs(filteredHorizontalError) < errorDeadZone)
filteredHorizontalError = 0;
if (Math.Abs(filteredVerticalError) < errorDeadZone)
filteredVerticalError = 0;
// 使用滤波后的误差替代原始误差
HorizontalError = filteredHorizontalError;
VerticalError = filteredVerticalError;
// 增强调试输出,同时显示水平和垂直误差
Debug.WriteLine($"原始误差: 水平={rawHorizontalError:F6}, 垂直={rawVerticalError:F6}, 滤波后: 水平={HorizontalError:F6}, 垂直={VerticalError:F6}");
}
else
{
HorizontalError = 0;
VerticalError = 0;
filteredHorizontalError = 0;
filteredVerticalError = 0;
}
}
/// <summary>
/// 获取目标方向向量
/// </summary>
/// <param name="currentDirection">当前指向方向</param>
/// <param name="sensitivity">灵敏度系数</param>
/// <returns>修正后的目标方向向量</returns>
/// <remarks>
/// 使用通用的正交基构建方法
/// 不依赖于特定的坐标系
/// 适用于任何飞行姿态
/// </remarks>
public Vector3D GetTargetDirection(Vector3D currentDirection, double sensitivity)
{
if (!IsTargetLocked)
{
return currentDirection;
}
// 1. 获取当前方向的单位向量
Vector3D forward = currentDirection.Normalize();
// 2. 构建任意正交基
// 选择一个非平行于forward的向量来构建正交基
Vector3D temp = Math.Abs(forward.X) < 0.9 ? Vector3D.UnitX : Vector3D.UnitY;
Vector3D right = Vector3D.CrossProduct(temp, forward).Normalize();
Vector3D up = Vector3D.CrossProduct(forward, right).Normalize();
// 3. 在这个局部坐标系中应用误差修正
// HorizontalError 对应 right 方向
// VerticalError 对应 up 方向
Vector3D correction = right * (HorizontalError * sensitivity) +
up * (VerticalError * sensitivity);
// 4. 计算新的方向向量并归一化
return (forward + correction).Normalize();
}
/// <summary>
/// 获取探测器状态信息
/// </summary>
/// <returns>包含探测器状态的详细描述</returns>
/// <remarks>
/// 返回信息包括:
/// - 锁定状态
/// - 总接收功率
/// - 最小可探测功率
/// - 水平和垂直误差
/// - 各象限信号强度
/// </remarks>
public string GetStatus()
{
return $"锁定={IsTargetLocked}, 总功率={TotalReceivedPower:E} W, 最小可探测功率={MinDetectablePower:E} W," +
$" 水平误差={HorizontalError:F4}, 垂直误差={VerticalError:F4}," +
$" 象限信号=[{quadrantSignals[0]:E}, {quadrantSignals[1]:E}, {quadrantSignals[2]:E}, {quadrantSignals[3]:E}]";
}
}
}