261 lines
9.1 KiB
C#
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, "导弹在激光照射停止后应该禁止进入制导状态");
|
|
}
|
|
}
|
|
} |