ThreatSourceLibaray/tools/ComprehensiveMissileSimulator.cs

1551 lines
62 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

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

using ThreatSource.Missile;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Jammable;
using ThreatSource.Jammer;
using ThreatSource.Equipment;
using ThreatSource.Indicator;
using ThreatSource.Data;
using System.Diagnostics;
namespace ThreatSource.Tools.MissileSimulation
{
/// <summary>
/// 坦克移动模式枚举
/// </summary>
public enum TankMovementMode
{
/// <summary>静止模式:位置(0,1.2,0)速度0</summary>
Stationary = 0,
/// <summary>超低速模式速度1m/s</summary>
VeryLowSpeed = 1,
/// <summary>低速模式速度5m/s</summary>
LowSpeed = 5,
/// <summary>中速模式速度10m/s</summary>
MediumSpeed = 10,
/// <summary>高速模式速度20m/s</summary>
HighSpeed = 20
}
/// <summary>
/// 综合导弹模拟器 - 支持6种不同类型的导弹模拟
/// </summary>
public class ComprehensiveMissileSimulator
{
// 定义仿真结束事件
public event EventHandler? SimulationEnded;
private ConsoleTraceListener consoleListener;
private readonly EventTypeFilter logLevelFilter;
private readonly SimulationManager simulationManager;
private readonly ThreatSourceFactory _threatSourceFactory;
private readonly ThreatSourceDataManager _dataManager;
private readonly Dictionary<string, BaseMissile> missiles;
private readonly Dictionary<string, SimulationElement> targets;
private readonly Dictionary<string, SimulationElement> indicators;
private readonly Dictionary<string, BaseJammer> jammers;
private readonly Dictionary<string, bool> missileActiveStatus;
public double TimeStep { get; set; } = 0.02; // 时间步长,单位:秒,默认为低精度
// 导弹-干扰映射表
private Dictionary<string, List<(JammingType Type, string DisplayName, string JammerId, string Mode, string Target)>> missileJammingMap;
// 当前选中的导弹ID
public string SelectedMissileId { get; private set; }
// 当前坦克移动模式
public TankMovementMode CurrentTankMovementMode { get; private set; } = TankMovementMode.Stationary;
private List<(JammingType Type, string DisplayName, string JammerId, string Mode, string Target)> activeJammings;
/// <summary>
/// 获取当前选中导弹的显示名称
/// </summary>
public string SelectedMissileDisplayName
{
get
{
return SelectedMissileId switch
{
"LSGM_1" => "激光半主动制导导弹",
"LBRM_1" => "激光驾束制导导弹",
"TSM_1" => "末敏子弹药",
"ICGM_1" => "红外指令制导导弹",
"ITGM_1" => "红外成像末制导导弹",
"MMWG_1" => "毫米波末制导导弹",
"CGGM_1" => "毫米波/红外复合制导导弹",
"CGGM_2" => "激光/红外复合制导导弹",
_ => "未知导弹",
};
}
}
/// <summary>
/// 初始化综合导弹模拟器
/// </summary>
public ComprehensiveMissileSimulator()
{
// 首先初始化过滤器和监听器
logLevelFilter = new EventTypeFilter(SourceLevels.Verbose); // 默认设置为Verbose
consoleListener = new ConsoleTraceListener
{
Filter = logLevelFilter
};
// 清除任何现有的ConsoleTraceListeners并添加我们的控制实例
for (int i = Trace.Listeners.Count - 1; i >= 0; i--)
{
if (Trace.Listeners[i] is ConsoleTraceListener)
{
Trace.Listeners.RemoveAt(i);
}
}
Trace.Listeners.Add(consoleListener);
simulationManager = new SimulationManager();
_dataManager = new ThreatSourceDataManager("../ThreatSource/data");
_threatSourceFactory = new ThreatSourceFactory(_dataManager, simulationManager);
missiles = [];
targets = [];
indicators = [];
jammers = [];
missileActiveStatus = [];
missileJammingMap = [];
SelectedMissileId = "";
activeJammings = [];
// 初始化导弹-干扰映射
InitializeMissileJammingMap();
}
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>
/// 初始化导弹-干扰映射关系
/// </summary>
private void InitializeMissileJammingMap()
{
missileJammingMap = new Dictionary<string, List<(JammingType, string, string, string, string)>>
{
// 激光驾束导弹
["LBRM_1"] =
[
(JammingType.Laser, "激光干扰", "LaserJammer_Designator", "阻塞", "驾束仪"),
(JammingType.SmokeGrenade, "烟幕弹", "SG_1", "遮蔽", "驾束仪")
],
// 激光半主动制导导弹
["LSGM_1"] =
[
(JammingType.Laser, "激光干扰(指示器)", "LaserJammer_Designator", "阻塞", "指示器"),
(JammingType.Laser, "激光干扰(导弹)", "LaserJammer_Missile", "阻塞", "导弹"),
(JammingType.LaserDecoy, "激光诱偏目标", "LDY_1", "欺骗", "导弹"),
(JammingType.SmokeGrenade, "烟幕弹", "SG_1", "遮蔽", "两者")
],
// 红外指令制导导弹
["ICGM_1"] =
[
(JammingType.Infrared, "红外干扰", "InfraredJammer_Designator", "阻塞", "指示器"),
(JammingType.SmokeGrenade, "烟幕弹", "SG_2", "遮蔽", "指示器")
],
// 红外成像末制导导弹
["ITGM_1"] =
[
(JammingType.Infrared, "红外干扰", "InfraredJammer_Missile", "阻塞", "导弹"),
(JammingType.SmokeGrenade, "红外烟幕弹", "SG_2", "遮蔽", "导弹")
],
// 毫米波末制导导弹
["MMWG_1"] =
[
(JammingType.MillimeterWave, "毫米波干扰", "MillimeterWaveJammer_Missile", "阻塞", "导弹"),
(JammingType.SmokeGrenade, "烟幕弹", "SG_3", "遮蔽", "导弹")
],
// 末敏子弹药
["TSM_1"] =
[
(JammingType.Laser, "激光干扰", "LaserJammer_Submunition", "阻塞", "子弹药"),
(JammingType.Infrared, "红外干扰", "InfraredJammer_Submunition", "阻塞", "子弹药"),
(JammingType.MillimeterWave, "毫米波干扰", "MillimeterWaveJammer_Submunition", "阻塞", "子弹药"),
(JammingType.MillimeterWave, "毫米波假信号", "MillimeterWaveCompensationJammer_Submunition", "欺骗", "子弹药"),
(JammingType.SmokeGrenade, "烟幕弹", "SG_4", "遮蔽", "子弹药")
],
// 复合制导导弹
["CGGM_1"] =
[
(JammingType.MillimeterWave, "毫米波干扰", "MillimeterWaveJammer_Missile", "阻塞", "导弹"),
(JammingType.Infrared, "红外干扰", "InfraredJammer_Missile", "阻塞", "导弹"),
(JammingType.SmokeGrenade, "烟幕弹", "SG_1", "遮蔽", "导弹")
],
// 激光/红外复合制导导弹
["CGGM_2"] =
[
(JammingType.Laser, "激光干扰", "LaserJammer_Missile", "阻塞", "导弹"),
(JammingType.Infrared, "红外干扰", "InfraredJammer_Missile", "阻塞", "导弹"),
(JammingType.SmokeGrenade, "烟幕弹", "SG_1", "遮蔽", "导弹")
]
};
}
/// <summary>
/// 添加天气
/// </summary>
private void AddWeathers()
{
// 创建晴天天气并设置为当前天气
var sunnyWeather = _threatSourceFactory.CreateWeather("sunny");
simulationManager.SetWeather(sunnyWeather);
Console.WriteLine("已添加并设置晴天天气环境");
}
/// <summary>
/// 添加目标
/// </summary>
private void AddTankTarget()
{
double speed = (double)CurrentTankMovementMode;
var motionParameters = new KinematicState
{
Position = new Vector3D(0, 1.2, 0),
Orientation = speed > 0 ? new Orientation(0.0, 0.0, 0.0) : new Orientation(0.0, 0.0, 0.0), // 朝向Z轴正方向
Speed = speed
};
// 如果是移动模式,设置速度矢量
if (speed > 0)
{
motionParameters.Velocity = new Vector3D(0, 0, speed); // Z轴正方向运动
}
string targetId = "Tank_1";
var target = _threatSourceFactory.CreateEquipment(targetId, "mbt_001", motionParameters);
targets[targetId] = target;
simulationManager.RegisterEntity(targetId, target);
target.Activate(); // 激活目标
Console.WriteLine($"添加目标 {targetId},位置:{motionParameters.Position}");
Console.WriteLine($"移动模式:{GetMovementModeDisplayName(CurrentTankMovementMode)}");
Console.WriteLine($"目标创建后实际位置:{target.KState.Position},速度:{target.KState.Speed} m/s");
}
/// <summary>
/// 添加激光半主动制导导弹
/// </summary>
private void AddLaserSemiActiveMissile()
{
var motionParameters = new KinematicState
{
Position = new Vector3D(5000, 1, 10),
Orientation = new Orientation(Math.PI/2, Math.PI/20, 0),
Speed = 700
};
string missileId = "LSGM_1";
var missile = _threatSourceFactory.CreateMissile(missileId, "lsgm_001", "Tank_1", motionParameters);
missiles[missileId] = missile;
simulationManager.RegisterEntity(missileId, missile);
Console.WriteLine($"注册激光半主动制导导弹 {missileId},初始位置:{motionParameters.Position}");
}
/// <summary>
/// 添加激光驾束制导导弹
/// </summary>
private void AddLaserBeamRiderMissile()
{
var motionParameters = new KinematicState
{
Position = new Vector3D(2000, 1, 10),
Orientation = new Orientation(Math.PI/2, 0.04, 0.0),
Speed = 10
};
string missileId = "LBRM_1";
var missile = _threatSourceFactory.CreateMissile(missileId, "hj10", "Tank_1", motionParameters);
missiles[missileId] = missile;
simulationManager.RegisterEntity(missileId, missile);
Console.WriteLine($"注册激光驾束制导导弹 {missileId},初始位置:{motionParameters.Position}");
}
/// <summary>
/// 添加末敏弹
/// </summary>
private void AddTerminalSensitiveMissile()
{
var motionParameters = new KinematicState
{
Position = new Vector3D(3000, 1, 20),
Orientation = new Orientation(Math.PI/2, 0.0, 0.0),
Speed = 950
};
string missileId = "TSM_1";
var missile = _threatSourceFactory.CreateMissile(missileId, "tsm_001", "Tank_1", motionParameters);
missiles[missileId] = missile;
simulationManager.RegisterEntity(missileId, missile);
Console.WriteLine($"注册末敏弹 {missileId},初始位置:{motionParameters.Position}");
}
/// <summary>
/// 添加红外指令制导导弹
/// </summary>
private void AddInfraredCommandMissile()
{
var motionParameters = new KinematicState
{
Position = new Vector3D(2000, 1, 20),
Orientation = new Orientation(Math.PI/2, 0.05, 0),
Speed = 10
};
string missileId = "ICGM_1";
var missile = _threatSourceFactory.CreateMissile(missileId, "irc_001", "Tank_1", motionParameters);
missiles[missileId] = missile;
simulationManager.RegisterEntity(missileId, missile);
Console.WriteLine($"注册红外指令制导导弹 {missileId},初始位置:{motionParameters.Position}");
}
/// <summary>
/// 添加红外成像末制导导弹
/// </summary>
private void AddInfraredImagingMissile()
{
var motionParameters = new KinematicState
{
Position = new Vector3D(2000, 1, 0),
Orientation = new Orientation(Math.PI/2, Math.PI/15, 0),
Speed = 10
};
string missileId = "ITGM_1";
var missile = _threatSourceFactory.CreateMissile(missileId, "itg_001", "Tank_1", motionParameters);
missiles[missileId] = missile;
simulationManager.RegisterEntity(missileId, missile);
Console.WriteLine($"注册红外成像末制导导弹 {missileId},初始位置:{motionParameters.Position}");
}
/// <summary>
/// 添加毫米波末制导导弹
/// </summary>
private void AddMillimeterWaveMissile()
{
var motionParameters = new KinematicState
{
Position = new Vector3D(2000, 1, 20),
Orientation = new Orientation(Math.PI/2, 0.05, 0),
Speed = 10
};
string missileId = "MMWG_1";
var missile = _threatSourceFactory.CreateMissile(missileId, "mmw_001", "Tank_1", motionParameters);
missiles[missileId] = missile;
simulationManager.RegisterEntity(missileId, missile);
Console.WriteLine($"注册毫米波末制导导弹 {missileId},初始位置:{motionParameters.Position}");
}
/// <summary>
/// 添加复合制导导弹
/// </summary>
private void AddCompositeGuidanceMissile()
{
string missileId = "CGGM_1";
var motionParameters = new KinematicState
{
Position = new Vector3D(2000, 1, 20),
Orientation = new Orientation(Math.PI/2, 0.05, 0),
Speed = 10
};
var missile = _threatSourceFactory.CreateMissile(missileId, "cg_001", "Tank_1", motionParameters);
missiles[missileId] = missile;
simulationManager.RegisterEntity(missileId, missile);
Console.WriteLine($"注册毫米波/红外复合制导导弹 {missileId},初始位置:{motionParameters.Position}");
missileId = "CGGM_2";
motionParameters = new KinematicState
{
Position = new Vector3D(2000, 1, 20),
Orientation = new Orientation(Math.PI/2, 0.05, 0),
Speed = 10
};
missile = _threatSourceFactory.CreateMissile(missileId, "cg_002", "Tank_1", motionParameters);
missiles[missileId] = missile;
simulationManager.RegisterEntity(missileId, missile);
Console.WriteLine($"注册激光/红外复合制导导弹 {missileId},初始位置:{motionParameters.Position}");
}
/// <summary>
/// 添加传感器和指示器
/// </summary>
private void AddIndicators()
{
// 添加激光目标指示器
string laserDesignatorId = "LD_1";
var laserDesignatorLaunchParams = new KinematicState
{
Position = new Vector3D(4000, 1, 100),
Orientation = new Orientation(Math.PI/2, 0.01, 0),
Speed = 0
};
var laserDesignator = _threatSourceFactory.CreateIndicator(laserDesignatorId, "ld_001", "Tank_1", "LSGM_1", laserDesignatorLaunchParams);
indicators[laserDesignatorId] = laserDesignator;
simulationManager.RegisterEntity(laserDesignatorId, laserDesignator);
Console.WriteLine($"注册激光目标指示器 {laserDesignatorId}");
// 添加激光驾束仪
string laserBeamRiderId = "LBR_1";
var laserBeamRiderLaunchParams = new KinematicState
{
Position = new Vector3D(2100, 1, 10),
Orientation = new Orientation(Math.PI/2, 0, 0),
Speed = 0
};
var laserBeamRider = _threatSourceFactory.CreateIndicator(laserBeamRiderId, "br_001", "Tank_1", "LBRM_1", laserBeamRiderLaunchParams);
indicators[laserBeamRiderId] = laserBeamRider;
simulationManager.RegisterEntity(laserBeamRiderId, laserBeamRider);
Console.WriteLine($"注册激光驾束仪 {laserBeamRiderId}");
// 添加红外测角仪
string infraredTrackerId = "IT_1";
var infraredTrackerLaunchParams = new KinematicState
{
Position = new Vector3D(2100, 1, 0),
Orientation = new Orientation(Math.PI/2, 0, 0),
Speed = 0
};
var infraredTracker = _threatSourceFactory.CreateIndicator(infraredTrackerId, "ir_001", "Tank_1", "ICGM_1", infraredTrackerLaunchParams);
indicators[infraredTrackerId] = infraredTracker;
simulationManager.RegisterEntity(infraredTrackerId, infraredTracker);
Console.WriteLine($"注册红外测角仪 {infraredTrackerId}");
}
/// <summary>
/// 计算朝向实体的方向
/// </summary>
private Orientation CalculateOrientationToEntity(SimulationElement target)
{
// 使用CalculateDirectionToTarget获取归一化方向向量
Vector3D direction = target.KState.Position - new Vector3D(0, 0, 0);
// 创建朝向目标的方向
return Orientation.FromVector(direction.Normalize());
}
/// <summary>
/// 选择导弹
/// </summary>
/// <param name="missileId">导弹ID</param>
public void SelectMissile(string missileId)
{
Console.WriteLine($"=== 选择导弹: {missileId} ===");
// 新架构:完全销毁所有现有实体
DestroyAllEntities();
// 重新创建选中的导弹及其相关实体
CreateMissileAndRelatedEntities(missileId);
Console.WriteLine($"=== 导弹选择完成: {missileId} ===");
}
/// <summary>
/// 激活与导弹相关的传感器、指示器、干扰器
/// </summary>
private void ActivateRelatedIndicators(string missileId)
{
// 根据导弹类型激活相应的传感器
switch (missileId)
{
case "LSGM_1": // 激光半主动制导导弹
if (indicators.TryGetValue("LD_1", out SimulationElement? value1))
{
value1.Activate();
}
Console.WriteLine($"干扰器数量 {jammers.Count}");
break;
case "LBRM_1": // 激光驾束制导导弹
if (indicators.TryGetValue("LBR_1", out SimulationElement? value2))
{
value2.Activate();
}
break;
case "ICGM_1": // 红外指令制导导弹
if (indicators.TryGetValue("IT_1", out SimulationElement? value3))
{
value3.Activate();
}
break;
case "CGGM_2": // 激光/红外复合制导导弹
if (indicators.TryGetValue("LD_1", out SimulationElement? value4))
{
value4.Activate();
}
break;
}
}
/// <summary>
/// 获取当前选中导弹可用的干扰选项
/// </summary>
public (JammingType Type, string DisplayName, string JammerId, string Mode, string Target)[] GetAvailableJammingOptions()
{
if (string.IsNullOrEmpty(SelectedMissileId) || !missileJammingMap.ContainsKey(SelectedMissileId))
{
return [];
}
return missileJammingMap[SelectedMissileId].ToArray();
}
/// <summary>
/// 应用干扰
/// </summary>
public void ApplyJamming(JammingType type, string displayName, string jammerId, string mode, string target)
{
// 检查并激活干扰器
if (jammers.ContainsKey(jammerId))
{
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 (!activeJammings.Any(j => j.JammerId == jammerId && j.Type == type)) // Simple check to avoid duplicates
{
activeJammings.Add(jammingTuple);
}
}
else
{
Console.WriteLine($"警告:找不到干扰器 {jammerId}...");
PrintAllJammers();
}
// 根据干扰目标对象应用干扰
ApplyJammingToTargets(type, displayName, mode, target);
}
/// <summary>
/// 打印所有注册的干扰器信息
/// </summary>
private void PrintAllJammers()
{
Console.WriteLine("\n所有注册的干扰器");
if (jammers.Count == 0)
{
Console.WriteLine("没有任何干扰器被注册!");
return;
}
foreach (var jammer in jammers)
{
Console.WriteLine($"- {jammer.Key}: 类型={jammer.Value.GetType().Name}, 激活状态={jammer.Value.IsActive}");
if (jammer.Value.IsActive)
{
Console.WriteLine($" 状态: {jammer.Value.GetStatus()}");
}
}
}
/// <summary>
/// 根据目标类型应用干扰
/// </summary>
private void ApplyJammingToTargets(JammingType type, string displayName, string mode, string target)
{
// 根据target决定干扰作用对象
switch (target.ToLower())
{
case "指示器":
ApplyJammingToIndicators(type, mode);
break;
case "导弹":
ApplyJammingToMissiles(type, mode);
break;
case "两者":
ApplyJammingToIndicators(type, mode);
ApplyJammingToMissiles(type, mode);
break;
case "子弹药":
ApplyJammingToMissiles(type, mode);
break;
}
}
/// <summary>
/// 应用干扰到指示器
/// </summary>
private void ApplyJammingToIndicators(JammingType type, string mode)
{
foreach (var indicator in indicators.Values.Where(i => i.IsActive))
{
Console.WriteLine($"应用{mode}干扰到指示器 {indicator.Id}");
try
{
// 根据干扰类型选择合适的干扰器ID
string jammerId = string.Empty;
switch (type)
{
case JammingType.Laser:
jammerId = "LaserJammer_Designator";
break;
case JammingType.Infrared:
jammerId = "InfraredJammer_Designator";
break;
case JammingType.MillimeterWave:
jammerId = "MillimeterWaveJammer_Missile"; // 假设这个也可以用于指示器
break;
case JammingType.SmokeGrenade:
if (indicator.Id.Contains("LD"))
jammerId = "SG_1"; // 激光烟幕
else if (indicator.Id.Contains("IR"))
jammerId = "SG_2"; // 红外烟幕
else
jammerId = "SG_3"; // 默认烟幕
break;
case JammingType.LaserDecoy:
jammerId = "LDY_1";
break;
}
if (!string.IsNullOrEmpty(jammerId) && jammers.ContainsKey(jammerId))
{
var jammer = jammers[jammerId];
// 创建干扰参数
JammingParameters jammingParams = new JammingParameters
{
Type = type,
Mode = mode.Equals("阻塞") ? JammingMode.Blocking :
mode.Equals("欺骗") ? JammingMode.Deception :
mode.Equals("噪声") ? JammingMode.Noise : JammingMode.Blocking,
JammerId = jammerId,
SourceId = jammer.Id,
Power = 800, // 设置合适功率
Direction = CalculateDirectionToTarget(jammer.KState.Position, indicator.KState.Position),
SourcePosition = jammer.KState.Position,
StartTime = DateTime.UtcNow,
Duration = 600 // 10分钟
};
// 找到指示器的实际实现类
if (indicator is IJammable jammableIndicator)
{
// 调用IJammable接口的ApplyJamming方法
jammableIndicator.ApplyJamming(jammingParams);
Console.WriteLine($"成功应用干扰到指示器 {indicator.Id},干扰源: {jammerId}");
}
else
{
Console.WriteLine($"警告: 指示器 {indicator.Id} 不支持IJammable接口");
}
}
else
{
Console.WriteLine($"警告: 找不到合适的干扰器ID: {jammerId}");
}
}
catch (Exception ex)
{
Console.WriteLine($"对指示器 {indicator.Id} 应用干扰时出错: {ex.Message}");
}
}
}
/// <summary>
/// 应用干扰到导弹
/// </summary>
private void ApplyJammingToMissiles(JammingType type, string mode)
{
foreach (var missile in missiles.Values.Where(m => m.IsActive))
{
Console.WriteLine($"应用{mode}干扰到导弹 {missile.Id}");
try
{
// 根据干扰类型和导弹类型选择合适的干扰器ID
string jammerId = string.Empty;
switch (type)
{
case JammingType.Laser:
jammerId = "LaserJammer_Missile";
break;
case JammingType.Infrared:
jammerId = "InfraredJammer_Missile";
break;
case JammingType.MillimeterWave:
if (missile.Id.Contains("TSM"))
jammerId = "MillimeterWaveJammer_Submunition"; // 针对子弹药
else
jammerId = "MillimeterWaveJammer_Missile";
break;
case JammingType.SmokeGrenade:
if (missile.Id.Contains("ITGM") || missile.Id.Contains("ICGM"))
jammerId = "SG_2"; // 红外烟幕用于红外导弹
else if (missile.Id.Contains("TSM"))
jammerId = "SG_3"; // 顶部烟幕用于子弹药
else
jammerId = "SG_1"; // 默认烟幕
break;
case JammingType.LaserDecoy:
jammerId = "LDY_1";
break;
}
if (!string.IsNullOrEmpty(jammerId) && jammers.ContainsKey(jammerId))
{
var jammer = jammers[jammerId];
// 创建干扰参数
JammingParameters jammingParams = new JammingParameters
{
Type = type,
Mode = mode.Equals("阻塞") ? JammingMode.Blocking :
mode.Equals("欺骗") ? JammingMode.Deception :
mode.Equals("噪声") ? JammingMode.Noise : JammingMode.Blocking,
JammerId = jammerId,
SourceId = jammer.Id,
Power = 1000, // 设置高功率
Direction = CalculateDirectionToTarget(jammer.KState.Position, missile.KState.Position),
SourcePosition = jammer.KState.Position,
StartTime = DateTime.UtcNow,
Duration = 600 // 10分钟
};
// 判断导弹是否实现了IJammable接口
if (missile is IJammable jammableMissile)
{
// 调用IJammable接口的ApplyJamming方法
jammableMissile.ApplyJamming(jammingParams);
Console.WriteLine($"成功应用干扰到导弹 {missile.Id},干扰源: {jammerId}");
}
else
{
Console.WriteLine($"警告: 导弹 {missile.Id} 不支持IJammable接口");
}
}
else
{
Console.WriteLine($"警告: 找不到合适的干扰器ID: {jammerId}");
}
}
catch (Exception ex)
{
Console.WriteLine($"对导弹 {missile.Id} 应用干扰时出错: {ex.Message}");
}
}
}
/// <summary>
/// 计算从源位置到目标位置的方向向量
/// </summary>
private Vector3D CalculateDirectionToTarget(Vector3D sourcePosition, Vector3D targetPosition)
{
Vector3D direction = targetPosition - sourcePosition;
return direction.Normalize();
}
/// <summary>
/// 清除干扰
/// </summary>
public void ClearJamming(JammingType type, string displayName, string jammerId)
{
if (jammers.ContainsKey(jammerId))
{
jammers[jammerId].Deactivate();
Console.WriteLine($"关闭干扰器 {jammerId}: {displayName}");
// Remove from activeJammings list
activeJammings.RemoveAll(j => j.JammerId == jammerId && j.Type == type);
}
}
/// <summary>
/// 应用干扰 (原有方法,保留向后兼容)
/// </summary>
public void ApplyJamming(JammingType type, string category)
{
switch (type)
{
case JammingType.SmokeGrenade:
if (category == "水平烟幕弹")
{
jammers["SG_1"].Activate();
}
else if (category == "红外烟幕弹")
{
jammers["SG_2"].Activate();
}
else if (category == "顶部烟幕弹")
{
jammers["SG_3"].Activate();
}
break;
case JammingType.LaserDecoy:
jammers["LDY_1"].Activate();
break;
}
}
/// <summary>
/// 清除干扰 (原有方法,保留向后兼容)
/// </summary>
public static void ClearJamming(JammingType type, string category)
{
var jammingParams = new JammingParameters
{
Type = type,
Power = 0,
Duration = 0,
Direction = new Vector3D(1, 0, 0),
SourcePosition = new Vector3D(0, 0, 0)
};
}
/// <summary>
/// 开始模拟
/// </summary>
public void Start()
{
Console.WriteLine("开始综合导弹模拟...");
// 使用新架构:销毁重建模式,确保每次都是全新的实体和位置
if (missiles.Count > 0 || targets.Count > 0)
{
Console.WriteLine("检测到现有实体,销毁并重新创建...");
// 保存当前选中的导弹ID和激活的干扰器列表避免在销毁时被清空
string currentSelectedMissileId = SelectedMissileId;
var savedActiveJammings = activeJammings.ToList(); // 保存当前激活的干扰器列表
DestroyAllEntities();
// 重新创建选中的导弹及其相关实体
if (!string.IsNullOrEmpty(currentSelectedMissileId))
{
CreateMissileAndRelatedEntities(currentSelectedMissileId);
// 恢复用户选择的干扰器配置
if (savedActiveJammings.Count > 0)
{
Console.WriteLine($"恢复用户选择的 {savedActiveJammings.Count} 个干扰器配置...");
foreach (var jammingConfig in savedActiveJammings)
{
// 检查干扰器是否已创建
if (jammers.ContainsKey(jammingConfig.JammerId))
{
// 重新应用干扰配置
ApplyJamming(jammingConfig.Type, jammingConfig.DisplayName, jammingConfig.JammerId, jammingConfig.Mode, jammingConfig.Target);
Console.WriteLine($"已激活干扰器: {jammingConfig.DisplayName}");
}
}
}
}
else
{
Console.WriteLine("错误:没有选中的导弹");
return;
}
}
// 打印仿真开始前的组件状态
PrintSimulationRegisteredComponents();
// 启动仿真系统
simulationManager.StartSimulation(TimeStep);
while (simulationManager.State == SimulationState.Running)
{
// 让仿真管理器统一处理所有实体的更新
simulationManager.Update(TimeStep);
// 检查是否还有活跃的导弹
var activeMissiles = simulationManager.GetEntitiesByType<BaseMissile>()
.Where(m => m.IsActive);
if (!activeMissiles.Any())
{
simulationManager.StopSimulation();
SimulationEnded?.Invoke(this, EventArgs.Empty);
Console.WriteLine("仿真结束,所有导弹已完成任务");
break;
}
// 打印状态
PrintSimulationStatus();
Thread.Sleep((int)(TimeStep * 1000));
}
}
/// <summary>
/// 打印当前模拟状态
/// </summary>
private void PrintSimulationStatus()
{
// 获取当前仿真时间
double simulationTime = simulationManager.CurrentTime;
var weather = simulationManager.CurrentWeather;
Console.WriteLine($"\n========== 模拟状态 (时间: {simulationTime:F3}s==========");
// 天气状态
Console.WriteLine("\n--- 天气环境 ---");
if (weather != null)
{
Console.WriteLine($"天气类型: {weather.Type}");
Console.WriteLine($"温度: {weather.Temperature:F1}°C, 湿度: {weather.RelativeHumidity:F1}%");
Console.WriteLine($"风速: {weather.WindSpeed:F1} m/s, 方向: ({weather.WindDirection:F1}°)");
Console.WriteLine($"雨量: {weather.Precipitation:F1} mm");
Console.WriteLine($"能见度: {weather.Visibility:F1} m");
}
// 导弹状态
Console.WriteLine("\n--- 导弹 ---");
var activeMissiles = simulationManager.GetEntitiesByType<BaseMissile>()
.Where(m => m.IsActive)
.ToList();
if (activeMissiles.Any())
{
foreach (var missile in activeMissiles)
{
// 直接调用导弹的GetStatus方法
Console.WriteLine(missile.GetStatus());
}
}
else
{
Console.WriteLine("没有激活的导弹");
}
// 目标状态
Console.WriteLine("\n--- 目标 ---");
var activeTargets = targets.Values.Where(t => t.IsActive).ToList();
if (activeTargets.Any())
{
foreach (var target in activeTargets)
{
// 调用目标的GetStatus方法
Console.WriteLine(target.GetStatus());
}
}
else
{
Console.WriteLine("没有激活的目标");
}
// 传感器状态
Console.WriteLine("\n--- 指示器 ---");
var activeIndicators = indicators.Values.Where(i => i.IsActive).ToList();
if (activeIndicators.Any())
{
foreach (var indicator in activeIndicators)
{
// 调用指示器的GetStatus方法
Console.WriteLine(indicator.GetStatus());
}
}
else
{
Console.WriteLine("没有激活的指示器");
}
// 干扰器状态
Console.WriteLine("\n--- 干扰器 ---");
var activeJammers = jammers.Values.Where(j => j.IsActive).ToList();
if (activeJammers.Any())
{
foreach (var jammer in activeJammers)
{
// 调用干扰器的GetStatus方法
Console.WriteLine(jammer.GetStatus());
// 如果正在干扰,显示更多详细信息
if (jammer.IsJamming)
{
try
{
var runningState = jammer.GetRunningState();
if (runningState.CurrentParameters != null)
{
var jammingParams = runningState.CurrentParameters;
// 计算已干扰时间和剩余时间
var jammingTimeSeconds = (DateTime.UtcNow.Ticks - jammingParams.StartTime.Ticks) / TimeSpan.TicksPerSecond;
Console.WriteLine($"- 已干扰时间: {jammingTimeSeconds:F1} 秒");
if (jammingParams.Duration.HasValue)
{
var remainingTime = jammingParams.Duration.Value - jammingTimeSeconds;
if (remainingTime > 0)
Console.WriteLine($"- 剩余时间: {remainingTime:F1} 秒");
else
Console.WriteLine("- 干扰即将结束");
}
}
}
catch (Exception ex)
{
Console.WriteLine($" 获取干扰器详细状态出错: {ex.Message}");
}
}
}
}
else
{
Console.WriteLine("没有激活的干扰器");
}
Console.WriteLine("\n========================================");
}
/// <summary>
/// 停止模拟
/// </summary>
public void Stop()
{
simulationManager.StopSimulation();
Console.WriteLine("模拟结束");
}
/// <summary>
/// 暂停模拟
/// </summary>
public void Pause()
{
simulationManager.PauseSimulation();
Console.WriteLine("模拟暂停");
}
/// <summary>
/// 恢复模拟
/// </summary>
public void Resume()
{
simulationManager.ResumeSimulation();
Console.WriteLine("模拟恢复");
}
/// <summary>
/// 重置仿真状态
/// </summary>
/// <remarks>
/// 新架构:由于采用销毁重建模式,此方法已简化
/// 主要功能已移至DestroyAllEntities和CreateMissileAndRelatedEntities方法
/// </remarks>
public void ResetSimulation()
{
Console.WriteLine("=== 开始重置仿真状态 ===");
// 停止仿真并清理事件系统
simulationManager.StopSimulation();
simulationManager.ClearAllEvents();
// 重置导弹激活状态
missileActiveStatus.Clear();
// 清理活跃干扰列表
activeJammings.Clear();
Console.WriteLine("=== 仿真状态重置完成 ===");
}
/// <summary>
/// 打印所有注册到仿真管理器中的组件
/// </summary>
public void PrintSimulationRegisteredComponents()
{
Console.WriteLine("\n========== 仿真管理器中的注册组件 ==========");
var allEntities = simulationManager.GetAllEntities();
foreach (var entity in allEntities)
{
if (entity is SimulationElement simElement)
{
Console.WriteLine($"{simElement.Id} ({entity.GetType().Name})");
}
else
{
Console.WriteLine($"未知组件 ({entity.GetType().Name})");
}
}
Console.WriteLine($"总计: {allEntities.Count} 个组件");
}
/// <summary>
/// 获取当前活动的传感器列表
/// </summary>
public (string Id, string Name, bool IsActive)[] GetActiveIndicators()
{
return indicators.Select(s => (
s.Value.Id,
GetIndicatorDisplayName(s.Value),
s.Value.IsActive
)).ToArray();
}
/// <summary>
/// 获取传感器的显示名称
/// </summary>
private string GetIndicatorDisplayName(SimulationElement indicator)
{
return indicator switch
{
LaserDesignator _ => "激光目标指示器",
LaserBeamRider _ => "激光驾束仪",
InfraredTracker _ => "红外测角仪",
_ => indicator.Id
};
}
/// <summary>
/// 切换传感器的激活状态
/// </summary>
public void ToggleIndicator(string indicatorId)
{
if (indicators.TryGetValue(indicatorId, out var indicator))
{
if (indicator.IsActive)
indicator.Deactivate();
else
indicator.Activate();
Console.WriteLine($"指示器 {GetIndicatorDisplayName(indicator)} 已{(indicator.IsActive ? "" : "")}");
}
}
/// <summary>
/// 切换天气
/// </summary>
/// <param name="weatherType">天气类型</param>
public void SwitchWeather(string weatherType)
{
// 创建新的天气实例
var newWeather = _threatSourceFactory.CreateWeather(weatherType);
// 设置为当前天气
simulationManager.SetWeather(newWeather);
// 打印天气详情
Console.WriteLine($"已切换到 {weatherType} 天气环境");
Console.WriteLine($"温度: {newWeather.Temperature}°C");
Console.WriteLine($"湿度: {newWeather.RelativeHumidity}%");
Console.WriteLine($"能见度: {newWeather.Visibility}公里");
Console.WriteLine($"风速: {newWeather.WindSpeed}米/秒");
Console.WriteLine($"风向: {newWeather.WindDirection}°");
}
public string GetActiveJammingDescription()
{
if (activeJammings == null || activeJammings.Count == 0)
{
return "(无干扰)";
}
if (activeJammings.Count == 1)
{
return $"(已激活: {activeJammings.First().DisplayName})";
}
else
{
return $"(已激活: {activeJammings.Count}个干扰器)";
}
}
public List<(JammingType Type, string DisplayName, string JammerId, string Mode, string Target)> GetCurrentlyActiveJammings()
{
// 返回一个新的列表,防止外部修改内部列表
return [.. activeJammings];
}
/// <summary>
/// 设置坦克移动模式
/// </summary>
/// <param name="mode">要设置的移动模式</param>
public void SetTankMovementMode(TankMovementMode mode)
{
CurrentTankMovementMode = mode;
Console.WriteLine($"坦克移动模式已设置为: {GetMovementModeDisplayName(mode)}");
// 如果坦克已经存在,更新其运动参数
if (targets.TryGetValue("Tank_1", out var tank))
{
UpdateTankMovementParameters(tank, mode);
}
}
/// <summary>
/// 获取移动模式的显示名称
/// </summary>
private static string GetMovementModeDisplayName(TankMovementMode mode)
{
return mode switch
{
TankMovementMode.Stationary => "静止, 0 m/s",
TankMovementMode.VeryLowSpeed => "超低速, 1 m/s",
TankMovementMode.LowSpeed => "低速, 5 m/s",
TankMovementMode.MediumSpeed => "中速, 10 m/s",
TankMovementMode.HighSpeed => "高速, 20 m/s",
_ => "未知模式"
};
}
/// <summary>
/// 更新坦克的运动参数
/// </summary>
private void UpdateTankMovementParameters(SimulationElement tank, TankMovementMode mode)
{
double speed = (double)mode;
// 设置运动参数
tank.KState.Speed = speed;
if (speed > 0)
{
// 移动模式设置X轴正方向运动坦克面向运动方向
tank.KState.Orientation = new Orientation(0, 0, 0); // 面向X轴正方向
tank.KState.Velocity = new Vector3D(speed, 0, 0);
}
else
{
// 静止模式:清零速度和方向
tank.KState.Velocity = Vector3D.Zero;
}
Console.WriteLine($"坦克运动参数已更新 - 速度: {speed} m/s, 位置: {tank.KState.Position}");
}
/// <summary>
/// 获取可用的坦克移动模式列表
/// </summary>
/// <returns>包含移动模式和显示名称的数组</returns>
public (TankMovementMode Mode, string DisplayName)[] GetAvailableMovementModes()
{
return new[]
{
(TankMovementMode.Stationary, GetMovementModeDisplayName(TankMovementMode.Stationary)),
(TankMovementMode.VeryLowSpeed, GetMovementModeDisplayName(TankMovementMode.VeryLowSpeed)),
(TankMovementMode.LowSpeed, GetMovementModeDisplayName(TankMovementMode.LowSpeed)),
(TankMovementMode.MediumSpeed, GetMovementModeDisplayName(TankMovementMode.MediumSpeed)),
(TankMovementMode.HighSpeed, GetMovementModeDisplayName(TankMovementMode.HighSpeed))
};
}
/// <summary>
/// 获取当前坦克移动模式信息
/// </summary>
/// <returns>当前移动模式和显示名称</returns>
public (TankMovementMode Mode, string DisplayName) GetCurrentMovementMode()
{
return (CurrentTankMovementMode, GetMovementModeDisplayName(CurrentTankMovementMode));
}
/// <summary>
/// 销毁所有实体并从仿真管理器中注销
/// </summary>
/// <remarks>
/// 新架构:每次仿真结束后完全销毁所有实体,下次选择时重新创建
/// 这样可以避免状态残留问题,确保每次都是全新的实体
/// </remarks>
private void DestroyAllEntities()
{
Console.WriteLine("=== 开始销毁所有实体 ===");
// 停止仿真并清理事件系统
simulationManager.StopSimulation();
simulationManager.ClearAllEvents();
// 获取仿真管理器中所有注册的实体(包括动态生成的末敏弹子弹)
var allEntities = simulationManager.GetAllEntities();
Console.WriteLine($"发现 {allEntities.Count} 个实体需要清理");
// 逐个清理所有实体
foreach (var entity in allEntities)
{
if (entity is SimulationElement simElement)
{
simElement.Deactivate();
simulationManager.UnregisterEntity(simElement.Id);
Console.WriteLine($"销毁实体: {simElement.Id} ({entity.GetType().Name})");
}
else
{
Console.WriteLine($"跳过非SimulationElement实体: {entity.GetType().Name}");
}
}
// 清理本地字典
missiles.Clear();
targets.Clear();
indicators.Clear();
jammers.Clear();
// 清理状态
missileActiveStatus.Clear();
activeJammings.Clear();
SelectedMissileId = "";
Console.WriteLine("=== 所有实体销毁完成 ===");
}
/// <summary>
/// 按需创建特定导弹及其相关实体
/// </summary>
/// <param name="missileId">要创建的导弹ID</param>
/// <remarks>
/// 新架构:每次选择导弹时重新创建所需的实体
/// 包括目标、导弹、指示器、干扰器等
/// </remarks>
private void CreateMissileAndRelatedEntities(string missileId)
{
Console.WriteLine($"=== 开始创建导弹 {missileId} 及相关实体 ===");
// 首先添加天气(如果还没有)
if (simulationManager.CurrentWeather == null)
{
AddWeathers();
}
// 创建目标
AddTankTarget();
// 根据导弹类型创建对应的导弹
switch (missileId)
{
case "LSGM_1":
AddLaserSemiActiveMissile();
break;
case "LBRM_1":
AddLaserBeamRiderMissile();
break;
case "TSM_1":
AddTerminalSensitiveMissile();
break;
case "ICGM_1":
AddInfraredCommandMissile();
break;
case "ITGM_1":
AddInfraredImagingMissile();
break;
case "MMWG_1":
AddMillimeterWaveMissile();
break;
case "CGGM_1":
case "CGGM_2":
AddCompositeGuidanceMissile(); // 这个方法会添加两种复合制导导弹
break;
default:
Console.WriteLine($"未知的导弹类型: {missileId}");
return;
}
// 添加所有指示器、干扰器和烟幕弹
AddIndicators();
// 根据导弹类型添加相应的干扰器
AddJammersForMissile(missileId);
// 激活选中的导弹
if (missiles.TryGetValue(missileId, out var selectedMissile))
{
selectedMissile.Activate();
SelectedMissileId = missileId;
missileActiveStatus[missileId] = true;
Console.WriteLine($"已激活导弹: {missileId}");
// 激活相关指示器
ActivateRelatedIndicators(missileId);
}
Console.WriteLine($"=== 导弹 {missileId} 及相关实体创建完成 ===");
}
private void AddJammersForMissile(string missileId)
{
Console.WriteLine($"为导弹 {missileId} 创建相应的干扰器");
// 利用现有的导弹-干扰器映射
if (missileJammingMap.TryGetValue(missileId, out var jammingList))
{
foreach (var (type, displayName, jammerId, mode, target) in jammingList)
{
CreateJammerById(jammerId, type, target);
}
}
else
{
Console.WriteLine($"未找到导弹 {missileId} 的干扰器映射");
}
}
/// <summary>
/// 根据干扰器ID创建干扰器实体
/// </summary>
private void CreateJammerById(string jammerId, JammingType type, string target)
{
try
{
// 根据干扰器ID确定朝向和位置
Orientation orientation = GetJammerOrientation(jammerId, target);
Vector3D position = GetJammerPosition(jammerId);
var jammerParams = new KinematicState
{
Position = position,
Orientation = orientation,
Speed = 0.0
};
// 根据干扰器ID确定类型配置
string jammerConfig = GetJammerConfig(jammerId);
var jammer = _threatSourceFactory.CreateJammer(jammerId, jammerConfig, jammerParams, "Tank_1");
if (jammer is BaseJammer baseJammer)
{
simulationManager.RegisterEntity(jammerId, jammer);
jammers[jammerId] = baseJammer;
Console.WriteLine($"注册干扰器 {jammerId},位置:{position}");
}
}
catch (Exception ex)
{
Console.WriteLine($"创建干扰器 {jammerId} 时出错: {ex.Message}");
}
}
/// <summary>
/// 根据干扰器ID和目标确定朝向
/// </summary>
private Orientation GetJammerOrientation(string jammerId, string target)
{
// 根据干扰器ID和目标类型确定朝向
return jammerId switch
{
"LaserJammer_Designator" => GetOrientationToRelatedIndicator(), // 朝向与当前导弹相关的指示器
"LaserJammer_Missile" => GetOrientationToCurrentMissile(), // 朝向当前选中的导弹
"InfraredJammer_Designator" => GetOrientationToRelatedIndicator(), // 朝向与当前导弹相关的指示器
"InfraredJammer_Missile" => GetOrientationToCurrentMissile(), // 朝向当前选中的导弹
"MillimeterWaveJammer_Missile" => GetOrientationToCurrentMissile(), // 朝向当前选中的导弹
"LaserJammer_Submunition" or "InfraredJammer_Submunition" or "MillimeterWaveJammer_Submunition" or "MillimeterWaveCompensationJammer_Submunition"
=> new Orientation(0, Math.PI/2, 0), // 垂直向上
_ => new Orientation(0, 0, 0) // 默认朝向
};
}
/// <summary>
/// 获取朝向与当前选中导弹相关的指示器的方向
/// </summary>
private Orientation GetOrientationToRelatedIndicator()
{
// 根据当前选中的导弹确定相关的指示器
string[] relatedIndicatorIds = SelectedMissileId switch
{
"LSGM_1" => ["LD_1"], // 激光半主动导弹 -> 激光指示器
"LBRM_1" => ["LBR_1"], // 激光驾束导弹 -> 激光驾束仪
"ICGM_1" => ["IT_1"], // 红外指令导弹 -> 红外测角仪
"CGGM_2" => ["LD_1"], // 激光/红外复合导弹 -> 激光指示器
_ => ["LD_1", "LBR_1", "IT_1"] // 默认尝试所有指示器
};
return GetOrientationToIndicator(relatedIndicatorIds);
}
/// <summary>
/// 获取朝向当前选中导弹的方向
/// </summary>
private Orientation GetOrientationToCurrentMissile()
{
if (!string.IsNullOrEmpty(SelectedMissileId) && missiles.TryGetValue(SelectedMissileId, out var missile))
{
return CalculateOrientationToEntity(missile);
}
return new Orientation(0, 0, 0); // 默认朝向
}
/// <summary>
/// 获取朝向指示器的方向
/// </summary>
private Orientation GetOrientationToIndicator(params string[] indicatorIds)
{
foreach (var indicatorId in indicatorIds)
{
if (indicators.TryGetValue(indicatorId, out var indicator))
{
return CalculateOrientationToEntity(indicator);
}
}
return new Orientation(0, 0, 0); // 默认朝向
}
/// <summary>
/// 根据干扰器ID确定配置类型
/// </summary>
private string GetJammerConfig(string jammerId)
{
return jammerId switch
{
"LaserJammer_Designator" or "LaserJammer_Missile" => "laser_blocking",
"LaserJammer_Submunition" => "laser_top_blocking",
"InfraredJammer_Designator" or "InfraredJammer_Missile" => "infrared_blocking",
"InfraredJammer_Submunition" => "infrared_top_blocking",
"MillimeterWaveJammer_Missile" or "MillimeterWaveJammer_Submunition" => "mmw_blocking",
"MillimeterWaveCompensationJammer_Submunition" => "mmw_compensation",
"LDY_1" => "laser_decoy",
"SG_1" => "surround",
"SG_2" => "infrared",
"SG_3" => "mmw",
"SG_4" => "top",
_ => "laser_blocking" // 默认配置
};
}
/// <summary>
/// 根据干扰器ID确定初始位置
/// </summary>
private Vector3D GetJammerPosition(string jammerId)
{
return jammerId switch
{
"LDY_1" => new Vector3D(0, 0, 50), // 激光诱偏目标目标后方50米
"SG_1" or "SG_2" or "SG_3" => new Vector3D(50, 5, 0), // 水平烟幕弹侧方50米高5米
"SG_4" => new Vector3D(0, 10, 0), // 顶部烟幕弹正上方10米
_ => new Vector3D(0, 0, 0) // 其他干扰器默认位置
};
}
}
}