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

261 lines
9.1 KiB
C#

using Xunit;
using ThreatSource.Missile;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Tests.Simulation;
using ThreatSource.Guidance;
using ThreatSource.Indicator;
using ThreatSource.Equipment;
using System.Diagnostics;
namespace ThreatSource.Tests.Missile
{
public class LaserSemiActiveGuidedMissileCodeTests
{
private readonly SimulationManager _simulationManager;
private readonly TestSimulationAdapter _testAdapter;
private readonly LaserSemiActiveGuidedMissile _missile;
private readonly MissileProperties _properties;
// Store the laser designator's config to modify it in tests
private readonly LaserDesignatorConfig _laserDesignatorConfig;
private readonly MockLaserDesignator _laserDesignator;
private readonly MockTarget _target;
// MockLaserDesignator now takes a LaserDesignatorConfig in its constructor
private class MockLaserDesignator : LaserDesignator
{
// No longer needs its own 'config' field if the passed-in one is used by base
public MockLaserDesignator(string id, LaserDesignatorConfig config, ISimulationManager manager)
: base(id,
"defaultTargetIdForMock",
"defaultMissileIdForMock",
config, // Use the passed-in config for the base class
new KinematicState(), // Default KinematicState for base
manager)
{
}
public override void Update(double deltaTime)
{
// Mock update
}
}
private class MockTarget : SimulationElement
{
public MockTarget(string id, ISimulationManager manager) : base(id, new KinematicState(), manager) { }
public override void Update(double deltaTime) { }
}
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 KinematicState
{
Position = new Vector3D(0, 0, 0),
Orientation = new Orientation(0, 0, 0),
Speed = 100
};
_laserDesignatorConfig = new LaserDesignatorConfig
{
Power = 10000, // 功率 (瓦特)
Wavelength = 1.06, // 波长 (微米)
DivergenceAngle = 0.0005 // 发散角 (弧度) - 减小
};
_laserDesignator = new MockLaserDesignator("laser1", _laserDesignatorConfig, _simulationManager);
_laserDesignator.KState.Position = new Vector3D(-100, 0, 0);
_testAdapter.AddTestEntity("laser1", _laserDesignator);
_target = new MockTarget("target1", _simulationManager);
_target.KState.Position = new Vector3D(1000, 0, 0);
_testAdapter.AddTestEntity("target1", _target);
var guidanceConfig = new LaserSemiActiveGuidanceConfig
{
FieldOfViewAngle = 60.0, // 视场角 (度) - 增大
LensDiameter = 0.1,
SensorDiameter = 0.03,
FocusedSpotDiameter = 0.006,
ReflectionCoefficient = 0.5, // 目标反射系数 - 增大
TargetReflectiveArea = 2.0, // 目标有效反射面积 - 增大
LockThreshold = 1e-15, // 锁定阈值 (瓦特) - 减小
SpotOffsetSensitivity = 0.5,
LaserCodeConfig = new LaserCodeConfig
{
IsCodeEnabled = true,
IsCodeMatchRequired = true,
Code = new LaserCode
{
CodeType = LaserCodeType.PRF,
CodeValue = 1234
}
}
};
_missile = new LaserSemiActiveGuidedMissile(
"missile1",
_properties,
missileInitialMotion,
guidanceConfig,
_simulationManager
);
_simulationManager.RegisterEntity("missile1", _missile);
}
[Fact]
public void MissileSetup_CorrectlyInitializes_ExpectedLaserCode()
{
Assert.NotNull(_properties);
}
[Fact]
public void LaserIlluminationWithNonMatchingCode_DisablesGuidance()
{
// Arrange
_missile.Fire();
_missile.Activate();
_missile.Update(0.1);
_laserDesignator.KState.Position = new Vector3D(-100, 0, 0);
_target.KState.Position = new Vector3D(1000, 0, 0);
// _laserDesignatorConfig.Power = 100;
// Act
var illuminationEvent = new LaserIlluminationEvent
{
LaserDesignatorId = "laser1",
TargetId = "target1",
LaserCodeConfig = new LaserCodeConfig
{
IsCodeEnabled = true,
Code = new LaserCode
{
CodeType = LaserCodeType.PRF,
CodeValue = 5678 // Non-matching
}
}
};
_simulationManager.PublishEvent(illuminationEvent);
for (int i = 0; i < 10; i++)
{
_missile.Update(0.1);
_laserDesignator.Update(0.1);
}
// Assert
Assert.False(_missile.IsGuidance, "导弹在接收到不匹配的激光编码照射时应该禁止进入制导状态");
}
[Fact]
public void LaserIlluminationWithCodeDisabled_DisablesGuidance()
{
// Arrange
_missile.Fire();
_missile.Activate();
_missile.Update(0.1);
_laserDesignator.KState.Position = new Vector3D(-100, 0, 0);
_target.KState.Position = new Vector3D(1000, 0, 0);
// _laserDesignatorConfig.Power = 100;
// Act
var illuminationEvent = new LaserIlluminationEvent
{
LaserDesignatorId = "laser1",
TargetId = "target1",
LaserCodeConfig = new LaserCodeConfig
{
IsCodeEnabled = false, // Code disabled
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.False(_missile.IsGuidance, "导弹在接收到编码禁用的激光照射时应该禁止进入制导状态");
}
[Fact]
public void LaserIlluminationStop_DisablesGuidance()
{
// Arrange
_missile.Fire();
_missile.Activate();
_missile.Update(0.1);
_laserDesignator.KState.Position = new Vector3D(-100, 0, 0);
_target.KState.Position = new Vector3D(1000, 0, 0);
// _laserDesignatorConfig.Power = 100;
var startEvent = new LaserIlluminationEvent
{
LaserDesignatorId = "laser1",
TargetId = "target1",
LaserCodeConfig = new LaserCodeConfig
{
IsCodeEnabled = true,
Code = new LaserCode
{
CodeType = LaserCodeType.PRF,
CodeValue = 1234
}
}
};
_simulationManager.PublishEvent(startEvent);
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);
for (int i = 0; i < 10; i++)
{
_missile.Update(0.1);
_laserDesignator.Update(0.1);
}
// Assert
Assert.False(_missile.IsGuidance, "导弹在激光照射停止后应该禁止进入制导状态");
}
}
}