增加了导弹的红外和紫外辐射强度属性
This commit is contained in:
parent
b37c5ddec2
commit
17eb9826b5
@ -19,6 +19,7 @@
|
||||
- 增加了SwerlingRCS回波模型
|
||||
- 在毫米波制导中使用SwerlingRCS回波模型获取目标RCS
|
||||
- 增加了扫描周期计时器,用于控制RCS的更新
|
||||
- 增加了导弹的红外和紫外辐射强度属性
|
||||
|
||||
## [1.1.19] - 2025-05-18
|
||||
- 增加了装备的RCS特征矩阵
|
||||
|
||||
388
ThreatSource.Tests/SwerlingRcsModelTests.cs
Normal file
388
ThreatSource.Tests/SwerlingRcsModelTests.cs
Normal file
@ -0,0 +1,388 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Equipment;
|
||||
|
||||
namespace ThreatSource.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public class SwerlingRcsModelTests
|
||||
{
|
||||
private const double DefaultAverageRcs = 10.0; // 默认平均RCS值,单位:平方米
|
||||
private const string TargetId1 = "target_tank_001"; // 测试用目标ID 1
|
||||
private const string TargetId2 = "target_heli_002"; // 测试用目标ID 2
|
||||
private const int TestSeed = 12345; // 测试用随机数种子
|
||||
|
||||
/// <summary>
|
||||
/// 测试:默认构造函数应成功初始化。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void Constructor_DefaultSeed_InitializesSuccessfully()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
SwerlingRcsModel model;
|
||||
|
||||
// 操作 (Act)
|
||||
model = new SwerlingRcsModel();
|
||||
|
||||
// 断言 (Assert)
|
||||
Assert.IsNotNull(model, "使用默认种子构造模型实例不应为null。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试:带特定种子的构造函数应成功初始化。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void Constructor_WithSpecificSeed_InitializesSuccessfully()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
SwerlingRcsModel model;
|
||||
|
||||
// 操作 (Act)
|
||||
model = new SwerlingRcsModel(TestSeed);
|
||||
|
||||
// 断言 (Assert)
|
||||
Assert.IsNotNull(model, "使用特定种子构造模型实例不应为null。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试:当目标是坦克且静止时,其RCS行为应类似Swerling I (慢起伏,使用缓存)。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void GetRealtimeRcs_Tank_Static_BehavesAsSwerlingI()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel(TestSeed);
|
||||
|
||||
// 操作 (Act)
|
||||
// 第一次调用,isNewScanPeriod为false但由于是首次,应采样并缓存
|
||||
double rcs1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
// 第二次调用,isNewScanPeriod为false,应从缓存获取
|
||||
double rcs2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
|
||||
// 断言 (Assert)
|
||||
Assert.AreEqual(rcs1, rcs2, "对于Swerling I模型 (Tank, Static),在同一扫描周期内(isNewScanPeriod=false),RCS值应从缓存读取且保持不变。");
|
||||
Assert.IsTrue(rcs1 > 0, "RCS值应大于0。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试:当目标是直升机且静止时,其RCS行为应类似Swerling II (快起伏,不使用缓存)。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void GetRealtimeRcs_Helicopter_Static_BehavesAsSwerlingII()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel(TestSeed);
|
||||
|
||||
// 操作 (Act)
|
||||
double rcs1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
double rcs2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
|
||||
// 断言 (Assert)
|
||||
// 对于快起伏,即使ID相同,种子固定情况下,连续调用也应基于随机数序列产生可预测的不同值
|
||||
// 注意:这里比较的是"不同",但因为种子固定,这两个值本身是确定的。
|
||||
// 如果需要严格验证"不同",可以比较两者差的绝对值大于某个小量,但更简单的做法是验证它们不相等。
|
||||
Assert.AreNotEqual(rcs1, rcs2, "对于Swerling II模型 (Helicopter, Static),连续调用RCS值理论上应不同(因为是快起伏,每次都重新采样)。");
|
||||
Assert.IsTrue(rcs1 > 0, "第一个RCS值应大于0。");
|
||||
Assert.IsTrue(rcs2 > 0, "第二个RCS值应大于0。");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 测试:当目标是坦克且机动时,其RCS行为应类似Swerling III (慢起伏,使用缓存)。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void GetRealtimeRcs_Tank_Maneuvering_BehavesAsSwerlingIII()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel(TestSeed);
|
||||
|
||||
// 操作 (Act)
|
||||
double rcs1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Maneuvering, DefaultAverageRcs, false);
|
||||
double rcs2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Maneuvering, DefaultAverageRcs, false);
|
||||
|
||||
// 断言 (Assert)
|
||||
Assert.AreEqual(rcs1, rcs2, "对于Swerling III模型 (Tank, Maneuvering),在同一扫描周期内,RCS值应从缓存读取且保持不变。");
|
||||
Assert.IsTrue(rcs1 > 0, "RCS值应大于0。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试:当目标是直升机且机动时,其RCS行为应类似Swerling IV (快起伏,不使用缓存)。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void GetRealtimeRcs_Helicopter_Maneuvering_BehavesAsSwerlingIV()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel(TestSeed);
|
||||
|
||||
// 操作 (Act)
|
||||
double rcs1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Maneuvering, DefaultAverageRcs, false);
|
||||
double rcs2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Maneuvering, DefaultAverageRcs, false);
|
||||
|
||||
// 断言 (Assert)
|
||||
Assert.AreNotEqual(rcs1, rcs2, "对于Swerling IV模型 (Helicopter, Maneuvering),连续调用RCS值应不同。");
|
||||
Assert.IsTrue(rcs1 > 0, "第一个RCS值应大于0。");
|
||||
Assert.IsTrue(rcs2 > 0, "第二个RCS值应大于0。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试:当目标是坦克且匀速运动时,其RCS行为应类似Swerling I (慢起伏,使用缓存)。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void GetRealtimeRcs_Tank_ConstantVelocity_BehavesAsSwerlingI()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel(TestSeed);
|
||||
|
||||
// 操作 (Act)
|
||||
double rcs1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.ConstantVelocity, DefaultAverageRcs, false);
|
||||
double rcs2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.ConstantVelocity, DefaultAverageRcs, false);
|
||||
|
||||
// 断言 (Assert)
|
||||
Assert.AreEqual(rcs1, rcs2, "对于Swerling I模型 (Tank, ConstantVelocity),在同一扫描周期内,RCS值应从缓存读取且保持不变。");
|
||||
Assert.IsTrue(rcs1 > 0, "RCS值应大于0。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试:当目标是直升机且匀速运动时,其RCS行为应类似Swerling II (快起伏,不使用缓存)。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void GetRealtimeRcs_Helicopter_ConstantVelocity_BehavesAsSwerlingII()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel(TestSeed);
|
||||
|
||||
// 操作 (Act)
|
||||
double rcs1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.ConstantVelocity, DefaultAverageRcs, false);
|
||||
double rcs2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.ConstantVelocity, DefaultAverageRcs, false);
|
||||
|
||||
// 断言 (Assert)
|
||||
Assert.AreNotEqual(rcs1, rcs2, "对于Swerling II模型 (Helicopter, ConstantVelocity),连续调用RCS值应不同。");
|
||||
Assert.IsTrue(rcs1 > 0, "第一个RCS值应大于0。");
|
||||
Assert.IsTrue(rcs2 > 0, "第二个RCS值应大于0。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试:当目标类型未知时,应默认为Swerling I行为。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void GetRealtimeRcs_UnknownEquipment_BehavesAsSwerlingI()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel(TestSeed);
|
||||
|
||||
// 操作 (Act)
|
||||
double rcs1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Unknown, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
double rcs2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Unknown, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
|
||||
// 断言 (Assert)
|
||||
Assert.AreEqual(rcs1, rcs2, "对于未知装备类型,应默认为Swerling I行为,RCS值在同一扫描周期内应保持不变。");
|
||||
Assert.IsTrue(rcs1 > 0, "RCS值应大于0。");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 测试:慢起伏模型在同一扫描周期内(isNewScanPeriod=false)应返回缓存的RCS值。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void GetRealtimeRcs_SlowFluctuation_SameScanPeriod_ReturnsCachedValue()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel(TestSeed);
|
||||
// 首次调用,isNewScanPeriod 为 true 或 false 都会导致采样和缓存 (对于Swerling I)
|
||||
double initialRcs = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, true);
|
||||
|
||||
// 操作 (Act)
|
||||
// 后续调用,isNewScanPeriod 为 false
|
||||
double cachedRcs = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
|
||||
// 断言 (Assert)
|
||||
Assert.AreEqual(initialRcs, cachedRcs, "慢起伏模型在同一扫描周期内应返回相同的缓存RCS值。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试:慢起伏模型在新扫描周期开始时(isNewScanPeriod=true)应更新并返回新的缓存RCS值。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void GetRealtimeRcs_SlowFluctuation_NewScanPeriod_UpdatesAndReturnsNewCachedValue()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel(TestSeed); // 使用固定种子
|
||||
double rcsScan1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
|
||||
// 操作 (Act)
|
||||
// 新扫描周期开始
|
||||
double rcsScan2PeriodStart = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, true);
|
||||
// 在新扫描周期内再次获取,应与周期开始时相同
|
||||
double rcsScan2SamePeriod = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
|
||||
// 断言 (Assert)
|
||||
// 由于种子固定,rcsScan1 和 rcsScan2PeriodStart 应该不同(因为重新采样了)
|
||||
// 但对于不同的随机数序列,它们也可能偶然相同,所以这个断言不是绝对的,更多的是检查行为
|
||||
// 更可靠的测试是验证 rcsScan2PeriodStart 和 rcsScan2SamePeriod 相同
|
||||
Assert.AreNotEqual(rcsScan1, rcsScan2PeriodStart, "新扫描周期开始时,RCS值应重新采样,与旧周期的值不同(高概率)。");
|
||||
Assert.AreEqual(rcsScan2PeriodStart, rcsScan2SamePeriod, "在新扫描周期内,后续获取的RCS值应与周期开始时采样并缓存的值相同。");
|
||||
Assert.IsTrue(rcsScan1 > 0, "第一个扫描周期的RCS值应大于0。");
|
||||
Assert.IsTrue(rcsScan2PeriodStart > 0, "第二个扫描周期开始的RCS值应大于0。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试:当平均RCS为0时,GetRealtimeRcs应返回0。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void GetRealtimeRcs_AverageRcsZero_ReturnsZero()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel();
|
||||
|
||||
// 操作 (Act)
|
||||
double rcsS1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, 0.0, false);
|
||||
double rcsS2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Static, 0.0, false);
|
||||
double rcsS3 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Maneuvering, 0.0, false);
|
||||
double rcsS4 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Maneuvering, 0.0, false);
|
||||
|
||||
// 断言 (Assert)
|
||||
Assert.AreEqual(0.0, rcsS1, "Swerling I,平均RCS为0时,应返回0。");
|
||||
Assert.AreEqual(0.0, rcsS2, "Swerling II,平均RCS为0时,应返回0。");
|
||||
Assert.AreEqual(0.0, rcsS3, "Swerling III,平均RCS为0时,应返回0。");
|
||||
Assert.AreEqual(0.0, rcsS4, "Swerling IV,平均RCS为0时,应返回0。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试:当平均RCS为负数时,GetRealtimeRcs应返回0。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void GetRealtimeRcs_AverageRcsNegative_ReturnsZero()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel();
|
||||
|
||||
// 操作 (Act)
|
||||
double rcs = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, -5.0, false);
|
||||
|
||||
// 断言 (Assert)
|
||||
Assert.AreEqual(0.0, rcs, "平均RCS为负数时,应返回0。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试:对于Swerling I模型,如果targetId为null,应抛出ArgumentNullException。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void GetRealtimeRcs_SwerlingI_NullTargetId_ThrowsArgumentNullException()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel();
|
||||
|
||||
// 操作 (Act)
|
||||
model.GetRealtimeRcs(null!, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试:对于Swerling I模型,如果targetId为空字符串,应抛出ArgumentNullException。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void GetRealtimeRcs_SwerlingI_EmptyTargetId_ThrowsArgumentNullException()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel();
|
||||
|
||||
// 操作 (Act)
|
||||
model.GetRealtimeRcs(string.Empty, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试:对于Swerling III模型,如果targetId为null,应抛出ArgumentNullException。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void GetRealtimeRcs_SwerlingIII_NullTargetId_ThrowsArgumentNullException()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel();
|
||||
|
||||
// 操作 (Act)
|
||||
model.GetRealtimeRcs(null!, EquipmentType.Tank, MotionStateType.Maneuvering, DefaultAverageRcs, false);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 测试:ClearCachedRcs应清除特定目标的缓存,导致下次调用重新采样。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void ClearCachedRcs_SlowFluctuation_ForcesNewSampleForSpecificTarget()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel(TestSeed);
|
||||
double rcs1Target1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
double rcs1Target2 = model.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); // 另一个目标以验证其缓存不受影响
|
||||
|
||||
// 操作 (Act)
|
||||
model.ClearCachedRcs(TargetId1); // 清除TargetId1的缓存
|
||||
double rcs2Target1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); // 重新获取TargetId1的RCS
|
||||
double rcs2Target2 = model.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); // 再次获取TargetId2的RCS
|
||||
|
||||
// 断言 (Assert)
|
||||
Assert.AreNotEqual(rcs1Target1, rcs2Target1, "清除缓存后,TargetId1的RCS值应重新采样而不同(高概率)。");
|
||||
Assert.AreEqual(rcs1Target2, rcs2Target2, "清除TargetId1的缓存不应影响TargetId2的缓存值。");
|
||||
Assert.IsTrue(rcs1Target1 > 0);
|
||||
Assert.IsTrue(rcs2Target1 > 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试:ClearAllCachedRcs应清除所有目标的缓存,导致下次所有慢起伏目标调用都重新采样。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void ClearAllCachedRcs_SlowFluctuation_ForcesNewSamplesForAllTargets()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model = new SwerlingRcsModel(TestSeed);
|
||||
double rcs1Target1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
double rcs1Target2 = model.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
|
||||
// 操作 (Act)
|
||||
model.ClearAllCachedRcs(); // 清除所有缓存
|
||||
double rcs2Target1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
double rcs2Target2 = model.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
|
||||
// 断言 (Assert)
|
||||
Assert.AreNotEqual(rcs1Target1, rcs2Target1, "清除所有缓存后,TargetId1的RCS值应重新采样而不同(高概率)。");
|
||||
Assert.AreNotEqual(rcs1Target2, rcs2Target2, "清除所有缓存后,TargetId2的RCS值应重新采样而不同(高概率)。");
|
||||
Assert.IsTrue(rcs1Target1 > 0);
|
||||
Assert.IsTrue(rcs1Target2 > 0);
|
||||
Assert.IsTrue(rcs2Target1 > 0);
|
||||
Assert.IsTrue(rcs2Target2 > 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试:使用相同种子的两个SwerlingRcsModel实例应产生可复现的RCS序列。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void GetRealtimeRcs_WithSameSeed_GeneratesReproducibleSequence()
|
||||
{
|
||||
// 准备 (Arrange)
|
||||
var model1 = new SwerlingRcsModel(TestSeed);
|
||||
var model2 = new SwerlingRcsModel(TestSeed);
|
||||
|
||||
// 操作 (Act) & 断言 (Assert)
|
||||
// 以Swerling II (快起伏) 为例,因为它不依赖缓存和isNewScanPeriod
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
double rcsM1 = model1.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
double rcsM2 = model2.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
Assert.AreEqual(rcsM1, rcsM2, $"在第 {i+1} 次调用时,使用相同种子的两个模型产生的RCS值应相同。");
|
||||
Assert.IsTrue(rcsM1 > 0, $"Model1, 调用 {i+1}, RCS 值应大于0。");
|
||||
}
|
||||
|
||||
// 测试Swerling I (慢起伏)
|
||||
double rcsS1M1_Initial = model1.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, true);
|
||||
double rcsS1M2_Initial = model2.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, true);
|
||||
Assert.AreEqual(rcsS1M1_Initial, rcsS1M2_Initial, "Swerling I,相同种子,首次调用(isNewScanPeriod=true),RCS值应相同。");
|
||||
|
||||
double rcsS1M1_Cached = model1.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
double rcsS1M2_Cached = model2.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false);
|
||||
Assert.AreEqual(rcsS1M1_Cached, rcsS1M2_Cached, "Swerling I,相同种子,后续调用(isNewScanPeriod=false),缓存的RCS值应相同。");
|
||||
Assert.AreEqual(rcsS1M1_Initial, rcsS1M1_Cached, "Swerling I,Model1,后续调用应返回首次缓存的值。");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -19,6 +19,8 @@ Mass = 25.0
|
||||
ExplosionRadius = 5.5
|
||||
HitProbability = 0.9
|
||||
SelfDestructHeight = 0.0
|
||||
InfraredRadiationIntensity = 96.0 # 红外辐射强度 (瓦特/球面度)
|
||||
UltravioletRadiationIntensity = 100.0 # 紫外辐射强度 (瓦特/球面度)
|
||||
# --- 复合制导特定属性 ---
|
||||
CompositeWorkMode = "Serial" # 工作模式:Serial (串行) 或 Parallel (并行)
|
||||
# FusionStrategy = "UseHighestPriority" # 仅在并行模式下相关
|
||||
|
||||
@ -19,6 +19,8 @@ Mass = 23.5 # 质量 (千克)
|
||||
ExplosionRadius = 5.0 # 爆炸半径 (米)
|
||||
HitProbability = 0.9 # 命中概率
|
||||
SelfDestructHeight = 0.0 # 自毁高度 (米)
|
||||
InfraredRadiationIntensity = 96.0 # 红外辐射强度 (瓦特/球面度)
|
||||
UltravioletRadiationIntensity = 100.0 # 紫外辐射强度 (瓦特/球面度)
|
||||
# TrackerSensitivity, CommandLatency, IrSignature 在JSON中为null,此处省略
|
||||
|
||||
[InfraredCommandGuidanceConfig]
|
||||
|
||||
@ -19,6 +19,8 @@ Mass = 25.0
|
||||
ExplosionRadius = 5.5
|
||||
HitProbability = 0.9
|
||||
SelfDestructHeight = 0.0
|
||||
InfraredRadiationIntensity = 96.0 # 红外辐射强度 (瓦特/球面度)
|
||||
UltravioletRadiationIntensity = 100.0 # 紫外辐射强度 (瓦特/球面度)
|
||||
|
||||
[InfraredImagingGuidanceConfig]
|
||||
MaxDetectionRange = 1000.0 # 最大探测距离 (米), JSON中为1000,对应C#默认为1000.0
|
||||
|
||||
@ -19,6 +19,8 @@ Mass = 24.5 # 质量 (千克)
|
||||
ExplosionRadius = 5.0 # 爆炸半径 (米)
|
||||
HitProbability = 0.9 # 命中概率
|
||||
SelfDestructHeight = 0.0 # 自毁高度 (米)
|
||||
InfraredRadiationIntensity = 96.0 # 红外辐射强度 (瓦特/球面度)
|
||||
UltravioletRadiationIntensity = 100.0 # 紫外辐射强度 (瓦特/球面度)
|
||||
|
||||
[Properties.LaserCodeConfig] # 激光编码配置
|
||||
IsCodeEnabled = true # 是否启用编码
|
||||
|
||||
@ -20,6 +20,8 @@ Mass = 22.0 # 导弹质量 (kg)
|
||||
ExplosionRadius = 5.0 # 爆炸半径 (米)
|
||||
HitProbability = 0.9 # 固有命中概率 (0.0 到 1.0)
|
||||
SelfDestructHeight = 0.0 # 离地自毁高度 (米)
|
||||
InfraredRadiationIntensity = 96.0 # 红外辐射强度 (瓦特/球面度)
|
||||
UltravioletRadiationIntensity = 100.0 # 紫外辐射强度 (瓦特/球面度)
|
||||
|
||||
[Properties.LaserCodeConfig] # properties内部的激光编码配置
|
||||
IsCodeEnabled = true # 激光编码系统是否启用?
|
||||
|
||||
@ -19,6 +19,8 @@ Mass = 28.0 # 质量 (千克)
|
||||
ExplosionRadius = 5.0 # 爆炸半径 (米)
|
||||
HitProbability = 0.9 # 命中概率
|
||||
SelfDestructHeight = 0.0 # 自毁高度 (米)
|
||||
InfraredRadiationIntensity = 96.0 # 红外辐射强度 (瓦特/球面度)
|
||||
UltravioletRadiationIntensity = 100.0 # 紫外辐射强度 (瓦特/球面度)
|
||||
|
||||
[MillimeterWaveGuidanceConfig]
|
||||
MaxDetectionRange = 5000.0 # 最大探测距离 (米)
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
using System.Reflection;
|
||||
using ThreatSource.Simulation;
|
||||
|
||||
namespace ThreatSource.Equipment
|
||||
@ -104,15 +105,22 @@ namespace ThreatSource.Equipment
|
||||
{
|
||||
// 获取基础状态信息
|
||||
var statusInfo = base.GetStatusInfo();
|
||||
|
||||
|
||||
// 添加装备特有属性
|
||||
statusInfo.ExtendedProperties["Health"] = Health;
|
||||
statusInfo.ExtendedProperties["Length"] = Properties.Length;
|
||||
statusInfo.ExtendedProperties["Width"] = Properties.Width;
|
||||
statusInfo.ExtendedProperties["Height"] = Properties.Height;
|
||||
statusInfo.ExtendedProperties["InfraredRadiationIntensity"] = Properties.InfraredRadiationIntensity;
|
||||
statusInfo.ExtendedProperties["MillimeterWaveRadiationIntensity"] = Properties.MillimeterWaveRadiationIntensity;
|
||||
statusInfo.ExtendedProperties["UltravioletRadiationIntensity"] = Properties.UltravioletRadiationIntensity;
|
||||
if (Properties != null)
|
||||
{
|
||||
var propertiesType = Properties.GetType();
|
||||
var props = propertiesType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
|
||||
foreach (var prop in props)
|
||||
{
|
||||
if (prop.CanRead) // 确保属性是可读的
|
||||
{
|
||||
object? propValue = prop.GetValue(Properties);
|
||||
statusInfo.ExtendedProperties[prop.Name] = propValue ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return statusInfo;
|
||||
}
|
||||
|
||||
@ -478,8 +478,6 @@ namespace ThreatSource.Guidance
|
||||
|
||||
// 将合成激光信号传递给四象限探测器
|
||||
quadrantDetector.ProcessLaserSignal(ReceivedLaserPower, spotOffset);
|
||||
|
||||
Debug.WriteLine($"处理激光信号: 总功率={ReceivedLaserPower:E}W, 目标位置={TargetPosition}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@ -245,7 +245,7 @@ namespace ThreatSource.Indicator
|
||||
// 获取基类状态信息
|
||||
var statusInfo = base.GetStatusInfo();
|
||||
|
||||
// 添加制导系统特有属性
|
||||
// 添加指示器特有属性
|
||||
statusInfo.ExtendedProperties["TargetId"] = TargetId ?? "";
|
||||
statusInfo.ExtendedProperties["MissileId"] = MissileId ?? "";
|
||||
statusInfo.ExtendedProperties["lastKnownTargetPosition"] = _lastKnownTargetPosition ?? Vector3D.Zero;
|
||||
|
||||
@ -223,7 +223,7 @@ namespace ThreatSource.Jammer
|
||||
// 获取基类状态信息
|
||||
var statusInfo = base.GetStatusInfo();
|
||||
|
||||
// 添加制导系统特有属性
|
||||
// 添加干扰器特有属性
|
||||
statusInfo.ExtendedProperties["JammingType"] = JammingType;
|
||||
statusInfo.ExtendedProperties["State"] = State;
|
||||
statusInfo.ExtendedProperties["IsJamming"] = IsJamming;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using System.Diagnostics;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ThreatSource.Missile
|
||||
{
|
||||
@ -456,22 +457,38 @@ namespace ThreatSource.Missile
|
||||
// 获取基础状态信息
|
||||
var statusInfo = base.GetStatusInfo();
|
||||
|
||||
// 添加导弹固有属性(通过MissileProperties)
|
||||
statusInfo.ExtendedProperties["Type"] = Properties.Type;
|
||||
statusInfo.ExtendedProperties["MaxSpeed"] = Properties.MaxSpeed;
|
||||
statusInfo.ExtendedProperties["MaxAcceleration"] = Properties.MaxAcceleration;
|
||||
statusInfo.ExtendedProperties["MaxRange"] = Properties.MaxFlightDistance;
|
||||
statusInfo.ExtendedProperties["MaxFlightTime"] = Properties.MaxFlightTime;
|
||||
statusInfo.ExtendedProperties["ExplosionRadius"] = Properties.ExplosionRadius;
|
||||
statusInfo.ExtendedProperties["Mass"] = Properties.Mass;
|
||||
// 使用反射动态添加来自 this.Properties 的导弹固有属性
|
||||
if (Properties != null)
|
||||
{
|
||||
var propertiesType = Properties.GetType();
|
||||
var props = propertiesType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
|
||||
foreach (var prop in props)
|
||||
{
|
||||
if (prop.CanRead)
|
||||
{
|
||||
// 复合制导导弹才有复合制导系统参数
|
||||
if ((prop.Name == nameof(MissileProperties.GuidanceSuite) ||
|
||||
prop.Name == nameof(MissileProperties.CompositeWorkMode) ||
|
||||
prop.Name == nameof(MissileProperties.FusionStrategy)) &&
|
||||
Properties.Type != MissileType.CompositeGuidance)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
object? propValue = prop.GetValue(Properties);
|
||||
statusInfo.ExtendedProperties[prop.Name] = propValue ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 添加导弹运行时状态
|
||||
statusInfo.ExtendedProperties["FlightTime"] = FlightTime;
|
||||
statusInfo.ExtendedProperties["FlightDistance"] = FlightDistance;
|
||||
statusInfo.ExtendedProperties["EngineBurnTime"] = EngineBurnTime;
|
||||
statusInfo.ExtendedProperties["IsGuidance"] = IsGuidance;
|
||||
// 添加 BaseMissile 类的运行时状态参数
|
||||
statusInfo.ExtendedProperties["FlightTime"] = FlightTime;
|
||||
statusInfo.ExtendedProperties["FlightDistance"] = FlightDistance;
|
||||
statusInfo.ExtendedProperties["EngineBurnTime"] = EngineBurnTime;
|
||||
statusInfo.ExtendedProperties["IsGuidance"] = IsGuidance;
|
||||
statusInfo.ExtendedProperties["LostGuidanceTime"] = LostGuidanceTime;
|
||||
statusInfo.ExtendedProperties["GuidanceAcceleration"] = GuidanceAcceleration;
|
||||
statusInfo.ExtendedProperties["GuidanceAcceleration"] = GuidanceAcceleration;
|
||||
|
||||
return statusInfo;
|
||||
}
|
||||
|
||||
@ -209,6 +209,15 @@ namespace ThreatSource.Missile
|
||||
/// </remarks>
|
||||
public class MissileProperties
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置导弹的类型
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 决定导弹的制导方式和行为特征
|
||||
/// 影响导弹的性能参数和作战能力
|
||||
/// </remarks>
|
||||
public MissileType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置导弹的最大速度限制
|
||||
/// </summary>
|
||||
@ -319,13 +328,22 @@ namespace ThreatSource.Missile
|
||||
public double MaxEngineBurnTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置导弹的类型
|
||||
/// 获取或设置红外辐射强度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 决定导弹的制导方式和行为特征
|
||||
/// 影响导弹的性能参数和作战能力
|
||||
/// 单位:瓦特/球面度
|
||||
/// 表示导弹在红外波段的发射功率
|
||||
/// </remarks>
|
||||
public MissileType Type { get; set; }
|
||||
public double InfraredRadiationIntensity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置紫外辐射强度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:瓦特/球面度
|
||||
/// 表示导弹在紫外波段的发射功率
|
||||
/// </remarks>
|
||||
public double UltravioletRadiationIntensity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光编码配置
|
||||
@ -357,13 +375,13 @@ namespace ThreatSource.Missile
|
||||
/// 复合制导模式下,多个制导系统的工作方式。默认为串行。
|
||||
/// 仅当 Type 为 CompositeGuidance 时有效。
|
||||
/// </summary>
|
||||
public CompositeWorkType CompositeWorkMode { get; set; } = CompositeWorkType.Serial;
|
||||
public CompositeWorkType CompositeWorkMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 并行工作模式下的指令融合策略。默认为使用最高优先级的指令。
|
||||
/// 仅当 Type 为 CompositeGuidance 且 CompositeWorkMode 为 Parallel 时有效。
|
||||
/// </summary>
|
||||
public CommandFusionStrategy FusionStrategy { get; set; } = CommandFusionStrategy.UseHighestPriority;
|
||||
public CommandFusionStrategy FusionStrategy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化导弹配置类的新实例
|
||||
@ -377,8 +395,6 @@ namespace ThreatSource.Missile
|
||||
public MissileProperties()
|
||||
{
|
||||
SetDefaultValues();
|
||||
Type = MissileType.StandardMissile;
|
||||
LaserCodeConfig = new LaserCodeConfig();
|
||||
GuidanceSuite = [];
|
||||
}
|
||||
|
||||
@ -395,6 +411,7 @@ namespace ThreatSource.Missile
|
||||
/// </remarks>
|
||||
public void SetDefaultValues()
|
||||
{
|
||||
Type = MissileType.StandardMissile;
|
||||
MaxSpeed = 400;
|
||||
MaxFlightTime = 60;
|
||||
MaxFlightDistance = 5000;
|
||||
@ -407,11 +424,16 @@ namespace ThreatSource.Missile
|
||||
ExplosionRadius = 5;
|
||||
HitProbability = 0.9;
|
||||
SelfDestructHeight = 0;
|
||||
InfraredRadiationIntensity = 100.0;
|
||||
UltravioletRadiationIntensity = 100.0;
|
||||
LaserCodeConfig = new LaserCodeConfig();
|
||||
|
||||
// 重置复合制导相关属性的默认值
|
||||
CompositeWorkMode = CompositeWorkType.Serial;
|
||||
FusionStrategy = CommandFusionStrategy.UseHighestPriority;
|
||||
if (GuidanceSuite != null) GuidanceSuite.Clear(); else GuidanceSuite = new List<GuidanceComponentConfig>();
|
||||
if(Type == MissileType.CompositeGuidance)
|
||||
{
|
||||
CompositeWorkMode = CompositeWorkType.Serial;
|
||||
FusionStrategy = CommandFusionStrategy.UseHighestPriority;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -303,7 +303,7 @@ namespace ThreatSource.Sensor
|
||||
// 获取基础状态信息
|
||||
var statusInfo = base.GetStatusInfo();
|
||||
|
||||
// 添加传感器状态
|
||||
// 添加传感器特有状态信息
|
||||
statusInfo.ExtendedProperties["IsJammed"] = IsJammed.ToString();
|
||||
statusInfo.ExtendedProperties["IsBlockingJammed"] = IsBlockingJammed.ToString();
|
||||
statusInfo.ExtendedProperties["SensorData"] = GetSensorData().ToString() ?? "无数据";
|
||||
|
||||
Loading…
Reference in New Issue
Block a user