统一了跟踪信息输出方式,合理使用 Debug.WriteLine 和 Trace类
This commit is contained in:
parent
56eafa392f
commit
e1d2ea4eac
@ -1,40 +0,0 @@
|
||||
---
|
||||
description: Base Guidelines for Sonnet-3.7 + Cursor Agent
|
||||
globs: *,**/*
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# prompts-claude-sonnet-37-rule-claude-sonnet-37.md
|
||||
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# DESCRIPTION:
|
||||
# this rule helps to better control sonnet-3.7 + cursor. (like doing to much, creating unnecessary new files e.g.).
|
||||
# especially the first two rules give the cursor agent already the most important instructions that worked for me.
|
||||
#
|
||||
# ❗ ATTENTION:
|
||||
# 1. this does not work so easily for large codebases
|
||||
# 2. remove everything from these rules that you do not need
|
||||
# 3. also remove this comments
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
|
||||
# Instructions
|
||||
|
||||
1. Always use codebase_search with target_directories="{{ThreatSource/src}}" first to find existing core files
|
||||
2. Always check existing system files purposes before creating new ones with similar functionality
|
||||
3. Always list the cursor rules youre using
|
||||
|
||||
# Optional
|
||||
|
||||
- If a prompt or request specifies certain behaviors, languages, or output formats, you must obey them without deviation.
|
||||
- Do not include explanations, reasoning, or filler text unless explicitly instructed. Stick strictly to the requested output.
|
||||
- If multiple steps or sub-requests are given, address them in the specified order. Provide answers in the exact format or sequence requested.
|
||||
- Pay close attention to all stated constraints (e.g., language choice, performance goals, coding style). Do not ignore any requirement or best practice stated.
|
||||
- Only produce output relevant to the question or instructions. Do not add features, code, or details beyond what is explicitly asked.
|
||||
- Deliver the response in a minimal yet complete form. Avoid unnecessary verbosity and tangential remarks.
|
||||
- If the prompt requests a specific output format (e.g., a fenced code block, bullet points, JSON), follow that format exactly.
|
||||
- If a prompt includes a pre-seeded answer structure (e.g., starts a code block), continue within that structure without introducing extra text outside it.
|
||||
- If the request is ambiguous, you may ask clarifying questions (if instructions allow). Otherwise, state briefly that more information is needed.
|
||||
- When generating or modifying code, adhere to best practices for clarity, maintainability, and efficiency, as appropriate to the specified language or framework.
|
||||
- Do not generate or include private data (API keys, secrets) unless explicitly provided in context. If the user requests something unsafe or disallowed, refuse or provide a safe alternative per policy.
|
||||
@ -1,16 +0,0 @@
|
||||
---
|
||||
description:
|
||||
globs:
|
||||
alwaysApply: true
|
||||
---
|
||||
# 注释
|
||||
使用中文注释
|
||||
|
||||
# 坐标系约定
|
||||
|
||||
- 采用右手坐标系
|
||||
- Y 轴向上
|
||||
- 逆时针旋转为正方向
|
||||
|
||||
# 运行命令
|
||||
- 在运行命令前,先运行 pwd 命令,了解当前目录
|
||||
@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using Xunit;
|
||||
using ThreatSource.Jammer;
|
||||
using ThreatSource.Utils;
|
||||
@ -6,6 +5,7 @@ using ThreatSource.Simulation;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
using ThreatSource.Data;
|
||||
using Xunit.Abstractions;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ThreatSource.Tests.Jamming
|
||||
{
|
||||
@ -34,16 +34,16 @@ namespace ThreatSource.Tests.Jamming
|
||||
_threatSourceFactory = new ThreatSourceFactory(_dataManager, _simulationManager);
|
||||
|
||||
// 显示可用的天气类型
|
||||
Console.WriteLine("可用的天气类型:");
|
||||
Debug.WriteLine("可用的天气类型:");
|
||||
foreach (var weatherType in _dataManager.GetAvailableWeathers())
|
||||
{
|
||||
Console.WriteLine($" - {weatherType}");
|
||||
Debug.WriteLine($" - {weatherType}");
|
||||
}
|
||||
|
||||
// 创建并设置天气
|
||||
var weather = _threatSourceFactory.CreateWeather("sunny");
|
||||
_simulationManager.SetWeather(weather);
|
||||
Console.WriteLine("已添加并设置晴天天气环境");
|
||||
Debug.WriteLine("已添加并设置晴天天气环境");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@ -6,6 +6,7 @@ using ThreatSource.Simulation;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
using ThreatSource.Equipment;
|
||||
using ThreatSource.Utils;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ThreatSource.Tests.Jamming
|
||||
{
|
||||
@ -309,10 +310,10 @@ namespace ThreatSource.Tests.Jamming
|
||||
submunition.Update(0.02);
|
||||
|
||||
// 输出调试信息
|
||||
Console.WriteLine($"更新 {i}:");
|
||||
Console.WriteLine($"子弹位置: {submunition.KState.Position}");
|
||||
Console.WriteLine($"目标位置: {tank.KState.Position}");
|
||||
Console.WriteLine($"距离: {(tank.KState.Position - submunition.KState.Position).Magnitude()}");
|
||||
Debug.WriteLine($"更新 {i}:");
|
||||
Debug.WriteLine($"子弹位置: {submunition.KState.Position}");
|
||||
Debug.WriteLine($"目标位置: {tank.KState.Position}");
|
||||
Debug.WriteLine($"距离: {(tank.KState.Position - submunition.KState.Position).Magnitude()}");
|
||||
|
||||
if ((tank.KState.Position - submunition.KState.Position).Magnitude() < 5)
|
||||
{
|
||||
@ -513,7 +514,7 @@ namespace ThreatSource.Tests.Jamming
|
||||
double? initialAltitude = ((AltimeterSensorData)altimeter.GetSensorData()).Altitude;
|
||||
Assert.IsTrue(initialAltitude.HasValue, "无法获取初始高度");
|
||||
var initialStatus = submunition.GetStatus();
|
||||
Console.WriteLine($"初始状态:{initialStatus}");
|
||||
Debug.WriteLine($"初始状态:{initialStatus}");
|
||||
|
||||
// 更新几次状态,使子弹进入开伞阶段
|
||||
for (int i = 0; i < 10; i++)
|
||||
@ -530,7 +531,7 @@ namespace ThreatSource.Tests.Jamming
|
||||
// 验证干扰效果
|
||||
Assert.IsTrue(altimeter.IsJammed, "测高仪应该处于被干扰状态");
|
||||
ElementStatusInfo status = submunition.GetStatusInfo();
|
||||
Console.WriteLine($"干扰后状态:{status}");
|
||||
Debug.WriteLine($"干扰后状态:{status}");
|
||||
Assert.IsTrue(status.ExtendedProperties["IsSensorsJammed"].ToString() == "True", "子弹状态应该反映传感器受到干扰");
|
||||
|
||||
// 记录干扰时的位置
|
||||
@ -544,7 +545,7 @@ namespace ThreatSource.Tests.Jamming
|
||||
|
||||
// 验证在干扰期间的行为
|
||||
var currentPosition = submunition.KState.Position;
|
||||
Console.WriteLine($"干扰期间位置变化:从 {jammedPosition} 到 {currentPosition}");
|
||||
Debug.WriteLine($"干扰期间位置变化:从 {jammedPosition} 到 {currentPosition}");
|
||||
|
||||
// 清除干扰
|
||||
altimeter.ClearJamming(millimeterWaveJamming);
|
||||
@ -553,7 +554,7 @@ namespace ThreatSource.Tests.Jamming
|
||||
// 验证恢复效果
|
||||
Assert.IsFalse(altimeter.IsJammed, "测高仪应该恢复正常工作");
|
||||
status = submunition.GetStatusInfo();
|
||||
Console.WriteLine($"恢复后状态:{status}");
|
||||
Debug.WriteLine($"恢复后状态:{status}");
|
||||
Assert.IsFalse(status.ExtendedProperties["IsSensorsJammed"].ToString() == "True", "子弹状态应该反映传感器恢复正常");
|
||||
|
||||
// 验证速度变化
|
||||
|
||||
@ -5,6 +5,7 @@ using ThreatSource.Simulation;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
using ThreatSource.Guidance;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ThreatSource.Tests.Sensor
|
||||
{
|
||||
@ -148,8 +149,8 @@ namespace ThreatSource.Tests.Sensor
|
||||
Vector3D result = _detector.GetTargetDirection(currentDirection, sensitivity);
|
||||
|
||||
// 输出调试信息
|
||||
Console.WriteLine($"水平误差: {_detector.HorizontalError}, 垂直误差: {_detector.VerticalError}");
|
||||
Console.WriteLine($"结果向量: X={result.X}, Y={result.Y}, Z={result.Z}");
|
||||
Debug.WriteLine($"水平误差: {_detector.HorizontalError}, 垂直误差: {_detector.VerticalError}");
|
||||
Debug.WriteLine($"结果向量: X={result.X}, Y={result.Y}, Z={result.Z}");
|
||||
|
||||
// Assert
|
||||
Assert.True(_detector.IsTargetLocked);
|
||||
@ -171,8 +172,8 @@ namespace ThreatSource.Tests.Sensor
|
||||
Vector3D result = _detector.GetTargetDirection(currentDirection, sensitivity);
|
||||
|
||||
// 输出调试信息
|
||||
Console.WriteLine($"水平误差: {_detector.HorizontalError}, 垂直误差: {_detector.VerticalError}");
|
||||
Console.WriteLine($"结果向量: X={result.X}, Y={result.Y}, Z={result.Z}");
|
||||
Debug.WriteLine($"水平误差: {_detector.HorizontalError}, 垂直误差: {_detector.VerticalError}");
|
||||
Debug.WriteLine($"结果向量: X={result.X}, Y={result.Y}, Z={result.Z}");
|
||||
|
||||
// Assert
|
||||
Assert.True(_detector.IsTargetLocked);
|
||||
@ -233,9 +234,9 @@ namespace ThreatSource.Tests.Sensor
|
||||
Vector3D resultMedium = _detector.GetTargetDirection(currentDirection, mediumSensitivity);
|
||||
|
||||
// 输出调试信息
|
||||
Console.WriteLine($"水平误差: {_detector.HorizontalError}, 垂直误差: {_detector.VerticalError}");
|
||||
Console.WriteLine($"标准灵敏度结果: X={resultStandard.X}, Y={resultStandard.Y}, Z={resultStandard.Z}");
|
||||
Console.WriteLine($"中等灵敏度结果: X={resultMedium.X}, Y={resultMedium.Y}, Z={resultMedium.Z}");
|
||||
Debug.WriteLine($"水平误差: {_detector.HorizontalError}, 垂直误差: {_detector.VerticalError}");
|
||||
Debug.WriteLine($"标准灵敏度结果: X={resultStandard.X}, Y={resultStandard.Y}, Z={resultStandard.Z}");
|
||||
Debug.WriteLine($"中等灵敏度结果: X={resultMedium.X}, Y={resultMedium.Y}, Z={resultMedium.Z}");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, resultStandard.Magnitude(), 0.001); // 确保是单位向量
|
||||
@ -266,10 +267,10 @@ namespace ThreatSource.Tests.Sensor
|
||||
Vector3D result = _detector.GetTargetDirection(currentDirection, sensitivity);
|
||||
|
||||
// 输出测试条件和结果
|
||||
Console.WriteLine($"测试条件: {testCondition}");
|
||||
Console.WriteLine($"灵敏度: {sensitivity}, 光斑偏移: {spotOffset}");
|
||||
Console.WriteLine($"水平误差: {_detector.HorizontalError}, 垂直误差: {_detector.VerticalError}");
|
||||
Console.WriteLine($"结果向量: X={result.X}, Y={result.Y}, Z={result.Z}");
|
||||
Debug.WriteLine($"测试条件: {testCondition}");
|
||||
Debug.WriteLine($"灵敏度: {sensitivity}, 光斑偏移: {spotOffset}");
|
||||
Debug.WriteLine($"水平误差: {_detector.HorizontalError}, 垂直误差: {_detector.VerticalError}");
|
||||
Debug.WriteLine($"结果向量: X={result.X}, Y={result.Y}, Z={result.Z}");
|
||||
|
||||
// Assert
|
||||
Assert.True(_detector.IsTargetLocked);
|
||||
|
||||
@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using ThreatSource.Simulation;
|
||||
using AirTransmission;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ThreatSource.Tests.Simulation
|
||||
{
|
||||
@ -48,7 +49,7 @@ namespace ThreatSource.Tests.Simulation
|
||||
public void SetWeather(Weather weather)
|
||||
{
|
||||
_currentWeather = weather;
|
||||
Console.WriteLine($"已设置天气:{weather.Type}");
|
||||
Debug.WriteLine($"已设置天气:{weather.Type}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -2,6 +2,7 @@ using System;
|
||||
using Xunit;
|
||||
using ThreatSource.Utils;
|
||||
using AirTransmission;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ThreatSource.Tests.Utils
|
||||
{
|
||||
@ -32,7 +33,7 @@ namespace ThreatSource.Tests.Utils
|
||||
);
|
||||
|
||||
// Assert - 验证结果在合理范围内
|
||||
Console.WriteLine($"激光透过率: {transmittance:F6}");
|
||||
Debug.WriteLine($"激光透过率: {transmittance:F6}");
|
||||
Assert.True(transmittance >= 0.0);
|
||||
Assert.True(transmittance <= 1.0);
|
||||
Assert.NotEqual(0.0, transmittance); // 确保不是0
|
||||
@ -63,7 +64,7 @@ namespace ThreatSource.Tests.Utils
|
||||
);
|
||||
|
||||
// Assert - 验证结果在合理范围内
|
||||
Console.WriteLine($"红外透过率: {transmittance:F6}");
|
||||
Debug.WriteLine($"红外透过率: {transmittance:F6}");
|
||||
Assert.True(transmittance >= 0.0);
|
||||
Assert.True(transmittance <= 1.0);
|
||||
Assert.NotEqual(0.0, transmittance); // 确保不是0
|
||||
@ -94,7 +95,7 @@ namespace ThreatSource.Tests.Utils
|
||||
);
|
||||
|
||||
// Assert - 验证结果在合理范围内
|
||||
Console.WriteLine($"湍流效应: {turbulenceEffect:F6}");
|
||||
Debug.WriteLine($"湍流效应: {turbulenceEffect:F6}");
|
||||
Assert.True(turbulenceEffect >= 0.0);
|
||||
Assert.True(turbulenceEffect <= 1.0);
|
||||
Assert.NotEqual(0.0, turbulenceEffect); // 确保不是0
|
||||
@ -115,7 +116,7 @@ namespace ThreatSource.Tests.Utils
|
||||
);
|
||||
|
||||
// Assert - 验证结果在合理范围内
|
||||
Console.WriteLine($"烟幕透过率: {smokeTransmittance:F6}");
|
||||
Debug.WriteLine($"烟幕透过率: {smokeTransmittance:F6}");
|
||||
Assert.True(smokeTransmittance >= 0.0);
|
||||
Assert.True(smokeTransmittance <= 1.0);
|
||||
}
|
||||
@ -163,9 +164,9 @@ namespace ThreatSource.Tests.Utils
|
||||
distance * 1000, radiationType, wavelength, rainyWeather); // 转换为米
|
||||
|
||||
// Assert - 验证不同天气条件对透过率有影响
|
||||
Console.WriteLine($"晴天透过率: {clearTransmittance:F6}");
|
||||
Console.WriteLine($"雾天透过率: {foggyTransmittance:F6}");
|
||||
Console.WriteLine($"雨天透过率: {rainyTransmittance:F6}");
|
||||
Debug.WriteLine($"晴天透过率: {clearTransmittance:F6}");
|
||||
Debug.WriteLine($"雾天透过率: {foggyTransmittance:F6}");
|
||||
Debug.WriteLine($"雨天透过率: {rainyTransmittance:F6}");
|
||||
|
||||
// 验证所有值在有效范围内
|
||||
Assert.True(clearTransmittance >= 0.0 && clearTransmittance <= 1.0);
|
||||
|
||||
@ -2,6 +2,7 @@ using System.IO;
|
||||
using Tomlyn;
|
||||
using Tomlyn.Model; // Required for TomlModelOptions
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
// No longer need Tomlyn.Syntax for exceptions if ConvertTo is removed
|
||||
|
||||
namespace ThreatSource.Data
|
||||
@ -66,7 +67,7 @@ namespace ThreatSource.Data
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Console.WriteLine($"导弹数据目录不存在:{path}");
|
||||
Trace.TraceError($"导弹数据目录不存在:{path}");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -88,8 +89,8 @@ namespace ThreatSource.Data
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"加载导弹数据文件失败:{file},错误:{ex.Message}");
|
||||
Console.WriteLine($"异常堆栈:{ex.StackTrace}");
|
||||
Trace.TraceError($"加载导弹数据文件失败:{file},错误:{ex.Message}");
|
||||
Trace.TraceError($"异常堆栈:{ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -101,7 +102,7 @@ namespace ThreatSource.Data
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Console.WriteLine($"指示器数据目录不存在:{path}");
|
||||
Trace.TraceError($"指示器数据目录不存在:{path}");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -119,8 +120,8 @@ namespace ThreatSource.Data
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"加载指示器数据文件失败:{file},错误:{ex.Message}");
|
||||
Console.WriteLine($"异常堆栈:{ex.StackTrace}");
|
||||
Trace.TraceError($"加载指示器数据文件失败:{file},错误:{ex.Message}");
|
||||
Trace.TraceError($"异常堆栈:{ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,7 +133,7 @@ namespace ThreatSource.Data
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Console.WriteLine($"传感器数据目录不存在:{path}");
|
||||
Trace.TraceError($"传感器数据目录不存在:{path}");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -150,8 +151,8 @@ namespace ThreatSource.Data
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"加载传感器数据文件失败:{file},错误:{ex.Message}");
|
||||
Console.WriteLine($"异常堆栈:{ex.StackTrace}");
|
||||
Trace.TraceError($"加载传感器数据文件失败:{file},错误:{ex.Message}");
|
||||
Trace.TraceError($"异常堆栈:{ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -163,7 +164,7 @@ namespace ThreatSource.Data
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Console.WriteLine($"目标数据目录不存在:{path}");
|
||||
Trace.TraceError($"目标数据目录不存在:{path}");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -181,8 +182,8 @@ namespace ThreatSource.Data
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"加载目标数据文件失败:{file},错误:{ex.Message}");
|
||||
Console.WriteLine($"异常堆栈:{ex.StackTrace}");
|
||||
Trace.TraceError($"加载目标数据文件失败:{file},错误:{ex.Message}");
|
||||
Trace.TraceError($"异常堆栈:{ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -195,7 +196,7 @@ namespace ThreatSource.Data
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Console.WriteLine($"天气数据目录不存在:{path}");
|
||||
Trace.TraceError($"天气数据目录不存在:{path}");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -213,8 +214,8 @@ namespace ThreatSource.Data
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"加载天气数据文件失败:{file},错误:{ex.Message}");
|
||||
Console.WriteLine($"异常堆栈:{ex.StackTrace}");
|
||||
Trace.TraceError($"加载天气数据文件失败:{file},错误:{ex.Message}");
|
||||
Trace.TraceError($"异常堆栈:{ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -226,7 +227,7 @@ namespace ThreatSource.Data
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Console.WriteLine($"干扰机数据目录不存在:{path}");
|
||||
Trace.TraceError($"干扰机数据目录不存在:{path}");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -244,8 +245,8 @@ namespace ThreatSource.Data
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"加载干扰机数据文件失败:{file},错误:{ex.Message}");
|
||||
Console.WriteLine($"异常堆栈:{ex.StackTrace}");
|
||||
Trace.TraceError($"加载干扰机数据文件失败:{file},错误:{ex.Message}");
|
||||
Trace.TraceError($"异常堆栈:{ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -331,7 +331,7 @@ namespace ThreatSource.Guidance
|
||||
if (parameters.Mode == JammingMode.Blocking)
|
||||
{
|
||||
HasGuidance = false; // 硬干扰立即停止制导
|
||||
Trace.WriteLine($"[{this.GetType().Name}] 硬干扰已应用: {parameters.Type}");
|
||||
Trace.TraceInformation($"[{this.GetType().Name}] 硬干扰已应用: {parameters.Type}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -345,7 +345,7 @@ namespace ThreatSource.Guidance
|
||||
if (!_jammingComponent.IsJammed)
|
||||
{
|
||||
HasGuidance = true;
|
||||
Trace.WriteLine($"[{GetType().Name}] 所有干扰已清除。");
|
||||
Trace.TraceInformation($"[{GetType().Name}] 所有干扰已清除。");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,8 @@ using ThreatSource.Equipment;
|
||||
using ThreatSource.Utils;
|
||||
using AirTransmission;
|
||||
using ThreatSource.Jammer; // 添加引用
|
||||
using ThreatSource.Simulation; // Add Simulation namespace
|
||||
using ThreatSource.Simulation;
|
||||
using System.Diagnostics; // Add Simulation namespace
|
||||
|
||||
namespace ThreatSource.Guidance
|
||||
{
|
||||
@ -101,7 +102,7 @@ namespace ThreatSource.Guidance
|
||||
// 计算视线方向
|
||||
forward = (targetPosition - missilePosition).Normalize();
|
||||
|
||||
Console.WriteLine($"视线方向: {forward}");
|
||||
Debug.WriteLine($"视线方向: {forward}");
|
||||
|
||||
// 选择合适的上方向
|
||||
Vector3D worldUp = Math.Abs(Vector3D.DotProduct(forward, Vector3D.UnitZ)) > 0.99
|
||||
@ -129,7 +130,7 @@ namespace ThreatSource.Guidance
|
||||
double angleX = Math.Atan2(x, z);
|
||||
double angleY = Math.Atan2(y, z);
|
||||
|
||||
Console.WriteLine($"投影角度: X={angleX:F6} 弧度, Y={angleY:F6} 弧度");
|
||||
Debug.WriteLine($"投影角度: X={angleX:F6} 弧度, Y={angleY:F6} 弧度");
|
||||
|
||||
return (angleX, angleY);
|
||||
}
|
||||
@ -207,7 +208,7 @@ namespace ThreatSource.Guidance
|
||||
if (smokeCenterX < -imageWidth/4 || smokeCenterX >= imageWidth*1.25 ||
|
||||
smokeCenterY < -imageHeight/4 || smokeCenterY >= imageHeight*1.25)
|
||||
{
|
||||
Console.WriteLine($"烟幕 {smoke.Id} 投影中心 ({smokeCenterX}, {smokeCenterY}) 远离图像范围,跳过");
|
||||
Debug.WriteLine($"烟幕 {smoke.Id} 投影中心 ({smokeCenterX}, {smokeCenterY}) 远离图像范围,跳过");
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -227,7 +228,7 @@ namespace ThreatSource.Guidance
|
||||
double wallHeight = smoke.config.WallHeight; // Y轴上的高度
|
||||
double wallThickness = smoke.config.Thickness; // X轴上的厚度
|
||||
|
||||
Console.WriteLine($"烟幕墙朝向: {smokeForward}, 与视线夹角: {angleToViewLine * 180 / Math.PI:F2}度");
|
||||
Debug.WriteLine($"烟幕墙朝向: {smokeForward}, 与视线夹角: {angleToViewLine * 180 / Math.PI:F2}度");
|
||||
|
||||
// 计算墙面的有效投影宽度(考虑朝向)
|
||||
// 当墙面垂直于视线时,宽度投影最大;平行时,宽度投影最小
|
||||
@ -237,7 +238,7 @@ namespace ThreatSource.Guidance
|
||||
int pixelWidth = (int)Math.Max(minPixelSize, (effectiveWidth / distance) * imageWidth / fieldOfView);
|
||||
int pixelHeight = (int)Math.Max(minPixelSize, (wallHeight / distance) * imageHeight / fieldOfView);
|
||||
|
||||
Console.WriteLine($"烟幕墙实际宽度: {wallWidth}m, 有效投影宽度: {effectiveWidth:F2}m");
|
||||
Debug.WriteLine($"烟幕墙实际宽度: {wallWidth}m, 有效投影宽度: {effectiveWidth:F2}m");
|
||||
|
||||
int halfPixelWidth = pixelWidth / 2;
|
||||
int halfPixelHeight = pixelHeight / 2;
|
||||
@ -256,7 +257,7 @@ namespace ThreatSource.Guidance
|
||||
smokeIntensityLayer[y, x] = Math.Max(smokeIntensityLayer[y, x], smokeIntensity);
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"记录遮蔽烟幕(Wall): 中心({smokeCenterX},{smokeCenterY}), 尺寸{pixelWidth}x{pixelHeight}px, 强度{smokeIntensity:F6}");
|
||||
Debug.WriteLine($"记录遮蔽烟幕(Wall): 中心({smokeCenterX},{smokeCenterY}), 尺寸{pixelWidth}x{pixelHeight}px, 强度{smokeIntensity:F6}");
|
||||
break;
|
||||
|
||||
case SmokeScreenType.Cloud:
|
||||
@ -285,7 +286,7 @@ namespace ThreatSource.Guidance
|
||||
}
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"记录遮蔽烟幕(Cloud): 中心({smokeCenterX},{smokeCenterY}), 半径{pixelRadius}px, 强度{smokeIntensity:F6}");
|
||||
Debug.WriteLine($"记录遮蔽烟幕(Cloud): 中心({smokeCenterX},{smokeCenterY}), 半径{pixelRadius}px, 强度{smokeIntensity:F6}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -348,11 +349,11 @@ namespace ThreatSource.Guidance
|
||||
pixelLength = Math.Max(1, pixelLength);
|
||||
pixelWidth = Math.Max(1, pixelWidth);
|
||||
|
||||
Console.WriteLine($"生成目标 {target.Id} 的图像,尺寸: {pixelLength}x{pixelWidth} 像素,目标中心: ({centerX}, {centerY})");
|
||||
Debug.WriteLine($"生成目标 {target.Id} 的图像,尺寸: {pixelLength}x{pixelWidth} 像素,目标中心: ({centerX}, {centerY})");
|
||||
|
||||
// 计算大气和衰减型烟幕的总透过率
|
||||
double transmittance = CalculateAtmosphericTransmittance(distance, simulationManager.CurrentWeather, smokeAttenuation);
|
||||
Console.WriteLine($"大气及衰减烟幕透过率: {transmittance},烟幕衰减: {smokeAttenuation}");
|
||||
Debug.WriteLine($"大气及衰减烟幕透过率: {transmittance},烟幕衰减: {smokeAttenuation}");
|
||||
|
||||
// 生成目标图像强度,考虑遮蔽烟幕覆盖
|
||||
GenerateTargetIntensity(image, smokeIntensityLayer, centerX, centerY, pixelLength, pixelWidth, target, distance, transmittance);
|
||||
@ -392,7 +393,7 @@ namespace ThreatSource.Guidance
|
||||
double[,] thermalPattern = target.GetCurrentThermalPattern();
|
||||
if (thermalPattern == null)
|
||||
{
|
||||
Console.WriteLine($"警告: 目标 {target.Id} 未提供 ThermalPattern,无法生成基于模式的强度。");
|
||||
Trace.TraceError($"警告: 目标 {target.Id} 未提供 ThermalPattern,无法生成基于模式的强度。");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -441,7 +442,7 @@ namespace ThreatSource.Guidance
|
||||
|
||||
// 计算烟幕覆盖率
|
||||
double smokeCoverageRatio = totalTargetPixels > 0 ? (double)smokeCoveredPixels / totalTargetPixels : 0.0;
|
||||
Console.WriteLine($"Blob {target.Id} 烟幕覆盖率: {smokeCoverageRatio:P2} ({smokeCoveredPixels}/{totalTargetPixels})");
|
||||
Debug.WriteLine($"Blob {target.Id} 烟幕覆盖率: {smokeCoverageRatio:P2} ({smokeCoveredPixels}/{totalTargetPixels})");
|
||||
|
||||
// 第二遍:根据覆盖率调整目标亮度
|
||||
// 遍历目标在图像中的包围盒
|
||||
@ -511,7 +512,7 @@ namespace ThreatSource.Guidance
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine($"目标基于ThermalPattern强度分布: 像素设置: {pixelsSet}, 最大强度: {maxSetIntensity:F6} W/sr");
|
||||
Debug.WriteLine($"目标基于ThermalPattern强度分布: 像素设置: {pixelsSet}, 最大强度: {maxSetIntensity:F6} W/sr");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -261,7 +261,7 @@ namespace ThreatSource.Guidance
|
||||
{
|
||||
HasGuidance = false;
|
||||
// 切换回搜索模式
|
||||
Console.WriteLine($"Target lost for {targetLostTimer:F3}s, switching back to search mode");
|
||||
Debug.WriteLine($"目标丢失 {targetLostTimer:F3}s, 切换回搜索模式");
|
||||
SwitchToSearchMode();
|
||||
}
|
||||
}
|
||||
@ -302,7 +302,7 @@ namespace ThreatSource.Guidance
|
||||
backgroundIntensity: config.BackgroundIntensity,
|
||||
wavelength: config.Wavelength
|
||||
);
|
||||
Console.WriteLine($"切换到搜索模式, 视场角: {config.SearchFieldOfView * 180 / Math.PI} 度");
|
||||
Debug.WriteLine($"切换到搜索模式, 视场角: {config.SearchFieldOfView * 180 / Math.PI} 度");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -327,7 +327,7 @@ namespace ThreatSource.Guidance
|
||||
backgroundIntensity: config.BackgroundIntensity,
|
||||
wavelength: config.Wavelength
|
||||
);
|
||||
Console.WriteLine($"切换到跟踪模式, 视场角: {config.TrackFieldOfView * 180 / Math.PI} 度");
|
||||
Debug.WriteLine($"切换到跟踪模式, 视场角: {config.TrackFieldOfView * 180 / Math.PI} 度");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -342,7 +342,7 @@ namespace ThreatSource.Guidance
|
||||
public void SwitchToLockMode()
|
||||
{
|
||||
currentMode = WorkMode.Lock;
|
||||
Console.WriteLine("Switched to lock mode - target type confirmed");
|
||||
Debug.WriteLine("切换到锁定模式 - 目标类型确认");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -388,7 +388,7 @@ namespace ThreatSource.Guidance
|
||||
bool isTargetGeometricallyObscured = CheckIfTargetObscuredBySmoke(missilePosition, target);
|
||||
if (isTargetGeometricallyObscured)
|
||||
{
|
||||
Console.WriteLine($"[红外成像制导系统] 目标 {target.Id} 被烟幕几何遮挡,跳过图像生成");
|
||||
Debug.WriteLine($"[红外成像制导系统] 目标 {target.Id} 被烟幕几何遮挡,跳过图像生成");
|
||||
continue; // 如果目标被完全遮挡,跳过此目标
|
||||
}
|
||||
|
||||
@ -518,18 +518,18 @@ namespace ThreatSource.Guidance
|
||||
targetCenter, targetDims, targetOrient // 目标数据(背景)
|
||||
);
|
||||
|
||||
Console.WriteLine($"[红外成像制导系统] 目标 {target.Id} 被烟幕 {smoke.Id} 遮挡比例: {overlapRatio:P2}");
|
||||
Debug.WriteLine($"[红外成像制导系统] 目标 {target.Id} 被烟幕 {smoke.Id} 遮挡比例: {overlapRatio:P2}");
|
||||
|
||||
// 如果任何一个烟幕的遮挡比例超过阈值,则认为目标被遮挡
|
||||
if (overlapRatio >= ObscurationThreshold)
|
||||
{
|
||||
Console.WriteLine($"[红外成像制导系统] 目标 {target.Id} 被烟幕 {smoke.Id} 遮挡超过阈值 {ObscurationThreshold:P0},视为完全遮挡");
|
||||
Debug.WriteLine($"[红外成像制导系统] 目标 {target.Id} 被烟幕 {smoke.Id} 遮挡超过阈值 {ObscurationThreshold:P0},视为完全遮挡");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[红外成像制导系统] 计算烟幕遮挡时出错: {ex.Message}");
|
||||
Debug.WriteLine($"[红外成像制导系统] 计算烟幕遮挡时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using ThreatSource.Equipment;
|
||||
using System.Diagnostics;
|
||||
using ThreatSource.Simulation;
|
||||
using System.Collections.Generic; // For Queue and List
|
||||
using System.Linq; // For OrderByDescending
|
||||
@ -104,7 +105,7 @@ namespace ThreatSource.Guidance
|
||||
var segment = SegmentTarget(image);
|
||||
if (!segment.IsValid)
|
||||
{
|
||||
Console.WriteLine("没有有效的分割区域");
|
||||
Debug.WriteLine("没有有效的分割区域");
|
||||
return new RecognitionResult(EquipmentType.Unknown, 0.0, (0, 0), (0, 0));
|
||||
}
|
||||
|
||||
@ -113,17 +114,17 @@ namespace ThreatSource.Guidance
|
||||
int minRequiredHeight = 5;
|
||||
if (segment.Size.Width < minRequiredWidth && segment.Size.Height < minRequiredHeight)
|
||||
{
|
||||
Console.WriteLine($"目标区域过小: {segment.Size.Width}x{segment.Size.Height} 像素,低于最小要求 {minRequiredWidth}x{minRequiredHeight}");
|
||||
Debug.WriteLine($"目标区域过小: {segment.Size.Width}x{segment.Size.Height} 像素,低于最小要求 {minRequiredWidth}x{minRequiredHeight}");
|
||||
return new RecognitionResult(EquipmentType.Unknown, 0.0, segment.Center, segment.Size);
|
||||
}
|
||||
|
||||
// 提取目标特征
|
||||
var features = ExtractFeatures(image, segment, target);
|
||||
Console.WriteLine($"提取的特征: 长宽比={features.AspectRatio:F2}, 尺寸={features.Size:F2}, 强度模式={features.IntensityPattern:F2}, 温度梯度={features.TemperatureGradient:F2}");
|
||||
Debug.WriteLine($"提取的特征: 长宽比={features.AspectRatio:F2}, 尺寸={features.Size:F2}, 强度模式={features.IntensityPattern:F2}, 温度梯度={features.TemperatureGradient:F2}");
|
||||
|
||||
// 特征匹配和分类
|
||||
var (type, confidence) = ClassifyTarget(features);
|
||||
Console.WriteLine($"分类结果: 类型={type}, 置信度={confidence:F2}");
|
||||
Debug.WriteLine($"分类结果: 类型={type}, 置信度={confidence:F2}");
|
||||
|
||||
// 返回识别结果
|
||||
return new RecognitionResult(
|
||||
@ -146,7 +147,7 @@ namespace ThreatSource.Guidance
|
||||
List<Blob> blobs = new List<Blob>();
|
||||
Queue<(int x, int y)> queue = new Queue<(int x, int y)>();
|
||||
|
||||
Console.WriteLine($"开始连通区域分析,阈值: {threshold:F6}");
|
||||
Debug.WriteLine($"开始连通区域分析,阈值: {threshold:F6}");
|
||||
|
||||
// 1. 查找所有连通区域 (Blobs)
|
||||
for (int y = 0; y < height; y++)
|
||||
@ -195,12 +196,12 @@ namespace ThreatSource.Guidance
|
||||
}
|
||||
}
|
||||
blobs.Add(currentBlob);
|
||||
Console.WriteLine($" 发现 Blob {currentBlob.Label}: 面积={currentBlob.Area}, 边界=({currentBlob.MinX},{currentBlob.MinY})-({currentBlob.MaxX},{currentBlob.MaxY})");
|
||||
Debug.WriteLine($" 发现 Blob {currentBlob.Label}: 面积={currentBlob.Area}, 边界=({currentBlob.MinX},{currentBlob.MinY})-({currentBlob.MaxX},{currentBlob.MaxY})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine($"发现 {blobs.Count} 个 Blobs");
|
||||
Debug.WriteLine($"发现 {blobs.Count} 个 Blobs");
|
||||
|
||||
// 2. 过滤 Blobs
|
||||
List<Blob> filteredBlobs = new List<Blob>();
|
||||
@ -213,7 +214,7 @@ namespace ThreatSource.Guidance
|
||||
// 检查面积
|
||||
if (blob.Area < minArea || blob.Area > maxArea)
|
||||
{
|
||||
Console.WriteLine($" Blob {blob.Label} 因面积 ({blob.Area}) 不符被过滤 (允许范围: {minArea}-{maxArea})");
|
||||
Debug.WriteLine($" Blob {blob.Label} 因面积 ({blob.Area}) 不符被过滤 (允许范围: {minArea}-{maxArea})");
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -239,29 +240,29 @@ namespace ThreatSource.Guidance
|
||||
if (totalPixelsInBox > 0)
|
||||
{
|
||||
double smokeCoverageRatio = (double)smokeCoveredPixelsInBox / totalPixelsInBox;
|
||||
Console.WriteLine($" Blob {blob.Label} 烟幕覆盖率: {smokeCoverageRatio:P2} ({smokeCoveredPixelsInBox}/{totalPixelsInBox})");
|
||||
Debug.WriteLine($" Blob {blob.Label} 烟幕覆盖率: {smokeCoverageRatio:P2} ({smokeCoveredPixelsInBox}/{totalPixelsInBox})");
|
||||
if (smokeCoverageRatio >= SMOKE_COVERAGE_THRESHOLD)
|
||||
{
|
||||
Console.WriteLine($" Blob {blob.Label} 因烟幕覆盖率过高被过滤");
|
||||
Debug.WriteLine($" Blob {blob.Label} 因烟幕覆盖率过高被过滤");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 通过所有检查,添加到过滤后的列表
|
||||
filteredBlobs.Add(blob);
|
||||
Console.WriteLine($" Blob {blob.Label} 通过过滤");
|
||||
Debug.WriteLine($" Blob {blob.Label} 通过过滤");
|
||||
}
|
||||
|
||||
// 3. 选择最佳 Blob
|
||||
if (filteredBlobs.Count == 0)
|
||||
{
|
||||
Console.WriteLine("没有找到有效的 Blob");
|
||||
Debug.WriteLine("没有找到有效的 Blob");
|
||||
return new ImageSegment(); // 返回无效分割
|
||||
}
|
||||
|
||||
// 选择面积最大的 Blob 作为目标
|
||||
Blob targetBlob = filteredBlobs.OrderByDescending(b => b.Area).First();
|
||||
Console.WriteLine($"选择 Blob {targetBlob.Label} 作为目标 (面积: {targetBlob.Area})");
|
||||
Debug.WriteLine($"选择 Blob {targetBlob.Label} 作为目标 (面积: {targetBlob.Area})");
|
||||
|
||||
// 4. 返回基于选定 Blob 的 ImageSegment
|
||||
return new ImageSegment(
|
||||
@ -300,7 +301,7 @@ namespace ThreatSource.Guidance
|
||||
// Handle case where image is entirely black or has no valid pixels
|
||||
if (count == 0 || maxIntensity <= minIntensity)
|
||||
{
|
||||
Console.WriteLine("图像全黑或无有效强度信息,无法计算阈值,返回0");
|
||||
Debug.WriteLine("图像全黑或无有效强度信息,无法计算阈值,返回0");
|
||||
return 0; // Or handle appropriately
|
||||
}
|
||||
|
||||
@ -313,13 +314,13 @@ namespace ThreatSource.Guidance
|
||||
double threshold = minIntensity + dynamicRange * thresholdFactor;
|
||||
|
||||
|
||||
Console.WriteLine($"图像统计:");
|
||||
Console.WriteLine($" 最大强度: {maxIntensity:F6}");
|
||||
Console.WriteLine($" 最小强度: {minIntensity:F6}");
|
||||
Console.WriteLine($" 平均强度: {mean:F6}");
|
||||
Console.WriteLine($" 动态范围: {dynamicRange:F6}");
|
||||
Console.WriteLine($" 动态阈值因子: {thresholdFactor:P1}");
|
||||
Console.WriteLine($" 最终阈值: {threshold:F6}");
|
||||
Debug.WriteLine($"图像统计:");
|
||||
Debug.WriteLine($" 最大强度: {maxIntensity:F6}");
|
||||
Debug.WriteLine($" 最小强度: {minIntensity:F6}");
|
||||
Debug.WriteLine($" 平均强度: {mean:F6}");
|
||||
Debug.WriteLine($" 动态范围: {dynamicRange:F6}");
|
||||
Debug.WriteLine($" 动态阈值因子: {thresholdFactor:P1}");
|
||||
Debug.WriteLine($" 最终阈值: {threshold:F6}");
|
||||
|
||||
return threshold;
|
||||
}
|
||||
@ -396,27 +397,7 @@ namespace ThreatSource.Guidance
|
||||
/// </summary>
|
||||
private double CalculateTemperatureGradient(InfraredImage image, ImageSegment segment, IEquipment target)
|
||||
{
|
||||
// -- 移除直接从目标获取理想温度分布数据的逻辑 --
|
||||
// double[,] thermalPattern = target.GetCurrentThermalPattern(); // 错误:这会绕过烟幕遮蔽效果
|
||||
// if (thermalPattern == null)
|
||||
// {
|
||||
// Console.WriteLine("没有温度分布数据, 使用图像计算梯度");
|
||||
// return CalculateImageBasedGradient(image, segment);
|
||||
// }
|
||||
//
|
||||
// var pattern = new ThermalPattern(thermalPattern, thermalPattern);
|
||||
//
|
||||
// // 判断目标是否在运动 (这个判断可能仍然有用,但基于图像的梯度计算目前不使用它)
|
||||
// bool isMoving = IsTargetMoving(image, segment);
|
||||
// Console.WriteLine($"目标运动状态: {(isMoving ? "移动" : "静止")}");
|
||||
//
|
||||
// // 使用理想温度分布模式计算梯度特征 (错误)
|
||||
// double gradientFeature = pattern.CalculateGradientFeature(isMoving);
|
||||
//
|
||||
// return gradientFeature;
|
||||
|
||||
// **修正:始终基于传入的红外图像计算梯度特征**
|
||||
Console.WriteLine("计算基于图像的温度梯度特征");
|
||||
Debug.WriteLine("计算基于图像的温度梯度特征");
|
||||
return CalculateImageBasedGradient(image, segment);
|
||||
}
|
||||
|
||||
@ -643,7 +624,7 @@ namespace ThreatSource.Guidance
|
||||
foreach (var kvp in targetFeatures)
|
||||
{
|
||||
double score = CalculateMatchScore(features, kvp.Value, weights);
|
||||
Console.WriteLine($"匹配得分: {kvp.Key}: {score:F2}");
|
||||
Debug.WriteLine($"匹配得分: {kvp.Key}: {score:F2}");
|
||||
if (score > bestScore)
|
||||
{
|
||||
bestScore = score;
|
||||
@ -653,7 +634,7 @@ namespace ThreatSource.Guidance
|
||||
|
||||
// 使用自适应阈值
|
||||
double threshold = CalculateAdaptiveThreshold(features);
|
||||
Console.WriteLine($"自适应阈值: {threshold:F2}");
|
||||
Debug.WriteLine($"自适应阈值: {threshold:F2}");
|
||||
|
||||
return bestScore > threshold ?
|
||||
(bestMatch, bestScore) :
|
||||
@ -708,11 +689,11 @@ namespace ThreatSource.Guidance
|
||||
double gradientScore = 1 - Math.Min(1, Math.Abs(features.TemperatureGradient - template.TemperatureGradient));
|
||||
|
||||
// 输出详细的匹配分数
|
||||
Console.WriteLine($"特征匹配得分:");
|
||||
Console.WriteLine($" 长宽比: {aspectRatioScore:F2} (权重: {weights[0]:F2})");
|
||||
Console.WriteLine($" 尺寸: {sizeScore:F2} (权重: {weights[1]:F2})");
|
||||
Console.WriteLine($" 模式: {patternScore:F2} (权重: {weights[2]:F2})");
|
||||
Console.WriteLine($" 梯度: {gradientScore:F2} (权重: {weights[3]:F2})");
|
||||
Debug.WriteLine($"特征匹配得分:");
|
||||
Debug.WriteLine($" 长宽比: {aspectRatioScore:F2} (权重: {weights[0]:F2})");
|
||||
Debug.WriteLine($" 尺寸: {sizeScore:F2} (权重: {weights[1]:F2})");
|
||||
Debug.WriteLine($" 模式: {patternScore:F2} (权重: {weights[2]:F2})");
|
||||
Debug.WriteLine($" 梯度: {gradientScore:F2} (权重: {weights[3]:F2})");
|
||||
|
||||
// 加权平均
|
||||
double totalScore = aspectRatioScore * weights[0] +
|
||||
@ -720,7 +701,7 @@ namespace ThreatSource.Guidance
|
||||
patternScore * weights[2] +
|
||||
gradientScore * weights[3];
|
||||
|
||||
Console.WriteLine($" 总得分: {totalScore:F2}");
|
||||
Debug.WriteLine($" 总得分: {totalScore:F2}");
|
||||
return totalScore;
|
||||
}
|
||||
|
||||
|
||||
@ -391,7 +391,7 @@ namespace ThreatSource.Guidance
|
||||
if (LaserSourcePosition == null)
|
||||
{
|
||||
HasGuidance = false;
|
||||
Trace.WriteLine($"激光驾束引导系统: 失去引导, 原因: 激光源位置未知");
|
||||
Trace.TraceInformation($"激光驾束引导系统: 失去引导, 原因: 激光源位置未知");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -401,7 +401,7 @@ namespace ThreatSource.Guidance
|
||||
if (shortestDistance > config.ControlFieldDiameter / 2)
|
||||
{
|
||||
HasGuidance = false;
|
||||
Trace.WriteLine($"激光驾束引导系统: 失去引导, 原因: 超出控制场范围, 距离: {shortestDistance}");
|
||||
Trace.TraceInformation($"激光驾束引导系统: 失去引导, 原因: 超出控制场范围, 距离: {shortestDistance}");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -420,7 +420,7 @@ namespace ThreatSource.Guidance
|
||||
else
|
||||
{
|
||||
HasGuidance = false;
|
||||
Trace.WriteLine($"激光驾束引导系统: 失去引导, 原因: 接收到的激光功率低于最小可探测功率,{LaserPower:E} W/{receivedPower:E} W");
|
||||
Trace.TraceInformation($"激光驾束引导系统: 失去引导, 原因: 接收到的激光功率低于最小可探测功率,{LaserPower:E} W/{receivedPower:E} W");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -220,7 +220,7 @@ namespace ThreatSource.Guidance
|
||||
{
|
||||
if (evt?.LaserDesignatorId == null || evt?.TargetId == null || evt?.SpotPosition == null)
|
||||
{
|
||||
Console.WriteLine("接收到无效的激光照射更新事件");
|
||||
Trace.TraceInformation("接收到无效的激光照射更新事件");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -230,19 +230,19 @@ namespace ThreatSource.Guidance
|
||||
if (!CheckLaserCode(evt.LaserCodeConfig)) // 使用辅助方法检查编码
|
||||
{
|
||||
PublishCodeMismatchEvent(evt.LaserDesignatorId, evt.LaserCodeConfig);
|
||||
Console.WriteLine($"[LASER_SEMI_ACTIVE] {Id} 接收到编码不匹配的激光照射事件,忽略。预期: {InternalLaserCodeConfig}, 收到: {evt.LaserCodeConfig}");
|
||||
Trace.TraceInformation($"[LASER_SEMI_ACTIVE] {Id} 接收到编码不匹配的激光照射事件,忽略。预期: {InternalLaserCodeConfig}, 收到: {evt.LaserCodeConfig}");
|
||||
// 编码不匹配,不处理此事件,也不设置 LaserIlluminationOn
|
||||
return;
|
||||
}
|
||||
Console.WriteLine($"[LASER_SEMI_ACTIVE] {Id} 激光编码匹配。");
|
||||
Debug.WriteLine($"[LASER_SEMI_ACTIVE] {Id} 激光编码匹配。");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"[LASER_SEMI_ACTIVE] {Id} 未配置编码检查或不要求匹配。");
|
||||
Debug.WriteLine($"[LASER_SEMI_ACTIVE] {Id} 未配置编码检查或不要求匹配。");
|
||||
}
|
||||
|
||||
// 2. 编码匹配或无需检查,处理事件
|
||||
Console.WriteLine($"[LASER_SEMI_ACTIVE] 处理激光照射更新事件: 指示器ID: {evt.LaserDesignatorId}, 目标ID: {evt.TargetId}");
|
||||
Debug.WriteLine($"[LASER_SEMI_ACTIVE] 处理激光照射更新事件: 指示器ID: {evt.LaserDesignatorId}, 目标ID: {evt.TargetId}");
|
||||
try
|
||||
{
|
||||
LaserDesignator laserDesignator = SimulationManager.GetEntityById(evt.LaserDesignatorId) as LaserDesignator ?? throw new Exception("激光指示器不存在");
|
||||
@ -261,7 +261,7 @@ namespace ThreatSource.Guidance
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"处理激光照射更新事件时出错: {ex.Message}");
|
||||
Trace.TraceError($"处理激光照射更新事件时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,7 +304,7 @@ namespace ThreatSource.Guidance
|
||||
}
|
||||
else if (parameters.Type == JammingType.LaserDecoy)
|
||||
{
|
||||
Console.WriteLine($"[LASER_SEMI_ACTIVE] 受到激光诱偏干扰。JammerId: {parameters.JammerId}, SourceId: {parameters.SourceId}");
|
||||
Debug.WriteLine($"[LASER_SEMI_ACTIVE] 受到激光诱偏干扰。JammerId: {parameters.JammerId}, SourceId: {parameters.SourceId}");
|
||||
if (parameters.JammerId != null && parameters.SourceId != null)
|
||||
{
|
||||
LaserDecoy decoyTarget = SimulationManager.GetEntityById(parameters.JammerId) as LaserDecoy ?? throw new Exception("诱偏目标不存在");
|
||||
@ -313,7 +313,7 @@ namespace ThreatSource.Guidance
|
||||
if (!laserTargets.Any(t => t.Target.Id == decoyTarget.Id))
|
||||
{
|
||||
laserTargets.Add((decoyTarget, decoyTarget.KState.Position, decoySource));
|
||||
Console.WriteLine($"[LASER_SEMI_ACTIVE] 诱偏目标添加到激光目标列表。当前激光目标数量: {laserTargets.Count}");
|
||||
Debug.WriteLine($"[LASER_SEMI_ACTIVE] 诱偏目标添加到激光目标列表。当前激光目标数量: {laserTargets.Count}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -416,7 +416,7 @@ namespace ThreatSource.Guidance
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine($"处理激光信号: 激光目标数量={laserTargets.Count}");
|
||||
Debug.WriteLine($"处理激光信号: 激光目标数量={laserTargets.Count}");
|
||||
|
||||
// 如果没有激光源,返回
|
||||
if (laserTargets.Count == 0)
|
||||
@ -435,7 +435,7 @@ namespace ThreatSource.Guidance
|
||||
double angleDeviation = CalculateAngleDeviation(target.SpotPosition);
|
||||
if (angleDeviation > config.FieldOfViewAngleInRadians / 2)
|
||||
{
|
||||
Console.WriteLine($"处理激光信号: 目标超出视野范围,目标ID: {target.Target.Id}, 角度偏差: {angleDeviation:F2}弧度, 视野范围: {config.FieldOfViewAngleInRadians:F2}弧度");
|
||||
Debug.WriteLine($"处理激光信号: 目标超出视野范围,目标ID: {target.Target.Id}, 角度偏差: {angleDeviation:F2}弧度, 视野范围: {config.FieldOfViewAngleInRadians:F2}弧度");
|
||||
continue; // 目标超出视野范围
|
||||
}
|
||||
|
||||
@ -444,13 +444,13 @@ namespace ThreatSource.Guidance
|
||||
{
|
||||
// 计算接收功率
|
||||
receivedPower = CalculateReceivedPower(target.Source.KState.Position, target.SpotPosition, decoy.config.Power, decoy.config.DivergenceAngle);
|
||||
Console.WriteLine($"处理激光信号: 诱偏目标接收功率={receivedPower:E}W, 诱偏目标ID: {target.Target.Id}, 诱偏目标位置: {target.SpotPosition}");
|
||||
Debug.WriteLine($"处理激光信号: 诱偏目标接收功率={receivedPower:E}W, 诱偏目标ID: {target.Target.Id}, 诱偏目标位置: {target.SpotPosition}");
|
||||
}
|
||||
else if (target.Source is LaserDesignator laserDesignator)
|
||||
{
|
||||
// 计算接收功率
|
||||
receivedPower = CalculateReceivedPower(target.Source.KState.Position, target.SpotPosition, laserDesignator.config.Power, laserDesignator.config.DivergenceAngle);
|
||||
Console.WriteLine($"处理激光信号: 真实目标接收功率={receivedPower:E}W, 真实目标ID: {target.Target.Id}, 真实目标位置: {target.SpotPosition}");
|
||||
Debug.WriteLine($"处理激光信号: 真实目标接收功率={receivedPower:E}W, 真实目标ID: {target.Target.Id}, 真实目标位置: {target.SpotPosition}");
|
||||
}
|
||||
|
||||
// 累加功率
|
||||
@ -458,7 +458,7 @@ namespace ThreatSource.Guidance
|
||||
|
||||
// 加权位置
|
||||
weightedPosition += target.SpotPosition * receivedPower;
|
||||
Console.WriteLine($"处理激光信号: 累加功率={ReceivedLaserPower:E}W, 加权位置={weightedPosition}");
|
||||
Debug.WriteLine($"处理激光信号: 累加功率={ReceivedLaserPower:E}W, 加权位置={weightedPosition}");
|
||||
}
|
||||
|
||||
// 如果总功率为0,表示没有在视野范围内的激光源
|
||||
@ -471,7 +471,7 @@ namespace ThreatSource.Guidance
|
||||
// 计算加权平均位置
|
||||
TargetPosition = weightedPosition / ReceivedLaserPower;
|
||||
|
||||
Console.WriteLine($"处理激光信号: 总功率={ReceivedLaserPower:E}W, 加权平均目标位置={TargetPosition}");
|
||||
Debug.WriteLine($"处理激光信号: 总功率={ReceivedLaserPower:E}W, 加权平均目标位置={TargetPosition}");
|
||||
|
||||
// 更新激光照射参数
|
||||
LaserIlluminationOn = true;
|
||||
@ -485,7 +485,7 @@ namespace ThreatSource.Guidance
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine($"处理激光信号时出错: {ex.Message}");
|
||||
Trace.TraceError($"处理激光信号时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -540,7 +540,7 @@ namespace ThreatSource.Guidance
|
||||
double lensArea = Math.PI * Math.Pow(config.LensDiameter / 2, 2);
|
||||
double finalReceivedPower = powerDensityAtMissileAperture * lensArea * config.ReceiverEfficiency;
|
||||
|
||||
Console.WriteLine($"激光功率计算: S2T D={distanceSourceToTarget:F1}m (Path1 T={totalTransmittance_S2T:F3}), " +
|
||||
Debug.WriteLine($"激光功率计算: S2T D={distanceSourceToTarget:F1}m (Path1 T={totalTransmittance_S2T:F3}), " +
|
||||
$"T2M D={distanceTargetToMissile:F1}m (Path2 T={totalTransmittance_T2M:F3}), " +
|
||||
$"最终功率={finalReceivedPower:E}W");
|
||||
|
||||
|
||||
@ -172,7 +172,7 @@ namespace ThreatSource.Guidance
|
||||
currentScanRadius = config.SearchBeamWidth * Math.PI / 720.0; // 从半个波束宽度的一半开始
|
||||
LastTargetPosition = null;
|
||||
LastTargetVelocity = null;
|
||||
Trace.WriteLine($"切换到搜索模式,波束宽度: {config.SearchBeamWidth}度");
|
||||
Trace.TraceInformation($"切换到搜索模式,波束宽度: {config.SearchBeamWidth}度");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -183,7 +183,7 @@ namespace ThreatSource.Guidance
|
||||
currentMode = WorkMode.Track;
|
||||
lockConfirmationTimer = 0;
|
||||
HasGuidance = true;
|
||||
Trace.WriteLine($"切换到跟踪模式,波束宽度: {config.TrackBeamWidth}度");
|
||||
Trace.TraceInformation($"切换到跟踪模式,波束宽度: {config.TrackBeamWidth}度");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -193,7 +193,7 @@ namespace ThreatSource.Guidance
|
||||
{
|
||||
currentMode = WorkMode.Lock;
|
||||
HasGuidance = true;
|
||||
Trace.WriteLine("切换到锁定模式 - 目标锁定成功");
|
||||
Trace.TraceInformation("切换到锁定模式 - 目标锁定成功");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -322,7 +322,7 @@ namespace ThreatSource.Guidance
|
||||
currentScanAngle -= 2 * Math.PI;
|
||||
}
|
||||
|
||||
Console.WriteLine($"扫描参数 - 半径: {currentScanRadius * 180/Math.PI:F2}度, 角度: {currentScanAngle * 180/Math.PI:F2}度");
|
||||
Debug.WriteLine($"扫描参数 - 半径: {currentScanRadius * 180/Math.PI:F2}度, 角度: {currentScanAngle * 180/Math.PI:F2}度");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -419,14 +419,14 @@ namespace ThreatSource.Guidance
|
||||
).Normalize();
|
||||
|
||||
// 调试输出
|
||||
Console.WriteLine($"导弹前进方向: {xAxis}");
|
||||
Console.WriteLine($"目标方向: {toTarget.Normalize()}");
|
||||
Console.WriteLine($"扫描方向: {scanDirection}");
|
||||
Debug.WriteLine($"导弹前进方向: {xAxis}");
|
||||
Debug.WriteLine($"目标方向: {toTarget.Normalize()}");
|
||||
Debug.WriteLine($"扫描方向: {scanDirection}");
|
||||
|
||||
// 计算目标夹角
|
||||
double angle = Vector3D.AngleBetween(scanDirection, toTarget.Normalize());
|
||||
Console.WriteLine($"目标夹角: {angle * 180/Math.PI:F2}度");
|
||||
Console.WriteLine($"波束宽度: {currentBeamWidth * 180/Math.PI:F2}度,SNR阈值: {config.RecognitionSNRThreshold}dB");
|
||||
Debug.WriteLine($"目标夹角: {angle * 180/Math.PI:F2}度");
|
||||
Debug.WriteLine($"波束宽度: {currentBeamWidth * 180/Math.PI:F2}度,SNR阈值: {config.RecognitionSNRThreshold}dB");
|
||||
|
||||
return angle <= currentBeamWidth;
|
||||
}
|
||||
@ -434,8 +434,8 @@ namespace ThreatSource.Guidance
|
||||
{
|
||||
// 跟踪/锁定模式使用单脉冲测角
|
||||
var (azError, elError) = ProcessMonopulse(toTarget.Normalize(), missileVelocity);
|
||||
Console.WriteLine($"[单脉冲测角] 方位误差: {azError * 180/Math.PI:F3}度, 俯仰误差: {elError * 180/Math.PI:F3}度");
|
||||
Console.WriteLine($"[波束宽度检查] 当前阈值: {currentBeamWidth * 180/Math.PI:F3}度,实际误差: {Math.Sqrt(azError*azError + elError*elError) * 180/Math.PI:F3}度");
|
||||
Debug.WriteLine($"[单脉冲测角] 方位误差: {azError * 180/Math.PI:F3}度, 俯仰误差: {elError * 180/Math.PI:F3}度");
|
||||
Debug.WriteLine($"[波束宽度检查] 当前阈值: {currentBeamWidth * 180/Math.PI:F3}度,实际误差: {Math.Sqrt(azError*azError + elError*elError) * 180/Math.PI:F3}度");
|
||||
return Math.Sqrt(azError*azError + elError*elError) < currentBeamWidth;
|
||||
}
|
||||
}
|
||||
@ -496,7 +496,7 @@ namespace ThreatSource.Guidance
|
||||
GuidanceAcceleration = GuidanceAcceleration.Normalize() * MaxAcceleration;
|
||||
}
|
||||
|
||||
Console.WriteLine($"制导加速度: {GuidanceAcceleration}");
|
||||
Debug.WriteLine($"制导加速度: {GuidanceAcceleration}");
|
||||
HasGuidance = true;
|
||||
}
|
||||
else
|
||||
@ -507,7 +507,7 @@ namespace ThreatSource.Guidance
|
||||
if (targetLostTimer >= config.TargetLostTolerance)
|
||||
{
|
||||
HasGuidance = false;
|
||||
Trace.WriteLine($"目标丢失 {targetLostTimer:F3}秒,切换回搜索模式");
|
||||
Trace.TraceInformation($"目标丢失 {targetLostTimer:F3}秒,切换回搜索模式");
|
||||
SwitchToSearchMode();
|
||||
}
|
||||
}
|
||||
@ -736,7 +736,7 @@ namespace ThreatSource.Guidance
|
||||
if (snr_linear <= 0) return -100.0;
|
||||
|
||||
double snr_dB_no_smoke = 10 * Math.Log10(snr_linear);
|
||||
Console.WriteLine($"[SNR_CALC] SNR_dB (before smoke): {snr_dB_no_smoke:F2} dB. Incoming SmokeTransmittance_Linear: {smokeTransmittanceLinear:F6}");
|
||||
Debug.WriteLine($"[SNR计算] SNR_dB (烟幕前): {snr_dB_no_smoke:F2} dB. Incoming SmokeTransmittance_Linear: {smokeTransmittanceLinear:F6}");
|
||||
|
||||
// 应用当前生效的烟幕衰减 (通过存储的透过率) - REMOVED _currentSmokeTransmittance FIELD USAGE
|
||||
// signalPower *= _currentSmokeTransmittance; // This line is now handled by the parameter
|
||||
@ -744,7 +744,7 @@ namespace ThreatSource.Guidance
|
||||
// 应用烟幕透过率 (smokeTransmittanceLinear is already linear 0-1)
|
||||
if (smokeTransmittanceLinear <= 0.000001) // Threshold to prevent log(0) or very large negative numbers
|
||||
{
|
||||
Console.WriteLine($"[SNR_CALC] Smoke transmittance too low. Final_SNR_dB: -100.0 dB");
|
||||
Debug.WriteLine($"[SNR计算] 烟幕透过率太低. Final_SNR_dB: -100.0 dB");
|
||||
return -100.0; // Effectively zero signal due to smoke
|
||||
}
|
||||
|
||||
@ -752,7 +752,7 @@ namespace ThreatSource.Guidance
|
||||
// SNR_final_dB = SNR_original_dB - Loss_smoke_dB = SNR_original_dB + 10 * log10(T_smoke_linear)
|
||||
double smokeEffect_dB = 10 * Math.Log10(smokeTransmittanceLinear);
|
||||
double final_snr_dB = snr_dB_no_smoke + smokeEffect_dB;
|
||||
Console.WriteLine($"[SNR_CALC] SmokeEffect: {smokeEffect_dB:F2} dB. Final_SNR_dB (after smoke): {final_snr_dB:F2} dB");
|
||||
Debug.WriteLine($"[SNR计算] 烟幕影响: {smokeEffect_dB:F2} dB. 最终SNR_dB (烟幕后): {final_snr_dB:F2} dB");
|
||||
|
||||
return final_snr_dB;
|
||||
}
|
||||
@ -768,7 +768,7 @@ namespace ThreatSource.Guidance
|
||||
double totalTransmittance = 1.0;
|
||||
if (SimulationManager == null)
|
||||
{
|
||||
Trace.WriteLineIf(SimulationManager == null, "[MMW_GUIDANCE] SimulationManager is null in CalculateLiveSmokeTransmittance. Assuming no smoke.", "Warning");
|
||||
Trace.TraceWarning("[毫米波制导] 仿真管理器是 null, 假设没有烟幕.");
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
@ -784,7 +784,7 @@ namespace ThreatSource.Guidance
|
||||
double wavelength_um = SpeedOfLight / config.WaveFrequency * 1e6;
|
||||
|
||||
if (wavelength_um <= 0) {
|
||||
Trace.WriteLine("[MMW_GUIDANCE] Calculated wavelength in meters is invalid in CalculateLiveSmokeTransmittance. Assuming no smoke effect.", "Error");
|
||||
Trace.TraceInformation("[毫米波制导] 计算波长为米时无效. 假设没有烟幕影响.");
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
@ -793,7 +793,7 @@ namespace ThreatSource.Guidance
|
||||
double transmittanceForThisSmoke = smokeGrenade.GetSmokeTransmittanceOnLine(observerPosition, targetEndPosition, wavelength_um);
|
||||
totalTransmittance *= transmittanceForThisSmoke;
|
||||
|
||||
if (totalTransmittance < 0.000001) // Use a smaller threshold for early exit if transmittance is effectively zero
|
||||
if (totalTransmittance < 0.000001) // 使用更小的阈值提前退出,如果透过率几乎为零
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@ -132,7 +132,7 @@ namespace ThreatSource.Indicator
|
||||
if (_lastKnownTargetPosition != null)
|
||||
{
|
||||
currentTargetPosition = _lastKnownTargetPosition;
|
||||
Console.WriteLine($"InfraredTracker {Id}: 目标被遮挡,使用最后已知位置 {currentTargetPosition}");
|
||||
Debug.WriteLine($"红外测角仪 {Id}: 目标被遮挡,使用最后已知位置 {currentTargetPosition}");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -137,7 +137,7 @@ namespace ThreatSource.Indicator
|
||||
KState.Orientation = new Orientation(yaw, pitch, 0);
|
||||
_lastKnownTargetPosition = target.KState.Position;
|
||||
|
||||
Console.WriteLine($"激光指示器 {Id} 更新朝向: {KState.Orientation}, _lastKnownTargetPosition: {_lastKnownTargetPosition}");
|
||||
Debug.WriteLine($"激光指示器 {Id} 更新朝向: {KState.Orientation}, _lastKnownTargetPosition: {_lastKnownTargetPosition}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -191,7 +191,7 @@ namespace ThreatSource.Indicator
|
||||
// 实现激光指示器的干扰效果
|
||||
if (parameters.Type == JammingType.Laser)
|
||||
{
|
||||
Console.WriteLine($"[LaserDesignator] {Id} 受到激光干扰,停止照射。", "Jamming");
|
||||
Debug.WriteLine($"[激光指示器] {Id} 受到激光干扰,停止照射。", "Jamming");
|
||||
// 停止激光照射
|
||||
StopLaserIllumination();
|
||||
}
|
||||
@ -208,7 +208,7 @@ namespace ThreatSource.Indicator
|
||||
// 添加子类特定响应:如果是激光干扰清除,并且设备仍激活,尝试启动照射
|
||||
if (parameters.Type == JammingType.Laser)
|
||||
{
|
||||
Console.WriteLine($"[LaserDesignator] {Id} 激光干扰已清除。", "Jamming");
|
||||
Debug.WriteLine($"[激光指示器] {Id} 激光干扰已清除。", "Jamming");
|
||||
// 如果设备仍处于激活状态,并且没有其他阻塞性干扰,恢复激光照射
|
||||
if (IsActive && !IsBlockingJammed)
|
||||
{
|
||||
@ -336,7 +336,7 @@ namespace ThreatSource.Indicator
|
||||
// 检查波长匹配 (单位: 微米)
|
||||
if (Math.Abs((parameters.Wavelength ?? 0) - config.Wavelength) > 1e-6) // 使用配置的波长
|
||||
{
|
||||
Console.WriteLine($"[LaserDesignator] {Id} 忽略激光干扰:波长 {parameters.Wavelength}um 与工作波长 {config.Wavelength}um 不匹配。", "Jamming");
|
||||
Debug.WriteLine($"[激光指示器] {Id} 忽略激光干扰:波长 {parameters.Wavelength}um 与工作波长 {config.Wavelength}um 不匹配。", "Jamming");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ namespace ThreatSource.Jammable
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"[JammableComponent] Unsupported jamming type: {parameters.Type}");
|
||||
Trace.TraceWarning($"[可干扰组件] 不支持的干扰类型: {parameters.Type}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,7 +174,7 @@ namespace ThreatSource.Jammable
|
||||
// 1. 检查是否支持该干扰类型 (这个检查保持在最前面)
|
||||
if (!_supportedJammingTypes.Contains(parameters.Type))
|
||||
{
|
||||
Console.WriteLine($"[干扰有效性检查] 不支持的干扰类型: {parameters.Type}");
|
||||
Trace.TraceWarning($"[干扰有效性检查] 不支持的干扰类型: {parameters.Type}");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -188,10 +188,10 @@ namespace ThreatSource.Jammable
|
||||
{
|
||||
distance = 0.1; // 设置最小距离
|
||||
isDistanceNearZero = true;
|
||||
Console.WriteLine($"干扰计算 - 调整近零距离为 {distance}m");
|
||||
Debug.WriteLine($"干扰计算 - 调整近零距离为 {distance}m");
|
||||
}
|
||||
Console.WriteLine($"干扰计算 - 设备位置: {devicePosition}, 干扰源位置: {parameters.SourcePosition}");
|
||||
Console.WriteLine($"干扰计算 - 相对位置: {relativePosition}, 距离: {distance:F2}m");
|
||||
Debug.WriteLine($"干扰计算 - 设备位置: {devicePosition}, 干扰源位置: {parameters.SourcePosition}");
|
||||
Debug.WriteLine($"干扰计算 - 相对位置: {relativePosition}, 距离: {distance:F2}m");
|
||||
|
||||
|
||||
// 2. 选择性角度约束检查
|
||||
@ -209,14 +209,14 @@ namespace ThreatSource.Jammable
|
||||
|
||||
if (performAngleCheck)
|
||||
{
|
||||
Console.WriteLine($"[干扰有效性检查] 类型 {parameters.Type},模式 {parameters.Mode}:需要进行角度检查。");
|
||||
Debug.WriteLine($"[干扰有效性检查] 类型 {parameters.Type},模式 {parameters.Mode}:需要进行角度检查。");
|
||||
Vector3D jammerDirection = parameters.Direction.Normalize();
|
||||
// 如果距离非常近,避免对零向量进行归一化
|
||||
Vector3D jammerToDeviceDirection = !isDistanceNearZero ? relativePosition.Normalize() : Vector3D.Zero;
|
||||
|
||||
// 如果距离非常近,我们可能认为它总是在波束内,跳过角度比较。
|
||||
if (isDistanceNearZero) {
|
||||
Console.WriteLine($"干扰计算 - 距离过近,跳过角度约束比较。");
|
||||
Debug.WriteLine($"干扰计算 - 距离过近,跳过角度约束比较。");
|
||||
}
|
||||
else // 距离不近,执行角度比较
|
||||
{
|
||||
@ -225,21 +225,21 @@ namespace ThreatSource.Jammable
|
||||
dotProduct = Math.Max(-1.0, Math.Min(1.0, dotProduct));
|
||||
double angle = Math.Acos(dotProduct); // 角度(弧度)
|
||||
|
||||
Console.WriteLine($"干扰计算 - 干扰器方向: {jammerDirection}, 到设备方向: {jammerToDeviceDirection}");
|
||||
Console.WriteLine($"干扰计算 - 点积: {dotProduct:F2}, 夹角: {angle * 180 / Math.PI:F2} 度, 波束范围: {parameters.AngleRange:F2} 度");
|
||||
Debug.WriteLine($"干扰计算 - 干扰器方向: {jammerDirection}, 到设备方向: {jammerToDeviceDirection}");
|
||||
Debug.WriteLine($"干扰计算 - 点积: {dotProduct:F2}, 夹角: {angle * 180 / Math.PI:F2} 度, 波束范围: {parameters.AngleRange:F2} 度");
|
||||
|
||||
// AngleRange 是总锥角,与半角进行比较
|
||||
if (angle > (parameters.AngleRange * Math.PI / 360.0))
|
||||
{
|
||||
Console.WriteLine($"[干扰有效性检查] 类型 {parameters.Type},模式 {parameters.Mode}:超出波束角度。判定无效。");
|
||||
Debug.WriteLine($"[干扰有效性检查] 类型 {parameters.Type},模式 {parameters.Mode}:超出波束角度。判定无效。");
|
||||
return false; // 未通过角度约束
|
||||
}
|
||||
Console.WriteLine($"[干扰有效性检查] 类型 {parameters.Type},模式 {parameters.Mode}:通过角度检查。");
|
||||
Debug.WriteLine($"[干扰有效性检查] 类型 {parameters.Type},模式 {parameters.Mode}:通过角度检查。");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"[干扰有效性检查] 类型 {parameters.Type},模式 {parameters.Mode}:无需角度检查 (AngleRange={parameters.AngleRange})。");
|
||||
Debug.WriteLine($"[干扰有效性检查] 类型 {parameters.Type},模式 {parameters.Mode}:无需角度检查 (AngleRange={parameters.AngleRange})。");
|
||||
}
|
||||
|
||||
// 3. 针对阻塞模式的检查
|
||||
@ -248,26 +248,26 @@ namespace ThreatSource.Jammable
|
||||
// 对阻塞干扰进行功率阈值检查
|
||||
if (!_jammingThresholds.TryGetValue(parameters.Type, out double threshold))
|
||||
{
|
||||
Console.WriteLine($"[干扰有效性检查] 阻塞干扰 {parameters.Type} 未找到阈值。判定无效。");
|
||||
Debug.WriteLine($"[干扰有效性检查] 阻塞干扰 {parameters.Type} 未找到阈值。判定无效。");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 使用已计算的距离
|
||||
double receivedPower = parameters.Power / (4 * Math.PI * distance * distance);
|
||||
Console.WriteLine($"[干扰有效性检查] 阻塞干扰 {parameters.Type} - 发射功率: {parameters.Power}W, 接收功率: {receivedPower:E6}W, 阈值: {threshold:E6}W, 距离: {distance:F2}m");
|
||||
Debug.WriteLine($"[干扰有效性检查] 阻塞干扰 {parameters.Type} - 发射功率: {parameters.Power}W, 接收功率: {receivedPower:E6}W, 阈值: {threshold:E6}W, 距离: {distance:F2}m");
|
||||
|
||||
if (receivedPower < threshold)
|
||||
{
|
||||
Console.WriteLine($"[干扰有效性检查] 阻塞干扰 {parameters.Type}:接收功率低于阈值。判定无效。");
|
||||
Debug.WriteLine($"[干扰有效性检查] 阻塞干扰 {parameters.Type}:接收功率低于阈值。判定无效。");
|
||||
return false; // 未通过功率阈值检查
|
||||
}
|
||||
|
||||
Console.WriteLine($"[干扰有效性检查] 阻塞干扰 {parameters.Type}:通过所有检查。判定有效。");
|
||||
Debug.WriteLine($"[干扰有效性检查] 阻塞干扰 {parameters.Type}:通过所有检查。判定有效。");
|
||||
return true; // 通过了阻塞模式的所有检查
|
||||
}
|
||||
else // 非阻塞模式 (Deception, Compensation, 等)
|
||||
{
|
||||
Console.WriteLine($"[干扰有效性检查] 非阻塞干扰 {parameters.Type}:通过检查。判定有效。");
|
||||
Debug.WriteLine($"[干扰有效性检查] 非阻塞干扰 {parameters.Type}:通过检查。判定有效。");
|
||||
return true; // 如果是非阻塞且通过了初步检查,则认为有效
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,14 +99,14 @@ namespace ThreatSource.Jammer
|
||||
// 检查是否是该类型的干扰
|
||||
if (JammingType != parameters.Type)
|
||||
{
|
||||
Console.WriteLine($"干扰器 {Id} 不支持 {parameters.Type} 类型的干扰");
|
||||
Trace.TraceWarning($"干扰器 {Id} 不支持 {parameters.Type} 类型的干扰");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查当前状态是否允许启动干扰
|
||||
if (State == JammerState.Fault || State == JammerState.Cooling)
|
||||
{
|
||||
Console.WriteLine($"干扰器 {Id} 当前状态 {State} 不允许启动干扰");
|
||||
Trace.TraceWarning($"干扰器 {Id} 当前状态 {State} 不允许启动干扰");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -118,7 +118,7 @@ namespace ThreatSource.Jammer
|
||||
// 发布干扰开始事件
|
||||
PublishJammingEvent(parameters);
|
||||
|
||||
Console.WriteLine($"干扰器 {Id} 开始 {parameters.Type} 类型的干扰,功率:{parameters.Power}W");
|
||||
Debug.WriteLine($"干扰器 {Id} 开始 {parameters.Type} 类型的干扰,功率:{parameters.Power}W");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -144,7 +144,7 @@ namespace ThreatSource.Jammer
|
||||
PublishJammingStoppedEvent(oldParameters);
|
||||
}
|
||||
|
||||
Console.WriteLine($"干扰器 {Id} 停止干扰");
|
||||
Debug.WriteLine($"干扰器 {Id} 停止干扰");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -187,7 +187,7 @@ namespace ThreatSource.Jammer
|
||||
/// </summary>
|
||||
protected void PublishJammingEvent(JammingParameters parameters)
|
||||
{
|
||||
Console.WriteLine($"干扰器 {Id} 发布干扰事件: {parameters}");
|
||||
Debug.WriteLine($"干扰器 {Id} 发布干扰事件: {parameters}");
|
||||
var jammingEvent = new JammingEvent
|
||||
{
|
||||
Parameters = parameters
|
||||
@ -206,7 +206,7 @@ namespace ThreatSource.Jammer
|
||||
/// </summary>
|
||||
protected void PublishJammingStoppedEvent(JammingParameters parameters)
|
||||
{
|
||||
Console.WriteLine($"干扰器 {Id} 发布干扰结束事件: {parameters}");
|
||||
Debug.WriteLine($"干扰器 {Id} 发布干扰结束事件: {parameters}");
|
||||
var stoppedEvent = new JammingStoppedEvent
|
||||
{
|
||||
Parameters = parameters
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation;
|
||||
using System.Numerics;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ThreatSource.Jammer
|
||||
{
|
||||
@ -163,7 +163,7 @@ namespace ThreatSource.Jammer
|
||||
if (thickness > 0.1 && config.IsObscuring)
|
||||
{
|
||||
effectiveTransmittance = physicalTransmittance * 1e-3;
|
||||
Console.WriteLine($"[烟幕透过率计算] 屏蔽型烟幕生效,透射率调整为: {effectiveTransmittance:F5} (物理透射率: {physicalTransmittance:F5})");
|
||||
Debug.WriteLine($"[烟幕透过率计算] 屏蔽型烟幕生效,透射率调整为: {effectiveTransmittance:F5} (物理透射率: {physicalTransmittance:F5})");
|
||||
}
|
||||
|
||||
return effectiveTransmittance;
|
||||
|
||||
@ -230,7 +230,7 @@ namespace ThreatSource.Missile
|
||||
// 合成总加速度(制导加速度 + 推力加速度 + 空气阻力加速度)
|
||||
Vector3D totalAcceleration = GuidanceAcceleration + ThrustAcceleration + dragAcceleration;
|
||||
|
||||
Console.WriteLine($"导弹 {Id} 的加速度: {totalAcceleration}, 制导加速度: {GuidanceAcceleration}, " +
|
||||
Debug.WriteLine($"导弹 {Id} 的加速度: {totalAcceleration}, 制导加速度: {GuidanceAcceleration}, " +
|
||||
$"推力加速度: {ThrustAcceleration}, 空气阻力加速度(含风影响): {dragAcceleration}");
|
||||
|
||||
if (totalAcceleration.Magnitude() > Properties.MaxAcceleration)
|
||||
@ -413,7 +413,7 @@ namespace ThreatSource.Missile
|
||||
reason = "未知原因触发自毁";
|
||||
}
|
||||
|
||||
Trace.WriteLine($"导弹 {Id} 自毁。原因: {reason}");
|
||||
Trace.TraceInformation($"导弹 {Id} 自毁。原因: {reason}");
|
||||
OnSelfDestruct();
|
||||
Deactivate();
|
||||
}
|
||||
|
||||
@ -320,12 +320,12 @@ namespace ThreatSource.Missile
|
||||
);
|
||||
|
||||
SimulationManager.RegisterEntity(submunitions[i].Id, submunitions[i]);
|
||||
Debug.WriteLine($"注册末敏弹子弹 {submunitions[i].Id}");
|
||||
Trace.TraceInformation($"注册末敏弹子弹 {submunitions[i].Id}");
|
||||
submunitions[i].Activate();
|
||||
Debug.WriteLine($"激活末敏弹子弹 {submunitions[i].Id}");
|
||||
Trace.TraceInformation($"激活末敏弹子弹 {submunitions[i].Id}");
|
||||
|
||||
Console.WriteLine($"[末敏弹分离] 母弹 KS: Pos={KState.Position}, Orient={KState.Orientation}, Speed={KState.Speed}, Vel={KState.Velocity}");
|
||||
Console.WriteLine($"[末敏弹分离] 子弹 {i} KS: Pos={submunitions[i].KState.Position}, Orient={submunitions[i].KState.Orientation}, Speed={submunitions[i].KState.Speed}, Vel={submunitions[i].KState.Velocity}");
|
||||
Trace.TraceInformation($"[末敏弹分离] 母弹 KS: Pos={KState.Position}, Orient={KState.Orientation}, Speed={KState.Speed}, Vel={KState.Velocity}");
|
||||
Trace.TraceInformation($"[末敏弹分离] 子弹 {i} KS: Pos={submunitions[i].KState.Position}, Orient={submunitions[i].KState.Orientation}, Speed={submunitions[i].KState.Speed}, Vel={submunitions[i].KState.Velocity}");
|
||||
|
||||
submunitions[i].Fire();
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
using ThreatSource.Utils;
|
||||
|
||||
using System.Diagnostics;
|
||||
namespace ThreatSource.Sensor
|
||||
{
|
||||
/// <summary>
|
||||
@ -302,7 +302,7 @@ namespace ThreatSource.Sensor
|
||||
VerticalError = filteredVerticalError;
|
||||
|
||||
// 增强调试输出,同时显示水平和垂直误差
|
||||
Console.WriteLine($"原始误差: 水平={rawHorizontalError:F6}, 垂直={rawVerticalError:F6}, 滤波后: 水平={HorizontalError:F6}, 垂直={VerticalError:F6}");
|
||||
Debug.WriteLine($"原始误差: 水平={rawHorizontalError:F6}, 垂直={rawVerticalError:F6}, 滤波后: 水平={HorizontalError:F6}, 垂直={VerticalError:F6}");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -177,8 +177,8 @@ namespace ThreatSource.Simulation
|
||||
var activeTargets = entities.Values.OfType<Tank>().Where(e => e.IsActive).ToList();
|
||||
var hitEvents = new List<(Tank tank, BaseMissile missile, double damage)>();
|
||||
|
||||
Console.WriteLine($"活动导弹数量: {activeMissiles.Count}");
|
||||
Console.WriteLine($"活动目标数量: {activeTargets.Count}");
|
||||
Debug.WriteLine($"活动导弹数量: {activeMissiles.Count}");
|
||||
Debug.WriteLine($"活动目标数量: {activeTargets.Count}");
|
||||
|
||||
// 收集所有的命中信息
|
||||
foreach (var missile in activeMissiles)
|
||||
@ -186,7 +186,7 @@ namespace ThreatSource.Simulation
|
||||
foreach (var target in activeTargets)
|
||||
{
|
||||
double distance = Vector3D.Distance(missile.KState.Position, target.KState.Position);
|
||||
Console.WriteLine($"导弹 {missile.Id} 和目标 {target.Id} 之间的距离: {distance:F2}");
|
||||
Debug.WriteLine($"导弹 {missile.Id} 和目标 {target.Id} 之间的距离: {distance:F2}");
|
||||
if (distance <= missile.Properties.ExplosionRadius)
|
||||
{
|
||||
double damage = CalculateMissileDamage(missile);
|
||||
@ -202,7 +202,7 @@ namespace ThreatSource.Simulation
|
||||
if (tank.IsActive)
|
||||
{
|
||||
tank.TakeDamage(damage);
|
||||
Console.WriteLine($"目标 {tank.Id} 被导弹 {missile.Id} 击中,造成 {damage} 点伤害");
|
||||
Debug.WriteLine($"目标 {tank.Id} 被导弹 {missile.Id} 击中,造成 {damage} 点伤害");
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,20 +215,20 @@ namespace ThreatSource.Simulation
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"发布命中事件时发生错误: {ex.Message}");
|
||||
Debug.WriteLine($"发布命中事件时发生错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"处理命中事件时发生错误: {ex.Message}");
|
||||
Debug.WriteLine($"处理命中事件时发生错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算导弹造成的伤害
|
||||
/// </summary>
|
||||
private double CalculateMissileDamage(BaseMissile missile)
|
||||
private static double CalculateMissileDamage(BaseMissile missile)
|
||||
{
|
||||
// 这里可以根据导弹类型、速度等因素计算伤害
|
||||
// 现在我们简单地返回一个固定值
|
||||
@ -543,7 +543,7 @@ namespace ThreatSource.Simulation
|
||||
public void SetWeather(Weather weather)
|
||||
{
|
||||
_currentWeather = weather;
|
||||
Console.WriteLine($"已设置天气:{weather.Type}");
|
||||
Debug.WriteLine($"已设置天气:{weather.Type}");
|
||||
|
||||
// 通知其他实体天气已变化
|
||||
var evt = new WeatherChangedEvent
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
using AirTransmission; // 引用 .NET DLL 的命名空间
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ThreatSource.Utils
|
||||
{
|
||||
@ -53,13 +53,13 @@ namespace ThreatSource.Utils
|
||||
distanceInKm, // 使用公里单位
|
||||
parameters);
|
||||
|
||||
Console.WriteLine($"[透过率] 类型: {radiationType}, 波长: {wavelength:F2}um, 距离: {distance:F1}m -> {transmittance:F3}");
|
||||
Debug.WriteLine($"[透过率] 类型: {radiationType}, 波长: {wavelength:F2}um, 距离: {distance:F1}m -> {transmittance:F3}");
|
||||
|
||||
return Math.Clamp(transmittance, 0.0, 1.0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"调用AirTransmission计算透过率时出错 (类型: {radiationType}, 波长: {wavelength}um, 距离: {distance}m): {ex.Message}");
|
||||
Debug.WriteLine($"调用AirTransmission计算透过率时出错 (类型: {radiationType}, 波长: {wavelength}um, 距离: {distance}m): {ex.Message}");
|
||||
// 发生错误时返回一个保守的默认值
|
||||
return 0.8;
|
||||
}
|
||||
@ -117,12 +117,12 @@ namespace ThreatSource.Utils
|
||||
parameters,
|
||||
height); // 使用米单位
|
||||
|
||||
Console.WriteLine($"[湍流效应] 波长: {wavelength:F2}um, 距离: {distance:F1}m, 高度: {height:F1}m -> {turbulenceEffect:F3}");
|
||||
Debug.WriteLine($"[湍流效应] 波长: {wavelength:F2}um, 距离: {distance:F1}m, 高度: {height:F1}m -> {turbulenceEffect:F3}");
|
||||
return turbulenceEffect;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"计算湍流效应时出错 (波长: {wavelength}um, 距离: {distance}m, 高度: {height}m): {ex.Message}");
|
||||
Debug.WriteLine($"计算湍流效应时出错 (波长: {wavelength}um, 距离: {distance}m, 高度: {height}m): {ex.Message}");
|
||||
return 1.0; // 假设无影响
|
||||
}
|
||||
}
|
||||
@ -144,12 +144,12 @@ namespace ThreatSource.Utils
|
||||
smokeConcentration,
|
||||
smokeThickness); // 使用米单位
|
||||
|
||||
Console.WriteLine($"[烟幕透过率] 波长: {wavelength:F2}um, 浓度: {smokeConcentration:F1}g/m³, 厚度: {smokeThickness:F1}m -> {smokeTransmittance:F3}");
|
||||
Debug.WriteLine($"[烟幕透过率] 波长: {wavelength:F2}um, 浓度: {smokeConcentration:F1}g/m³, 厚度: {smokeThickness:F1}m -> {smokeTransmittance:F3}");
|
||||
return smokeTransmittance;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"计算烟幕透过率时出错 (波长: {wavelength}um, 浓度: {smokeConcentration}g/m³, 厚度: {smokeThickness}m): {ex.Message}");
|
||||
Debug.WriteLine($"计算烟幕透过率时出错 (波长: {wavelength}um, 浓度: {smokeConcentration}g/m³, 厚度: {smokeThickness}m): {ex.Message}");
|
||||
return 0.0; // 假设完全衰减
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ class Program
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine($"Error: {ex.Message}");
|
||||
Trace.TraceError($"Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -185,7 +185,7 @@ int main() {
|
||||
return 0;
|
||||
}
|
||||
catch (Exception^ e) {
|
||||
Trace::WriteLine("Error: {0}", e->Message);
|
||||
Trace::TraceError("Error: {0}", e->Message);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -311,7 +311,7 @@ public:
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Trace::WriteLine("错误: {0}", e->Message);
|
||||
Trace::TraceError("错误: {0}", e->Message);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -330,7 +330,7 @@ int main()
|
||||
}
|
||||
catch (Exception^ e)
|
||||
{
|
||||
Trace::WriteLine("错误: {0}", e->Message);
|
||||
Trace::TraceError("错误: {0}", e->Message);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,22 +90,22 @@ namespace ThreatSource.Examples
|
||||
|
||||
// 步骤9:获取仿真结果
|
||||
var results = await _adapter.GetSimulationResults();
|
||||
Console.WriteLine($"仿真结束,命中精度: {results.MissDistance:F2}米");
|
||||
Trace.TraceInformation($"仿真结束,命中精度: {results.MissDistance:F2}米");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"仿真过程出错: {ex.Message}");
|
||||
Trace.TraceError($"仿真过程出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEntityUpdated(SimulationEntity entity)
|
||||
{
|
||||
Console.WriteLine($"实体 {entity.Id} 位置更新: ({entity.Position.X:F2}, {entity.Position.Y:F2}, {entity.Position.Z:F2})");
|
||||
Trace.TraceInformation($"实体 {entity.Id} 位置更新: ({entity.Position.X:F2}, {entity.Position.Y:F2}, {entity.Position.Z:F2})");
|
||||
}
|
||||
|
||||
private void OnGuidanceUpdate(GuidanceInfo info)
|
||||
{
|
||||
Console.WriteLine($"制导更新: 距离目标 {info.DistanceToTarget:F2}米");
|
||||
Trace.TraceInformation($"制导更新: 距离目标 {info.DistanceToTarget:F2}米");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -134,9 +134,9 @@ public class IRMissileSimulation
|
||||
private void ProcessResults(SimulationResults results)
|
||||
{
|
||||
// 处理仿真结果
|
||||
Console.WriteLine($"仿真完成时间: {results.CompletionTime}秒");
|
||||
Console.WriteLine($"命中精度: {results.HitAccuracy}米");
|
||||
Console.WriteLine($"导引头跟踪时间: {results.TrackingTime}秒");
|
||||
Trace.TraceInformation($"仿真完成时间: {results.CompletionTime}秒");
|
||||
Trace.TraceInformation($"命中精度: {results.HitAccuracy}米");
|
||||
Trace.TraceInformation($"导引头跟踪时间: {results.TrackingTime}秒");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -7,6 +7,36 @@
|
||||
- 事件描述
|
||||
- 分析处理
|
||||
|
||||
## 2025-05-12 规范了调试信息的输出
|
||||
- 规范了调试信息的输出,使用 Debug 和 Trace 输出日志
|
||||
- 修改了集成测试程序的菜单,增加了日志级别设置
|
||||
|
||||
System.Diagnostics 命名空间提供了用于日志记录的类:
|
||||
|
||||
- Debug.WriteLine(...):用于开发阶段,详细的内部调试信息。
|
||||
- Trace.WriteLine(...):用于开发和发布阶段,跟踪应用程序的执行流程,记录重要的事件、错误或状态信息。
|
||||
- Trace.TraceInformation(...):用于一般的操作信息。
|
||||
- Trace.TraceWarning(...):用于潜在问题。
|
||||
- Trace.TraceError(...):用于已发生的错误。
|
||||
|
||||
System.Diagnostics.Debug.WriteLine 和 System.Diagnostics.Trace.WriteLine 之间, 在用途和行为上有一些关键的不同:
|
||||
1. 编译条件与用途:
|
||||
Debug.WriteLine (以及 Debug 类的其他方法):
|
||||
编译条件: 这些方法调用通常只在定义了 DEBUG 编译常量时才会被编译到程序中。在 Visual Studio 或 dotnet build 中,"Debug" 配置默认会定义 DEBUG (和 TRACE) 常量。"Release" 配置默认只定义 TRACE 常量。
|
||||
用途: 主要用于开发和调试阶段。这些日志信息帮助开发者理解代码执行流程、变量状态等,通常不应出现在最终的发布版本中,因为它们可能会暴露过多内部信息或影响性能。
|
||||
Trace.WriteLine (以及 Trace 类的其他方法):
|
||||
编译条件: 这些方法调用通常在定义了 TRACE 编译常量时被编译。如上所述,"Debug" 和 "Release" 配置默认都会定义 TRACE。
|
||||
用途: 用于跟踪应用程序的执行流程,记录重要的事件、错误或状态信息,这些信息在应用程序的发布版本中也可能是有用的。例如,记录关键操作的开始和结束,或者记录发生的异常。
|
||||
总结编译与用途:
|
||||
用 Debug.WriteLine 输出只在开发调试时需要看的信息。
|
||||
用 Trace.WriteLine (推荐使用更具体的 Trace.TraceInformation, Trace.TraceWarning, Trace.TraceError) 输出在发布后也可能需要查看的跟踪信息。
|
||||
|
||||
|
||||
在模拟器中,您可以设置日志级别来控制哪些日志信息会被输出。
|
||||
|
||||
例如,在模拟器启动时,您可以设置日志级别:
|
||||
|
||||
|
||||
## 2025-05-09 完善了各组件的干扰功能
|
||||
- 把各组件的烟幕透过率计算移到 update 方法中
|
||||
- 完善了指示器的烟幕遮挡计算逻辑
|
||||
|
||||
@ -1,8 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
using ThreatSource.Missile;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
@ -14,6 +9,9 @@ using ThreatSource.Guidance;
|
||||
using ThreatSource.Indicator;
|
||||
using ThreatSource.Data;
|
||||
using AirTransmission;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ThreatSource.Tools.MissileSimulation
|
||||
{
|
||||
@ -25,6 +23,9 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
// 定义仿真结束事件
|
||||
public event EventHandler? SimulationEnded;
|
||||
|
||||
private ConsoleTraceListener consoleListener;
|
||||
private EventTypeFilter logLevelFilter;
|
||||
|
||||
private readonly SimulationManager simulationManager;
|
||||
private readonly ThreatSourceFactory _threatSourceFactory;
|
||||
private readonly ThreatSourceDataManager _dataManager;
|
||||
@ -41,6 +42,8 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
// 当前选中的导弹ID
|
||||
public string SelectedMissileId { get; private set; }
|
||||
|
||||
private List<(JammingType Type, string DisplayName, string JammerId, string Mode, string Target)> activeJammings;
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前选中导弹的显示名称
|
||||
/// </summary>
|
||||
@ -66,6 +69,21 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
/// </summary>
|
||||
public ComprehensiveMissileSimulator()
|
||||
{
|
||||
// Initialize filter and listener first
|
||||
this.logLevelFilter = new EventTypeFilter(SourceLevels.Verbose); // Default to Verbose
|
||||
this.consoleListener = new ConsoleTraceListener();
|
||||
this.consoleListener.Filter = this.logLevelFilter;
|
||||
|
||||
// Clear any existing ConsoleTraceListeners and add our controlled instance
|
||||
for (int i = Trace.Listeners.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (Trace.Listeners[i] is ConsoleTraceListener)
|
||||
{
|
||||
Trace.Listeners.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
Trace.Listeners.Add(this.consoleListener);
|
||||
|
||||
simulationManager = new SimulationManager();
|
||||
_dataManager = new ThreatSourceDataManager("../ThreatSource/data");
|
||||
_threatSourceFactory = new ThreatSourceFactory(_dataManager, simulationManager);
|
||||
@ -77,11 +95,28 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
missileJammingMap = [];
|
||||
SelectedMissileId = "";
|
||||
|
||||
this.activeJammings = new List<(JammingType Type, string DisplayName, string JammerId, string Mode, string Target)>();
|
||||
|
||||
// 初始化导弹-干扰映射
|
||||
InitializeMissileJammingMap();
|
||||
|
||||
InitializeSimulation();
|
||||
}
|
||||
|
||||
public SourceLevels CurrentLogLevel => logLevelFilter?.EventType ?? SourceLevels.Off;
|
||||
|
||||
public void SetLogLevel(SourceLevels level)
|
||||
{
|
||||
if (logLevelFilter != null)
|
||||
{
|
||||
logLevelFilter.EventType = level;
|
||||
Console.WriteLine($"[Simulator] 日志输出级别已设置为: {level}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("[Simulator] Error: Log level filter not initialized.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化导弹-干扰映射关系
|
||||
@ -91,51 +126,51 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
missileJammingMap = new Dictionary<string, List<(JammingType, string, string, string, string)>>();
|
||||
|
||||
// 激光驾束导弹
|
||||
missileJammingMap["LBRM_1"] = new List<(JammingType, string, string, string, string)>
|
||||
{
|
||||
missileJammingMap["LBRM_1"] =
|
||||
[
|
||||
(JammingType.Laser, "激光干扰", "LaserJammer_Designator", "阻塞", "驾束仪"),
|
||||
(JammingType.SmokeGrenade, "烟幕弹", "SG_1", "遮蔽", "驾束仪")
|
||||
};
|
||||
];
|
||||
|
||||
// 激光半主动制导导弹
|
||||
missileJammingMap["LSGM_1"] = new List<(JammingType, string, string, string, string)>
|
||||
{
|
||||
missileJammingMap["LSGM_1"] =
|
||||
[
|
||||
(JammingType.Laser, "激光干扰(指示器)", "LaserJammer_Designator", "阻塞", "指示器"),
|
||||
(JammingType.Laser, "激光干扰(导弹)", "LaserJammer_Missile", "阻塞", "导弹"),
|
||||
(JammingType.LaserDecoy, "激光诱偏目标", "LDY_1", "欺骗", "导弹"),
|
||||
(JammingType.SmokeGrenade, "烟幕弹", "SG_1", "遮蔽", "两者")
|
||||
};
|
||||
];
|
||||
|
||||
// 红外指令制导导弹
|
||||
missileJammingMap["ICGM_1"] = new List<(JammingType, string, string, string, string)>
|
||||
{
|
||||
missileJammingMap["ICGM_1"] =
|
||||
[
|
||||
(JammingType.Infrared, "红外干扰", "InfraredJammer_Designator", "阻塞", "指示器"),
|
||||
(JammingType.SmokeGrenade, "烟幕弹", "SG_2", "遮蔽", "指示器")
|
||||
};
|
||||
];
|
||||
|
||||
// 红外成像末制导导弹
|
||||
missileJammingMap["ITGM_1"] = new List<(JammingType, string, string, string, string)>
|
||||
{
|
||||
missileJammingMap["ITGM_1"] =
|
||||
[
|
||||
(JammingType.Infrared, "红外干扰", "InfraredJammer_Missile", "阻塞", "导弹"),
|
||||
(JammingType.SmokeGrenade, "红外烟幕弹", "SG_2", "遮蔽", "导弹")
|
||||
};
|
||||
];
|
||||
|
||||
// 毫米波末制导导弹
|
||||
missileJammingMap["MMWG_1"] = new List<(JammingType, string, string, string, string)>
|
||||
{
|
||||
missileJammingMap["MMWG_1"] =
|
||||
[
|
||||
(JammingType.MillimeterWave, "毫米波干扰", "MillimeterWaveJammer_Missile", "阻塞", "导弹"),
|
||||
(JammingType.SmokeGrenade, "烟幕弹", "SG_3", "遮蔽", "导弹")
|
||||
};
|
||||
];
|
||||
|
||||
// 末敏子弹药
|
||||
missileJammingMap["TSM_1"] = new List<(JammingType, string, string, string, string)>
|
||||
{
|
||||
missileJammingMap["TSM_1"] =
|
||||
[
|
||||
(JammingType.Laser, "激光干扰", "LaserJammer_Submunition", "阻塞", "子弹药"),
|
||||
(JammingType.Infrared, "红外干扰", "InfraredJammer_Submunition", "阻塞", "子弹药"),
|
||||
(JammingType.MillimeterWave, "毫米波干扰", "MillimeterWaveJammer_Submunition", "阻塞", "子弹药"),
|
||||
(JammingType.MillimeterWave, "毫米波假信号", "MillimeterWaveCompensationJammer_Submunition", "欺骗", "子弹药"),
|
||||
(JammingType.SmokeGrenade, "烟幕弹", "SG_4", "遮蔽", "子弹药")
|
||||
};
|
||||
];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -214,8 +249,7 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
Speed = 0.0
|
||||
};
|
||||
string laserDecoyId = "LDY_1";
|
||||
var laserDecoy = _threatSourceFactory.CreateJammer(laserDecoyId, "laser_decoy", motionParameters, "Tank_1") as LaserDecoy;
|
||||
if (laserDecoy != null)
|
||||
if (_threatSourceFactory.CreateJammer(laserDecoyId, "laser_decoy", motionParameters, "Tank_1") is LaserDecoy laserDecoy)
|
||||
{
|
||||
simulationManager.RegisterEntity(laserDecoyId, laserDecoy);
|
||||
jammers[laserDecoyId] = laserDecoy as BaseJammer;
|
||||
@ -692,16 +726,20 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
// 检查并激活干扰器
|
||||
if (jammers.ContainsKey(jammerId))
|
||||
{
|
||||
var jammer = jammers[jammerId];
|
||||
|
||||
// 激活干扰器实例
|
||||
jammer.Activate();
|
||||
|
||||
var jammerToActivate = jammers[jammerId];
|
||||
jammerToActivate.Activate();
|
||||
Console.WriteLine($"激活干扰器并开始干扰: {jammerId}: {displayName} (模式: {mode}, 作用: {target})");
|
||||
|
||||
// Add to activeJammings list if not already present
|
||||
var jammingTuple = (Type: type, DisplayName: displayName, JammerId: jammerId, Mode: mode, Target: target);
|
||||
if (!this.activeJammings.Any(j => j.JammerId == jammerId && j.Type == type)) // Simple check to avoid duplicates
|
||||
{
|
||||
this.activeJammings.Add(jammingTuple);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"警告:找不到干扰器 {jammerId},可用干扰器: {string.Join(", ", jammers.Keys)}");
|
||||
Console.WriteLine($"警告:找不到干扰器 {jammerId}...");
|
||||
PrintAllJammers();
|
||||
}
|
||||
|
||||
@ -939,6 +977,9 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
{
|
||||
jammers[jammerId].Deactivate();
|
||||
Console.WriteLine($"关闭干扰器 {jammerId}: {displayName}");
|
||||
|
||||
// Remove from activeJammings list
|
||||
this.activeJammings.RemoveAll(j => j.JammerId == jammerId && j.Type == type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1314,5 +1355,20 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
Console.WriteLine($"风速: {newWeather.WindSpeed}米/秒");
|
||||
Console.WriteLine($"风向: {newWeather.WindDirection}°");
|
||||
}
|
||||
|
||||
public string GetActiveJammingDescription()
|
||||
{
|
||||
if (this.activeJammings == null || !this.activeJammings.Any())
|
||||
{
|
||||
return "(无干扰)";
|
||||
}
|
||||
return $"(已激活: {this.activeJammings.First().DisplayName})";
|
||||
}
|
||||
|
||||
public List<(JammingType Type, string DisplayName, string JammerId, string Mode, string Target)> GetCurrentlyActiveJammings()
|
||||
{
|
||||
// Return a new list to prevent external modification of the internal list
|
||||
return new List<(JammingType Type, string DisplayName, string JammerId, string Mode, string Target)>(this.activeJammings);
|
||||
}
|
||||
}
|
||||
}
|
||||
380
tools/Program.cs
380
tools/Program.cs
@ -2,6 +2,8 @@ using ThreatSource.Utils;
|
||||
using ThreatSource.Jammer;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace ThreatSource.Tools.MissileSimulation
|
||||
{
|
||||
@ -11,97 +13,187 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
{
|
||||
Console.WriteLine("综合导弹模拟程序启动...");
|
||||
var simulator = new ComprehensiveMissileSimulator();
|
||||
|
||||
// 标记是否收到仿真结束事件
|
||||
var simulationEndedEvent = new ManualResetEvent(false);
|
||||
|
||||
// 订阅仿真结束事件
|
||||
simulator.SimulationEnded += (sender, e) => {
|
||||
simulationEndedEvent.Set();
|
||||
};
|
||||
|
||||
while (true)
|
||||
{
|
||||
// 显示主菜单,如果返回false则退出程序
|
||||
if (!ShowMainMenu(simulator))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// 重置事件状态
|
||||
simulationEndedEvent.Reset();
|
||||
|
||||
// 开始仿真
|
||||
var simulationThread = new Thread(simulator.Start);
|
||||
simulationThread.Start();
|
||||
|
||||
// 等待退出命令
|
||||
Console.WriteLine("\n仿真已开始运行。输入 'exit' 退出程序。");
|
||||
bool exitProgram = false;
|
||||
while (true)
|
||||
{
|
||||
if (Console.KeyAvailable)
|
||||
{
|
||||
var input = Console.ReadLine();
|
||||
if (input?.ToLower() == "exit")
|
||||
{
|
||||
simulator.Stop();
|
||||
exitProgram = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查仿真是否结束
|
||||
if (simulationEndedEvent.WaitOne(100)) // 等待100ms
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (exitProgram)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// 等待仿真线程完全结束
|
||||
simulationThread.Join();
|
||||
|
||||
// 显示分隔线和新的仿真选项
|
||||
Console.WriteLine("\n" + new string('=', 50));
|
||||
Console.WriteLine("当前导弹仿真结束。");
|
||||
Console.WriteLine("按任意键返回主菜单,或输入 'exit' 退出程序...");
|
||||
Console.WriteLine(new string('=', 50) + "\n");
|
||||
|
||||
string userInput = Console.ReadLine()?.ToLower() ?? string.Empty;
|
||||
if (userInput == "exit")
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set a default log level on startup if desired, or rely on Simulator's default
|
||||
// simulator.SetLogLevel(SourceLevels.Information);
|
||||
ApplicationHostLoop(simulator);
|
||||
Console.WriteLine("\n程序已退出。");
|
||||
}
|
||||
|
||||
static bool ShowMainMenu(ComprehensiveMissileSimulator simulator)
|
||||
|
||||
static void ApplicationHostLoop(ComprehensiveMissileSimulator simulator)
|
||||
{
|
||||
Console.WriteLine("=== 导弹仿真系统主菜单 ===\n");
|
||||
|
||||
// 第一步:选择导弹
|
||||
if (!SelectMissile(simulator))
|
||||
return false;
|
||||
|
||||
// 第二步:配置传感器
|
||||
if (!ConfigureSensors(simulator))
|
||||
return false;
|
||||
|
||||
// 第三步:配置干扰
|
||||
if (!ConfigureJamming(simulator))
|
||||
return false;
|
||||
bool exitProgram = false;
|
||||
while (!exitProgram)
|
||||
{
|
||||
Console.WriteLine("\n=== 导弹仿真系统主菜单 ===");
|
||||
string missileStatus = string.IsNullOrEmpty(simulator.SelectedMissileId) ? "未选择" : $"已选: {simulator.SelectedMissileDisplayName}";
|
||||
|
||||
return true;
|
||||
string sensorStatusString = "";
|
||||
if (!string.IsNullOrEmpty(simulator.SelectedMissileId))
|
||||
{
|
||||
var indicators = simulator.GetActiveIndicators();
|
||||
var firstActiveIndicator = indicators.FirstOrDefault(ind => ind.IsActive);
|
||||
if (firstActiveIndicator.Name != null) // Name is a string, check for null if tuple might not be found
|
||||
{
|
||||
sensorStatusString = $"(已激活: {firstActiveIndicator.Name})";
|
||||
}
|
||||
else
|
||||
{
|
||||
sensorStatusString = "(无默认激活指示器)"; // Or "(配置)" or similar
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sensorStatusString = "(需先选导弹)";
|
||||
}
|
||||
|
||||
Console.WriteLine($"1. 选择导弹 ({missileStatus})");
|
||||
Console.WriteLine($"2. 配置传感器 {sensorStatusString}");
|
||||
Console.WriteLine($"3. 配置干扰 {simulator.GetActiveJammingDescription()} {(string.IsNullOrEmpty(simulator.SelectedMissileId) ? "(需先选导弹)" : "")}");
|
||||
Console.WriteLine($"4. 设置日志级别 (当前级别: {simulator.CurrentLogLevel})");
|
||||
Console.WriteLine($"5. 开始仿真 {(string.IsNullOrEmpty(simulator.SelectedMissileId) ? "(需先选导弹)" : "")}");
|
||||
Console.WriteLine("0. 退出程序");
|
||||
Console.Write("\n请选择: ");
|
||||
string choice = Console.ReadLine()?.ToLower() ?? string.Empty;
|
||||
|
||||
switch (choice)
|
||||
{
|
||||
case "1":
|
||||
SelectMissile(simulator);
|
||||
break;
|
||||
case "2":
|
||||
if (!string.IsNullOrEmpty(simulator.SelectedMissileId))
|
||||
ConfigureSensors(simulator);
|
||||
else
|
||||
Console.WriteLine("请先选择导弹。");
|
||||
break;
|
||||
case "3":
|
||||
if (!string.IsNullOrEmpty(simulator.SelectedMissileId))
|
||||
ConfigureJamming(simulator);
|
||||
else
|
||||
Console.WriteLine("请先选择导弹。");
|
||||
break;
|
||||
case "4":
|
||||
ShowLogLevelMenu(simulator);
|
||||
break;
|
||||
case "5":
|
||||
if (!string.IsNullOrEmpty(simulator.SelectedMissileId))
|
||||
{
|
||||
RunSimulationInstance(simulator);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("请先选择导弹并完成基本配置 (选择导弹是启动仿真的最低要求)。");
|
||||
}
|
||||
break;
|
||||
case "0":
|
||||
exitProgram = true;
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine("无效选择,请重试。");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool SelectMissile(ComprehensiveMissileSimulator simulator)
|
||||
|
||||
// Placeholder for ShowLogLevelMenu - to be implemented next
|
||||
static void ShowLogLevelMenu(ComprehensiveMissileSimulator simulator)
|
||||
{
|
||||
bool backToMainMenu = false;
|
||||
while (!backToMainMenu)
|
||||
{
|
||||
Console.WriteLine("\n--- 设置日志级别 ---");
|
||||
Console.WriteLine("1. Off (关闭所有Trace/Debug输出)");
|
||||
Console.WriteLine("2. Error (仅错误信息)");
|
||||
Console.WriteLine("3. Warning (警告及错误)");
|
||||
Console.WriteLine("4. Information (普通信息、警告、错误)");
|
||||
Console.WriteLine("5. Verbose (所有信息,包括Debug.WriteLine)");
|
||||
Console.WriteLine("0. 返回主菜单");
|
||||
Console.Write("请选择日志级别: ");
|
||||
string input = Console.ReadLine()?.ToLower() ?? string.Empty;
|
||||
|
||||
SourceLevels currentLevel = simulator.CurrentLogLevel; // Use the new public property
|
||||
SourceLevels selectedLevel = currentLevel; // Default to current if invalid choice
|
||||
bool levelSet = false;
|
||||
|
||||
switch (input)
|
||||
{
|
||||
case "1": selectedLevel = SourceLevels.Off; levelSet = true; break;
|
||||
case "2": selectedLevel = SourceLevels.Error; levelSet = true; break;
|
||||
case "3": selectedLevel = SourceLevels.Warning; levelSet = true; break;
|
||||
case "4": selectedLevel = SourceLevels.Information; levelSet = true; break;
|
||||
case "5": selectedLevel = SourceLevels.Verbose; levelSet = true; break;
|
||||
case "0": backToMainMenu = true; break;
|
||||
default: Console.WriteLine("无效选择,请重试。"); break;
|
||||
}
|
||||
|
||||
if (levelSet)
|
||||
{
|
||||
simulator.SetLogLevel(selectedLevel);
|
||||
// Confirmation is printed by SetLogLevel in simulator
|
||||
return; // Return to main menu after setting level
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Placeholder for RunSimulationInstance - to be implemented next
|
||||
static void RunSimulationInstance(ComprehensiveMissileSimulator simulator)
|
||||
{
|
||||
Console.WriteLine("\n--- 开始仿真 --- ");
|
||||
var simulationEndedEvent = new ManualResetEvent(false);
|
||||
simulator.SimulationEnded += (sender, e) => {
|
||||
simulationEndedEvent.Set();
|
||||
// Unsubscribe to prevent issues if RunSimulationInstance is called again
|
||||
if (sender is ComprehensiveMissileSimulator sim) // C# 7.0 pattern matching
|
||||
{
|
||||
sim.SimulationEnded -= (s, args) => simulationEndedEvent.Set(); // Attempt to unsubscribe, exact lambda match is tricky
|
||||
}
|
||||
};
|
||||
|
||||
var simulationThread = new Thread(simulator.Start);
|
||||
simulationThread.Start();
|
||||
|
||||
Console.WriteLine("仿真已开始运行。在主菜单输入 '0' 可在下次返回主菜单时退出程序。");
|
||||
Console.WriteLine("仿真过程中,您可以随时按 Enter 键尝试提前中止当前仿真实例并返回主菜单。");
|
||||
|
||||
bool simulationForceStopped = false;
|
||||
while (!simulationEndedEvent.WaitOne(100)) // Check every 100ms if simulation ended naturally
|
||||
{
|
||||
if (Console.KeyAvailable)
|
||||
{
|
||||
// Read the key, but don't wait if it was just a check.
|
||||
// We want to allow Enter to break, not necessarily other typed commands during active sim.
|
||||
// A simple Console.ReadLine() here would block until Enter.
|
||||
// If user presses Enter, ReadLine will return empty or the character if it was typed fast enough.
|
||||
var keyInfo = Console.ReadKey(intercept: true); // Intercept to prevent display
|
||||
if (keyInfo.Key == ConsoleKey.Enter)
|
||||
{
|
||||
Console.WriteLine("\n用户请求中止当前仿真实例...");
|
||||
simulator.Stop(); // Request simulator to stop
|
||||
simulationForceStopped = true;
|
||||
break; // Exit the wait loop
|
||||
}
|
||||
// If other keys are pressed, we can choose to ignore them or buffer them for a potential command parser later.
|
||||
// For now, only Enter is an active interrupt.
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the simulation thread to actually finish, especially if force stopped.
|
||||
simulationThread.Join();
|
||||
|
||||
if (simulationForceStopped)
|
||||
{
|
||||
Console.WriteLine("当前仿真实例已被用户中止。");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("当前导弹仿真自然结束。");
|
||||
}
|
||||
|
||||
Console.WriteLine("按任意键返回主菜单...");
|
||||
Console.ReadKey(); // Wait for user to acknowledge before returning to main menu
|
||||
}
|
||||
|
||||
static void SelectMissile(ComprehensiveMissileSimulator simulator)
|
||||
{
|
||||
var missiles = new[]
|
||||
{
|
||||
@ -115,100 +207,146 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
|
||||
while (true)
|
||||
{
|
||||
Console.WriteLine("\n第一步:请选择导弹类型:");
|
||||
Console.WriteLine("\n--- 选择导弹类型 ---");
|
||||
for (int i = 0; i < missiles.Length; i++)
|
||||
{
|
||||
Console.WriteLine($" {i + 1}. {missiles[i].Item2}");
|
||||
}
|
||||
Console.WriteLine(" exit. 退出程序");
|
||||
Console.WriteLine(" 0. 返回主菜单");
|
||||
Console.Write("请选择: ");
|
||||
|
||||
var input = Console.ReadLine()?.ToLower();
|
||||
if (input == "exit")
|
||||
return false;
|
||||
string input = Console.ReadLine()?.ToLower() ?? string.Empty;
|
||||
if (input == "0")
|
||||
return;
|
||||
|
||||
if (int.TryParse(input, out int choice) &&
|
||||
choice >= 1 && choice <= missiles.Length)
|
||||
{
|
||||
simulator.SelectMissile(missiles[choice - 1].Item1);
|
||||
return true;
|
||||
Console.WriteLine($"已选择: {simulator.SelectedMissileDisplayName}");
|
||||
return;
|
||||
}
|
||||
Console.WriteLine("无效选择,请重试");
|
||||
Console.WriteLine("无效选择,请重试。");
|
||||
}
|
||||
}
|
||||
|
||||
static bool ConfigureSensors(ComprehensiveMissileSimulator simulator)
|
||||
static void ConfigureSensors(ComprehensiveMissileSimulator simulator)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Console.WriteLine("\n第二步:配置传感器和指示器");
|
||||
Console.WriteLine("\n--- 配置传感器和指示器 ---");
|
||||
Console.WriteLine("当前传感器状态:");
|
||||
var indicators = simulator.GetActiveIndicators();
|
||||
for (int i = 0; i < indicators.Length; i++)
|
||||
if (indicators.Length == 0)
|
||||
{
|
||||
Console.WriteLine($" {i + 1}. {indicators[i].Name} [{(indicators[i].IsActive ? "激活" : "未激活")}]");
|
||||
Console.WriteLine("当前导弹类型没有可配置的独立传感器/指示器,或未实现获取接口。");
|
||||
}
|
||||
Console.WriteLine(" 0. 继续下一步");
|
||||
Console.WriteLine(" exit. 退出程序");
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < indicators.Length; i++)
|
||||
{
|
||||
Console.WriteLine($" {i + 1}. {indicators[i].Name} [{(indicators[i].IsActive ? "激活" : "未激活")}]");
|
||||
}
|
||||
}
|
||||
Console.WriteLine(" 0. 返回主菜单");
|
||||
Console.Write("请选择切换状态的传感器,或返回: ");
|
||||
|
||||
var input = Console.ReadLine()?.ToLower();
|
||||
if (input == "exit")
|
||||
return false;
|
||||
string input = Console.ReadLine()?.ToLower() ?? string.Empty;
|
||||
if (input == "0")
|
||||
return;
|
||||
|
||||
if (int.TryParse(input, out int choice))
|
||||
{
|
||||
if (choice == 0) return true;
|
||||
if (choice >= 1 && choice <= indicators.Length)
|
||||
{
|
||||
simulator.ToggleIndicator(indicators[choice - 1].Id);
|
||||
continue;
|
||||
// Loop continues to show updated status
|
||||
return; // Return to main menu after toggling sensor
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("无效选择,请重试。");
|
||||
}
|
||||
}
|
||||
Console.WriteLine("无效选择,请重试");
|
||||
else
|
||||
{
|
||||
Console.WriteLine("无效输入,请输入数字。");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool ConfigureJamming(ComprehensiveMissileSimulator simulator)
|
||||
static void ConfigureJamming(ComprehensiveMissileSimulator simulator)
|
||||
{
|
||||
var availableJammingOptions = simulator.GetAvailableJammingOptions();
|
||||
var currentlyActiveJammingsFromSimulator = simulator.GetCurrentlyActiveJammings();
|
||||
var jammingStatus = new bool[availableJammingOptions.Length];
|
||||
|
||||
for (int i = 0; i < availableJammingOptions.Length; i++)
|
||||
{
|
||||
var currentOptionForLoop = availableJammingOptions[i]; // Renamed to avoid conflict
|
||||
if (currentlyActiveJammingsFromSimulator.Any(activeJam => activeJam.JammerId == currentOptionForLoop.JammerId && activeJam.Type == currentOptionForLoop.Type))
|
||||
{
|
||||
jammingStatus[i] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
jammingStatus[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
Console.WriteLine("\n第三步:配置干扰方式");
|
||||
Console.WriteLine("\n--- 配置干扰方式 ---");
|
||||
Console.WriteLine($"当前导弹: {simulator.SelectedMissileDisplayName}");
|
||||
Console.WriteLine("可用干扰方式:");
|
||||
|
||||
for (int i = 0; i < availableJammingOptions.Length; i++)
|
||||
if (availableJammingOptions.Length == 0)
|
||||
{
|
||||
var option = availableJammingOptions[i];
|
||||
Console.WriteLine($" {i + 1}. {option.DisplayName} [{(jammingStatus[i] ? "激活" : "未激活")}] " +
|
||||
$"(干扰模式: {option.Mode}, 作用对象: {option.Target})");
|
||||
Console.WriteLine("当前导弹类型没有可配置的干扰选项。");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("可用干扰方式:");
|
||||
for (int i = 0; i < availableJammingOptions.Length; i++)
|
||||
{
|
||||
var option = availableJammingOptions[i];
|
||||
// To get actual status, you'd query simulator: e.g., simulator.IsJammerActive(option.JammerId)
|
||||
// For now, we use local `jammingStatus` which is temporary for this menu session.
|
||||
Console.WriteLine($" {i + 1}. {option.DisplayName} [{(jammingStatus[i] ? "激活" : "未激活")}] " +
|
||||
$"(干扰模式: {option.Mode}, 作用对象: {option.Target})");
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine(" 0. 开始仿真");
|
||||
Console.WriteLine(" exit. 退出程序");
|
||||
Console.WriteLine(" 0. 返回主菜单");
|
||||
Console.Write("请选择切换状态的干扰项,或返回: ");
|
||||
|
||||
var input = Console.ReadLine()?.ToLower();
|
||||
if (input == "exit")
|
||||
return false;
|
||||
string input = Console.ReadLine()?.ToLower() ?? string.Empty;
|
||||
if (input == "0")
|
||||
return;
|
||||
|
||||
if (int.TryParse(input, out int choice))
|
||||
{
|
||||
if (choice == 0) return true;
|
||||
if (choice >= 1 && choice <= availableJammingOptions.Length)
|
||||
{
|
||||
var option = availableJammingOptions[choice - 1];
|
||||
jammingStatus[choice - 1] = !jammingStatus[choice - 1];
|
||||
jammingStatus[choice - 1] = !jammingStatus[choice - 1]; // Toggle local status for display
|
||||
|
||||
if (jammingStatus[choice - 1])
|
||||
simulator.ApplyJamming(option.Type, option.DisplayName, option.JammerId, option.Mode, option.Target);
|
||||
else
|
||||
simulator.ClearJamming(option.Type, option.DisplayName, option.JammerId);
|
||||
|
||||
continue;
|
||||
// Loop continues
|
||||
return; // Return to main menu after applying/clearing jamming
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("无效选择,请重试。");
|
||||
}
|
||||
}
|
||||
Console.WriteLine("无效选择,请重试");
|
||||
else
|
||||
{
|
||||
Console.WriteLine("无效输入,请输入数字。");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user