优化了毫米波制导的性能,修改了红外成像制导的参数,包括复合制导

This commit is contained in:
Tian jianyong 2025-06-05 17:14:15 +08:00
parent dea12867f0
commit 131ba3997c
20 changed files with 254 additions and 211 deletions

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<TestRunParameters>
<Parameter name="SkipPerformanceTests" value="true" />
</TestRunParameters>
<RunConfiguration>
<TestSessionTimeout>120000</TestSessionTimeout>
</RunConfiguration>
</RunSettings>

View File

@ -1,147 +0,0 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Diagnostics;
using ThreatSource.Utils; // Assuming Vector3D is here, adjust if necessary
using System.Collections.Generic;
using System;
namespace ThreatSource.Tests.Utils
{
[TestClass]
public class Vector3DPerformanceTests
{
private const int Iterations = 1000000; // Number of iterations for performance testing
private Vector3D CreateVector(double i)
{
// Helper to create slightly different vectors
return new Vector3D(i, i + 1.5, i * 0.8);
}
[TestMethod]
public void Baseline_Vector3D_Class_Performance()
{
// This test assumes Vector3D is currently a CLASS.
// We will run this once, record results, then change Vector3D to struct and run again.
Stopwatch stopwatch = new Stopwatch();
List<Vector3D> vectors = new List<Vector3D>(Iterations);
double totalMagnitude = 0;
Random rand = new Random(123); // Seeded for reproducibility
// --- Test 1: Creation Performance ---
stopwatch.Start();
for (int i = 0; i < Iterations; i++)
{
vectors.Add(CreateVector(i * rand.NextDouble()));
}
stopwatch.Stop();
Console.WriteLine($"[Baseline Class] Creation of {Iterations} Vector3D instances: {stopwatch.ElapsedMilliseconds} ms");
long creationTime = stopwatch.ElapsedMilliseconds;
// Ensure vectors are used to prevent over-optimization by compiler
if (vectors.Count == 0) throw new Exception("Vector list empty after creation.");
Vector3D tempVector1 = CreateVector(10.1);
Vector3D tempVector2 = CreateVector(20.2);
// --- Test 2: Addition Performance ---
stopwatch.Restart();
for (int i = 0; i < Iterations; i++)
{
tempVector1 = tempVector1 + vectors[i];
}
stopwatch.Stop();
Console.WriteLine($"[Baseline Class] {Iterations} Vector3D Additions: {stopwatch.ElapsedMilliseconds} ms");
long additionTime = stopwatch.ElapsedMilliseconds;
// --- Test 3: Subtraction Performance ---
stopwatch.Restart();
for (int i = 0; i < Iterations; i++)
{
tempVector1 = tempVector1 - vectors[i];
}
stopwatch.Stop();
Console.WriteLine($"[Baseline Class] {Iterations} Vector3D Subtractions: {stopwatch.ElapsedMilliseconds} ms");
long subtractionTime = stopwatch.ElapsedMilliseconds;
// --- Test 4: Scalar Multiplication Performance ---
stopwatch.Restart();
for (int i = 0; i < Iterations; i++)
{
tempVector1 = vectors[i] * 2.5;
}
stopwatch.Stop();
Console.WriteLine($"[Baseline Class] {Iterations} Vector3D Scalar Multiplications: {stopwatch.ElapsedMilliseconds} ms");
long scalarMultTime = stopwatch.ElapsedMilliseconds;
// --- Test 5: Dot Product Performance ---
double dotProductSum = 0;
stopwatch.Restart();
for (int i = 0; i < Iterations; i++)
{
dotProductSum += Vector3D.DotProduct(vectors[i], tempVector2);
}
stopwatch.Stop();
Console.WriteLine($"[Baseline Class] {Iterations} Vector3D Dot Products: {stopwatch.ElapsedMilliseconds} ms");
long dotProductTime = stopwatch.ElapsedMilliseconds;
// --- Test 6: Cross Product Performance ---
stopwatch.Restart();
for (int i = 0; i < Iterations; i++)
{
tempVector1 = Vector3D.CrossProduct(vectors[i], tempVector2);
}
stopwatch.Stop();
Console.WriteLine($"[Baseline Class] {Iterations} Vector3D Cross Products: {stopwatch.ElapsedMilliseconds} ms");
long crossProductTime = stopwatch.ElapsedMilliseconds;
// --- Test 7: Magnitude Performance ---
stopwatch.Restart();
for (int i = 0; i < Iterations; i++)
{
totalMagnitude += vectors[i].Magnitude();
}
stopwatch.Stop();
Console.WriteLine($"[Baseline Class] {Iterations} Vector3D Magnitudes: {stopwatch.ElapsedMilliseconds} ms");
long magnitudeTime = stopwatch.ElapsedMilliseconds;
// --- Test 8: Normalization Performance ---
stopwatch.Restart();
for (int i = 0; i < Iterations; i++)
{
// Avoid normalizing zero vectors which might throw exceptions or return NaN
if (vectors[i].MagnitudeSquared() > 0.00001)
{
tempVector1 = vectors[i].Normalize();
}
else
{
tempVector1 = vectors[i]; // Assign to ensure work is done
}
}
stopwatch.Stop();
Console.WriteLine($"[Baseline Class] {Iterations} Vector3D Normalizations: {stopwatch.ElapsedMilliseconds} ms");
long normalizeTime = stopwatch.ElapsedMilliseconds;
Console.WriteLine($"[Baseline Class] Total magnitude sum (to prevent optimization): {totalMagnitude}");
Console.WriteLine($"[Baseline Class] Final tempVector1 (to prevent optimization): {tempVector1}");
Console.WriteLine($"[Baseline Class] Final dotProductSum (to prevent optimization): {dotProductSum}");
// For MSTest, Assert.Inconclusive can be used to output results without failing the test.
// Alternatively, a simple Console.WriteLine at the end of the test with a summary is also fine
// if the test isn't meant to pass/fail based on performance but just to gather data.
// For this baseline, we'll use Assert.Inconclusive to clearly mark the output in test results.
string resultSummary = $"Baseline performance (Vector3D as CLASS):\n" +
$"Creation: {creationTime} ms\n" +
$"Addition: {additionTime} ms\n" +
$"Subtraction: {subtractionTime} ms\n" +
$"Scalar Mult: {scalarMultTime} ms\n" +
$"Dot Product: {dotProductTime} ms\n" +
$"Cross Product: {crossProductTime} ms\n" +
$"Magnitude: {magnitudeTime} ms\n" +
$"Normalization: {normalizeTime} ms";
Console.WriteLine(resultSummary); // Ensure it's also printed to console output for easy viewing
Assert.Inconclusive(resultSummary); // Marks test as inconclusive and shows message in test explorer
}
}
}

View File

@ -83,8 +83,8 @@ JammingResistanceThreshold = 1.0e-5 # 干扰抗性阈值 (瓦特)
MaxDetectionRange = 1000.0 # 最大探测距离 (米)
SearchFieldOfView = 12.0 # 搜索视场角 (度)
TrackFieldOfView = 6.0 # 跟踪视场角 (度)
ImageWidth = 640 # 图像宽度 (像素)
ImageHeight = 480 # 图像高度 (像素)
ImageWidth = 256 # 图像宽度 (像素)
ImageHeight = 256 # 图像高度 (像素)
BackgroundIntensity = 1.0e-4 # 背景辐射强度 (瓦特/球面度)
SearchRecognitionProbability = 0.6 # 搜索模式目标识别概率阈值
TrackRecognitionProbability = 0.8 # 跟踪模式目标识别概率阈值

View File

@ -77,8 +77,8 @@ CodeValue = 1010 # 激光编码的实际值
MaxDetectionRange = 1000.0 # 最大探测距离 (米)
SearchFieldOfView = 12.0 # 搜索视场角 (度)
TrackFieldOfView = 6.0 # 跟踪视场角 (度)
ImageWidth = 640 # 图像宽度 (像素)
ImageHeight = 480 # 图像高度 (像素)
ImageWidth = 256 # 图像宽度 (像素)
ImageHeight = 256 # 图像高度 (像素)
BackgroundIntensity = 1.0e-4 # 背景辐射强度 (瓦特/球面度)
SearchRecognitionProbability = 0.6 # 搜索模式目标识别概率阈值
TrackRecognitionProbability = 0.8 # 跟踪模式目标识别概率阈值

View File

@ -166,8 +166,6 @@ namespace ThreatSource.Guidance
// 更新导引头朝向
KState.Orientation = targetOrientation;
Debug.WriteLine($"[INFRARED_COMMAND] 导引头朝向已调整指向目标: {targetOrientation}");
}
}

View File

@ -409,8 +409,6 @@ namespace ThreatSource.Guidance
// 更新导引头朝向
KState.Orientation = targetOrientation;
Debug.WriteLine($"[IR IMAGING] 导引头朝向已调整指向目标 {currentlyTrackedTargetId}: {targetOrientation}");
}
}

View File

@ -690,8 +690,6 @@ namespace ThreatSource.Guidance
// 更新导引头朝向
KState.Orientation = targetOrientation;
Debug.WriteLine($"[LASER_SEMI_ACTIVE] 导引头朝向已调整指向目标: {targetOrientation}");
}
}

View File

@ -91,14 +91,14 @@ namespace ThreatSource.Guidance
private string? currentlyTrackedTargetId;
/// <summary>
/// 当前活动模式 (Search焦点、Track、Lock) 的探测历史队列
/// 当前活动模式 (Search焦点、Track、Lock) 的探测历史缓冲区
/// </summary>
private readonly Queue<bool> activeDetectionHistory = new();
private CircularBuffer<bool> activeDetectionHistory = new(TRACK_DETECTION_WINDOW_SIZE);
/// <summary>
/// Lock模式的SNR历史队列用于计算平均SNR
/// Lock模式的SNR历史缓冲区用于计算平均SNR
/// </summary>
private readonly Queue<double> lockSnrHistory = new();
private CircularBuffer<double> lockSnrHistory = new(LOCK_SNR_WINDOW_SIZE);
/// <summary>
/// Track模式探测历史滑动窗口大小
@ -273,8 +273,6 @@ namespace ThreatSource.Guidance
// 更新导引头朝向
KState.Orientation = targetOrientation;
Debug.WriteLine($"[MMW_GUIDANCE] 导引头朝向已调整指向目标 {currentlyTrackedTargetId}: {targetOrientation}");
}
}
@ -489,7 +487,7 @@ namespace ThreatSource.Guidance
return double.MinValue; // 无历史数据
}
double averageSnr = lockSnrHistory.Average();
double averageSnr = lockSnrHistory.CalculateAverage();
Debug.WriteLine($"[SNR平均] 窗口大小: {lockSnrHistory.Count}/{LOCK_SNR_WINDOW_SIZE}, 平均SNR: {averageSnr:F2}dB");
return averageSnr;
}
@ -590,7 +588,7 @@ namespace ThreatSource.Guidance
if (IsBlockingJammed)
{
if (currentMode != WorkMode.Search) SwitchToSearchMode();
this.HasTarget = false;
HasTarget = false;
GuidanceAcceleration = Vector3D.Zero;
HasGuidance = false;
return;
@ -629,8 +627,6 @@ namespace ThreatSource.Guidance
{
UpdateSeekerOrientation();
}
Debug.WriteLine($"制导加速度: {GuidanceAcceleration}");
}
else
{
@ -731,7 +727,7 @@ namespace ThreatSource.Guidance
case WorkMode.Search:
if (IsTargetInBeam(missileVelocity, toTarget) && localSnrDb >= config.RecognitionSNRThreshold)
{
Debug.WriteLine($"[MMW SEARCH] TryDetect发现目标: {target.Id}, SNR: {localSnrDb:F2} dB.");
Debug.WriteLine($"[MMW SEARCH] 发现目标: {target.Id}, SNR: {localSnrDb:F2} dB.");
targetPosition = target.KState!.Position;
UpdateStateAndPotentiallySwitchMode(true, localSnrDb, target.Id, targetPosition, deltaTime);
return true;
@ -745,23 +741,22 @@ namespace ThreatSource.Guidance
}
bool currentFrameSuccessForTrack = IsTargetInBeam(missileVelocity, toTarget) && localSnrDb >= config.RecognitionSNRThreshold;
activeDetectionHistory.Enqueue(currentFrameSuccessForTrack);
while (activeDetectionHistory.Count > TRACK_DETECTION_WINDOW_SIZE) activeDetectionHistory.Dequeue();
activeDetectionHistory.Add(currentFrameSuccessForTrack);
Debug.WriteLine($"[MMW TRACK] TryDetect目标 {currentlyTrackedTargetId} 本帧探测: {currentFrameSuccessForTrack}, SNR: {localSnrDb:F2} dB. 窗口 ({activeDetectionHistory.Count}/{TRACK_DETECTION_WINDOW_SIZE})");
Debug.WriteLine($"[MMW TRACK] 目标 {currentlyTrackedTargetId} 本帧探测: {currentFrameSuccessForTrack}, SNR: {localSnrDb:F2} dB. 窗口 ({activeDetectionHistory.Count}/{TRACK_DETECTION_WINDOW_SIZE})");
bool trackOverallSuccess;
if (activeDetectionHistory.Count == TRACK_DETECTION_WINDOW_SIZE)
{
double successRate = (double)activeDetectionHistory.Count(s => s) / TRACK_DETECTION_WINDOW_SIZE;
double successRate = activeDetectionHistory.CalculateBooleanSuccessRate();
trackOverallSuccess = successRate >= SUCCESS_RATE_THRESHOLD;
if(trackOverallSuccess) Debug.WriteLine($"[MMW TRACK] TryDetect目标 {currentlyTrackedTargetId} 滑动窗口稳定 (率: {successRate:P2}).");
else Debug.WriteLine($"[MMW TRACK] TryDetect目标 {currentlyTrackedTargetId} 滑动窗口不稳定 (率: {successRate:P2}).");
if(trackOverallSuccess) Debug.WriteLine($"[MMW TRACK] 目标 {currentlyTrackedTargetId} 滑动窗口稳定 (成功率: {successRate:P2}).");
else Debug.WriteLine($"[MMW TRACK] 目标 {currentlyTrackedTargetId} 滑动窗口不稳定 (成功率: {successRate:P2}).");
}
else
{
trackOverallSuccess = currentFrameSuccessForTrack;
Debug.WriteLine($"[MMW TRACK] TryDetect目标 {currentlyTrackedTargetId} 窗口未满. trackOverallSuccess = currentFrameSuccessForTrack ({currentFrameSuccessForTrack}).");
Debug.WriteLine($"[MMW TRACK] 目标 {currentlyTrackedTargetId} 窗口未满. 当前帧成功: {currentFrameSuccessForTrack}.");
}
targetPosition = trackOverallSuccess ?
@ -776,9 +771,8 @@ namespace ThreatSource.Guidance
continue;
}
// 添加SNR到历史队列
lockSnrHistory.Enqueue(localSnrDb);
while (lockSnrHistory.Count > LOCK_SNR_WINDOW_SIZE) lockSnrHistory.Dequeue();
// 添加SNR到历史缓冲区
lockSnrHistory.Add(localSnrDb);
// 计算平均SNR
double averageSnr = CalculateAverageLockSnr();
@ -787,23 +781,22 @@ namespace ThreatSource.Guidance
double snrForDecision = lockSnrHistory.Count >= LOCK_SNR_WINDOW_SIZE ? averageSnr : localSnrDb;
bool currentFrameSuccessForLock = IsTargetInBeam(missileVelocity, toTarget) && snrForDecision >= config.LockSNRThreshold;
activeDetectionHistory.Enqueue(currentFrameSuccessForLock);
while (activeDetectionHistory.Count > TRACK_DETECTION_WINDOW_SIZE) activeDetectionHistory.Dequeue();
activeDetectionHistory.Add(currentFrameSuccessForLock);
Debug.WriteLine($"[MMW LOCK] TryDetect目标 {currentlyTrackedTargetId} 本帧探测: {currentFrameSuccessForLock}, 瞬时SNR: {localSnrDb:F2}dB, 平均SNR: {averageSnr:F2}dB, 决策SNR: {snrForDecision:F2}dB. 窗口 ({activeDetectionHistory.Count}/{TRACK_DETECTION_WINDOW_SIZE}).");
Debug.WriteLine($"[MMW LOCK] 目标 {currentlyTrackedTargetId} 本帧探测: {currentFrameSuccessForLock}, 瞬时SNR: {localSnrDb:F2}dB, 平均SNR: {averageSnr:F2}dB, 决策SNR: {snrForDecision:F2}dB. 窗口 ({activeDetectionHistory.Count}/{TRACK_DETECTION_WINDOW_SIZE}).");
bool lockOverallSuccess;
if (activeDetectionHistory.Count == TRACK_DETECTION_WINDOW_SIZE)
{
double successRate = (double)activeDetectionHistory.Count(s => s) / TRACK_DETECTION_WINDOW_SIZE;
double successRate = activeDetectionHistory.CalculateBooleanSuccessRate();
lockOverallSuccess = successRate >= SUCCESS_RATE_THRESHOLD;
if(lockOverallSuccess) Debug.WriteLine($"[MMW LOCK] TryDetect目标 {currentlyTrackedTargetId} 滑动窗口稳定 (率: {successRate:P2}).");
else Debug.WriteLine($"[MMW LOCK] TryDetect目标 {currentlyTrackedTargetId} 滑动窗口不稳定 (率: {successRate:P2}).");
if(lockOverallSuccess) Debug.WriteLine($"[MMW LOCK] 目标 {currentlyTrackedTargetId} 滑动窗口稳定 (成功率: {successRate:P2}).");
else Debug.WriteLine($"[MMW LOCK] 目标 {currentlyTrackedTargetId} 滑动窗口不稳定 (成功率: {successRate:P2}).");
}
else
{
lockOverallSuccess = currentFrameSuccessForLock;
Debug.WriteLine($"[MMW LOCK] TryDetect目标 {currentlyTrackedTargetId} 窗口未满. lockOverallSuccess = currentFrameSuccessForLock ({currentFrameSuccessForLock}).");
Debug.WriteLine($"[MMW LOCK] 目标 {currentlyTrackedTargetId} 窗口未满. 当前帧成功: {currentFrameSuccessForLock}.");
}
targetPosition = lockOverallSuccess ?
@ -813,16 +806,6 @@ namespace ThreatSource.Guidance
return lockOverallSuccess;
}
}
// 搜索模式:如果没有找到合适的目标,这是正常情况
if (currentMode == WorkMode.Search)
{
Debug.WriteLine($"[MMW SEARCH] 本帧扫描完成,未发现符合条件的目标。螺旋参数: {spiralRadius * 180/Math.PI:F2}°/{MaxScanRadius * 180/Math.PI:F1}°");
}
else
{
Debug.WriteLine($"[MMW {currentMode.ToString().ToUpper()}] TryDetect循环结束当前跟踪目标: {currentlyTrackedTargetId}");
}
UpdateStateAndPotentiallySwitchMode(false, double.MinValue, currentlyTrackedTargetId, Vector3D.Zero, deltaTime);
targetPosition = Vector3D.Zero;
@ -842,7 +825,7 @@ namespace ThreatSource.Guidance
{
if (currentMode == WorkMode.Track || currentMode == WorkMode.Lock)
{
Debug.WriteLine($"[MMW {currentMode.ToString().ToUpper()}] UpdateState判定目标丢失/不稳定 (frameSuccess=false),切换到搜索模式。");
Debug.WriteLine($"[MMW {currentMode.ToString().ToUpper()}] 判定目标丢失/不稳定 (frameSuccess=false),切换到搜索模式。");
SwitchToSearchMode();
}
return;

View File

@ -0,0 +1,195 @@
using System;
namespace ThreatSource.Utils
{
/// <summary>
/// 高性能循环缓冲区用于替代Queue避免内存分配
/// </summary>
/// <typeparam name="T">缓冲区元素类型</typeparam>
/// <remarks>
/// 该类提供以下特性:
/// - 零内存分配的添加和访问操作
/// - 固定大小的预分配数组
/// - O(1)复杂度的添加操作
/// - 缓存友好的连续内存访问
/// - 支持历史数据滑动窗口管理
/// </remarks>
public struct CircularBuffer<T> where T : struct
{
/// <summary>
/// 内部存储数组
/// </summary>
private readonly T[] _buffer;
/// <summary>
/// 头部索引(最旧元素位置)
/// </summary>
private int _head;
/// <summary>
/// 当前元素数量
/// </summary>
private int _count;
/// <summary>
/// 缓冲区容量
/// </summary>
public readonly int Capacity;
/// <summary>
/// 当前元素数量
/// </summary>
public readonly int Count => _count;
/// <summary>
/// 缓冲区是否已满
/// </summary>
public readonly bool IsFull => _count == _buffer.Length;
/// <summary>
/// 初始化指定容量的循环缓冲区
/// </summary>
/// <param name="capacity">缓冲区容量</param>
public CircularBuffer(int capacity)
{
if (capacity <= 0)
throw new ArgumentException("容量必须大于0", nameof(capacity));
_buffer = new T[capacity];
_head = 0;
_count = 0;
Capacity = capacity;
}
/// <summary>
/// 添加新元素到缓冲区
/// </summary>
/// <param name="item">要添加的元素</param>
/// <remarks>
/// 如果缓冲区已满,将覆盖最旧的元素
/// 操作复杂度O(1)
/// </remarks>
public void Add(T item)
{
int writeIndex = (_head + _count) % _buffer.Length;
_buffer[writeIndex] = item;
if (_count < _buffer.Length)
{
_count++;
}
else
{
// 缓冲区已满,移动头部指针覆盖最旧元素
_head = (_head + 1) % _buffer.Length;
}
}
/// <summary>
/// 清空缓冲区
/// </summary>
public void Clear()
{
_head = 0;
_count = 0;
// 不需要清零数组内容,因为会被新数据覆盖
}
/// <summary>
/// 计算布尔类型的成功率(专用于探测历史)
/// </summary>
/// <returns>成功率0.0到1.0之间)</returns>
/// <remarks>
/// 仅当T为bool类型时使用
/// 零分配的高性能实现
/// </remarks>
public readonly double CalculateBooleanSuccessRate()
{
if (_count == 0) return 0.0;
int successCount = 0;
for (int i = 0; i < _count; i++)
{
int index = (_head + i) % _buffer.Length;
// 使用模式匹配避免装箱
if (_buffer[index] is bool success && success)
successCount++;
}
return (double)successCount / _count;
}
/// <summary>
/// 计算数值的平均值专用于SNR历史
/// </summary>
/// <returns>平均值</returns>
/// <remarks>
/// 仅当T为数值类型时使用
/// 零分配的高性能实现
/// </remarks>
public readonly double CalculateAverage()
{
if (_count == 0) return double.MinValue;
double sum = 0.0;
for (int i = 0; i < _count; i++)
{
int index = (_head + i) % _buffer.Length;
// 使用模式匹配处理不同数值类型
sum += _buffer[index] switch
{
double d => d,
float f => f,
int n => n,
long l => l,
_ => 0.0
};
}
return sum / _count;
}
/// <summary>
/// 获取指定索引的元素
/// </summary>
/// <param name="index">元素索引0表示最旧元素</param>
/// <returns>指定位置的元素</returns>
/// <exception cref="ArgumentOutOfRangeException">索引超出范围</exception>
public readonly T this[int index]
{
get
{
if (index < 0 || index >= _count)
throw new ArgumentOutOfRangeException(nameof(index));
int actualIndex = (_head + index) % _buffer.Length;
return _buffer[actualIndex];
}
}
/// <summary>
/// 获取最新添加的元素
/// </summary>
/// <returns>最新元素</returns>
/// <exception cref="InvalidOperationException">缓冲区为空</exception>
public readonly T GetLatest()
{
if (_count == 0)
throw new InvalidOperationException("缓冲区为空");
int latestIndex = (_head + _count - 1) % _buffer.Length;
return _buffer[latestIndex];
}
/// <summary>
/// 获取最旧的元素
/// </summary>
/// <returns>最旧元素</returns>
/// <exception cref="InvalidOperationException">缓冲区为空</exception>
public readonly T GetOldest()
{
if (_count == 0)
throw new InvalidOperationException("缓冲区为空");
return _buffer[_head];
}
}
}

View File

@ -124,10 +124,10 @@ bool currentFrameSuccessForLock = IsTargetInBeam(missileDirection, targetDirecti
添加了RCS波动的详细调试信息
```csharp
Debug.WriteLine($"[MMW_GUIDANCE] 目标 {target.Id}: 原始RCS: {rcsDbSm:F2} dBsm ({rcsLinear:F4} m²).");
Debug.WriteLine($"[MMW_RCS计算] 目标 {target.Id}: 原始RCS: {rcsDbSm:F2} dBsm ({rcsLinear:F4} m²).");
double rcsDbSmAfterSwerling = 10.0 * Math.Log10(rcsLinear);
double rcsVariationDb = rcsDbSmAfterSwerling - rcsDbSm;
Debug.WriteLine($"[MMW_GUIDANCE] 目标 {target.Id}: Swerling后RCS: {rcsDbSmAfterSwerling:F2} dBsm ({rcsLinear:F4} m²), 波动: {rcsVariationDb:+F2} dB.");
Debug.WriteLine($"[MMW_RCS计算] 目标 {target.Id}: Swerling后RCS: {rcsDbSmAfterSwerling:F2} dBsm ({rcsLinear:F4} m²), 波动: {rcsVariationDb:+F2} dB.");
```
## 技术原理

View File

@ -194,6 +194,8 @@ GC频率: 优秀 ✅
#### 毫米波制导导弹
- 优化前:
=== 详细性能测试结果 ===
【基本统计】
@ -225,8 +227,35 @@ GC频率: 优秀 ✅
帧时间表现: 优秀 ✅
内存管理: 优秀 ✅
GC频率: 优秀 ✅
【潜在问题分析】
- 优化后:
=== 详细性能测试结果 ===
【基本统计】
测试时长: 30.0 秒
总更新次数: 1417
平均FPS: 47.2
平均帧时间: 0.63 ms
【帧时间分析】
最小帧时间: 0.00 ms
最大帧时间: 10.71 ms
95%分位数: 2.78 ms
99%分位数: 4.89 ms
【内存使用分析】
起始内存: 1.76 MB
结束内存: 5.21 MB
峰值内存: 11.70 MB
内存增长: 3.45 MB
平均内存增长率: 0.11 MB/s
【垃圾回收分析】
Gen0 GC次数: 25 (0.8 次/秒)
Gen1 GC次数: 2 (0.1 次/秒)
Gen2 GC次数: 1 (0.0 次/秒)
总GC次数: 28
【性能评级】
帧时间表现: 优秀 ✅
内存管理: 优秀 ✅
GC频率: 优秀 ✅
#### 末敏弹
@ -261,8 +290,6 @@ GC频率: 优秀 ✅
帧时间表现: 优秀 ✅
内存管理: 优秀 ✅
GC频率: 优秀 ✅
【潜在问题分析】