ThreatSourceLibaray/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileCodeTests.cs

426 lines
15 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 Xunit;
using ThreatSource.Missile;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Tests.Simulation;
using ThreatSource.Guidance;
using ThreatSource.Indicator;
using ThreatSource.Target;
namespace ThreatSource.Tests.Missile
{
public class LaserSemiActiveGuidedMissileCodeTests
{
private readonly SimulationManager _simulationManager;
private readonly TestSimulationAdapter _testAdapter;
private readonly LaserSemiActiveGuidedMissile _missile;
private readonly MissileProperties _properties;
private readonly MockLaserDesignator _laserDesignator;
private readonly MockTarget _target;
public LaserSemiActiveGuidedMissileCodeTests()
{
_simulationManager = new SimulationManager();
_testAdapter = new TestSimulationAdapter(_simulationManager);
_simulationManager.SetSimulationAdapter(_testAdapter);
_properties = new MissileProperties
{
MaxSpeed = 1000,
MaxFlightTime = 100,
MaxFlightDistance = 10000,
MaxAcceleration = 50,
ProportionalNavigationCoefficient = 3,
Mass = 100,
ExplosionRadius = 10,
HitProbability = 0.9,
Type = MissileType.LaserSemiActiveGuidance
};
var missileInitialMotion = new InitialMotionParameters
{
Position = new Vector3D(0, 0, 0),
Orientation = new Orientation(0, 0, 0),
InitialSpeed = 100
};
// 创建并注册模拟的激光指示器位置在导弹后方100米处
_laserDesignator = new MockLaserDesignator("laser1", _simulationManager);
_laserDesignator.Position = new Vector3D(-100, 0, 0);
_laserDesignator.LaserPower = 100; // 设置足够高的激光功率
_testAdapter.AddTestEntity("laser1", _laserDesignator);
// 创建并注册模拟的目标位置在导弹前方1000米处
_target = new MockTarget("target1", _simulationManager);
_target.Position = new Vector3D(1000, 0, 0);
_testAdapter.AddTestEntity("target1", _target);
var laserCodeConfig = new LaserCodeConfig
{
Code = new LaserCode
{
CodeType = LaserCodeType.PRF,
CodeValue = 1234
}
};
var guidanceConfig = new LaserSemiActiveGuidanceConfig
{
FieldOfViewAngle = 30,
LensDiameter = 0.1,
SensorDiameter = 0.03,
FocusedSpotDiameter = 0.006,
ReflectionCoefficient = 0.2,
TargetReflectiveArea = 1.0,
LockThreshold = 1e-12,
SpotOffsetSensitivity = 0.5
};
_missile = new LaserSemiActiveGuidedMissile(
"missile1",
_properties,
missileInitialMotion,
laserCodeConfig,
guidanceConfig,
_simulationManager
);
_simulationManager.RegisterEntity("missile1", _missile);
// 创建独立的制导系统用于测试
var guidanceSystem = new LaserSemiActiveGuidanceSystem(
"guidance1",
_properties.MaxAcceleration,
_properties.ProportionalNavigationCoefficient,
laserCodeConfig,
guidanceConfig,
_simulationManager
);
guidanceSystem.ParentId = "missile1";
_simulationManager.RegisterEntity("guidance1", guidanceSystem);
}
private LaserSemiActiveGuidanceSystem GetGuidanceSystem()
{
return (_simulationManager.GetEntityById("guidance1") as LaserSemiActiveGuidanceSystem)!;
}
// 模拟的激光指示器类
private class MockLaserDesignator : LaserDesignator
{
public MockLaserDesignator(string id, ISimulationManager simulationManager)
: base(id, "target1", "missile1", new LaserDesignatorConfig
{
LaserPower = 100,
LaserDivergenceAngle = 0.001,
MinWavelength = 1.0,
MaxWavelength = 1.1
}, new InitialMotionParameters
{
Position = new Vector3D(100, 0, 0),
Orientation = new Orientation(0, 0, 0),
InitialSpeed = 0
}, simulationManager)
{
// 不需要额外设置属性,因为基类构造函数已经设置了
}
}
// 模拟的目标类
private class MockTarget : Tank
{
public MockTarget(string id, ISimulationManager simulationManager)
: base(id, new InitialMotionParameters
{
Position = new Vector3D(1000, 0, 0),
Orientation = new Orientation(0, 0, 0),
InitialSpeed = 0
}, simulationManager)
{
// 不需要额外设置属性,因为基类构造函数已经设置了
}
}
[Fact]
public void SetLaserCode_SetsCodeCorrectly()
{
// Arrange
_missile.Fire();
_missile.Activate();
var guidanceSystem = GetGuidanceSystem();
// Act
guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234);
// Assert - We can't directly check the private field, but we can test the behavior
// This will be tested in the LaserIllumination test
}
[Fact]
public void AddLaserCodeParameter_AddsParameterCorrectly()
{
// Arrange
_missile.Fire();
_missile.Activate();
var guidanceSystem = GetGuidanceSystem();
guidanceSystem.SetExpectedLaserCode(LaserCodeType.PPM, 5678);
// Act
guidanceSystem.AddExpectedCodeParameter("PulseWidth", 0.001);
// Assert - We can't directly check the private field, but we can test the behavior
// This will be tested in the LaserIllumination test
}
[Fact]
public void SetCodeMatchRequired_SetsRequirementCorrectly()
{
// Arrange
_missile.Fire();
_missile.Activate();
var guidanceSystem = GetGuidanceSystem();
// Act
_missile.LaserCodeConfig = new LaserCodeConfig
{
IsCodeMatchRequired = true,
Code = new LaserCode
{
CodeType = LaserCodeType.PRF,
CodeValue = 1234
}
};
// Assert - We can't directly check the private field, but we can test the behavior
// This will be tested in the LaserIllumination test
}
[Fact]
public void LaserIllumination_WithMatchingCode_EnablesGuidance()
{
// Arrange
_missile.Fire();
_missile.Activate();
var guidanceSystem = GetGuidanceSystem();
guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234);
_missile.LaserCodeConfig.IsCodeMatchRequired = true;
_missile.Update(0.1); // Move past launch stage
// 设置激光指示器和目标位置,确保在视场角内
_laserDesignator.Position = new Vector3D(-100, 0, 0);
_target.Position = new Vector3D(1000, 0, 0);
_laserDesignator.LaserPower = 100; // 设置足够高的激光功率
// Act - Send matching code illumination
var illuminationEvent = new LaserIlluminationStartEvent
{
LaserDesignatorId = "laser1",
TargetId = "target1",
LaserCodeConfig = new LaserCodeConfig
{
Code = new LaserCode
{
CodeType = LaserCodeType.PRF,
CodeValue = 1234
}
}
};
_simulationManager.PublishEvent(illuminationEvent);
// 多次更新导弹状态,给系统更多时间处理事件
for (int i = 0; i < 10; i++)
{
_missile.Update(0.1);
_laserDesignator.Update(0.1);
}
// Assert
var matchEvents = _testAdapter.GetPublishedEvents<LaserCodeMatchEvent>();
Assert.NotEmpty(matchEvents);
Assert.True(_missile.IsGuidance);
}
[Fact]
public void LaserIllumination_WithMismatchingCode_DisablesGuidance()
{
// Arrange
_missile.Fire();
_missile.Activate();
var guidanceSystem = GetGuidanceSystem();
guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234);
_missile.LaserCodeConfig.IsCodeMatchRequired = true;
_missile.Update(0.1); // Move past launch stage
// 设置激光指示器和目标位置,确保在视场角内
_laserDesignator.Position = new Vector3D(-100, 0, 0);
_target.Position = new Vector3D(1000, 0, 0);
_laserDesignator.LaserPower = 100; // 设置足够高的激光功率
// Act - Send mismatching code illumination
var illuminationEvent = new LaserIlluminationStartEvent
{
LaserDesignatorId = "laser1",
TargetId = "target1",
LaserCodeConfig = new LaserCodeConfig
{
Code = new LaserCode
{
CodeType = LaserCodeType.PRF,
CodeValue = 5678 // Different code
}
}
};
_simulationManager.PublishEvent(illuminationEvent);
// 多次更新导弹状态,给系统更多时间处理事件
for (int i = 0; i < 10; i++)
{
_missile.Update(0.1);
_laserDesignator.Update(0.1);
}
// Assert
var mismatchEvents = _testAdapter.GetPublishedEvents<LaserCodeMismatchEvent>();
Assert.NotEmpty(mismatchEvents);
Assert.False(_missile.IsGuidance);
}
[Fact]
public void LaserIllumination_WithCodeDisabled_EnablesGuidanceIfNotRequired()
{
// Arrange
_missile.Fire();
_missile.Activate();
var guidanceSystem = GetGuidanceSystem();
guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234);
_missile.LaserCodeConfig.IsCodeMatchRequired = false; // Not required
_missile.Update(0.1); // Move past launch stage
// 设置激光指示器和目标位置,确保在视场角内
_laserDesignator.Position = new Vector3D(-100, 0, 0);
_target.Position = new Vector3D(1000, 0, 0);
_laserDesignator.LaserPower = 100; // 设置足够高的激光功率
// Act - Send illumination with code disabled
var illuminationEvent = new LaserIlluminationStartEvent
{
LaserDesignatorId = "laser1",
TargetId = "target1",
LaserCodeConfig = new LaserCodeConfig
{
Code = new LaserCode
{
CodeType = LaserCodeType.PRF,
CodeValue = 1234
}
}
};
_simulationManager.PublishEvent(illuminationEvent);
// 多次更新导弹状态,给系统更多时间处理事件
for (int i = 0; i < 10; i++)
{
_missile.Update(0.1);
_laserDesignator.Update(0.1);
}
// Assert
Assert.True(_missile.IsGuidance);
}
[Fact]
public void LaserIllumination_WithCodeDisabled_DisablesGuidanceIfRequired()
{
// Arrange
_missile.Fire();
_missile.Activate();
var guidanceSystem = GetGuidanceSystem();
guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234);
_missile.LaserCodeConfig.IsCodeMatchRequired = true; // Required
_missile.Update(0.1); // Move past launch stage
// Act - Send illumination with code disabled
var illuminationEvent = new LaserIlluminationStartEvent
{
LaserDesignatorId = "laser1",
TargetId = "target1",
LaserCodeConfig = new LaserCodeConfig
{
Code = new LaserCode
{
CodeType = LaserCodeType.PRF,
CodeValue = 1234
}
}
};
_simulationManager.PublishEvent(illuminationEvent);
// 多次更新导弹状态,给系统更多时间处理事件
for (int i = 0; i < 5; i++)
{
_missile.Update(0.1);
}
// Assert
// Guidance should be disabled without code when required
Assert.False(_missile.IsGuidance);
}
[Fact]
public void LaserIlluminationStop_DisablesGuidance()
{
// Arrange
_missile.Fire();
_missile.Activate();
var guidanceSystem = GetGuidanceSystem();
guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234);
_missile.LaserCodeConfig.IsCodeMatchRequired = true;
_missile.Update(0.1); // Move past launch stage
// 设置激光指示器和目标位置,确保在视场角内
_laserDesignator.Position = new Vector3D(-100, 0, 0);
_target.Position = new Vector3D(1000, 0, 0);
_laserDesignator.LaserPower = 100; // 设置足够高的激光功率
// First enable guidance with matching code
var startEvent = new LaserIlluminationStartEvent
{
LaserDesignatorId = "laser1",
TargetId = "target1",
LaserCodeConfig = new LaserCodeConfig
{
Code = new LaserCode
{
CodeType = LaserCodeType.PRF,
CodeValue = 1234
}
}
};
_simulationManager.PublishEvent(startEvent);
// Update several times to ensure guidance is enabled
for (int i = 0; i < 10; i++)
{
_missile.Update(0.1);
_laserDesignator.Update(0.1);
}
// Act - Stop laser illumination
var stopEvent = new LaserIlluminationStopEvent
{
LaserDesignatorId = "laser1",
TargetId = "target1"
};
_simulationManager.PublishEvent(stopEvent);
// Update several more times to ensure guidance is disabled
for (int i = 0; i < 10; i++)
{
_missile.Update(0.1);
_laserDesignator.Update(0.1);
}
// Assert
Assert.False(_missile.IsGuidance);
}
}
}