创建项目,添加文档

This commit is contained in:
Tian jianyong 2024-12-30 15:51:19 +08:00
commit 2969706400
66 changed files with 13491 additions and 0 deletions

128
.gitignore vendored Normal file
View File

@ -0,0 +1,128 @@
.DS_Store
.vscode/
# Visual Studio files
.vs/
*.user
*.userosscache
*.sln.docstates
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
bin/
obj/
out/
msbuild.log
msbuild.err
msbuild.wrn
# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# ReSharper
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# NuGet
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Backup & report files from converting an old project file
# to a newer Visual Studio version
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# Local History for Visual Studio
.localhistory/
# JetBrains Rider
.idea/
*.sln.iml
# Docs
docs/_site/
docs/api/

View File

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ThreatSource\ThreatSource.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,235 @@
using Xunit;
using ThreatSource.Indicator;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Simulation.Testing;
using ThreatSource.Target;
using ThreatSource.Missile;
namespace ThreatSource.Tests.Indicator
{
public class InfraredTrackerTests
{
private readonly SimulationManager _simulationManager;
private readonly TestSimulationAdapter _testAdapter;
private readonly InfraredTracker _infraredTracker;
private readonly InfraredTrackerConfig _config;
private readonly Tank _tank;
public InfraredTrackerTests()
{
_simulationManager = new SimulationManager();
_testAdapter = new TestSimulationAdapter(_simulationManager);
_simulationManager.SetSimulationAdapter(_testAdapter);
_config = new InfraredTrackerConfig
{
Id = "tracker1",
InitialPosition = new Vector3D(0, 0, 0),
InitialOrientation = new Orientation(0, 0, 0),
MaxTrackingRange = 10000,
FieldOfView = Math.PI / 3,
AngleMeasurementAccuracy = 0.001,
UpdateFrequency = 10
};
_tank = new Tank("target1", new Vector3D(100, 0, 0), 0, _simulationManager);
_simulationManager.RegisterEntity("target1", _tank);
_infraredTracker = new InfraredTracker(
"tracker1",
"target1",
_config,
_simulationManager
);
_simulationManager.RegisterEntity("tracker1", _infraredTracker);
}
[Fact]
public void Constructor_InitializesPropertiesCorrectly()
{
Assert.Equal("tracker1", _infraredTracker.Id);
Assert.Equal("target1", _infraredTracker.TargetId);
Assert.Null(_infraredTracker.MissileId);
Assert.False(_infraredTracker.IsActive);
}
[Fact]
public void Activate_SetsCorrectState()
{
// Act
_infraredTracker.Activate();
// Assert
Assert.True(_infraredTracker.IsActive);
}
[Fact]
public void Deactivate_SetsCorrectState()
{
// Arrange
_infraredTracker.Activate();
// Act
_infraredTracker.Deactivate();
// Assert
Assert.False(_infraredTracker.IsActive);
}
[Fact]
public void StopTracking_ClearsMissileId()
{
// Arrange
_infraredTracker.Activate();
// 模拟导弹点亮红外热源
_simulationManager.PublishEvent(new InfraredGuidanceMissileLightEvent
{
SenderId = "missile1",
RadiationPower = 100
});
_infraredTracker.Update(0.1);
// Act
_infraredTracker.StopTracking();
// Assert
Assert.Null(_infraredTracker.MissileId);
}
[Fact]
public void Update_SendsGuidanceCommand_WhenTrackingMissile()
{
// Arrange
_infraredTracker.Activate();
// 创建导弹配置
var missileConfig = new MissileProperties
{
Id = "missile1",
InitialPosition = new Vector3D(50, 0, 0),
MaxAcceleration = 100,
ProportionalNavigationCoefficient = 3
};
// 注册一个导弹实体
var missile = new InfraredCommandGuidedMissile(missileConfig, _simulationManager);
_simulationManager.RegisterEntity("missile1", missile);
// 模拟导弹点亮红外热源
_simulationManager.PublishEvent(new InfraredGuidanceMissileLightEvent
{
SenderId = "missile1",
RadiationPower = 100,
Timestamp = DateTime.UtcNow.Ticks
});
_infraredTracker.Update(0.1);
// 清除之前的事件
_testAdapter.GetPublishedEvents();
// Act
_infraredTracker.Update(0.1);
// Assert
var publishedEvents = _testAdapter.GetPublishedEvents();
Assert.Contains(publishedEvents, evt => evt is InfraredGuidanceCommandEvent);
}
[Fact]
public void MissileLightOff_StopsTracking()
{
// Arrange
_infraredTracker.Activate();
// 先让导弹点亮
_simulationManager.PublishEvent(new InfraredGuidanceMissileLightEvent
{
SenderId = "missile1",
RadiationPower = 100
});
_infraredTracker.Update(0.1);
// Act - 导弹熄灭
_simulationManager.PublishEvent(new InfraredGuidanceMissileLightOffEvent
{
SenderId = "missile1"
});
_infraredTracker.Update(0.1);
// Assert
Assert.Null(_infraredTracker.MissileId);
}
[Fact]
public void GetStatus_ReturnsCorrectStatus()
{
// Act
string status = _infraredTracker.GetStatus();
// Assert
var expectedParts = new[]
{
"红外测角仪",
_infraredTracker.Id,
"位置",
"跟踪导弹",
"目标",
"状态"
};
foreach (var part in expectedParts)
{
Assert.Contains(part, status);
}
}
[Fact]
public void EntityDeactivation_StopsTracking()
{
// Arrange
_infraredTracker.Activate();
// 创建导弹配置
var missileConfig = new MissileProperties
{
Id = "missile1",
InitialPosition = new Vector3D(50, 0, 0),
MaxAcceleration = 100,
ProportionalNavigationCoefficient = 3
};
// 注册一个导弹实体并激活
var missile = new InfraredCommandGuidedMissile(missileConfig, _simulationManager);
_simulationManager.RegisterEntity("missile1", missile);
missile.Activate();
// 先让导弹点亮
_simulationManager.PublishEvent(new InfraredGuidanceMissileLightEvent
{
SenderId = "missile1",
RadiationPower = 100,
Timestamp = DateTime.UtcNow.Ticks
});
_infraredTracker.Update(0.1);
// Act - 停用导弹
missile.Deactivate(); // 直接停用导弹对象
_simulationManager.PublishEvent(new EntityDeactivatedEvent
{
DeactivatedEntityId = "missile1",
SenderId = "system",
Timestamp = DateTime.UtcNow.Ticks
});
// 给系统一些时间处理事件
_infraredTracker.Update(0.1);
missile.Update(0.1);
_infraredTracker.Update(0.1);
// Assert
Assert.Null(_infraredTracker.MissileId);
}
}
}

View File

@ -0,0 +1,129 @@
using Xunit;
using ThreatSource.Indicator;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Simulation.Testing;
using ThreatSource.Target;
namespace ThreatSource.Tests.Indicator
{
public class LaserBeamRiderTests
{
private readonly SimulationManager _simulationManager;
private readonly TestSimulationAdapter _testAdapter;
private readonly LaserBeamRider _laserBeamRider;
private readonly LaserBeamRiderConfig _config;
private readonly Tank _tank;
public LaserBeamRiderTests()
{
_simulationManager = new SimulationManager();
_testAdapter = new TestSimulationAdapter(_simulationManager);
_simulationManager.SetSimulationAdapter(_testAdapter);
_config = new LaserBeamRiderConfig
{
Id = "beamRider1",
InitialPosition = new Vector3D(0, 0, 0),
LaserPower = 1000,
ControlFieldDiameter = 5.0,
MaxGuidanceDistance = 5000
};
_tank = new Tank("target1", new Vector3D(100, 0, 0), 0, _simulationManager);
_simulationManager.RegisterEntity("target1", _tank);
_laserBeamRider = new LaserBeamRider(
"beamRider1",
"missile1",
"target1",
10,
_config,
_simulationManager
);
_simulationManager.RegisterEntity("beamRider1", _laserBeamRider);
}
[Fact]
public void Constructor_InitializesPropertiesCorrectly()
{
Assert.Equal("beamRider1", _laserBeamRider.Id);
Assert.Equal("missile1", _laserBeamRider.MissileId);
Assert.Equal("target1", _laserBeamRider.TargetId);
Assert.Equal(1000, _laserBeamRider.LaserPower);
Assert.Equal(5.0, _laserBeamRider.ControlFieldDiameter);
Assert.Equal(5000, _laserBeamRider.MaxGuidanceDistance);
Assert.False(_laserBeamRider.IsActive);
Assert.False(_laserBeamRider.IsBeamOn);
}
[Fact]
public void Activate_SetsCorrectState()
{
// Act
_laserBeamRider.Activate();
// Assert
Assert.True(_laserBeamRider.IsActive);
Assert.True(_laserBeamRider.IsBeamOn);
var publishedEvents = _testAdapter.GetPublishedEvents();
Assert.Contains(publishedEvents, evt => evt is LaserBeamStartEvent);
}
[Fact]
public void Deactivate_SetsCorrectState()
{
// Arrange
_laserBeamRider.Activate();
// Act
_laserBeamRider.Deactivate();
// Assert
Assert.False(_laserBeamRider.IsActive);
Assert.False(_laserBeamRider.IsBeamOn);
var publishedEvents = _testAdapter.GetPublishedEvents();
Assert.Contains(publishedEvents, evt => evt is LaserBeamStopEvent);
}
[Fact]
public void Update_PublishesBeamUpdateEvent_WhenActive()
{
// Arrange
_laserBeamRider.Activate();
_testAdapter.GetPublishedEvents(); // 清除之前的事件
// Act
_laserBeamRider.Update(0.1);
// Assert
var publishedEvents = _testAdapter.GetPublishedEvents();
Assert.Contains(publishedEvents, evt => evt is LaserBeamUpdateEvent);
}
[Fact]
public void GetStatus_ReturnsCorrectStatus()
{
// Act
string status = _laserBeamRider.GetStatus();
// Assert
var expectedParts = new[]
{
"激光驾束仪",
_laserBeamRider.Id,
"位置",
"方向",
"激活状态",
"激光功率",
"控制场直径",
"最大导引距离"
};
foreach (var part in expectedParts)
{
Assert.Contains(part, status);
}
}
}
}

View File

@ -0,0 +1,142 @@
using Xunit;
using ThreatSource.Indicator;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Simulation.Testing;
using ThreatSource.Target;
namespace ThreatSource.Tests.Indicator
{
public class LaserDesignatorTests
{
private readonly SimulationManager _simulationManager;
private readonly TestSimulationAdapter _testAdapter;
private readonly LaserDesignator _laserDesignator;
private readonly LaserDesignatorConfig _config;
private readonly Tank _tank;
public LaserDesignatorTests()
{
_simulationManager = new SimulationManager();
_testAdapter = new TestSimulationAdapter(_simulationManager);
_simulationManager.SetSimulationAdapter(_testAdapter);
_config = new LaserDesignatorConfig
{
Id = "laser1",
InitialPosition = new Vector3D(0, 0, 0),
LaserPower = 1000,
LaserDivergenceAngle = 0.001
};
_tank = new Tank("target1", new Vector3D(100, 0, 0), 0, _simulationManager);
_simulationManager.RegisterEntity("target1", _tank);
_laserDesignator = new LaserDesignator(
"laser1",
"target1",
"missile1",
10,
_config,
_simulationManager
);
_simulationManager.RegisterEntity("laser1", _laserDesignator);
}
[Fact]
public void Constructor_InitializesPropertiesCorrectly()
{
Assert.Equal("laser1", _laserDesignator.Id);
Assert.Equal("target1", _laserDesignator.TargetId);
Assert.Equal("missile1", _laserDesignator.MissileId);
Assert.Equal(1000, _laserDesignator.LaserPower);
Assert.Equal(0.001, _laserDesignator.LaserDivergenceAngle);
Assert.False(_laserDesignator.IsActive);
Assert.False(_laserDesignator.IsIlluminationOn);
Assert.False(_laserDesignator.IsJammed);
}
[Fact]
public void Activate_SetsCorrectState()
{
// Act
_laserDesignator.Activate();
// Assert
Assert.True(_laserDesignator.IsActive);
}
[Fact]
public void Deactivate_SetsCorrectState()
{
// Arrange
_laserDesignator.Activate();
// Act
_laserDesignator.Deactivate();
// Assert
Assert.False(_laserDesignator.IsActive);
}
[Theory]
[InlineData(1000000, true)] // 高功率干扰
[InlineData(1, false)] // 低功率干扰
public void LaserJamming_SetsCorrectJammedState(double jammingPower, bool expectedJammedState)
{
// Arrange
_laserDesignator.Activate();
// Act
_simulationManager.PublishEvent(new LaserJammingEvent
{
TargetId = "target1",
JammingPower = jammingPower,
SenderId = "jammer1"
});
_laserDesignator.Update(0.1);
// Assert
Assert.Equal(expectedJammedState, _laserDesignator.IsJammed);
}
[Fact]
public void GetStatus_ReturnsCorrectStatus()
{
// Act
string status = _laserDesignator.GetStatus();
// Assert
var expectedParts = new[]
{
"激光目标指示器",
_laserDesignator.Id,
"位置",
_laserDesignator.Position.ToString()
};
foreach (var part in expectedParts)
{
Assert.Contains(part, status);
}
}
[Fact]
public void EntityDeactivation_HandlesTargetDeactivationCorrectly()
{
// Arrange
_laserDesignator.Activate();
// Act
_simulationManager.PublishEvent(new EntityDeactivatedEvent
{
DeactivatedEntityId = "target1",
SenderId = "system"
});
_laserDesignator.Update(0.1);
// Assert
Assert.False(_laserDesignator.IsIlluminationOn);
}
}
}

View File

@ -0,0 +1,157 @@
using Xunit;
using ThreatSource.Missile;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Simulation.Testing;
namespace ThreatSource.Tests.Missile
{
public class BaseMissileTests
{
private readonly SimulationManager _simulationManager;
private readonly TestSimulationAdapter _testAdapter;
private readonly BaseMissile _missile;
private readonly MissileProperties _properties;
public BaseMissileTests()
{
_simulationManager = new SimulationManager();
_testAdapter = new TestSimulationAdapter(_simulationManager);
_simulationManager.SetSimulationAdapter(_testAdapter);
_properties = new MissileProperties
{
Id = "missile1",
InitialPosition = new Vector3D(0, 0, 0),
InitialOrientation = new Orientation(0, 0, 0),
InitialSpeed = 100,
MaxSpeed = 1000,
MaxFlightTime = 100,
MaxFlightDistance = 10000,
MaxAcceleration = 50,
ProportionalNavigationCoefficient = 3,
Mass = 100,
ExplosionRadius = 10,
HitProbability = 0.9,
Type = MissileType.StandardMissile
};
_missile = new BaseMissile(_properties, _simulationManager);
_simulationManager.RegisterEntity("missile1", _missile);
}
[Fact]
public void Constructor_InitializesPropertiesCorrectly()
{
Assert.Equal("missile1", _missile.Id);
Assert.Equal(new Vector3D(0, 0, 0), _missile.Position);
Assert.Equal(new Orientation(0, 0, 0), _missile.Orientation);
Assert.Equal(100, _missile.Speed);
Assert.False(_missile.IsActive);
Assert.False(_missile.IsGuidance);
Assert.Equal(0, _missile.FlightTime);
Assert.Equal(0, _missile.FlightDistance);
Assert.Equal(0, _missile.EngineBurnTime);
}
[Fact]
public void Fire_ActivatesMissile()
{
// Act
_missile.Fire();
// Assert
Assert.True(_missile.IsActive);
}
[Fact]
public void Update_UpdatesFlightParameters()
{
// Arrange
_missile.Fire();
var initialPosition = _missile.Position;
var deltaTime = 1.0;
// Act
_missile.Update(deltaTime);
// Assert
Assert.Equal(deltaTime, _missile.FlightTime);
Assert.Equal(_missile.Speed * deltaTime, _missile.FlightDistance);
Assert.NotEqual(initialPosition, _missile.Position);
}
[Fact]
public void Update_LimitsSpeed()
{
// Arrange
_missile.Fire();
var deltaTime = 1.0;
// Act - 给导弹一个超过最大速度的速度
_missile.Update(deltaTime);
// Assert
Assert.True(_missile.Speed <= _properties.MaxSpeed);
}
[Fact]
public void Explode_DeactivatesMissile()
{
// Arrange
_missile.Fire();
// Act
_missile.Explode();
// Assert
Assert.False(_missile.IsActive);
}
[Fact]
public void SelfDestruct_DeactivatesMissile()
{
// Arrange
_missile.Fire();
// Act
_missile.SelfDestruct();
// Assert
Assert.False(_missile.IsActive);
}
[Fact]
public void GetStatus_ReturnsCorrectStatus()
{
// Act
string status = _missile.GetStatus();
// Assert
Assert.Contains(_missile.Id, status);
Assert.Contains(_missile.Position.ToString(), status);
Assert.Contains(_missile.Speed.ToString(), status);
Assert.Contains(_missile.FlightTime.ToString(), status);
Assert.Contains(_missile.FlightDistance.ToString(), status);
}
[Fact]
public void GetRunningState_ReturnsCorrectState()
{
// Act
var state = _missile.GetRunningState();
// Assert
Assert.Equal(_missile.Id, state.Id);
Assert.Equal(_properties.Type, state.Type);
Assert.Equal(_missile.Position, state.Position);
Assert.Equal(_missile.Velocity, state.Velocity);
Assert.Equal(_missile.Orientation, state.Orientation);
Assert.Equal(_missile.Speed, state.Speed);
Assert.Equal(_missile.FlightTime, state.FlightTime);
Assert.Equal(_missile.FlightDistance, state.FlightDistance);
Assert.Equal(_missile.IsGuidance, state.IsGuidance);
Assert.Equal(_missile.IsActive, state.IsActive);
}
}
}

View File

@ -0,0 +1,199 @@
using Xunit;
using ThreatSource.Missile;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Simulation.Testing;
namespace ThreatSource.Tests.Missile
{
public class InfraredCommandGuidedMissileTests
{
private readonly SimulationManager _simulationManager;
private readonly TestSimulationAdapter _testAdapter;
private readonly InfraredCommandGuidedMissile _missile;
private readonly MissileProperties _properties;
public InfraredCommandGuidedMissileTests()
{
_simulationManager = new SimulationManager();
_testAdapter = new TestSimulationAdapter(_simulationManager);
_simulationManager.SetSimulationAdapter(_testAdapter);
_properties = new MissileProperties
{
Id = "missile1",
InitialPosition = new Vector3D(0, 0, 0),
InitialOrientation = new Orientation(0, 0, 0),
InitialSpeed = 100,
MaxSpeed = 1000,
MaxFlightTime = 100,
MaxFlightDistance = 10000,
MaxAcceleration = 50,
ProportionalNavigationCoefficient = 3,
Mass = 100,
ExplosionRadius = 10,
HitProbability = 0.9,
Type = MissileType.InfraredCommandGuidance
};
_missile = new InfraredCommandGuidedMissile(_properties, _simulationManager);
_simulationManager.RegisterEntity("missile1", _missile);
}
[Fact]
public void Constructor_InitializesPropertiesCorrectly()
{
Assert.Equal("missile1", _missile.Id);
Assert.Equal(new Vector3D(0, 0, 0), _missile.Position);
Assert.Equal(new Orientation(0, 0, 0), _missile.Orientation);
Assert.Equal(100, _missile.Speed);
Assert.False(_missile.IsActive);
Assert.False(_missile.IsGuidance);
Assert.Equal(1000, _missile.RadiationPower); // 默认红外辐射功率
}
[Fact]
public void Update_InLaunchStage_NoGuidance()
{
// Arrange
_missile.Fire();
_missile.Activate();
// Act
_missile.Update(0.01); // 发射阶段很短用0.01秒
// Assert
Assert.False(_missile.IsGuidance, "发射阶段不应该有制导");
}
[Fact]
public void Update_InCruiseStage_NoGuidanceWithoutCommand()
{
// Arrange
_missile.Fire();
_missile.Activate();
// Act - 等待超过发射阶段
_missile.Update(0.1); // 发射阶段0.1秒这里用0.1秒确保进入巡航阶段
// Assert
Assert.False(_missile.IsGuidance, "没有制导指令时不应该有制导");
}
[Fact]
public void Update_LightsInfraredSource_WhenActive()
{
// Arrange
_missile.Fire();
_missile.Activate();
// Act
_missile.Update(0.1);
// Assert
var publishedEvents = _testAdapter.GetPublishedEvents();
Assert.Contains(publishedEvents, evt => evt is InfraredGuidanceMissileLightEvent);
}
[Fact]
public void Deactivate_TurnsOffInfraredSource()
{
// Arrange
_missile.Fire();
_missile.Activate();
_missile.Update(0.1);
_testAdapter.GetPublishedEvents(); // 清除之前的事件
// Act
_missile.Deactivate();
// Assert
var publishedEvents = _testAdapter.GetPublishedEvents();
Assert.Contains(publishedEvents, evt => evt is InfraredGuidanceMissileLightOffEvent);
}
[Fact]
public void Update_ExceedsMaxFlightTime_SelfDestructs()
{
// Arrange
_missile.Fire();
_missile.Activate();
var maxFlightTime = _properties.MaxFlightTime;
// Act
for (double time = 0; time < maxFlightTime + 1; time += 0.1)
{
_missile.Update(0.1);
}
// Assert
Assert.False(_missile.IsActive, "超出最大飞行时间应该自毁");
}
[Fact]
public void Update_ExceedsMaxFlightDistance_SelfDestructs()
{
// Arrange
_missile.Fire();
_missile.Activate();
var maxDistance = _properties.MaxFlightDistance;
var timeToExceedDistance = maxDistance / _properties.InitialSpeed + 1;
// Act
for (double time = 0; time < timeToExceedDistance; time += 0.1)
{
_missile.Update(0.1);
}
// Assert
Assert.False(_missile.IsActive, "超出最大飞行距离应该自毁");
}
[Fact]
public void GetStatus_ReturnsCorrectStatus()
{
// Act
string status = _missile.GetStatus();
// Assert
var expectedParts = new[]
{
"导弹",
_missile.Id,
"位置",
_missile.Position.ToString(),
"速度",
_missile.Speed.ToString(),
"飞行时间",
_missile.FlightTime.ToString(),
"飞行距离",
_missile.FlightDistance.ToString(),
"当前阶段"
};
foreach (var part in expectedParts)
{
Assert.Contains(part, status);
}
}
[Fact]
public void GetRunningState_ReturnsCorrectState()
{
// Act
var state = _missile.GetRunningState();
// Assert
Assert.Equal(_missile.Id, state.Id);
Assert.Equal(MissileType.InfraredCommandGuidance, state.Type);
Assert.Equal(_missile.Position, state.Position);
Assert.Equal(_missile.Velocity, state.Velocity);
Assert.Equal(_missile.Orientation, state.Orientation);
Assert.Equal(_missile.Speed, state.Speed);
Assert.Equal(_missile.FlightTime, state.FlightTime);
Assert.Equal(_missile.FlightDistance, state.FlightDistance);
Assert.Equal(_missile.IsGuidance, state.IsGuidance);
Assert.Equal(_missile.IsActive, state.IsActive);
}
}
}

View File

@ -0,0 +1,184 @@
using Xunit;
using ThreatSource.Missile;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Simulation.Testing;
using ThreatSource.Target;
namespace ThreatSource.Tests.Missile
{
public class InfraredImagingTerminalGuidedMissileTests
{
private readonly SimulationManager _simulationManager;
private readonly TestSimulationAdapter _testAdapter;
private readonly InfraredImagingTerminalGuidedMissile _missile;
private readonly MissileProperties _properties;
public InfraredImagingTerminalGuidedMissileTests()
{
_simulationManager = new SimulationManager();
_testAdapter = new TestSimulationAdapter(_simulationManager);
_simulationManager.SetSimulationAdapter(_testAdapter);
_properties = new MissileProperties
{
Id = "missile1",
InitialPosition = new Vector3D(0, 0, 0),
InitialOrientation = new Orientation(0, 0, 0),
InitialSpeed = 100,
MaxSpeed = 1000,
MaxFlightTime = 100,
MaxFlightDistance = 10000,
MaxAcceleration = 50,
ProportionalNavigationCoefficient = 3,
Mass = 100,
ExplosionRadius = 10,
HitProbability = 0.9,
Type = MissileType.InfraredImagingTerminalGuidance
};
_missile = new InfraredImagingTerminalGuidedMissile(_properties, _simulationManager);
_simulationManager.RegisterEntity("missile1", _missile);
}
[Fact]
public void Constructor_InitializesPropertiesCorrectly()
{
Assert.Equal("missile1", _missile.Id);
Assert.Equal(new Vector3D(0, 0, 0), _missile.Position);
Assert.Equal(new Orientation(0, 0, 0), _missile.Orientation);
Assert.Equal(100, _missile.Speed);
Assert.False(_missile.IsActive);
Assert.False(_missile.IsGuidance);
}
[Fact]
public void Update_StageTransition_WorksCorrectly()
{
// Arrange
var tank = new Tank("target1", new Vector3D(1000, 0, 0), 0, _simulationManager);
_simulationManager.RegisterEntity("target1", tank);
tank.Activate();
_missile.Fire();
_missile.Activate();
// Act & Assert
// 发射阶段
_missile.Update(0.01);
var status = _missile.GetStatus();
Assert.Contains("Launch", status);
// 巡航阶段
for (double time = 0; time < 1.0; time += 0.1)
{
_missile.Update(0.1);
}
status = _missile.GetStatus();
Assert.Contains("Cruise", status);
// 末制导阶段
for (double time = 0; time < 3.0; time += 0.1)
{
// 发布坦克辐射事件
_simulationManager.PublishEvent(new TankRadiationEvent
{
SenderId = "target1",
InfraredRadiationIntensity = 100.0,
LaserReflectionIntensity = 0.0,
MillimeterWaveReflectionIntensity = 0.0,
MillimeterWaveRadiationTemperature = 300.0,
Timestamp = DateTime.UtcNow.Ticks
});
tank.Update(0.1);
_missile.Update(0.1);
}
status = _missile.GetStatus();
Assert.Contains("Terminal", status);
}
[Fact]
public void Update_ExceedsMaxFlightTime_SelfDestructs()
{
// Arrange
_missile.Fire();
_missile.Activate();
var maxFlightTime = _properties.MaxFlightTime;
// Act
for (double time = 0; time < maxFlightTime + 1; time += 0.1)
{
_missile.Update(0.1);
}
// Assert
Assert.False(_missile.IsActive, "超出最大飞行时间应该自毁");
}
[Fact]
public void Update_ExceedsMaxFlightDistance_SelfDestructs()
{
// Arrange
_missile.Fire();
_missile.Activate();
var maxDistance = _properties.MaxFlightDistance;
var timeToExceedDistance = maxDistance / _properties.InitialSpeed + 1;
// Act
for (double time = 0; time < timeToExceedDistance; time += 0.1)
{
_missile.Update(0.1);
}
// Assert
Assert.False(_missile.IsActive, "超出最大飞行距离应该自毁");
}
[Fact]
public void GetStatus_ReturnsCorrectStatus()
{
// Act
string status = _missile.GetStatus();
// Assert
var expectedParts = new[]
{
"导弹",
_missile.Id,
"位置",
_missile.Position.ToString(),
"速度",
_missile.Speed.ToString(),
"飞行时间",
_missile.FlightTime.ToString(),
"飞行距离",
_missile.FlightDistance.ToString()
};
foreach (var part in expectedParts)
{
Assert.Contains(part, status);
}
}
[Fact]
public void GetRunningState_ReturnsCorrectState()
{
// Act
var state = _missile.GetRunningState();
// Assert
Assert.Equal(_missile.Id, state.Id);
Assert.Equal(MissileType.InfraredImagingTerminalGuidance, state.Type);
Assert.Equal(_missile.Position, state.Position);
Assert.Equal(_missile.Velocity, state.Velocity);
Assert.Equal(_missile.Orientation, state.Orientation);
Assert.Equal(_missile.Speed, state.Speed);
Assert.Equal(_missile.FlightTime, state.FlightTime);
Assert.Equal(_missile.FlightDistance, state.FlightDistance);
Assert.Equal(_missile.IsGuidance, state.IsGuidance);
Assert.Equal(_missile.IsActive, state.IsActive);
}
}
}

View File

@ -0,0 +1,153 @@
using Xunit;
using ThreatSource.Missile;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Simulation.Testing;
namespace ThreatSource.Tests.Missile
{
public class LaserBeamRiderMissileTests
{
private readonly SimulationManager _simulationManager;
private readonly TestSimulationAdapter _testAdapter;
private readonly LaserBeamRiderMissile _missile;
private readonly MissileProperties _properties;
public LaserBeamRiderMissileTests()
{
_simulationManager = new SimulationManager();
_testAdapter = new TestSimulationAdapter(_simulationManager);
_simulationManager.SetSimulationAdapter(_testAdapter);
_properties = new MissileProperties
{
Id = "missile1",
InitialPosition = new Vector3D(0, 0, 0),
InitialOrientation = new Orientation(0, 0, 0),
InitialSpeed = 100,
MaxSpeed = 1000,
MaxFlightTime = 100,
MaxFlightDistance = 10000,
MaxAcceleration = 50,
ProportionalNavigationCoefficient = 3,
Mass = 100,
ExplosionRadius = 10,
HitProbability = 0.9,
Type = MissileType.LaserBeamRiderGuidance
};
_missile = new LaserBeamRiderMissile(_properties, _simulationManager);
_simulationManager.RegisterEntity("missile1", _missile);
}
[Fact]
public void Constructor_InitializesPropertiesCorrectly()
{
Assert.Equal("missile1", _missile.Id);
Assert.Equal(new Vector3D(0, 0, 0), _missile.Position);
Assert.Equal(new Orientation(0, 0, 0), _missile.Orientation);
Assert.Equal(100, _missile.Speed);
Assert.False(_missile.IsActive);
Assert.False(_missile.IsGuidance);
}
[Fact]
public void Update_InLaunchStage_NoGuidance()
{
// Arrange
_missile.Fire();
_missile.Activate();
// Act
_missile.Update(0.01); // 发射阶段很短用0.01秒
// Assert
Assert.False(_missile.IsGuidance, "发射阶段不应该有制导");
}
[Fact]
public void Update_InCruiseStage_NoGuidanceWithoutLaserBeam()
{
// Arrange
_missile.Fire();
_missile.Activate();
// Act - 等待超过发射阶段
_missile.Update(0.1); // 发射阶段0.01秒这里用0.1秒确保进入巡航阶段
// Assert
Assert.False(_missile.IsGuidance, "没有激光束照射时不应该有制导");
}
[Fact]
public void Update_ExceedsMaxFlightTime_SelfDestructs()
{
// Arrange
_missile.Fire();
_missile.Activate();
var maxFlightTime = _properties.MaxFlightTime;
// Act
for (double time = 0; time < maxFlightTime + 1; time += 0.1)
{
_missile.Update(0.1);
}
// Assert
Assert.False(_missile.IsActive, "超出最大飞行时间应该自毁");
}
[Fact]
public void Update_ExceedsMaxFlightDistance_SelfDestructs()
{
// Arrange
_missile.Fire();
_missile.Activate();
var maxDistance = _properties.MaxFlightDistance;
var timeToExceedDistance = maxDistance / _properties.InitialSpeed + 1;
// Act
for (double time = 0; time < timeToExceedDistance; time += 0.1)
{
_missile.Update(0.1);
}
// Assert
Assert.False(_missile.IsActive, "超出最大飞行距离应该自毁");
}
[Fact]
public void GetStatus_ReturnsCorrectStatus()
{
// Act
string status = _missile.GetStatus();
// Assert
Assert.Contains("激光驾束制导导弹", status);
Assert.Contains(_missile.Id, status);
Assert.Contains(_missile.Position.ToString(), status);
Assert.Contains(_missile.Speed.ToString(), status);
Assert.Contains(_missile.FlightTime.ToString(), status);
Assert.Contains(_missile.FlightDistance.ToString(), status);
}
[Fact]
public void GetRunningState_ReturnsCorrectState()
{
// Act
var state = _missile.GetRunningState();
// Assert
Assert.Equal(_missile.Id, state.Id);
Assert.Equal(MissileType.LaserBeamRiderGuidance, state.Type);
Assert.Equal(_missile.Position, state.Position);
Assert.Equal(_missile.Velocity, state.Velocity);
Assert.Equal(_missile.Orientation, state.Orientation);
Assert.Equal(_missile.Speed, state.Speed);
Assert.Equal(_missile.FlightTime, state.FlightTime);
Assert.Equal(_missile.FlightDistance, state.FlightDistance);
Assert.Equal(_missile.IsGuidance, state.IsGuidance);
Assert.Equal(_missile.IsActive, state.IsActive);
}
}
}

View File

@ -0,0 +1,165 @@
using Xunit;
using ThreatSource.Missile;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Simulation.Testing;
namespace ThreatSource.Tests.Missile
{
public class LaserSemiActiveGuidedMissileTests
{
private readonly SimulationManager _simulationManager;
private readonly TestSimulationAdapter _testAdapter;
private readonly LaserSemiActiveGuidedMissile _missile;
private readonly MissileProperties _properties;
public LaserSemiActiveGuidedMissileTests()
{
_simulationManager = new SimulationManager();
_testAdapter = new TestSimulationAdapter(_simulationManager);
_simulationManager.SetSimulationAdapter(_testAdapter);
_properties = new MissileProperties
{
Id = "missile1",
InitialPosition = new Vector3D(0, 0, 0),
InitialOrientation = new Orientation(0, 0, 0),
InitialSpeed = 100,
MaxSpeed = 1000,
MaxFlightTime = 100,
MaxFlightDistance = 10000,
MaxAcceleration = 50,
ProportionalNavigationCoefficient = 3,
Mass = 100,
ExplosionRadius = 10,
HitProbability = 0.9,
Type = MissileType.LaserSemiActiveGuidance
};
_missile = new LaserSemiActiveGuidedMissile(_properties, _simulationManager);
_simulationManager.RegisterEntity("missile1", _missile);
}
[Fact]
public void Constructor_InitializesPropertiesCorrectly()
{
Assert.Equal("missile1", _missile.Id);
Assert.Equal(new Vector3D(0, 0, 0), _missile.Position);
Assert.Equal(new Orientation(0, 0, 0), _missile.Orientation);
Assert.Equal(100, _missile.Speed);
Assert.False(_missile.IsActive);
Assert.False(_missile.IsGuidance);
}
[Fact]
public void Update_InLaunchStage_NoGuidance()
{
// Arrange
_missile.Fire();
_missile.Activate();
// Act
_missile.Update(0.01); // 发射阶段很短用0.01秒
// Assert
Assert.False(_missile.IsGuidance, "发射阶段不应该有制导");
}
[Fact]
public void Update_InCruiseStage_NoGuidanceWithoutLaserIllumination()
{
// Arrange
_missile.Fire();
_missile.Activate();
// Act - 等待超过发射阶段
_missile.Update(0.1); // 发射阶段0.1秒这里用0.1秒确保进入巡航阶段
// Assert
Assert.False(_missile.IsGuidance, "没有激光照射时不应该有制导");
}
[Fact]
public void Update_ExceedsMaxFlightTime_SelfDestructs()
{
// Arrange
_missile.Fire();
_missile.Activate();
var maxFlightTime = _properties.MaxFlightTime;
// Act
for (double time = 0; time < maxFlightTime + 1; time += 0.1)
{
_missile.Update(0.1);
}
// Assert
Assert.False(_missile.IsActive, "超出最大飞行时间应该自毁");
}
[Fact]
public void Update_ExceedsMaxFlightDistance_SelfDestructs()
{
// Arrange
_missile.Fire();
_missile.Activate();
var maxDistance = _properties.MaxFlightDistance;
var timeToExceedDistance = maxDistance / _properties.InitialSpeed + 1;
// Act
for (double time = 0; time < timeToExceedDistance; time += 0.1)
{
_missile.Update(0.1);
}
// Assert
Assert.False(_missile.IsActive, "超出最大飞行距离应该自毁");
}
[Fact]
public void GetStatus_ReturnsCorrectStatus()
{
// Act
string status = _missile.GetStatus();
// Assert
var expectedParts = new[]
{
"激光半主动制导导弹",
_missile.Id,
"位置",
_missile.Position.ToString(),
"速度",
_missile.Speed.ToString(),
"飞行时间",
_missile.FlightTime.ToString(),
"飞行距离",
_missile.FlightDistance.ToString()
};
foreach (var part in expectedParts)
{
Assert.Contains(part, status);
}
}
[Fact]
public void GetRunningState_ReturnsCorrectState()
{
// Act
var state = _missile.GetRunningState();
// Assert
Assert.Equal(_missile.Id, state.Id);
Assert.Equal(MissileType.LaserSemiActiveGuidance, state.Type);
Assert.Equal(_missile.Position, state.Position);
Assert.Equal(_missile.Velocity, state.Velocity);
Assert.Equal(_missile.Orientation, state.Orientation);
Assert.Equal(_missile.Speed, state.Speed);
Assert.Equal(_missile.FlightTime, state.FlightTime);
Assert.Equal(_missile.FlightDistance, state.FlightDistance);
Assert.Equal(_missile.IsGuidance, state.IsGuidance);
Assert.Equal(_missile.IsActive, state.IsActive);
}
}
}

View File

@ -0,0 +1,184 @@
using Xunit;
using ThreatSource.Missile;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Simulation.Testing;
using ThreatSource.Target;
namespace ThreatSource.Tests.Missile
{
public class MillimeterWaveTerminalGuidedMissileTests
{
private readonly SimulationManager _simulationManager;
private readonly TestSimulationAdapter _testAdapter;
private readonly MillimeterWaveTerminalGuidedMissile _missile;
private readonly MissileProperties _properties;
public MillimeterWaveTerminalGuidedMissileTests()
{
_simulationManager = new SimulationManager();
_testAdapter = new TestSimulationAdapter(_simulationManager);
_simulationManager.SetSimulationAdapter(_testAdapter);
_properties = new MissileProperties
{
Id = "missile1",
InitialPosition = new Vector3D(0, 0, 0),
InitialOrientation = new Orientation(0, 0, 0),
InitialSpeed = 100,
MaxSpeed = 1000,
MaxFlightTime = 100,
MaxFlightDistance = 10000,
MaxAcceleration = 50,
ProportionalNavigationCoefficient = 3,
Mass = 100,
ExplosionRadius = 10,
HitProbability = 0.9,
Type = MissileType.MillimeterWaveTerminalGuidance
};
_missile = new MillimeterWaveTerminalGuidedMissile(_properties, _simulationManager);
_simulationManager.RegisterEntity("missile1", _missile);
}
[Fact]
public void Constructor_InitializesPropertiesCorrectly()
{
Assert.Equal("missile1", _missile.Id);
Assert.Equal(new Vector3D(0, 0, 0), _missile.Position);
Assert.Equal(new Orientation(0, 0, 0), _missile.Orientation);
Assert.Equal(100, _missile.Speed);
Assert.False(_missile.IsActive);
Assert.False(_missile.IsGuidance);
}
[Fact]
public void Update_StageTransition_WorksCorrectly()
{
// Arrange
var tank = new Tank("target1", new Vector3D(1000, 0, 0), 0, _simulationManager);
_simulationManager.RegisterEntity("target1", tank);
tank.Activate();
_missile.Fire();
_missile.Activate();
// Act & Assert
// 发射阶段
_missile.Update(0.01);
var status = _missile.GetStatus();
Assert.Contains("Launch", status);
// 巡航阶段
for (double time = 0; time < 1.0; time += 0.1)
{
_missile.Update(0.1);
}
status = _missile.GetStatus();
Assert.Contains("Cruise", status);
// 末制导阶段
for (double time = 0; time < 3.0; time += 0.1)
{
// 发布坦克辐射事件
_simulationManager.PublishEvent(new TankRadiationEvent
{
SenderId = "target1",
InfraredRadiationIntensity = 0.0,
LaserReflectionIntensity = 0.0,
MillimeterWaveReflectionIntensity = 1.0,
MillimeterWaveRadiationTemperature = 300.0,
Timestamp = DateTime.UtcNow.Ticks
});
tank.Update(0.1);
_missile.Update(0.1);
}
status = _missile.GetStatus();
Assert.Contains("Terminal", status);
}
[Fact]
public void Update_ExceedsMaxFlightTime_SelfDestructs()
{
// Arrange
_missile.Fire();
_missile.Activate();
var maxFlightTime = _properties.MaxFlightTime;
// Act
for (double time = 0; time < maxFlightTime + 1; time += 0.1)
{
_missile.Update(0.1);
}
// Assert
Assert.False(_missile.IsActive, "超出最大飞行时间应该自毁");
}
[Fact]
public void Update_ExceedsMaxFlightDistance_SelfDestructs()
{
// Arrange
_missile.Fire();
_missile.Activate();
var maxDistance = _properties.MaxFlightDistance;
var timeToExceedDistance = maxDistance / _properties.InitialSpeed + 1;
// Act
for (double time = 0; time < timeToExceedDistance; time += 0.1)
{
_missile.Update(0.1);
}
// Assert
Assert.False(_missile.IsActive, "超出最大飞行距离应该自毁");
}
[Fact]
public void GetStatus_ReturnsCorrectStatus()
{
// Act
string status = _missile.GetStatus();
// Assert
var expectedParts = new[]
{
"导弹",
_missile.Id,
"位置",
_missile.Position.ToString(),
"速度",
_missile.Speed.ToString(),
"飞行时间",
_missile.FlightTime.ToString(),
"飞行距离",
_missile.FlightDistance.ToString()
};
foreach (var part in expectedParts)
{
Assert.Contains(part, status);
}
}
[Fact]
public void GetRunningState_ReturnsCorrectState()
{
// Act
var state = _missile.GetRunningState();
// Assert
Assert.Equal(_missile.Id, state.Id);
Assert.Equal(MissileType.MillimeterWaveTerminalGuidance, state.Type);
Assert.Equal(_missile.Position, state.Position);
Assert.Equal(_missile.Velocity, state.Velocity);
Assert.Equal(_missile.Orientation, state.Orientation);
Assert.Equal(_missile.Speed, state.Speed);
Assert.Equal(_missile.FlightTime, state.FlightTime);
Assert.Equal(_missile.FlightDistance, state.FlightDistance);
Assert.Equal(_missile.IsGuidance, state.IsGuidance);
Assert.Equal(_missile.IsActive, state.IsActive);
}
}
}

View File

@ -0,0 +1,204 @@
using Xunit;
using Xunit.Abstractions;
using ThreatSource.Missile;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Simulation.Testing;
using ThreatSource.Target;
namespace ThreatSource.Tests.Missile
{
public class TerminalSensitiveMissileTests
{
private readonly ITestOutputHelper _output;
private readonly SimulationManager _simulationManager;
private readonly TestSimulationAdapter _testAdapter;
private readonly TerminalSensitiveMissile _missile;
private readonly MissileProperties _properties;
private readonly Tank _tank;
public TerminalSensitiveMissileTests(ITestOutputHelper output)
{
_output = output;
_simulationManager = new SimulationManager();
_testAdapter = new TestSimulationAdapter(_simulationManager);
_simulationManager.SetSimulationAdapter(_testAdapter);
// 先创建并注册目标
_tank = new Tank(
"tank1",
new Vector3D(100, 0, 100),
Math.PI/4, // 目标朝向45度
_simulationManager
);
_simulationManager.RegisterEntity("tank1", _tank);
_tank.Activate();
_properties = new MissileProperties
{
Id = "missile1",
InitialPosition = new Vector3D(3000, 0, 100),
InitialOrientation = new Orientation(Math.PI, 0, 0),
InitialSpeed = 800,
MaxSpeed = 1000,
MaxFlightTime = 30,
MaxFlightDistance = 5000,
LaunchAcceleration = 0,
MaxEngineBurnTime = 0,
MaxAcceleration = 10,
ProportionalNavigationCoefficient = 3,
ExplosionRadius = 5,
HitProbability = 0.9,
Mass = 50,
Type = MissileType.TerminalSensitiveMissile
};
_missile = new TerminalSensitiveMissile("tank1", _properties, _simulationManager);
_simulationManager.RegisterEntity("missile1", _missile);
}
[Fact]
public void Constructor_InitializesPropertiesCorrectly()
{
Assert.Equal("missile1", _missile.Id);
Assert.Equal(new Vector3D(3000, 0, 100), _missile.Position);
Assert.Equal(800, _missile.Speed);
Assert.False(_missile.IsActive);
Assert.False(_missile.IsGuidance);
}
[Fact]
public void Update_SeparationOccurs_AtCorrectHeight()
{
// Arrange
_missile.Fire();
_missile.Activate();
// Act - 更新直到分离高度
var publishedEvents = _testAdapter.GetPublishedEvents();
bool submunitionsRegistered = false;
double totalTime = 0;
Vector3D lastPosition = _missile.Position;
_output.WriteLine("\n开始测试导弹分离");
_output.WriteLine($"初始位置:{_missile.Position}");
_output.WriteLine($"初始速度:{_missile.Velocity},大小:{_missile.Velocity.Magnitude():F1}米/秒");
_output.WriteLine($"目标位置:{_tank.Position}");
Vector3D separationPoint = Vector3D.PointOnLine(_tank.Position, _missile.Position, 1000) + new Vector3D(0, 1000, 0);
_output.WriteLine($"分离点:{separationPoint}");
_output.WriteLine($"制导状态:{_missile.IsGuidance}");
_output.WriteLine("-------------------");
// 更新直到分离或最大时间30秒
while (totalTime < 30.0 && !submunitionsRegistered && _missile.IsActive)
{
_missile.Update(0.05);
_tank.Update(0.025);
totalTime += 0.025;
// 每一步都输出状态
_output.WriteLine($"\n时间{totalTime:F1}秒");
_output.WriteLine($"位置:({_missile.Position.X:F1}, {_missile.Position.Y:F1}, {_missile.Position.Z:F1})");
_output.WriteLine($"速度:{_missile.Velocity.Magnitude():F1}米/秒");
_output.WriteLine($"速度方向:({_missile.Velocity.X:F1}, {_missile.Velocity.Y:F1}, {_missile.Velocity.Z:F1})");
_output.WriteLine($"制导状态:{_missile.IsGuidance}");
_output.WriteLine($"距离分离点:{(separationPoint - _missile.Position).Magnitude():F1}米");
lastPosition = _missile.Position;
// 检查是否有子弹被注册
var entities = _simulationManager.GetAllEntities();
submunitionsRegistered = entities.Any(e => e is TerminalSensitiveSubmunition);
if (submunitionsRegistered)
{
_output.WriteLine($"\n分离发生在时间{totalTime:F1}秒");
_output.WriteLine($"分离位置:{_missile.Position}");
break;
}
}
// Assert
Assert.True(submunitionsRegistered, "子弹应该被注册和激活");
Assert.False(_missile.IsActive, "母弹应该在分离后停用");
// 验证子弹的属性
var submunition = _simulationManager.GetAllEntities()
.OfType<TerminalSensitiveSubmunition>()
.FirstOrDefault();
Assert.NotNull(submunition);
Assert.True(submunition.IsActive);
Assert.StartsWith($"{_missile.Id}_Sub_", submunition.Id);
}
[Fact]
public void Update_ExceedsMaxFlightTime_SelfDestructs()
{
// Arrange
_missile.Fire();
_missile.Activate();
var maxFlightTime = _properties.MaxFlightTime;
double totalTime = 0;
// Act
while (totalTime < maxFlightTime + 1 && _missile.IsActive)
{
_missile.Update(0.1);
totalTime += 0.1;
// 如果导弹已经分离,就停止测试
if (!_missile.IsActive)
{
break;
}
}
// Assert
Assert.False(_missile.IsActive, "超出最大飞行时间或分离后应该停用");
}
[Fact]
public void GetStatus_ReturnsCorrectStatus()
{
// Act
string status = _missile.GetStatus();
// Assert
var expectedParts = new[]
{
"导弹",
_missile.Id,
"位置",
_missile.Position.ToString(),
"速度",
_missile.Speed.ToString(),
"飞行时间",
_missile.FlightDistance.ToString(),
"母弹"
};
foreach (var part in expectedParts)
{
Assert.Contains(part, status);
}
}
[Fact]
public void GetRunningState_ReturnsCorrectState()
{
// Act
var state = _missile.GetRunningState();
// Assert
Assert.Equal(_missile.Id, state.Id);
Assert.Equal(MissileType.TerminalSensitiveMissile, state.Type);
Assert.Equal(_missile.Position, state.Position);
Assert.Equal(_missile.Velocity, state.Velocity);
Assert.Equal(_missile.Orientation, state.Orientation);
Assert.Equal(_missile.Speed, state.Speed);
Assert.Equal(_missile.FlightTime, state.FlightTime);
Assert.Equal(_missile.FlightDistance, state.FlightDistance);
Assert.Equal(_missile.IsGuidance, state.IsGuidance);
Assert.Equal(_missile.IsActive, state.IsActive);
}
}
}

View File

@ -0,0 +1,172 @@
using Xunit;
using ThreatSource.Missile;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Simulation.Testing;
using ThreatSource.Target;
namespace ThreatSource.Tests.Missile
{
public class TerminalSensitiveSubmunitionTests
{
private readonly SimulationManager _simulationManager;
private readonly TestSimulationAdapter _testAdapter;
private readonly TerminalSensitiveSubmunition _submunition;
private readonly MissileProperties _properties;
private readonly Tank _tank;
public TerminalSensitiveSubmunitionTests()
{
_simulationManager = new SimulationManager();
_testAdapter = new TestSimulationAdapter(_simulationManager);
_simulationManager.SetSimulationAdapter(_testAdapter);
// 先创建并注册目标
_tank = new Tank(
"tank1",
new Vector3D(100, 0, 100), // 目标位置
Math.PI/4, // 目标朝向45度
_simulationManager
);
_simulationManager.RegisterEntity("tank1", _tank);
_tank.Activate();
// 子弹的初始配置
_properties = new MissileProperties
{
Id = "missile1_Sub_0",
InitialPosition = new Vector3D(1100, 400, 100), // 在目标前方1000米高度400米
InitialOrientation = new Orientation(0, -Math.PI/6, 0), // 向下30度
InitialSpeed = 200,
MaxSpeed = 2000,
MaxFlightTime = 50,
MaxFlightDistance = 1000,
MaxAcceleration = 50,
ProportionalNavigationCoefficient = 3,
Mass = 10,
ExplosionRadius = 5,
HitProbability = 0.9,
Type = MissileType.TerminalSensitiveMissile
};
_submunition = new TerminalSensitiveSubmunition("tank1", _properties, _simulationManager);
_simulationManager.RegisterEntity("missile1_Sub_0", _submunition);
}
[Fact]
public void Constructor_InitializesPropertiesCorrectly()
{
Assert.Equal("missile1_Sub_0", _submunition.Id);
Assert.Equal(_properties.InitialPosition, _submunition.Position);
Assert.Equal(_properties.InitialSpeed, _submunition.Speed);
Assert.False(_submunition.IsActive);
Assert.False(_submunition.IsGuidance);
}
[Fact]
public void Update_InSeparationStage_HasCorrectBehavior()
{
// Arrange
_submunition.Fire();
_submunition.Activate();
var initialPosition = _submunition.Position;
// Act
_submunition.Update(0.1);
// Assert
Assert.True(_submunition.IsActive);
Assert.NotEqual(initialPosition, _submunition.Position);
var publishedEvents = _testAdapter.GetPublishedEvents();
Assert.Contains(publishedEvents, evt => evt is EntityActivatedEvent);
}
[Fact]
public void Update_InDecelerationStage_ReducesSpeed()
{
// Arrange
_submunition.Fire();
_submunition.Activate();
var initialSpeed = _submunition.Speed;
// Act - 等待进入减速阶段
for (double time = 0; time < 2.0; time += 0.1)
{
_submunition.Update(0.1);
}
// Assert
Assert.True(_submunition.Speed < initialSpeed);
}
[Fact]
public void Update_InSpiralScanStage_DetectsTarget()
{
// Arrange
_submunition.Fire();
_submunition.Activate();
// Act - 等待进入螺旋扫描阶段并发送目标辐射
for (double time = 0; time < 5.0; time += 0.1)
{
// 发布坦克辐射事件
_simulationManager.PublishEvent(new TankRadiationEvent
{
SenderId = "tank1",
InfraredRadiationIntensity = 100.0,
LaserReflectionIntensity = 0.0,
MillimeterWaveReflectionIntensity = 1.0,
MillimeterWaveRadiationTemperature = 300.0,
Timestamp = DateTime.UtcNow.Ticks
});
_tank.Update(0.1);
_submunition.Update(0.1);
}
// Assert
Assert.True(_submunition.IsGuidance);
}
[Fact]
public void Update_ExceedsMaxFlightTime_SelfDestructs()
{
// Arrange
_submunition.Fire();
_submunition.Activate();
// Act
for (double time = 0; time < _properties.MaxFlightTime + 1; time += 0.1)
{
_submunition.Update(0.1);
}
// Assert
Assert.False(_submunition.IsActive);
}
[Fact]
public void GetStatus_ReturnsCorrectStatus()
{
// Act
string status = _submunition.GetStatus();
// Assert
var expectedParts = new[]
{
"导弹",
_submunition.Id,
"位置",
"速度",
"飞行时间",
"飞行距离",
"运行状态"
};
foreach (var part in expectedParts)
{
Assert.Contains(part, status);
}
}
}
}

View File

@ -0,0 +1,236 @@
using System;
using Xunit;
using ThreatSource.Simulation;
using ThreatSource.Simulation.Testing;
namespace ThreatSource.Tests.Simulation
{
public class SimulationManagerTests
{
private readonly SimulationManager _simulationManager;
private readonly TestSimulationAdapter _testAdapter;
public SimulationManagerTests()
{
_simulationManager = new SimulationManager();
_testAdapter = new TestSimulationAdapter(_simulationManager);
_simulationManager.SetSimulationAdapter(_testAdapter);
}
[Fact]
public void TestEventPublishing()
{
// Arrange
var missileEvent = new MissileFireEvent
{
SenderId = "missile1",
TargetId = "target1",
Timestamp = 1.0
};
bool eventReceived = false;
_simulationManager.SubscribeToEvent<MissileFireEvent>(evt =>
{
eventReceived = true;
Assert.Equal("missile1", evt.SenderId);
Assert.Equal("target1", evt.TargetId);
});
// Act
_simulationManager.PublishEvent(missileEvent);
// Assert
Assert.True(eventReceived);
var publishedEvents = _testAdapter.GetPublishedEvents();
Assert.Single(publishedEvents);
Assert.IsType<MissileFireEvent>(publishedEvents[0]);
}
[Fact]
public void TestEntityManagement()
{
// Arrange
var testEntity = new { Id = "test1", Name = "TestEntity" };
_testAdapter.AddTestEntity("external1", new { Id = "external1", Name = "ExternalEntity" });
// Act
_simulationManager.RegisterEntity("test1", testEntity);
// Assert
// 测试内部实体获取
var internalEntity = _simulationManager.GetEntityById("test1");
Assert.NotNull(internalEntity);
Assert.Equal("TestEntity", (internalEntity as dynamic).Name);
// 测试外部实体获取
var externalEntity = _simulationManager.GetEntityById("external1");
Assert.NotNull(externalEntity);
Assert.Equal("ExternalEntity", (externalEntity as dynamic).Name);
}
[Fact]
public void TestEventSubscriptionAndUnsubscription()
{
// Arrange
int eventCount = 0;
Action<MissileFireEvent> handler = _ => eventCount++;
// Act
_simulationManager.SubscribeToEvent(handler);
_simulationManager.PublishEvent(new MissileFireEvent());
_simulationManager.UnsubscribeFromEvent(handler);
_simulationManager.PublishEvent(new MissileFireEvent());
// Assert
Assert.Equal(1, eventCount);
}
[Fact]
public void TestExternalEventReception()
{
// Arrange
var externalEvent = new LaserIlluminationStartEvent
{
LaserDesignatorId = "laser1",
TargetId = "target1"
};
bool eventReceived = false;
_simulationManager.SubscribeToEvent<LaserIlluminationStartEvent>(evt =>
{
eventReceived = true;
Assert.Equal("laser1", evt.LaserDesignatorId);
});
// Act
_testAdapter.ReceiveFromExternalSimulation(externalEvent);
// Assert
Assert.True(eventReceived);
}
[Fact]
public void TestNullEventPublishing()
{
// Arrange
MissileFireEvent? nullEvent = null;
// Act & Assert
Assert.Throws<ArgumentNullException>(() => _simulationManager.PublishEvent(nullEvent));
}
[Fact]
public void TestNullEventExternalPublishing()
{
// Arrange
MissileFireEvent? nullEvent = null;
// Act & Assert
Assert.Throws<ArgumentNullException>(() => _testAdapter.PublishToExternalSimulation(nullEvent));
}
[Fact]
public void TestNullEventExternalReceiving()
{
// Arrange
MissileFireEvent? nullEvent = null;
// Act & Assert
Assert.Throws<ArgumentNullException>(() => _testAdapter.ReceiveFromExternalSimulation(nullEvent));
}
[Fact]
public void TestUnregisterEntity()
{
// Arrange
var testEntity = new { Id = "test1", Name = "TestEntity" };
_simulationManager.RegisterEntity("test1", testEntity);
// Act
bool unregistered = _simulationManager.UnregisterEntity("test1");
bool notFound = _simulationManager.UnregisterEntity("nonexistent");
// Assert
Assert.True(unregistered);
Assert.False(notFound);
Assert.Null(_simulationManager.GetEntityById("test1"));
}
[Fact]
public void TestGetEntitiesByType()
{
// Arrange
var testEntity1 = new TestEntity { Id = "test1" };
var testEntity2 = new TestEntity { Id = "test2" };
var differentEntity = new { Id = "diff1" };
_simulationManager.RegisterEntity("test1", testEntity1);
_simulationManager.RegisterEntity("test2", testEntity2);
_simulationManager.RegisterEntity("diff1", differentEntity);
// Act
var entities = _simulationManager.GetEntitiesByType<TestEntity>();
// Assert
Assert.Equal(2, entities.Count);
Assert.Contains(testEntity1, entities);
Assert.Contains(testEntity2, entities);
}
[Fact]
public void TestGetAllEntities()
{
// Arrange
var entity1 = new { Id = "test1" };
var entity2 = new { Id = "test2" };
_simulationManager.RegisterEntity("test1", entity1);
_simulationManager.RegisterEntity("test2", entity2);
// Act
var allEntities = _simulationManager.GetAllEntities();
// Assert
Assert.Equal(2, allEntities.Count);
Assert.Contains(entity1, allEntities);
Assert.Contains(entity2, allEntities);
}
[Fact]
public void TestGetSimulationAdapter()
{
// Act
var adapter = _simulationManager.GetSimulationAdapter();
// Assert
Assert.NotNull(adapter);
Assert.Same(_testAdapter, adapter);
}
[Fact]
public void TestRegisterEntityWithInvalidInput()
{
// Arrange & Act & Assert
Assert.False(_simulationManager.RegisterEntity("", new object()));
Assert.False(_simulationManager.RegisterEntity("test", null!));
}
[Fact]
public void TestConcurrentEntityOperations()
{
// Arrange
var entity = new { Id = "test1" };
// Act & Assert
Assert.True(_simulationManager.RegisterEntity("test1", entity));
Assert.False(_simulationManager.RegisterEntity("test1", entity)); // 重复注册
Assert.True(_simulationManager.UnregisterEntity("test1"));
Assert.True(_simulationManager.RegisterEntity("test1", entity)); // 重新注册
}
// 用于测试的辅助类
private class TestEntity
{
public string Id { get; set; } = "";
}
}
}

View File

@ -0,0 +1,108 @@
using Xunit;
using ThreatSource.Target;
using ThreatSource.Simulation;
using ThreatSource.Utils;
namespace ThreatSource.Tests.Target
{
public class TankTests
{
private readonly Tank _tank;
private readonly SimulationManager _simulationManager;
public TankTests()
{
_simulationManager = new SimulationManager();
_tank = new Tank("tank1", new Vector3D(100, 0, 0), 10, _simulationManager);
}
[Fact]
public void Constructor_InitializesPropertiesCorrectly()
{
// Arrange & Act
var tank = new Tank("tank2", new Vector3D(200, 0, 0), 10, _simulationManager);
// Assert
Assert.NotNull(tank);
Assert.Equal("tank2", tank.Id);
Assert.NotNull(tank.Position);
Assert.NotNull(tank.Velocity);
}
[Fact]
public void Update_UpdatesPositionBasedOnVelocity()
{
// Arrange
var initialPosition = _tank.Position;
var deltaTime = 1.0f;
// Act
_tank.Update(deltaTime);
// Assert
Assert.Equal(initialPosition.X + _tank.Velocity.X * deltaTime, _tank.Position.X);
Assert.Equal(initialPosition.Y + _tank.Velocity.Y * deltaTime, _tank.Position.Y);
Assert.Equal(initialPosition.Z + _tank.Velocity.Z * deltaTime, _tank.Position.Z);
}
[Fact]
public void TakeDamage_ReducesHealthCorrectly()
{
// Arrange
double initialHealth = _tank.Health;
double damageAmount = 25.0;
// Act
_tank.TakeDamage(damageAmount);
// Assert
Assert.Equal(initialHealth - damageAmount, _tank.Health);
}
[Fact]
public void TakeDamage_PublishesDestroyedEventWhenHealthReachesZero()
{
// Arrange
bool eventReceived = false;
_simulationManager.SubscribeToEvent<TargetDestroyedEvent>(evt =>
{
eventReceived = true;
Assert.Equal(_tank.Id, evt.TargetId);
});
// Act
_tank.TakeDamage(_tank.Health); // 造成足够的伤害以摧毁坦克
// Assert
Assert.True(eventReceived);
Assert.Equal(0, _tank.Health);
}
[Fact]
public void GetRadarCrossSection_ReturnsExpectedValue()
{
// Arrange
var observerPosition = new Vector3D(0, 0, 0);
// Act
double rcs = _tank.RadarCrossSection;
// Assert
Assert.True(rcs > 0); // RCS应该是正值
}
[Fact]
public void GetInfraredSignature_ReturnsExpectedValue()
{
// Arrange
var observerPosition = new Vector3D(0, 0, 0);
// Act
double signature = _tank.InfraredRadiationIntensity;
// Assert
Assert.True(signature > 0); // 红外特征应该是正值
}
}
}

30
ThreatSource.sln Normal file
View File

@ -0,0 +1,30 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.002.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThreatSource", "ThreatSource\ThreatSource.csproj", "{D2CE51DA-8CB8-4C5E-83A6-ADA29B394185}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThreatSource.Tests", "ThreatSource.Tests\ThreatSource.Tests.csproj", "{973EB84A-AED4-49A3-A12A-C0969F022915}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D2CE51DA-8CB8-4C5E-83A6-ADA29B394185}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D2CE51DA-8CB8-4C5E-83A6-ADA29B394185}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D2CE51DA-8CB8-4C5E-83A6-ADA29B394185}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D2CE51DA-8CB8-4C5E-83A6-ADA29B394185}.Release|Any CPU.Build.0 = Release|Any CPU
{973EB84A-AED4-49A3-A12A-C0969F022915}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{973EB84A-AED4-49A3-A12A-C0969F022915}.Debug|Any CPU.Build.0 = Debug|Any CPU
{973EB84A-AED4-49A3-A12A-C0969F022915}.Release|Any CPU.ActiveCfg = Release|Any CPU
{973EB84A-AED4-49A3-A12A-C0969F022915}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {251B5E38-65B7-4714-8786-772B962EC789}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,165 @@
using System;
using ThreatSource.Utils;
namespace ThreatSource.Guidance
{
/// <summary>
/// 基础制导系统类,实现了制导系统的基本功能框架
/// </summary>
/// <remarks>
/// 该类提供了制导系统的通用实现:
/// - 制导状态管理
/// - 运动参数记录
/// - 加速度限制
/// - 比例导引系数
/// 是其他具体制导系统的基类
/// </remarks>
public class BasicGuidanceSystem : IGuidanceSystem
{
/// <summary>
/// 获取或设置是否有有效的制导信息
/// </summary>
/// <remarks>
/// true表示当前有可用的制导信息
/// false表示无法获得有效制导
/// 用于判断制导系统的工作状态
/// </remarks>
public bool HasGuidance { get; protected set; }
/// <summary>
/// 获取或设置最大加速度,单位:米/平方秒
/// </summary>
/// <remarks>
/// 定义了制导加速度的上限
/// 用于限制导弹的机动能力
/// 考虑结构和动力限制
/// </remarks>
public double MaxAcceleration { get; set; }
/// <summary>
/// 获取或设置比例导引系数
/// </summary>
/// <remarks>
/// 定义了制导指令的增益
/// 影响制导系统的响应特性
/// 通常取值3~5
/// </remarks>
public double ProportionalNavigationCoefficient { get; set; }
/// <summary>
/// 获取或设置导弹位置,单位:米
/// </summary>
/// <remarks>
/// 记录导弹的当前位置
/// 用于制导计算和状态更新
/// </remarks>
protected Vector3D Position { get; set; }
/// <summary>
/// 获取或设置导弹速度,单位:米/秒
/// </summary>
/// <remarks>
/// 记录导弹的当前速度
/// 用于制导计算和状态更新
/// </remarks>
protected Vector3D Velocity { get; set; }
/// <summary>
/// 获取或设置制导加速度,单位:米/平方秒
/// </summary>
/// <remarks>
/// 存储计算得到的制导指令
/// 用于控制导弹的运动轨迹
/// </remarks>
protected Vector3D GuidanceAcceleration { get; set; }
/// <summary>
/// 初始化基础制导系统的新实例
/// </summary>
/// <param name="maxAcceleration">最大加速度,单位:米/平方秒</param>
/// <param name="proportionalNavigationCoefficient">比例导引系数</param>
/// <remarks>
/// 构造过程:
/// - 初始化制导状态
/// - 设置运动参数
/// - 配置制导参数
/// </remarks>
public BasicGuidanceSystem(double maxAcceleration, double proportionalNavigationCoefficient)
{
HasGuidance = false;
GuidanceAcceleration = Vector3D.Zero;
Position = Vector3D.Zero;
Velocity = Vector3D.Zero;
MaxAcceleration = maxAcceleration;
ProportionalNavigationCoefficient = proportionalNavigationCoefficient;
}
/// <summary>
/// 更新制导系统的状态和计算结果
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔,单位:秒</param>
/// <param name="missilePosition">导弹当前位置,单位:米</param>
/// <param name="missileVelocity">导弹当前速度,单位:米/秒</param>
/// <remarks>
/// 更新过程:
/// - 更新位置信息
/// - 更新速度信息
/// - 准备制导计算
/// </remarks>
public virtual void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity)
{
Position = missilePosition;
Velocity = missileVelocity;
}
/// <summary>
/// 获取制导加速度指令
/// </summary>
/// <returns>三维制导加速度向量,单位:米/平方秒</returns>
/// <remarks>
/// 返回数据:
/// - X分量横向制导加速度
/// - Y分量垂直制导加速度
/// - Z分量纵向制导加速度
/// 用于导弹的轨迹控制
/// </remarks>
public Vector3D GetGuidanceAcceleration()
{
return GuidanceAcceleration;
}
/// <summary>
/// 计算制导加速度(需要在子类中实现)
/// </summary>
/// <param name="deltaTime">时间间隔,单位:秒</param>
/// <remarks>
/// 计算要求:
/// - 实现特定的制导律
/// - 考虑最大加速度限制
/// - 更新制导加速度
/// 基类中不实现具体计算
/// </remarks>
protected virtual void CalculateGuidanceAcceleration(double deltaTime)
{
// 基础制导系统不计算制导指令
// 派生类应该重写这个方法来实现特定的制导逻辑
}
/// <summary>
/// 获取制导系统的状态信息
/// </summary>
/// <returns>包含关键状态参数的字符串</returns>
/// <remarks>
/// 返回信息:
/// - 制导状态
/// - 位置信息
/// - 速度信息
/// - 加速度信息
/// 用于状态监控和调试
/// </remarks>
public virtual string GetStatus()
{
return $" 导引头状态: 有制导={HasGuidance}, 位置={Position}, 速度={Velocity}, 制导加速度={GuidanceAcceleration}";
}
}
}

View File

@ -0,0 +1,55 @@
using ThreatSource.Utils;
namespace ThreatSource.Guidance
{
/// <summary>
/// 制导系统接口,定义了所有制导系统的通用功能
/// </summary>
/// <remarks>
/// 该接口提供了制导系统的基本功能规范:
/// - 制导状态判断
/// - 制导信息更新
/// - 制导加速度计算
/// 是所有具体制导系统实现的基础
/// </remarks>
public interface IGuidanceSystem
{
/// <summary>
/// 获取是否有有效的制导信息
/// </summary>
/// <remarks>
/// true表示当前有可用的制导信息
/// false表示无法获得有效制导
/// 用于判断制导系统的工作状态
/// </remarks>
bool HasGuidance { get; }
/// <summary>
/// 更新制导系统的状态和计算结果
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔,单位:秒</param>
/// <param name="missilePosition">导弹当前位置,单位:米</param>
/// <param name="missileVelocity">导弹当前速度,单位:米/秒</param>
/// <remarks>
/// 更新过程:
/// - 获取最新目标信息
/// - 计算制导参数
/// - 更新制导状态
/// - 生成制导指令
/// </remarks>
void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity);
/// <summary>
/// 获取制导加速度指令
/// </summary>
/// <returns>三维制导加速度向量,单位:米/平方秒</returns>
/// <remarks>
/// 返回数据:
/// - X分量横向制导加速度
/// - Y分量垂直制导加速度
/// - Z分量纵向制导加速度
/// 用于导弹的轨迹控制
/// </remarks>
Vector3D GetGuidanceAcceleration();
}
}

View File

@ -0,0 +1,205 @@
using ThreatSource.Utils;
namespace ThreatSource.Guidance
{
/// <summary>
/// 红外指令导引系统类,实现了基于红外跟踪器的指令制导功能
/// </summary>
/// <remarks>
/// 该类提供了红外指令制导系统的核心功能:
/// - 指令接收和处理
/// - 转向速率控制
/// - 提前量计算
/// - 制导加速度生成
/// 用于实现地面指令制导的导弹控制
/// </remarks>
public class InfraredCommandGuidanceSystem : BasicGuidanceSystem
{
/// <summary>
/// 跟踪器到导弹的方向向量
/// </summary>
/// <remarks>
/// 记录上一次接收到的跟踪器指向导弹的方向
/// 用于计算导弹的相对位置
/// </remarks>
private Vector3D lastTrackerToMissileVector;
/// <summary>
/// 跟踪器到目标的方向向量
/// </summary>
/// <remarks>
/// 记录上一次接收到的跟踪器指向目标的方向
/// 用于计算目标的相对位置
/// </remarks>
private Vector3D lastTrackerToTargetVector;
/// <summary>
/// 上一次的期望飞行方向
/// </summary>
/// <remarks>
/// 记录上一次计算的期望飞行方向
/// 用于计算转向速率
/// </remarks>
private Vector3D lastDesiredDirection;
/// <summary>
/// 当前转向速率,单位:弧度/秒
/// </summary>
/// <remarks>
/// 记录导弹的实时转向速率
/// 用于计算提前量
/// </remarks>
private double turnRate;
/// <summary>
/// 转向速率平滑因子取值范围0.1~0.5
/// </summary>
/// <remarks>
/// 用于平滑转向速率的变化
/// 值越大,平滑效果越强
/// 影响导弹的机动特性
/// </remarks>
private const double TurnRateSmoothingFactor = 0.5;
/// <summary>
/// 提前量因子单位一般取0.5秒
/// </summary>
/// <remarks>
/// 用于计算转向提前量
/// 值越大,提前量越大
/// 影响制导精度和稳定性
/// </remarks>
private const double LeadTimeFactor = 0.3;
/// <summary>
/// 初始化红外指令导引系统的新实例
/// </summary>
/// <param name="maxAcceleration">最大加速度,单位:米/平方秒</param>
/// <param name="guidanceCoefficient">制导系数</param>
/// <remarks>
/// 构造过程:
/// - 初始化基类参数
/// - 初始化向量记录
/// - 清零转向速率
/// </remarks>
public InfraredCommandGuidanceSystem(double maxAcceleration, double guidanceCoefficient)
: base(maxAcceleration, guidanceCoefficient)
{
lastTrackerToMissileVector = Vector3D.Zero;
lastTrackerToTargetVector = Vector3D.Zero;
lastDesiredDirection = Vector3D.Zero;
turnRate = 0;
}
/// <summary>
/// 更新制导系统的状态和计算结果
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔,单位:秒</param>
/// <param name="missilePosition">导弹当前位置,单位:米</param>
/// <param name="missileVelocity">导弹当前速度,单位:米/秒</param>
/// <remarks>
/// 更新过程:
/// - 更新基类状态
/// - 计算制导加速度
/// </remarks>
public override void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity)
{
base.Update(deltaTime, missilePosition, missileVelocity);
CalculateGuidanceAcceleration(deltaTime);
}
/// <summary>
/// 接收并处理制导指令
/// </summary>
/// <param name="trackerToMissileVector">跟踪器到导弹的方向向量</param>
/// <param name="trackerToTargetVector">跟踪器到目标的方向向量</param>
/// <remarks>
/// 处理过程:
/// - 更新制导状态
/// - 记录方向向量
/// - 准备制导计算
/// </remarks>
public void ReceiveGuidanceCommand(Vector3D trackerToMissileVector, Vector3D trackerToTargetVector)
{
HasGuidance = true;
lastTrackerToMissileVector = trackerToMissileVector;
lastTrackerToTargetVector = trackerToTargetVector;
}
/// <summary>
/// 计算制导加速度
/// </summary>
/// <param name="deltaTime">时间间隔,单位:秒</param>
/// <remarks>
/// 计算过程:
/// - 计算期望方向
/// - 更新转向速率
/// - 计算提前量
/// - 生成制导指令
/// - 限制最大加速度
/// </remarks>
protected override void CalculateGuidanceAcceleration(double deltaTime)
{
if (HasGuidance)
{
// 计算期望飞行方向(从导弹指向目标)
Vector3D currentDesiredDirection = (lastTrackerToTargetVector - lastTrackerToMissileVector).Normalize();
// 计算当前飞行方向
Vector3D currentDirection = Velocity.Normalize();
// 更新转向速率
if (lastDesiredDirection != Vector3D.Zero)
{
double instantTurnRate = Vector3D.CrossProduct(lastDesiredDirection, currentDesiredDirection).Magnitude() / deltaTime;
turnRate = turnRate * (1 - TurnRateSmoothingFactor) + instantTurnRate * TurnRateSmoothingFactor;
}
// 计算带有提前量的期望方向
Vector3D leadDirection = Vector3D.CrossProduct(currentDesiredDirection, Vector3D.CrossProduct(currentDesiredDirection, currentDirection).Normalize());
Vector3D desiredDirectionWithLead = (currentDesiredDirection + leadDirection * turnRate * LeadTimeFactor).Normalize();
// 计算转向轴
Vector3D turnAxis = Vector3D.CrossProduct(currentDirection, desiredDirectionWithLead).Normalize();
// 计算所需转向角度
double turnAngle = Math.Acos(Vector3D.DotProduct(currentDirection, desiredDirectionWithLead));
// 计算制导加速度
double accelerationMagnitude = ProportionalNavigationCoefficient * turnAngle * Velocity.Magnitude();
GuidanceAcceleration = Vector3D.CrossProduct(turnAxis, currentDirection) * accelerationMagnitude;
// 限制最大加速度
if (GuidanceAcceleration.Magnitude() > MaxAcceleration)
{
GuidanceAcceleration = GuidanceAcceleration.Normalize() * MaxAcceleration;
}
lastDesiredDirection = currentDesiredDirection;
}
else
{
GuidanceAcceleration = Vector3D.Zero;
}
}
/// <summary>
/// 获取制导系统的详细状态信息
/// </summary>
/// <returns>包含完整状态参数的字符串</returns>
/// <remarks>
/// 返回信息:
/// - 基本状态信息
/// - 制导加速度
/// - 方向向量
/// - 转向速率
/// 用于系统监控和调试
/// </remarks>
public override string GetStatus()
{
return base.GetStatus() + $", GuidanceAcceleration: {GuidanceAcceleration}, " +
$"Tracker to Target Vector: {lastTrackerToTargetVector}, Tracker to Missile Vector: {lastTrackerToMissileVector}, " +
$"Turn Rate: {turnRate}";
}
}
}

View File

@ -0,0 +1,244 @@
using System;
using ThreatSource.Simulation;
using ThreatSource.Target;
using ThreatSource.Utils;
namespace ThreatSource.Guidance
{
/// <summary>
/// 红外成像引导系统类,实现了基于红外图像的目标探测和跟踪功能
/// </summary>
/// <remarks>
/// 该类提供了红外成像制导系统的核心功能:
/// - 目标自动探测
/// - 图像识别处理
/// - 信噪比计算
/// - 比例导引控制
/// 用于实现自主寻的制导
/// </remarks>
public class InfraredImagingGuidanceSystem : BasicGuidanceSystem
{
/// <summary>
/// 最大探测范围,单位:米
/// </summary>
/// <remarks>
/// 定义了红外成像系统的最大作用距离
/// 超出此范围的目标无法有效探测
/// </remarks>
private const double MAX_DETECTION_RANGE = 5000;
/// <summary>
/// 视场角,单位:弧度
/// </summary>
/// <remarks>
/// 定义了成像系统的视场范围
/// 标枪导弹为40度
/// 坦克破坏者为24度
/// </remarks>
private const double FIELD_OF_VIEW = Math.PI / 6;
/// <summary>
/// 目标识别概率
/// </summary>
/// <remarks>
/// 定义了目标识别的成功率
/// 影响系统的可靠性
/// 典型值为0.9
/// </remarks>
private const double TARGET_RECOGNITION_PROBABILITY = 0.9;
/// <summary>
/// 识别目标的信噪比阈值,单位:分贝
/// </summary>
/// <remarks>
/// 定义了目标识别的最小信噪比要求
/// 大于此值时认为目标有效
/// 典型值为6dB
/// </remarks>
private const double RECOGNITION_SNR_THRESHOLD = 6;
/// <summary>
/// 背景辐射强度,单位:瓦特/球面度
/// </summary>
/// <remarks>
/// 定义了环境背景的红外辐射强度
/// 用于信噪比计算
/// 典型值为10W/sr
/// </remarks>
private const double BACKGROUND_RADIATION_INTENSITY = 10;
/// <summary>
/// 随机数生成器实例
/// </summary>
/// <remarks>
/// 用于生成随机扰动
/// 模拟系统噪声
/// </remarks>
private readonly Random random = new();
/// <summary>
/// 获取或设置仿真管理器实例
/// </summary>
/// <remarks>
/// 用于获取场景中的目标信息
/// 实现目标探测功能
/// </remarks>
public ISimulationManager SimulationManager { get; set; }
/// <summary>
/// 上一次探测到的目标位置
/// </summary>
/// <remarks>
/// 记录目标的历史位置
/// 用于计算目标速度
/// </remarks>
private Vector3D lastTargetPosition;
/// <summary>
/// 初始化红外成像引导系统的新实例
/// </summary>
/// <param name="maxAcceleration">最大加速度,单位:米/平方秒</param>
/// <param name="proportionalNavigationCoefficient">比例导引系数</param>
/// <param name="simulationManager">仿真管理器实例</param>
/// <remarks>
/// 构造过程:
/// - 初始化基类参数
/// - 设置仿真管理器
/// - 初始化目标位置
/// </remarks>
public InfraredImagingGuidanceSystem(double maxAcceleration, double proportionalNavigationCoefficient, ISimulationManager simulationManager) : base(maxAcceleration, proportionalNavigationCoefficient)
{
SimulationManager = simulationManager;
lastTargetPosition = Vector3D.Zero;
}
/// <summary>
/// 更新引导系统的状态和计算结果
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔,单位:秒</param>
/// <param name="missilePosition">导弹当前位置,单位:米</param>
/// <param name="missileVelocity">导弹当前速度,单位:米/秒</param>
/// <remarks>
/// 更新过程:
/// - 探测目标位置
/// - 计算目标速度
/// - 生成制导指令
/// - 限制最大加速度
/// </remarks>
public override void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity)
{
base.Update(deltaTime, missilePosition, missileVelocity);
if (TryDetectTank(missilePosition, missileVelocity, out Vector3D tankPosition))
{
//根据目标当前位置和上一次位置计算目标速度
Vector3D targetVelocity = (tankPosition - lastTargetPosition) / deltaTime;
lastTargetPosition = tankPosition;
// 使用比例控制算法
GuidanceAcceleration = MotionAlgorithm.CalculateProportionalNavigation(ProportionalNavigationCoefficient, missilePosition, missileVelocity, tankPosition, targetVelocity);
// 限制最大加速度
if (GuidanceAcceleration.Magnitude() > MaxAcceleration)
{
GuidanceAcceleration = GuidanceAcceleration.Normalize() * MaxAcceleration;
}
HasGuidance = true;
}
else
{
HasGuidance = false;
}
}
/// <summary>
/// 尝试探测目标坦克
/// </summary>
/// <param name="missilePosition">导弹当前位置,单位:米</param>
/// <param name="missileVelocity">导弹当前速度,单位:米/秒</param>
/// <param name="tankPosition">输出探测到的坦克位置,单位:米</param>
/// <returns>是否成功探测到目标</returns>
/// <remarks>
/// 探测过程:
/// - 遍历场景中的目标
/// - 检查距离和角度
/// - 计算信噪比
/// - 判断目标有效性
/// </remarks>
private bool TryDetectTank(Vector3D missilePosition, Vector3D missileVelocity, out Vector3D tankPosition)
{
tankPosition = Vector3D.Zero;
foreach (var element in SimulationManager.GetEntitiesByType<SimulationElement>())
{
if (element is Tank tank)
{
Vector3D toTarget = tank.Position - missilePosition;
double distance = toTarget.Magnitude();
if (distance <= MAX_DETECTION_RANGE)
{
double angle = Math.Acos(Vector3D.DotProduct(toTarget.Normalize(), missileVelocity.Normalize()));
if (angle <= FIELD_OF_VIEW / 2)
{
double snr = CalculateSNR(tank, distance);
Console.WriteLine($"SNR: {snr}");
if (snr > RECOGNITION_SNR_THRESHOLD)
{
tankPosition = tank.Position;
return true;
}
}
}
}
}
return false;
}
/// <summary>
/// 获取制导系统的详细状态信息
/// </summary>
/// <returns>包含完整状态参数的字符串</returns>
/// <remarks>
/// 返回信息:
/// - 基本状态信息
/// - 制导加速度
/// - 目标位置
/// 用于系统监控和调试
/// </remarks>
public override string GetStatus()
{
return base.GetStatus() + $", GuidanceAcceleration: {GuidanceAcceleration}, " +
$"Tank Position: {lastTargetPosition}";
}
/// <summary>
/// 计算目标的信噪比
/// </summary>
/// <param name="target">目标对象</param>
/// <param name="distance">到目标的距离,单位:米</param>
/// <returns>信噪比,单位:分贝</returns>
/// <remarks>
/// 计算过程:
/// - 获取目标辐射强度
/// - 考虑距离衰减
/// - 计算信号强度
/// - 计算噪声强度
/// - 转换为分贝值
/// </remarks>
private static double CalculateSNR(ITarget target, double distance)
{
double targetRadiation = target.InfraredRadiationIntensity;
double backgroundRadiation = BACKGROUND_RADIATION_INTENSITY;
// 考虑距离衰减
double attenuationFactor = 1 / (distance * distance);
double signal = (targetRadiation - backgroundRadiation) * attenuationFactor;
double noise = backgroundRadiation * attenuationFactor;
return 10 * Math.Log10(signal / noise); // 转换为dB
}
}
}

View File

@ -0,0 +1,367 @@
using ThreatSource.Utils;
namespace ThreatSource.Guidance
{
/// <summary>
/// 激光驾束制导系统类,实现了基于激光束跟踪的制导功能
/// </summary>
/// <remarks>
/// 该类提供了激光驾束制导系统的核心功能:
/// - 激光束生成和控制
/// - 偏差检测和计算
/// - PID控制器
/// - 非线性增益控制
/// 用于实现高精度的制导控制
/// </remarks>
public class LaserBeamRiderGuidanceSystem : BasicGuidanceSystem
{
/// <summary>
/// 获取或设置激光源位置
/// </summary>
/// <remarks>
/// 记录激光发射源的三维位置
/// 用于计算导弹与激光束的相对位置
/// </remarks>
private Vector3D LaserSourcePosition { get; set; }
/// <summary>
/// 获取或设置激光方向
/// </summary>
/// <remarks>
/// 记录激光束的传播方向
/// 用于计算导弹与激光束的偏差
/// </remarks>
private Vector3D LaserDirection { get; set; }
/// <summary>
/// 获取或设置激光功率,单位:瓦特
/// </summary>
/// <remarks>
/// 记录激光源的发射功率
/// 影响系统的探测距离和可靠性
/// </remarks>
public double LaserPower { get; set; }
/// <summary>
/// 最小可探测功率,单位:瓦特
/// </summary>
/// <remarks>
/// 定义了探测器的灵敏度阈值
/// 低于此值时无法有效探测
/// 典型值为1毫瓦
/// </remarks>
private const double MinDetectablePower = 1e-3;
/// <summary>
/// 探测器直径,单位:米
/// </summary>
/// <remarks>
/// 定义了探测器的物理尺寸
/// 影响系统的接收能力
/// 典型值为0.1米
/// </remarks>
private const double DetectorDiameter = 0.1;
/// <summary>
/// 控制场直径,单位:米
/// </summary>
/// <remarks>
/// 定义了有效制导范围
/// 超出此范围将失去制导
/// 典型值为20米
/// </remarks>
private const double ControlFieldDiameter = 20.0;
/// <summary>
/// 上一次的误差向量
/// </summary>
/// <remarks>
/// 记录PID控制器的历史误差
/// 用于计算微分项
/// </remarks>
private Vector3D LastError = Vector3D.Zero;
/// <summary>
/// 获取上一次的制导加速度
/// </summary>
/// <remarks>
/// 记录历史制导指令
/// 用于实现低通滤波
/// </remarks>
public Vector3D LastGuidanceAcceleration { get; private set; }
/// <summary>
/// 积分误差向量
/// </summary>
/// <remarks>
/// 记录PID控制器的积分项
/// 用于消除稳态误差
/// </remarks>
private Vector3D IntegralError = Vector3D.Zero;
/// <summary>
/// 获取或设置激光照射状态
/// </summary>
/// <remarks>
/// 指示当前是否有激光照射
/// 影响系统的工作状态
/// </remarks>
private bool LaserIlluminationOn { get; set; }
/// <summary>
/// 初始化激光驾束制导系统的新实例
/// </summary>
/// <param name="maxAcceleration">最大加速度,单位:米/平方秒</param>
/// <param name="guidanceCoefficient">制导系数</param>
/// <remarks>
/// 构造过程:
/// - 初始化基类参数
/// - 初始化激光参数
/// - 初始化控制参数
/// </remarks>
public LaserBeamRiderGuidanceSystem(double maxAcceleration, double guidanceCoefficient) : base(maxAcceleration, guidanceCoefficient)
{
LaserSourcePosition = Vector3D.Zero;
LaserDirection = Vector3D.Zero;
LaserPower = 0;
HasGuidance = false;
LastGuidanceAcceleration = Vector3D.Zero;
}
/// <summary>
/// 更新激光驾束仪参数
/// </summary>
/// <param name="sourcePosition">激光源位置,单位:米</param>
/// <param name="direction">激光方向向量</param>
/// <param name="laserPower">激光功率,单位:瓦特</param>
/// <remarks>
/// 更新过程:
/// - 激活激光照射
/// - 更新位置信息
/// - 更新方向信息
/// - 更新功率参数
/// </remarks>
public void UpdateLaserBeamRider(Vector3D sourcePosition, Vector3D direction, double laserPower)
{
LaserIlluminationOn = true;
LaserSourcePosition = sourcePosition;
LaserDirection = direction.Normalize();
LaserPower = laserPower;
}
/// <summary>
/// 关闭激光照射系统
/// </summary>
/// <remarks>
/// 关闭过程:
/// - 清除位置信息
/// - 清除方向信息
/// - 清除功率参数
/// - 停止制导
/// </remarks>
public void DeactivateLaserBeam()
{
LaserSourcePosition = Vector3D.Zero;
LaserDirection = Vector3D.Zero;
LaserPower = 0;
HasGuidance = false;
}
/// <summary>
/// 更新制导系统的状态和计算结果
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <param name="missilePosition">导弹位置,单位:米</param>
/// <param name="missileVelocity">导弹速度,单位:米/秒</param>
/// <remarks>
/// 更新过程:
/// - 检查激光照射状态
/// - 更新制导状态
/// - 计算制导指令
/// - 更新输出参数
/// </remarks>
public override void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity)
{
base.Update(deltaTime, missilePosition, missileVelocity);
if (LaserIlluminationOn)
{
UpdateGuidanceStatus();
if (HasGuidance)
{
CalculateGuidanceAcceleration(deltaTime);
}
else
{
GuidanceAcceleration = Vector3D.Zero;
}
}
else
{
GuidanceAcceleration = Vector3D.Zero;
}
}
/// <summary>
/// 更新制导系统状态
/// </summary>
/// <remarks>
/// 更新过程:
/// - 计算与激光束的距离
/// - 检查是否在控制场内
/// - 计算接收功率
/// - 判断是否满足制导条件
/// </remarks>
private void UpdateGuidanceStatus()
{
// 计算导弹到激光束的最短距离
Vector3D shortestDistanceVector = CalculateShortestDistanceToLaserBeam();
double shortestDistance = shortestDistanceVector.Magnitude();
// 检查导弹是否在控制场内
if (shortestDistance > ControlFieldDiameter / 2)
{
HasGuidance = false;
Console.WriteLine($"激光驾束引导系统: 失去引导, 原因: 超出控制场范围, 距离: {shortestDistance}");
return;
}
Console.WriteLine($"激光驾束引导系统: 在控制场内, 距离: {shortestDistance}");
// 计算接收到的激光功率
double beamArea = Math.PI * Math.Pow(ControlFieldDiameter / 2, 2);
double powerDensity = LaserPower / beamArea;
double receivedPower = powerDensity * (Math.PI * Math.Pow(DetectorDiameter / 2, 2));
if(HasGuidance = receivedPower >= MinDetectablePower)
{
HasGuidance = true;
}
else
{
HasGuidance = false;
Console.WriteLine($"激光驾束引导系统: 失去引导, 原因: 接收到的激光功率低于最小可探测功率,{LaserPower:E} W/{receivedPower:E} W");
}
}
/// <summary>
/// 计算制导加速度
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 计算过程:
/// - 计算偏差向量
/// - 执行PID控制
/// - 应用非线性增益
/// - 计算横向加速度
/// - 计算前向加速度
/// - 合成最终制导指令
/// - 应用低通滤波
/// </remarks>
protected override void CalculateGuidanceAcceleration(double deltaTime)
{
if (!HasGuidance)
{
GuidanceAcceleration = Vector3D.Zero;
return;
}
// 计算导弹到激光束的最短距离
Vector3D shortestDistanceVector = CalculateShortestDistanceToLaserBeam();
// PID控制
double Kp = 30; // 增加比例系数,使系统对误差更敏感,反应更快 30
double Ki = 0.05; // 减小积分系数,减少长期误差累积的影响 0.05
double Kd = 5; // 增加微分系数,减少系统的超调量,提高稳定性 5
double Kc = 0.5; // 减小非线性增益系数, 控制偏移量, 使得在更小的误差范围内有更大的修正 0.5
// 计算误差
Vector3D error = shortestDistanceVector;
// 积分项
IntegralError += error * deltaTime;
// 微分项
Vector3D derivativeError = (error - LastError) / deltaTime;
// 计算PID输出
Vector3D pidOutput = error * Kp + IntegralError * Ki + derivativeError * Kd;
// 非线性增益
double distance = shortestDistanceVector.Magnitude();
double nonLinearGain = Math.Tanh(distance / Kc);
// 计算横向加速度
Vector3D lateralAcceleration = pidOutput * nonLinearGain;
// 限制最大加速度
double maxAcceleration = 50; // 稍微增加最大加速度 50
if (lateralAcceleration.Magnitude() > maxAcceleration)
{
lateralAcceleration = lateralAcceleration.Normalize() * maxAcceleration;
}
// 计算前向加速度
Vector3D forwardDirection = LaserDirection;
Vector3D currentDirection = Velocity.Normalize();
Vector3D rotationAxis = Vector3D.CrossProduct(currentDirection, forwardDirection);
double rotationAngle = Math.Acos(Vector3D.DotProduct(currentDirection, forwardDirection));
Vector3D forwardAcceleration = Vector3D.CrossProduct(rotationAxis, Velocity) * rotationAngle * ProportionalNavigationCoefficient;
// 合并横向和前向加速度
GuidanceAcceleration = lateralAcceleration + forwardAcceleration;
// 低通滤波
const double alpha = 0.2;
GuidanceAcceleration = GuidanceAcceleration * alpha + LastGuidanceAcceleration * (1 - alpha);
// 更新上一次的误差和制导加速度
LastError = error;
LastGuidanceAcceleration = GuidanceAcceleration;
}
/// <summary>
/// 获取制导系统的详细状态信息
/// </summary>
/// <returns>包含完整状态参数的字符串</returns>
/// <remarks>
/// 返回信息:
/// - 基本状态信息
/// - 制导参数
/// - 控制状态
/// 用于系统监控和调试
/// </remarks>
public override string GetStatus()
{
return base.GetStatus();
}
/// <summary>
/// 计算导弹到激光束的最短距离向量
/// </summary>
/// <returns>最短距离向量,单位:米</returns>
/// <remarks>
/// 计算过程:
/// - 计算导弹到激光源的向量
/// - 计算在激光方向上的投影
/// - 计算最近点位置
/// - 计算最短距离向量
/// </remarks>
private Vector3D CalculateShortestDistanceToLaserBeam()
{
// 计算导弹到激光源的向量
Vector3D missileToSource = LaserSourcePosition - Position;
// 计算导弹在激光方向上的投影长度
double projectionLength = Vector3D.DotProduct(missileToSource, LaserDirection);
// 计算激光束上最接近导弹的点
Vector3D closestPointOnBeam = LaserSourcePosition - LaserDirection * projectionLength;
// 计算导弹到激光束最近点的向量(即最短距离向量)
Vector3D shortestDistanceVector = closestPointOnBeam - Position;
return shortestDistanceVector;
}
}
}

View File

@ -0,0 +1,318 @@
using ThreatSource.Utils;
namespace ThreatSource.Guidance
{
/// <summary>
/// 激光半主动制导系统类,实现了基于激光照射的目标跟踪和制导功能
/// </summary>
/// <remarks>
/// 该类提供了激光半主动制导系统的核心功能:
/// - 激光目标照射
/// - 反射光探测
/// - 信号处理
/// - 比例导引控制
/// 用于实现精确制导打击
/// </remarks>
public class LaserSemiActiveGuidanceSystem : BasicGuidanceSystem
{
/// <summary>
/// 视场角,单位:弧度
/// </summary>
/// <remarks>
/// 定义了探测器的视场范围
/// 设置为30度π/6弧度
/// 影响系统的探测能力
/// </remarks>
private const double FieldOfViewAngle = Math.PI / 6;
/// <summary>
/// 探测器直径,单位:米
/// </summary>
/// <remarks>
/// 定义了探测器的物理尺寸
/// 影响系统的接收能力
/// 典型值为0.1米
/// </remarks>
private const double DetectorDiameter = 0.1;
/// <summary>
/// 聚焦后光斑直径,单位:米
/// </summary>
/// <remarks>
/// 定义了光学系统聚焦后的光斑大小
/// 影响系统的探测灵敏度
/// 典型值为0.003米
/// </remarks>
private const double FocusedSpotDiameter = 0.003;
/// <summary>
/// 目标反射系数
/// </summary>
/// <remarks>
/// 定义了目标表面的激光反射能力
/// 影响反射信号强度
/// 典型值为0.2
/// </remarks>
private const double ReflectionCoefficient = 0.2;
/// <summary>
/// 锁定阈值,单位:瓦特
/// </summary>
/// <remarks>
/// 定义了系统锁定目标的最小功率要求
/// 低于此值时认为无法有效跟踪目标
/// 典型值为1e-12瓦特
/// </remarks>
private const double LockThreshold = 1e-12;
/// <summary>
/// 目标有效反射面积,单位:平方米
/// </summary>
/// <remarks>
/// 定义了目标的等效反射面积
/// 影响反射信号强度
/// 典型值为1.0平方米
/// </remarks>
private const double TargetReflectiveArea = 1.0;
/// <summary>
/// 获取或设置目标位置
/// </summary>
/// <remarks>
/// 记录当前跟踪目标的三维位置
/// 用于制导计算
/// </remarks>
private Vector3D TargetPosition { get; set; }
/// <summary>
/// 获取或设置目标速度
/// </summary>
/// <remarks>
/// 记录当前跟踪目标的三维速度
/// 用于制导计算和预测
/// </remarks>
private Vector3D TargetVelocity { get; set; }
/// <summary>
/// 获取或设置激光照射状态
/// </summary>
/// <remarks>
/// 指示当前是否有激光照射目标
/// 影响系统的工作状态
/// </remarks>
private bool LaserIlluminationOn { get; set; }
/// <summary>
/// 获取或设置激光指示器位置
/// </summary>
/// <remarks>
/// 记录激光发射源的三维位置
/// 用于功率计算
/// </remarks>
private Vector3D LaserDesignatorPosition { get; set; }
/// <summary>
/// 获取或设置激光功率,单位:瓦特
/// </summary>
/// <remarks>
/// 记录激光源的发射功率
/// 影响系统的探测距离
/// </remarks>
private double LaserPower { get; set; }
/// <summary>
/// 获取或设置激光发散角,单位:弧度
/// </summary>
/// <remarks>
/// 记录激光束的发散角度
/// 影响光斑大小和功率密度
/// </remarks>
private double LaserDivergenceAngle { get; set; }
/// <summary>
/// 初始化激光半主动制导系统的新实例
/// </summary>
/// <param name="maxAcceleration">最大加速度,单位:米/平方秒</param>
/// <param name="guidanceCoefficient">制导系数</param>
/// <remarks>
/// 构造过程:
/// - 初始化基类参数
/// - 初始化目标信息
/// - 初始化激光参数
/// </remarks>
public LaserSemiActiveGuidanceSystem(double maxAcceleration, double guidanceCoefficient) : base(maxAcceleration, guidanceCoefficient)
{
TargetPosition = Vector3D.Zero;
TargetVelocity = Vector3D.Zero;
LaserIlluminationOn = false;
LaserDesignatorPosition = Vector3D.Zero;
LaserPower = 0;
}
/// <summary>
/// 更新激光指示器参数
/// </summary>
/// <param name="sourcePosition">激光源位置,单位:米</param>
/// <param name="targetPosition">目标位置,单位:米</param>
/// <param name="targetVelocity">目标速度,单位:米/秒</param>
/// <param name="laserPower">激光功率,单位:瓦特</param>
/// <param name="laserDivergenceAngle">激光发散角,单位:弧度</param>
/// <remarks>
/// 更新过程:
/// - 激活激光照射
/// - 更新位置信息
/// - 更新目标信息
/// - 更新激光参数
/// </remarks>
public void UpdateLaserDesignator(Vector3D sourcePosition, Vector3D targetPosition, Vector3D targetVelocity, double laserPower, double laserDivergenceAngle)
{
LaserIlluminationOn = true;
LaserDesignatorPosition = sourcePosition;
TargetPosition = targetPosition;
TargetVelocity = targetVelocity;
LaserPower = laserPower;
LaserDivergenceAngle = laserDivergenceAngle;
}
/// <summary>
/// 关闭激光照射系统
/// </summary>
/// <remarks>
/// 关闭过程:
/// - 停止激光照射
/// - 清除位置信息
/// - 清除目标信息
/// - 清除激光参数
/// </remarks>
public void DeactivateLaserDesignator()
{
LaserIlluminationOn = false;
LaserDesignatorPosition = Vector3D.Zero;
TargetPosition = Vector3D.Zero;
TargetVelocity = Vector3D.Zero;
LaserPower = 0;
LaserDivergenceAngle = 0;
}
/// <summary>
/// 更新制导系统的状态和计算结果
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <param name="missilePosition">导弹位置,单位:米</param>
/// <param name="missileVelocity">导弹速度,单位:米/秒</param>
/// <remarks>
/// 更新过程:
/// - 检查激光照射状态
/// - 计算接收功率
/// - 判断是否锁定目标
/// - 计算制导指令
/// </remarks>
public override void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity)
{
base.Update(deltaTime, missilePosition, missileVelocity);
if (LaserIlluminationOn)
{
HasGuidance = CalculateReceivedLaserPower() > LockThreshold;
if (HasGuidance)
{
CalculateGuidanceAcceleration(deltaTime);
}
else
{
GuidanceAcceleration = Vector3D.Zero;
}
}
else
{
GuidanceAcceleration = Vector3D.Zero;
}
}
/// <summary>
/// 计算接收到的激光功率
/// </summary>
/// <returns>接收到的激光功率,单位:瓦特</returns>
/// <remarks>
/// 计算过程:
/// - 计算传播距离
/// - 计算光斑面积
/// - 计算功率密度
/// - 考虑目标反射
/// - 计算接收功率
/// - 考虑光学系统效率
/// </remarks>
private double CalculateReceivedLaserPower()
{
double distanceDesignatorToTarget = (LaserDesignatorPosition - TargetPosition).Magnitude();
double distanceMissileToTarget = (Position - TargetPosition).Magnitude();
// 计算目标处的光斑面积
double spotAreaAtTarget = Math.PI * Math.Pow(distanceDesignatorToTarget * Math.Tan(LaserDivergenceAngle), 2);
// 计算目标处的激光功率密度
double powerDensityAtTarget = LaserPower / spotAreaAtTarget;
// 计算从目标反射的总功率
double reflectedPower = powerDensityAtTarget * TargetReflectiveArea * ReflectionCoefficient;
// 计算反射光在导弹处的扩散面积(假设漫反射)
double reflectedSpotArea = 2 * Math.PI * Math.Pow(distanceMissileToTarget, 2);
// 计算导弹接收到的功率
double receivedPower = reflectedPower / reflectedSpotArea;
// 计算探测器接收到的功率比例
double detectorArea = Math.PI * Math.Pow(DetectorDiameter / 2, 2);
double illuminatedArea = Math.PI * Math.Pow(distanceMissileToTarget * Math.Tan(FieldOfViewAngle / 2), 2);
double powerRatio = Math.Min(1, detectorArea / illuminatedArea);
// 计算聚焦后的功率密度增加
double focusedArea = Math.PI * Math.Pow(FocusedSpotDiameter / 2, 2);
double focusingFactor = detectorArea / focusedArea;
// 计算最终接收到的功率
double finalReceivedPower = receivedPower * powerRatio * focusingFactor;
return finalReceivedPower;
}
/// <summary>
/// 计算制导加速度
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 计算过程:
/// - 使用比例导引算法
/// - 考虑目标运动
/// - 限制最大加速度
/// </remarks>
protected override void CalculateGuidanceAcceleration(double deltaTime)
{
// 计算比例导引加速度
GuidanceAcceleration = MotionAlgorithm.CalculateProportionalNavigation(ProportionalNavigationCoefficient, Position, Velocity, TargetPosition, TargetVelocity);
// 限制最大加速度
double maxAcceleration = 100; // 根据实际情况调整
if (GuidanceAcceleration.Magnitude() > maxAcceleration)
{
GuidanceAcceleration = GuidanceAcceleration.Normalize() * maxAcceleration;
}
}
/// <summary>
/// 获取制导系统的详细状态信息
/// </summary>
/// <returns>包含完整状态参数的字符串</returns>
/// <remarks>
/// 返回信息:
/// - 基本状态信息
/// - 接收功率数据
/// - 锁定阈值
/// 用于系统监控和调试
/// </remarks>
public override string GetStatus()
{
return base.GetStatus() + $" 接收到的激光功率: {CalculateReceivedLaserPower():E} W 锁定阈值: {LockThreshold:E} W";
}
}
}

View File

@ -0,0 +1,310 @@
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Target;
namespace ThreatSource.Guidance
{
/// <summary>
/// 毫米波导引头系统类,实现了基于毫米波雷达的目标探测和跟踪功能
/// </summary>
/// <remarks>
/// 该类提供了毫米波导引头系统的核心功能:
/// - 目标探测和识别
/// - 信噪比计算
/// - 抗干扰处理
/// - 比例导引控制
/// 用于实现全天候制导打击
/// </remarks>
public class MillimeterWaveGuidanceSystem : BasicGuidanceSystem
{
/// <summary>
/// 最大探测范围,单位:米
/// </summary>
/// <remarks>
/// 定义了毫米波雷达的最大作用距离
/// 超出此范围的目标无法有效探测
/// 典型值为5000米
/// </remarks>
private const double MAX_DETECTION_RANGE = 5000;
/// <summary>
/// 视场角,单位:弧度
/// </summary>
/// <remarks>
/// 定义了雷达的扫描范围
/// 设置为45度π/4弧度
/// 影响系统的搜索能力
/// </remarks>
private const double FIELD_OF_VIEW = Math.PI / 4;
/// <summary>
/// 目标识别概率
/// </summary>
/// <remarks>
/// 定义了目标识别的成功率
/// 影响系统的可靠性
/// 典型值为0.95
/// </remarks>
private const double TARGET_RECOGNITION_PROBABILITY = 0.95;
/// <summary>
/// 毫米波频率,单位:赫兹
/// </summary>
/// <remarks>
/// 定义了雷达工作频率
/// 设置为94GHz
/// 影响探测性能和抗干扰能力
/// </remarks>
private const double WAVE_FREQUENCY = 94e9;
/// <summary>
/// 脉冲持续时间,单位:秒
/// </summary>
/// <remarks>
/// 定义了雷达发射脉冲的时长
/// 影响距离分辨率
/// 典型值为1微秒
/// </remarks>
private const double PULSE_DURATION = 1e-6;
/// <summary>
/// 识别目标的信噪比阈值,单位:分贝
/// </summary>
/// <remarks>
/// 定义了目标识别的最小信噪比要求
/// 大于此值时认为目标有效
/// 典型值为6dB
/// </remarks>
private const double RECOGNITION_SNR_THRESHOLD = 6;
/// <summary>
/// 随机数生成器实例
/// </summary>
/// <remarks>
/// 用于生成随机扰动
/// 模拟系统噪声和识别概率
/// </remarks>
private readonly Random random = new();
/// <summary>
/// 上一次探测到的目标位置
/// </summary>
/// <remarks>
/// 记录目标的历史位置
/// 用于计算目标速度
/// </remarks>
private Vector3D lastTargetPosition;
/// <summary>
/// 是否受到干扰
/// </summary>
/// <remarks>
/// 指示当前是否受到电子干扰
/// 影响系统的工作状态
/// </remarks>
private bool isJammed = false;
/// <summary>
/// 干扰功率,单位:瓦特
/// </summary>
/// <remarks>
/// 记录接收到的干扰信号功率
/// 用于评估干扰效果
/// </remarks>
private double jammingPower = 0;
/// <summary>
/// 获取或设置仿真管理器实例
/// </summary>
/// <remarks>
/// 用于获取场景中的目标信息
/// 实现目标探测功能
/// </remarks>
public ISimulationManager SimulationManager { get; set; }
/// <summary>
/// 初始化毫米波导引头系统的新实例
/// </summary>
/// <param name="maxAcceleration">最大加速度,单位:米/平方秒</param>
/// <param name="guidanceCoefficient">制导系数</param>
/// <param name="simulationManager">仿真管理器实例</param>
/// <remarks>
/// 构造过程:
/// - 初始化基类参数
/// - 设置仿真管理器
/// - 初始化目标位置
/// - 注册干扰事件处理
/// </remarks>
public MillimeterWaveGuidanceSystem(double maxAcceleration, double guidanceCoefficient, ISimulationManager simulationManager) : base(maxAcceleration, guidanceCoefficient)
{
SimulationManager = simulationManager;
lastTargetPosition = Vector3D.Zero;
// 订阅干扰事件
simulationManager.SubscribeToEvent<MillimeterWaveJammingEvent>(HandleJammingEvent);
}
/// <summary>
/// 处理毫米波干扰事件
/// </summary>
/// <param name="evt">干扰事件参数</param>
/// <remarks>
/// 处理过程:
/// - 更新干扰状态
/// - 记录干扰功率
/// </remarks>
private void HandleJammingEvent(MillimeterWaveJammingEvent evt)
{
isJammed = true;
jammingPower = evt.JammingPower;
}
/// <summary>
/// 更新制导系统的状态和计算结果
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔,单位:秒</param>
/// <param name="missilePosition">导弹当前位置,单位:米</param>
/// <param name="missileVelocity">导弹当前速度,单位:米/秒</param>
/// <remarks>
/// 更新过程:
/// - 探测目标位置
/// - 计算目标速度
/// - 生成制导指令
/// - 限制最大加速度
/// </remarks>
public override void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity)
{
base.Update(deltaTime, missilePosition, missileVelocity);
if (TryDetectTank(missilePosition, missileVelocity, out Vector3D tankPosition))
{
//根据目标当前位置和上一次位置计算目标速度
Vector3D targetVelocity = (tankPosition - lastTargetPosition) / deltaTime;
lastTargetPosition = tankPosition;
// 使用基类的比例控制算法
GuidanceAcceleration = MotionAlgorithm.CalculateProportionalNavigation(ProportionalNavigationCoefficient, missilePosition, missileVelocity, tankPosition, targetVelocity);
if (GuidanceAcceleration.Magnitude() > MaxAcceleration)
{
GuidanceAcceleration = GuidanceAcceleration.Normalize() * MaxAcceleration;
}
HasGuidance = true;
}
else
{
HasGuidance = false;
}
}
/// <summary>
/// 尝试探测目标坦克
/// </summary>
/// <param name="missilePosition">导弹当前位置,单位:米</param>
/// <param name="missileVelocity">导弹当前速度,单位:米/秒</param>
/// <param name="targetPosition">输出探测到的目标位置,单位:米</param>
/// <returns>是否成功探测到目标</returns>
/// <remarks>
/// 探测过程:
/// - 检查干扰状态
/// - 遍历场景中的目标
/// - 检查距离和角度
/// - 计算信噪比
/// - 判断目标有效性
/// </remarks>
private bool TryDetectTank(Vector3D missilePosition, Vector3D missileVelocity, out Vector3D targetPosition)
{
targetPosition = Vector3D.Zero;
// 如果被干扰直接返回false
if (isJammed)
{
Console.WriteLine($"毫米波导引头受到干扰,干扰功率: {jammingPower:F2}W");
return false;
}
foreach (var element in SimulationManager.GetEntitiesByType<SimulationElement>())
{
if (element is Tank tank)
{
Vector3D toTarget = tank.Position - missilePosition;
double distance = toTarget.Magnitude();
if (distance <= MAX_DETECTION_RANGE)
{
double angle = Math.Acos(Vector3D.DotProduct(toTarget.Normalize(), missileVelocity.Normalize()));
if (angle <= FIELD_OF_VIEW / 2)
{
// 模拟毫米波探测
double snr = CalculateSNR(distance, tank.RadarCrossSection);
if(snr > RECOGNITION_SNR_THRESHOLD && random.NextDouble() < TARGET_RECOGNITION_PROBABILITY)
{
targetPosition = tank.Position;
return true;
}
}
}
}
}
return false;
}
/// <summary>
/// 获取制导系统的详细状态信息
/// </summary>
/// <returns>包含完整状态参数的字符串</returns>
/// <remarks>
/// 返回信息:
/// - 基本状态信息
/// - 目标位置
/// 用于系统监控和调试
/// </remarks>
public override string GetStatus()
{
return base.GetStatus() + $", Target Position: {lastTargetPosition}";
}
/// <summary>
/// 计算目标的信噪比
/// </summary>
/// <param name="distance">到目标的距离,单位:米</param>
/// <param name="radarCrossSection">目标雷达散射截面积,单位:平方米</param>
/// <returns>信噪比,单位:分贝</returns>
/// <remarks>
/// 计算过程:
/// - 设置雷达参数
/// - 计算信号功率
/// - 计算噪声功率
/// - 计算信噪比
/// - 转换为分贝值
/// </remarks>
private static double CalculateSNR(double distance, double radarCrossSection)
{
// 雷达参数
double transmitPower = 100; // 发射功率(W)
double antennaGain = Math.Pow(10, 30/10); // 天线增益(线性值从dB转换)
double wavelength = 3e8 / WAVE_FREQUENCY; // 波长(m)
double bandwidth = 1e6; // 接收机带宽(Hz)假设为1MHz
double noiseFigure = Math.Pow(10, 3/10); // 噪声系数(线性值假设为3dB)
// 常量
double k = 1.38e-23; // 玻尔兹曼常数
double T0 = 290; // 标准噪声温度(K)
// 计算接收信号功率
double signalPower = (transmitPower * Math.Pow(antennaGain, 2) * Math.Pow(wavelength, 2) * radarCrossSection)
/ (Math.Pow(4 * Math.PI, 3) * Math.Pow(distance, 4));
// 计算噪声功率
double noisePower = k * T0 * bandwidth * noiseFigure;
// 计算信噪比
double snr = signalPower / noisePower;
// 转换为dB
return 10 * Math.Log10(snr);
}
}
}

View File

@ -0,0 +1,166 @@
using ThreatSource.Utils;
namespace ThreatSource.Indicator
{
/// <summary>
/// 指示器接口,定义了所有指示器的通用功能
/// </summary>
/// <remarks>
/// 该接口提供了指示器的基本功能:
/// - 目标和导弹的关联
/// - 运行状态的获取
/// - 位置和姿态的管理
/// 是激光指示器、红外跟踪器等具体指示器的抽象基础
/// </remarks>
public interface IIndicator
{
/// <summary>
/// 获取或设置目标ID
/// </summary>
/// <remarks>
/// 用于标识和跟踪目标
/// 可以为null表示当前没有关联目标
/// </remarks>
string? TargetId { get; }
/// <summary>
/// 获取或设置导弹ID
/// </summary>
/// <remarks>
/// 用于标识和控制关联的导弹
/// 可以为null表示当前没有关联导弹
/// </remarks>
string? MissileId { get; }
/// <summary>
/// 获取指示器的当前运行状态
/// </summary>
/// <returns>包含指示器完整状态信息的结构体</returns>
/// <remarks>
/// 返回的状态信息包括:
/// - 目标和导弹的关联状态
/// - 指示器的工作状态
/// - 位置、速度和姿态信息
/// - 激活状态
/// </remarks>
IndicatorRunningState GetRunningState();
}
/// <summary>
/// 指示器运行状态结构体,包含了指示器的完整状态信息
/// </summary>
/// <remarks>
/// 该结构体封装了指示器的所有关键状态:
/// - 关联信息(目标和导弹)
/// - 工作状态(类型和状态)
/// - 运动状态(位置、速度、姿态)
/// - 功能状态(是否激活)
/// 用于状态监控和控制决策
/// </remarks>
public struct IndicatorRunningState
{
/// <summary>
/// 获取或设置目标ID
/// </summary>
/// <remarks>
/// 标识当前跟踪的目标
/// 用于目标关联和状态更新
/// </remarks>
public string TargetId { get; set; }
/// <summary>
/// 获取或设置导弹ID
/// </summary>
/// <remarks>
/// 标识当前控制的导弹
/// 用于导弹制导和状态同步
/// </remarks>
public string MissileId { get; set; }
/// <summary>
/// 获取或设置指示器类型
/// </summary>
/// <remarks>
/// 表示指示器的具体类型
/// 影响指示器的工作模式和性能参数
/// </remarks>
public IndicatorType Type { get; set; }
/// <summary>
/// 获取或设置指示器状态
/// </summary>
/// <remarks>
/// 表示指示器的当前工作状态
/// 用于控制指示器的工作模式
/// </remarks>
public IndicatorState State { get; set; }
/// <summary>
/// 获取或设置指示器位置
/// </summary>
/// <remarks>
/// 指示器在三维空间中的位置向量
/// 用于空间定位和运动控制
/// </remarks>
public Vector3D Position { get; set; }
/// <summary>
/// 获取或设置指示器速度
/// </summary>
/// <remarks>
/// 指示器在三维空间中的速度向量
/// 用于运动状态更新和预测
/// </remarks>
public Vector3D Velocity { get; set; }
/// <summary>
/// 获取或设置指示器朝向
/// </summary>
/// <remarks>
/// 指示器在三维空间中的姿态
/// 影响指示器的工作效果和精度
/// </remarks>
public Orientation Orientation { get; set; }
/// <summary>
/// 获取或设置指示器是否激活
/// </summary>
/// <remarks>
/// 表示指示器是否处于工作状态
/// true表示正在工作false表示待机
/// </remarks>
public bool IsActive { get; set; }
}
/// <summary>
/// 指示器类型枚举,定义了支持的指示器类型
/// </summary>
/// <remarks>
/// 包含三种主要的指示器类型:
/// - LaserDisintegrator激光指示器用于半主动激光制导
/// - LaserBeamRider激光波束制导器用于波束乘波制导
/// - InfraredTracker红外跟踪器用于红外制导
/// 每种类型具有不同的工作原理和性能特点
/// </remarks>
public enum IndicatorType
{
LaserDisintegrator, // 激光指示器
LaserBeamRider, // 激光波束制导器
InfraredTracker // 红外跟踪器
}
/// <summary>
/// 指示器状态枚举,定义了指示器的工作状态
/// </summary>
/// <remarks>
/// 包含两种基本状态:
/// - Indicating指示状态正在执行指示或跟踪任务
/// - Idle空闲状态等待新的指示任务
/// 用于控制指示器的工作流程
/// </remarks>
public enum IndicatorState
{
Indicating, // 指示状态
Idle // 空闲状态
}
}

View File

@ -0,0 +1,293 @@
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Missile;
namespace ThreatSource.Indicator
{
/// <summary>
/// 红外测角仪类,实现了红外制导导弹的跟踪和制导功能
/// </summary>
/// <remarks>
/// 该类提供了红外测角仪的核心功能:
/// - 红外目标跟踪
/// - 角度测量和计算
/// - 制导指令生成
/// - 事件处理和状态管理
/// 通过测量目标的红外辐射实现对导弹的制导控制
/// </remarks>
public class InfraredTracker : SimulationElement, IIndicator
{
/// <summary>
/// 获取或设置当前跟踪的导弹ID
/// </summary>
/// <remarks>
/// 记录当前正在跟踪的导弹标识符
/// 用于导弹识别和制导控制
/// </remarks>
public string? MissileId { get; private set; }
/// <summary>
/// 获取或设置目标ID
/// </summary>
/// <remarks>
/// 记录当前跟踪的目标标识符
/// 用于目标识别和状态更新
/// </remarks>
public string? TargetId { get; private set; }
/// <summary>
/// 红外测角仪配置参数
/// </summary>
/// <remarks>
/// 包含测角仪的工作参数:
/// - 初始位置和姿态
/// - 最大跟踪距离
/// - 视场角等性能参数
/// </remarks>
private readonly InfraredTrackerConfig config;
/// <summary>
/// 获取或设置红外测角仪是否正在跟踪目标
/// </summary>
/// <remarks>
/// true表示正在跟踪目标
/// false表示未在跟踪状态
/// 用于控制测角仪的工作状态
/// </remarks>
public bool IsTracking { get; private set; }
/// <summary>
/// 初始化红外测角仪的新实例
/// </summary>
/// <param name="id">测角仪ID</param>
/// <param name="targetId">目标ID</param>
/// <param name="config">配置参数</param>
/// <param name="manager">仿真管理器实例</param>
/// <remarks>
/// 构造过程:
/// - 初始化基本属性
/// - 设置目标关联
/// - 配置工作参数
/// - 设置初始状态
/// </remarks>
public InfraredTracker(string id, string targetId, InfraredTrackerConfig config, ISimulationManager manager)
: base(id, config.InitialPosition, config.InitialOrientation, 0, manager)
{
TargetId = targetId;
MissileId = null;
this.config = config;
IsTracking = false;
}
/// <summary>
/// 更新红外测角仪状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 检查激活状态
/// - 更新跟踪状态
/// - 处理目标跟踪
/// </remarks>
public override void Update(double deltaTime)
{
if (!IsActive) return;
UpdateTracking();
}
/// <summary>
/// 更新跟踪状态
/// </summary>
/// <remarks>
/// 跟踪过程:
/// - 获取目标和导弹实体
/// - 计算相对位置和距离
/// - 检查跟踪条件
/// - 生成制导指令
/// </remarks>
private void UpdateTracking()
{
if (MissileId == null || TargetId == null) return;
var target = SimulationManager.GetEntityById(TargetId);
var missile = SimulationManager.GetEntityById(MissileId);
if (target is not SimulationElement targetElement ||
missile is not InfraredCommandGuidedMissile missileElement) return;
IsTracking = true;
// 计算导弹到测角仪的距离
double distanceToMissile = Vector3D.Distance(Position, missileElement.Position);
// 检查导弹是否在跟踪范围内
if (distanceToMissile <= config.MaxTrackingRange)
{
// 计算测角仪到导弹的向量
Vector3D trackerToMissile = missileElement.Position - Position;
// 计算测角仪到目标的向量
Vector3D trackerToTarget = targetElement.Position - Position;
// 发送制导指令事件
PublishGuidanceCommandEvent(missileElement.Id, trackerToMissile, trackerToTarget, Id);
}
else
{
// 导弹超出跟踪范围,停止跟踪
StopTracking();
}
}
/// <summary>
/// 停止跟踪目标
/// </summary>
/// <remarks>
/// 停止过程:
/// - 清除导弹关联
/// - 清除目标关联
/// - 重置跟踪状态
/// </remarks>
public void StopTracking()
{
MissileId = null;
TargetId = null;
IsTracking = false;
}
/// <summary>
/// 发布制导指令事件
/// </summary>
/// <param name="missileId">导弹ID</param>
/// <param name="trackerToMissileVector">测角仪到导弹的向量</param>
/// <param name="trackerToTargetVector">测角仪到目标的向量</param>
/// <param name="senderId">发送者ID</param>
/// <remarks>
/// 发布过程:
/// - 创建制导指令事件
/// - 设置事件参数
/// - 发布到事件系统
/// </remarks>
private void PublishGuidanceCommandEvent(string missileId, Vector3D trackerToMissileVector, Vector3D trackerToTargetVector, string senderId)
{
var evt = new InfraredGuidanceCommandEvent
{
TargetMissileId = missileId,
TrackerToMissileVector = trackerToMissileVector,
TrackerToTargetVector = trackerToTargetVector,
SenderId = senderId
};
SimulationManager.PublishEvent(evt);
}
/// <summary>
/// 处理红外指令制导导弹点亮红外热源事件
/// </summary>
/// <param name="evt">红外热源点亮事件数据</param>
/// <remarks>
/// 处理过程:
/// - 记录导弹ID
/// - 准备开始跟踪
/// </remarks>
private void OnInfraredGuidanceMissileLight(InfraredGuidanceMissileLightEvent evt)
{
// 处理导弹点亮红外热源事件
MissileId = evt.SenderId ?? "";
}
/// <summary>
/// 处理红外指令制导导弹熄灭红外热源事件
/// </summary>
/// <param name="evt">红外热源熄灭事件数据</param>
/// <remarks>
/// 处理过程:
/// - 验证导弹ID
/// - 停止跟踪
/// </remarks>
private void OnInfraredGuidanceMissileLightOff(InfraredGuidanceMissileLightOffEvent evt)
{
// 处理导弹熄灭红外热源事件
if (evt.SenderId == MissileId) StopTracking();
}
/// <summary>
/// 激活红外测角仪
/// </summary>
/// <remarks>
/// 激活过程:
/// - 调用基类激活方法
/// - 订阅红外事件
/// - 准备开始工作
/// </remarks>
public override void Activate()
{
base.Activate();
SimulationManager.SubscribeToEvent<InfraredGuidanceMissileLightEvent>(OnInfraredGuidanceMissileLight);
SimulationManager.SubscribeToEvent<InfraredGuidanceMissileLightOffEvent>(OnInfraredGuidanceMissileLightOff);
}
/// <summary>
/// 停用红外测角仪
/// </summary>
/// <remarks>
/// 停用过程:
/// - 调用基类停用方法
/// - 取消事件订阅
/// - 清理工作状态
/// </remarks>
public override void Deactivate()
{
base.Deactivate();
SimulationManager.UnsubscribeFromEvent<InfraredGuidanceMissileLightEvent>(OnInfraredGuidanceMissileLight);
SimulationManager.UnsubscribeFromEvent<InfraredGuidanceMissileLightOffEvent>(OnInfraredGuidanceMissileLightOff);
}
/// <summary>
/// 获取红外测角仪运行状态
/// </summary>
/// <returns>包含测角仪完整状态信息的结构体</returns>
/// <remarks>
/// 返回信息包括:
/// - 目标和导弹关联状态
/// - 工作类型和状态
/// - 位置和姿态信息
/// - 激活状态
/// </remarks>
public IndicatorRunningState GetRunningState()
{
return new IndicatorRunningState
{
TargetId = TargetId ?? "",
MissileId = MissileId ?? "",
Type = IndicatorType.InfraredTracker,
State = IsTracking ? IndicatorState.Indicating : IndicatorState.Idle,
Position = Position,
Orientation = Orientation,
IsActive = IsActive
};
}
/// <summary>
/// 获取红外测角仪状态信息
/// </summary>
/// <returns>包含测角仪状态的详细描述</returns>
/// <remarks>
/// 返回信息包括:
/// - 基本标识信息
/// - 位置信息
/// - 跟踪状态
/// - 目标关联状态
/// - 工作状态
/// </remarks>
public override string GetStatus()
{
return $"红外测角仪 {Id}:\n" +
$" 位置: {Position}\n" +
$" 跟踪导弹: {MissileId ?? ""}\n" +
$" 目标: {TargetId ?? ""}\n" +
$" 状态: {(IsActive ? "" : "")}\n" +
$" 跟踪状态: {(IsTracking ? "" : "")}\n";
}
}
}

View File

@ -0,0 +1,325 @@
using ThreatSource.Simulation;
using System;
using ThreatSource.Utils;
namespace ThreatSource.Indicator
{
/// <summary>
/// 激光波束制导器类,用于生成激光波束制导场
/// </summary>
/// <remarks>
/// 该类提供了激光波束制导系统的核心功能:
/// - 生成和维护激光波束制导场
/// - 控制激光波束的开启和关闭
/// - 实时更新波束位置和方向
/// - 发布波束状态事件
/// </remarks>
public class LaserBeamRider : SimulationElement, IIndicator
{
/// <summary>
/// 获取或设置激光功率
/// </summary>
/// <remarks>
/// 单位:瓦特
/// 影响激光波束的有效作用距离和制导精度
/// </remarks>
public double LaserPower { get; private set; }
/// <summary>
/// 获取或设置激光发散角
/// </summary>
/// <remarks>
/// 单位:毫弧度
/// 影响激光波束的扩散特性和制导精度
/// </remarks>
public double BeamDivergence { get; private set; } = 0.0;
/// <summary>
/// 获取或设置控制场直径
/// </summary>
/// <remarks>
/// 单位:米
/// 定义了激光波束制导场的有效范围
/// </remarks>
public double ControlFieldDiameter { get; private set; }
/// <summary>
/// 获取或设置激光方向
/// </summary>
/// <remarks>
/// 使用三维向量表示激光波束的指向
/// 向量的模为1归一化
/// </remarks>
public Vector3D LaserDirection { get; private set; }
/// <summary>
/// 获取或设置最大导引距离
/// </summary>
/// <remarks>
/// 单位:米
/// 超出此距离的导弹将无法接收到有效的制导信号
/// </remarks>
public double MaxGuidanceDistance { get; private set; }
/// <summary>
/// 获取激光束是否开启
/// </summary>
/// <remarks>
/// true表示激光波束正在发射
/// false表示激光波束已关闭
/// </remarks>
public bool IsBeamOn { get; private set; }
/// <summary>
/// 获取当前制导的导弹ID
/// </summary>
/// <remarks>
/// 记录正在接受制导的导弹标识符
/// 如果为null表示当前没有制导目标
/// </remarks>
public string? MissileId { get; private set; }
/// <summary>
/// 获取目标ID
/// </summary>
/// <remarks>
/// 记录当前跟踪的目标标识符
/// 如果为null表示当前没有跟踪目标
/// </remarks>
public string? TargetId { get; private set; }
/// <summary>
/// 初始化激光波束制导器的新实例
/// </summary>
/// <param name="id">制导器的唯一标识符</param>
/// <param name="missileId">导弹ID</param>
/// <param name="targetId">目标ID</param>
/// <param name="speed">初始速度</param>
/// <param name="config">配置参数</param>
/// <param name="simulationManager">仿真管理器实例</param>
/// <remarks>
/// 构造过程:
/// - 初始化基本属性
/// - 设置激光参数
/// - 配置制导范围
/// - 建立目标关联
/// </remarks>
public LaserBeamRider(string id, string missileId, string targetId, double speed, LaserBeamRiderConfig config, ISimulationManager simulationManager)
: base(id, config.InitialPosition, new Orientation(0, 0, 0), speed, simulationManager)
{
LaserPower = config.LaserPower;
ControlFieldDiameter = config.ControlFieldDiameter;
LaserDirection = Vector3D.Zero;
MaxGuidanceDistance = config.MaxGuidanceDistance;
IsActive = false; // 初始状态为非激活
IsBeamOn = false;
MissileId = missileId;
TargetId = targetId;
base.SimulationManager = simulationManager;
}
/// <summary>
/// 更新激光驾束仪状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 检查激活状态
/// - 更新激光指向
/// - 发布状态更新事件
/// </remarks>
public override void Update(double deltaTime)
{
if (IsActive && IsBeamOn)
{
// 更新驾束仪的激光指向
if (TargetId != null && SimulationManager.GetEntityById(TargetId) is SimulationElement target)
{
Vector3D targetPosition = target.Position;
LaserDirection = (targetPosition - Position).Normalize();
Console.WriteLine($"激光驾束仪 {Id} 更新激光指向: {LaserDirection}");
PublishLaserBeamUpdateEvent();
}
}
}
/// <summary>
/// 激活激光驾束仪
/// </summary>
/// <remarks>
/// 激活过程:
/// - 设置激活状态
/// - 开始激光照射
/// - 发布激活事件
/// </remarks>
public override void Activate()
{
if (!IsActive)
{
IsActive = true;
Console.WriteLine($"激光驾束仪 {Id} 已激活");
// 激光驾束仪开始照射
StartBeamIllumination();
}
base.Activate();
}
/// <summary>
/// 停用激光驾束仪
/// </summary>
/// <remarks>
/// 停用过程:
/// - 停止激光照射
/// - 清理状态
/// - 发布停用事件
/// </remarks>
public override void Deactivate()
{
if (IsActive)
{
IsActive = false;
if (IsBeamOn)
{
StopBeamIllumination();
}
Console.WriteLine($"激光驾束仪 {Id} 已停用");
}
base.Deactivate();
}
/// <summary>
/// 开启激光束照射
/// </summary>
/// <remarks>
/// 开启过程:
/// - 计算初始指向
/// - 设置照射状态
/// - 发布开始事件
/// </remarks>
public void StartBeamIllumination()
{
if (!IsBeamOn)
{
if (TargetId != null && SimulationManager.GetEntityById(TargetId) is SimulationElement target)
{
LaserDirection = (target.Position - Position).Normalize();
IsBeamOn = true;
PublishLaserBeamStartEvent();
}
}
}
/// <summary>
/// 停止激光束照射
/// </summary>
/// <remarks>
/// 停止过程:
/// - 关闭激光输出
/// - 清除指向信息
/// - 发布停止事件
/// </remarks>
public void StopBeamIllumination()
{
if (IsBeamOn)
{
IsBeamOn = false;
LaserDirection = Vector3D.Zero;
PublishLaserBeamStopEvent();
}
}
/// <summary>
/// 发布激光束开始事件
/// </summary>
/// <remarks>
/// 通知仿真系统激光波束开始工作
/// 包含制导器ID等关键信息
/// </remarks>
private void PublishLaserBeamStartEvent()
{
PublishEvent(new LaserBeamStartEvent
{
LaserBeamRiderId = Id
});
}
/// <summary>
/// 发布激光束更新事件
/// </summary>
/// <remarks>
/// 通知仿真系统激光波束状态已更新
/// 包含最新的位置和方向信息
/// </remarks>
private void PublishLaserBeamUpdateEvent()
{
PublishEvent(new LaserBeamUpdateEvent
{
LaserBeamRiderId = Id
});
}
/// <summary>
/// 发布激光束停止事件
/// </summary>
/// <remarks>
/// 通知仿真系统激光波束已停止工作
/// 包含制导器ID等关键信息
/// </remarks>
private void PublishLaserBeamStopEvent()
{
PublishEvent(new LaserBeamStopEvent
{
LaserBeamRiderId = Id
});
}
/// <summary>
/// 获取激光驾束仪运行状态
/// </summary>
/// <returns>包含完整状态信息的结构体</returns>
/// <remarks>
/// 返回信息包括:
/// - 目标和导弹ID
/// - 设备类型和工作状态
/// - 位置和朝向信息
/// - 激活状态
/// </remarks>
public IndicatorRunningState GetRunningState()
{
return new IndicatorRunningState
{
TargetId = TargetId ?? "",
MissileId = MissileId ?? "",
Type = IndicatorType.LaserBeamRider,
State = IsBeamOn ? IndicatorState.Indicating : IndicatorState.Idle,
Position = Position,
Orientation = Orientation,
IsActive = IsActive
};
}
/// <summary>
/// 获取激光驾束仪状态字符串
/// </summary>
/// <returns>包含设备状态的详细描述</returns>
/// <remarks>
/// 返回信息包括:
/// - 设备ID和位置
/// - 激光参数(功率、发散角等)
/// - 工作状态(激活、照射等)
/// - 制导范围参数
/// </remarks>
public override string GetStatus()
{
return $"激光驾束仪 {Id}:\n" +
$" 位置: {Position}\n" +
$" 方向: {LaserDirection}\n" +
$" 激活状态: {(IsActive ? "" : "")}\n" +
$" 激光束状态: {(IsBeamOn ? "" : "")}\n" +
$" 激光功率: {LaserPower} W\n" +
$" 发散角: {BeamDivergence} rad\n" +
$" 控制场直径: {ControlFieldDiameter} m\n" +
$" 最大导引距离: {MaxGuidanceDistance} m\n";
}
}
}

View File

@ -0,0 +1,383 @@
using ThreatSource.Simulation;
using System;
using ThreatSource.Utils;
namespace ThreatSource.Indicator
{
/// <summary>
/// 激光指示器类,实现了对目标的激光照射和制导功能
/// </summary>
/// <remarks>
/// 该类提供了激光指示器的核心功能:
/// - 激光目标照射
/// - 抗干扰处理
/// - 事件管理
/// - 状态监控
/// 通过激光照射目标实现半主动激光制导
/// </remarks>
public class LaserDesignator : SimulationElement
{
/// <summary>
/// 获取或设置目标ID
/// </summary>
/// <remarks>
/// 记录当前照射的目标标识符
/// 用于目标识别和状态更新
/// </remarks>
public string? TargetId { get; private set; }
/// <summary>
/// 获取或设置导弹ID
/// </summary>
/// <remarks>
/// 记录当前关联的导弹标识符
/// 用于导弹制导控制
/// </remarks>
public string? MissileId { get; private set; }
/// <summary>
/// 获取或设置干扰阈值,单位:分贝
/// </summary>
/// <remarks>
/// 定义了激光指示器的抗干扰能力
/// 当干扰信号强度超过此阈值时触发干扰效果
/// </remarks>
public double JammingThreshold { get; private set; } = 0.0;
/// <summary>
/// 获取或设置是否被干扰状态
/// </summary>
/// <remarks>
/// true表示当前受到有效干扰
/// false表示工作正常
/// 影响激光照射的有效性
/// </remarks>
public bool IsJammed { get; private set; } = false;
/// <summary>
/// 获取或设置是否正在照射状态
/// </summary>
/// <remarks>
/// true表示正在执行激光照射
/// false表示未在照射状态
/// 控制激光发射状态
/// </remarks>
public bool IsIlluminationOn { get; private set; } = false;
/// <summary>
/// 获取或设置激光功率,单位:瓦特
/// </summary>
/// <remarks>
/// 定义了激光照射的能量强度
/// 影响照射距离和制导效果
/// </remarks>
public double LaserPower { get; private set; } = 0;
/// <summary>
/// 获取或设置激光发散角,单位:弧度
/// </summary>
/// <remarks>
/// 定义了激光束的扩展角度
/// 影响照射面积和能量密度
/// </remarks>
public double LaserDivergenceAngle { get; private set; } = 0;
/// <summary>
/// 初始化激光指示器的新实例
/// </summary>
/// <param name="id">激光指示器ID</param>
/// <param name="targetId">目标ID</param>
/// <param name="missileId">导弹ID</param>
/// <param name="speed">移动速度</param>
/// <param name="config">配置参数</param>
/// <param name="simulationManager">仿真管理器实例</param>
/// <remarks>
/// 构造过程:
/// - 初始化基本属性
/// - 设置目标和导弹关联
/// - 配置激光参数
/// - 设置初始状态
/// </remarks>
public LaserDesignator(string id, string targetId, string missileId, double speed, LaserDesignatorConfig config, ISimulationManager simulationManager)
: base(id, config.InitialPosition, new Orientation(), speed, simulationManager)
{
TargetId = targetId;
MissileId = missileId;
IsActive = false;
IsIlluminationOn = false;
LaserPower = config.LaserPower;
LaserDivergenceAngle = config.LaserDivergenceAngle;
}
/// <summary>
/// 更新激光指示器状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 检查激活状态
/// - 检查干扰状态
/// - 更新照射状态
/// - 发布状态事件
/// </remarks>
public override void Update(double deltaTime)
{
if (IsActive && !IsJammed)
{
if (IsIlluminationOn)
{
PublishIlluminationUpdateEvent();
}
}
}
/// <summary>
/// 开始激光照射
/// </summary>
/// <remarks>
/// 启动过程:
/// - 设置照射状态
/// - 记录开始时间
/// - 发布开始事件
/// - 输出状态信息
/// </remarks>
private void StartLaserIllumination()
{
if (!IsIlluminationOn)
{
IsIlluminationOn = true;
Console.WriteLine($"激光目标指示器 {Id} 开始照射目标 {TargetId}");
PublishIlluminationStartEvent();
}
}
/// <summary>
/// 停止激光照射
/// </summary>
/// <remarks>
/// 停止过程:
/// - 清除照射状态
/// - 记录停止时间
/// - 发布停止事件
/// - 输出状态信息
/// </remarks>
private void StopLaserIllumination()
{
if (IsIlluminationOn)
{
IsIlluminationOn = false;
Console.WriteLine($"激光目标指示器 {Id} 停止照射目标 {TargetId}");
PublishIlluminationStopEvent();
}
}
/// <summary>
/// 处理激光干扰事件
/// </summary>
/// <param name="evt">激光干扰事件数据</param>
/// <remarks>
/// 处理过程:
/// - 验证目标ID
/// - 计算干扰效果
/// - 更新干扰状态
/// - 处理工作模式
/// </remarks>
private void OnLaserJamming(LaserJammingEvent evt)
{
if (evt.TargetId == TargetId && TargetId != null && SimulationManager.GetEntityById(TargetId) is Target.Tank tank)
{
double distanceToTarget = Vector3D.Distance(Position, tank.Position);
double jammingEffectiveness = 20 * Math.Log10(evt.JammingPower) - 20 * Math.Log10(distanceToTarget) - 20 * Math.Log10(4 * Math.PI);
Console.WriteLine($"激光目标指示器 {Id} 收到干扰事件,干扰功率: {evt.JammingPower:F2}, 距离: {distanceToTarget:F2}, 干扰效果: {jammingEffectiveness:F2} dB, 阈值: {JammingThreshold:F2} dB");
if (jammingEffectiveness > JammingThreshold)
{
if (!IsJammed)
{
Console.WriteLine($"激光目标指示器 {Id} 被干扰,停止工作");
IsJammed = true;
StopLaserIllumination();
}
}
else
{
if (IsJammed)
{
Console.WriteLine($"激光目标指示器 {Id} 干扰解除,恢复工作");
IsJammed = false;
}
}
}
}
/// <summary>
/// 激活激光指示器
/// </summary>
/// <remarks>
/// 激活过程:
/// - 设置激活状态
/// - 清除干扰状态
/// - 开始激光照射
/// - 订阅相关事件
/// - 调用基类激活
/// </remarks>
public override void Activate()
{
if (!IsActive)
{
IsActive = true;
IsJammed = false;
Console.WriteLine($"激光目标指示器 {Id} 已激活");
StartLaserIllumination();
SimulationManager.SubscribeToEvent<LaserJammingEvent>(OnLaserJamming);
SimulationManager.SubscribeToEvent<EntityDeactivatedEvent>(OnEntityDeactivatedEvent);
}
base.Activate();
}
/// <summary>
/// 停用激光指示器
/// </summary>
/// <remarks>
/// 停用过程:
/// - 清除激活状态
/// - 停止激光照射
/// - 取消事件订阅
/// - 清理工作状态
/// - 调用基类停用
/// </remarks>
public override void Deactivate()
{
if (IsActive)
{
IsActive = false;
StopLaserIllumination();
Console.WriteLine($"激光目标指示器 {Id} 已停用");
SimulationManager.UnsubscribeFromEvent<LaserJammingEvent>(OnLaserJamming);
SimulationManager.UnsubscribeFromEvent<EntityDeactivatedEvent>(OnEntityDeactivatedEvent);
}
base.Deactivate();
}
/// <summary>
/// 发布激光照射开始事件
/// </summary>
/// <remarks>
/// 发布过程:
/// - 创建事件对象
/// - 设置事件参数
/// - 发布到事件系统
/// - 记录事件日志
/// </remarks>
private void PublishIlluminationStartEvent()
{
var evt = new LaserIlluminationStartEvent { LaserDesignatorId = Id, TargetId = TargetId };
PublishEvent(evt);
Console.WriteLine($"激光指示器 {Id} 发布激光照射事件");
}
/// <summary>
/// 发布激光照射更新事件
/// </summary>
/// <remarks>
/// 发布过程:
/// - 创建更新事件
/// - 设置最新参数
/// - 发布到事件系统
/// - 记录更新日志
/// </remarks>
private void PublishIlluminationUpdateEvent()
{
var evt = new LaserIlluminationUpdateEvent { LaserDesignatorId = Id, TargetId = TargetId };
PublishEvent(evt);
Console.WriteLine($"激光指示器 {Id} 发布激光照射更新事件");
}
/// <summary>
/// 发布激光照射停止事件
/// </summary>
/// <remarks>
/// 发布过程:
/// - 创建停止事件
/// - 设置结束参数
/// - 发布到事件系统
/// - 记录停止日志
/// </remarks>
private void PublishIlluminationStopEvent()
{
var evt = new LaserIlluminationStopEvent { LaserDesignatorId = Id, TargetId = TargetId };
PublishEvent(evt);
Console.WriteLine($"激光指示器 {Id} 发布激光照射停止事件");
}
/// <summary>
/// 处理实体停用事件
/// </summary>
/// <param name="evt">实体停用事件数据</param>
/// <remarks>
/// 处理过程:
/// - 检查停用实体
/// - 处理关联实体
/// - 更新工作状态
/// </remarks>
private void OnEntityDeactivatedEvent(EntityDeactivatedEvent evt)
{
if (evt.DeactivatedEntityId == TargetId || evt.DeactivatedEntityId == MissileId)
{
StopLaserIllumination();
}
}
/// <summary>
/// 获取激光指示器运行状态
/// </summary>
/// <returns>包含指示器完整状态信息的结构体</returns>
/// <remarks>
/// 返回信息包括:
/// - 目标和导弹关联状态
/// - 工作类型和状态
/// - 位置和姿态信息
/// - 激活状态
/// </remarks>
public IndicatorRunningState GetRunningState()
{
return new IndicatorRunningState
{
TargetId = TargetId ?? "",
MissileId = MissileId ?? "",
Type = IndicatorType.LaserDisintegrator,
State = IsIlluminationOn ? IndicatorState.Indicating : IndicatorState.Idle,
Position = Position,
Orientation = Orientation,
IsActive = IsActive
};
}
/// <summary>
/// 获取激光指示器状态信息
/// </summary>
/// <returns>包含指示器状态的详细描述</returns>
/// <remarks>
/// 返回信息包括:
/// - 基本标识信息
/// - 位置信息
/// - 目标关联状态
/// - 工作状态
/// - 干扰状态
/// - 激光参数
/// </remarks>
public override string GetStatus()
{
return $"激光目标指示器 {Id}:\n" +
$" 位置: {Position}\n" +
$" 目标: {TargetId}\n" +
$" 导弹: {MissileId}\n" +
$" 激活状态: {(IsActive ? "" : "")}\n" +
$" 照射状态: {(IsIlluminationOn ? "" : "")}\n" +
$" 干扰状态: {(IsJammed ? "" : "")}\n" +
$" 激光功率: {LaserPower:E} W";
}
}
}

View File

@ -0,0 +1,415 @@
using ThreatSource.Simulation;
using ThreatSource.Utils;
namespace ThreatSource.Missile
{
/// <summary>
/// 导弹基类,实现了导弹的基本功能和状态管理
/// </summary>
/// <remarks>
/// 该类提供了导弹的核心功能:
/// - 运动状态计算和更新
/// - 制导系统管理
/// - 发动机控制
/// - 自毁和爆炸处理
/// - 状态监控和事件处理
/// 所有具体的导弹类型都继承自此基类
/// </remarks>
public class BaseMissile : SimulationElement, IMissile
{
/// <summary>
/// 获取导弹的当前飞行时间
/// </summary>
/// <value>飞行时间,单位:秒</value>
/// <remarks>
/// 从发射时刻开始计时
/// 用于控制导弹的生命周期
/// </remarks>
public double FlightTime { get; protected set; }
/// <summary>
/// 获取导弹的当前飞行距离
/// </summary>
/// <value>飞行距离,单位:米</value>
/// <remarks>
/// 从发射点到当前位置的累计飞行距离
/// 用于判断是否超出最大射程
/// </remarks>
public double FlightDistance { get; protected set; }
/// <summary>
/// 获取发动机的当前燃烧时间
/// </summary>
/// <value>发动机燃烧时间,单位:秒</value>
/// <remarks>
/// 发动机工作的累计时间
/// 用于控制推力变化和燃料消耗
/// </remarks>
public double EngineBurnTime { get; protected set; }
/// <summary>
/// 获取导弹是否处于制导状态
/// </summary>
/// <value>true表示导弹当前在制导false表示导弹处于非制导状态</value>
/// <remarks>
/// 影响导弹的运动学计算方法
/// 制导状态下使用制导律计算加速度
/// 非制导状态下使用弹道方程计算运动
/// </remarks>
public bool IsGuidance { get; protected set; }
/// <summary>
/// 获取或设置导弹失去制导的持续时间
/// </summary>
/// <value>失去制导的时间,单位:秒</value>
/// <remarks>
/// 用于判断是否需要触发自毁
/// 超过阈值时可能导致导弹自毁
/// </remarks>
protected double LostGuidanceTime { get; set; } = 0;
/// <summary>
/// 获取或设置导弹的最后已知速度向量
/// </summary>
/// <value>三维速度向量</value>
/// <remarks>
/// 用于在失去制导时保持导弹的运动状态
/// 作为弹道计算的参考数据
/// </remarks>
protected Vector3D LastKnownVelocity = Vector3D.Zero;
/// <summary>
/// 获取或设置导弹的制导加速度
/// </summary>
/// <value>三维加速度向量,单位:米/秒²</value>
/// <remarks>
/// 由制导系统计算得出的期望加速度
/// 用于修正导弹的飞行路径
/// </remarks>
protected Vector3D GuidanceAcceleration { get; set; }
/// <summary>
/// 获取或设置导弹的推力加速度
/// </summary>
/// <value>三维加速度向量,单位:米/秒²</value>
/// <remarks>
/// 由发动机产生的推进加速度
/// 影响导弹的速度变化
/// </remarks>
protected Vector3D ThrustAcceleration { get; set; }
/// <summary>
/// 获取导弹的固定配置参数
/// </summary>
/// <value>导弹属性配置对象</value>
/// <remarks>
/// 包含导弹的所有基本属性和性能限制
/// 在导弹创建时设置,运行期间保持不变
/// </remarks>
public readonly MissileProperties MissileProperties;
/// <summary>
/// 初始化导弹基类的新实例
/// </summary>
/// <param name="properties">导弹的配置参数</param>
/// <param name="manager">仿真管理器实例</param>
/// <remarks>
/// 构造过程:
/// - 初始化基本属性(位置、朝向、速度)
/// - 设置初始状态(未激活、未制导)
/// - 清零计时器和计数器
/// - 初始化加速度向量
/// </remarks>
public BaseMissile(MissileProperties properties, ISimulationManager manager)
: base(properties.Id, properties.InitialPosition, properties.InitialOrientation, properties.InitialSpeed, manager)
{
MissileProperties = properties;
SimulationManager = manager;
IsActive = false;
IsGuidance = false;
FlightTime = 0;
FlightDistance = 0;
EngineBurnTime = 0;
GuidanceAcceleration = Vector3D.Zero;
ThrustAcceleration = Vector3D.Zero;
}
/// <summary>
/// 更新导弹的状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 检查导弹是否处于活动状态
/// - 更新导弹的运动状态
/// - 更新计时器和计数器
/// </remarks>
public override void Update(double deltaTime)
{
if (IsActive)
{
// 更新导弹运动状态
UpdateMotionState(deltaTime);
}
}
protected virtual void UpdateMotionState(double deltaTime)
{
//Vector3D acceleration = CalculateAcceleration(Velocity);
Vector3D acceleration = GuidanceAcceleration;
if (IsGuidance)
{
// 制导条件下,使用四阶龙格-库塔方法更新导弹的位置和速度
(Position, Velocity) = MotionAlgorithm.RungeKutta4(deltaTime, Position, Velocity, acceleration);
}
else
{
// 无制导条件下,使用运动学方程更新导弹的位置和速度
(Position, Velocity) = MotionAlgorithm.CalculateBallisticMotion(Position, Velocity, acceleration, deltaTime);
}
// 限制速度不超过最大速度
if (Velocity.Magnitude() > MissileProperties.MaxSpeed)
{
Velocity = Velocity.Normalize() * MissileProperties.MaxSpeed;
}
Speed = Velocity.Magnitude();
Orientation = Orientation.FromVector(Velocity);
// 添加高斯噪声(测试用,用于测试运动中概率的影响)
// Position = MotionAlgorithm.AddRandomPerturbation(Position);
// Velocity = MotionAlgorithm.AddRandomPerturbation(Velocity);
FlightTime += deltaTime;
FlightDistance += Speed * deltaTime;
}
/// <summary>
/// 计算导弹的合加速度
/// </summary>
/// <param name="velocity">当前速度向量</param>
/// <returns>合加速度向量</returns>
/// <remarks>
/// 计算过程:
/// - 计算空气阻力加速度
/// - 合成制导、推力和阻力加速度
/// - 限制合加速度不超过最大值
/// </remarks>
private Vector3D CalculateAcceleration(Vector3D velocity)
{
// 计算空气阻力的影响
Vector3D dragAcceleration = velocity.Normalize() * -1 * CalculateDrag(velocity.Magnitude()) / MissileProperties.Mass;
Vector3D totalAcceleration = GuidanceAcceleration + ThrustAcceleration + dragAcceleration;
Console.WriteLine($"导弹 {Id} 的加速度: {totalAcceleration}, 制导加速度: {GuidanceAcceleration}, 推力加速度: {ThrustAcceleration}, 空气阻力加速度: {dragAcceleration}");
if (totalAcceleration.Magnitude() > MissileProperties.MaxAcceleration)
{
totalAcceleration = totalAcceleration.Normalize() * MissileProperties.MaxAcceleration;
}
return totalAcceleration;
}
/// <summary>
/// 计算空气阻力
/// </summary>
/// <param name="speed">当前速度大小,单位:米/秒</param>
/// <returns>空气阻力大小,单位:牛顿</returns>
/// <remarks>
/// 计算公式:
/// F = 0.5 * Cd * ρ * A * v²
/// 其中:
/// - Cd阻力系数
/// - ρ:空气密度
/// - A参考面积
/// - v速度
/// </remarks>
private static double CalculateDrag(double speed)
{
const double dragCoefficient = 0.1; // 减小阻力系数
const double airDensity = 1.225; // 海平面空气密度kg/m^3
const double referenceArea = 0.01; // 减小导弹的参考面积m^2
return 0.5 * dragCoefficient * airDensity * referenceArea * speed * speed;
}
/// <summary>
/// 发射导弹
/// </summary>
/// <remarks>
/// 发射过程:
/// - 激活导弹
/// - 开始计时和计数
/// - 启动发动机
/// - 初始化运动状态
/// </remarks>
public virtual void Fire()
{
Activate();
}
/// <summary>
/// 检查是否应该自毁
/// </summary>
/// <returns>true表示需要自毁false表示可以继续飞行</returns>
/// <remarks>
/// 自毁条件:
/// - 超出最大飞行时间
/// - 超出最大飞行距离
/// - 高度低于安全阈值
/// - 失去制导时间过长
/// </remarks>
protected bool ShouldSelfDestruct()
{
if (FlightTime >= MissileProperties.MaxFlightTime)
{
Console.WriteLine($"导弹 {Id} 超出最大飞行时间 ({FlightTime:F2}/{MissileProperties.MaxFlightTime:F2}),准备自毁");
return true;
}
if (FlightDistance >= MissileProperties.MaxFlightDistance)
{
Console.WriteLine($"导弹 {Id} 超出最大飞行距离 ({FlightDistance:F2}/{MissileProperties.MaxFlightDistance:F2}),准备自毁");
return true;
}
if (Position.Y <= -1.0) // 数字略小于0
{
Console.WriteLine($"导弹 {Id} 高度小于等于0 ({Position.Y:F2}),准备自毁");
return true;
}
return false;
}
/// <summary>
/// 导弹爆炸
/// </summary>
/// <remarks>
/// 爆炸过程:
/// - 停止导弹运动
/// - 触发爆炸效果
/// - 发布爆炸事件
/// - 结束导弹任务
/// </remarks>
public virtual void Explode()
{
Deactivate();
}
public override void Activate()
{
base.Activate();
SimulationManager.SubscribeToEvent<TargetHitEvent>(OnTargetHitEvent);
}
public override void Deactivate()
{
base.Deactivate();
SimulationManager.UnsubscribeFromEvent<TargetHitEvent>(OnTargetHitEvent);
}
private void OnTargetHitEvent(TargetHitEvent eventData)
{
if (eventData.MissileId == Id)
{
Explode();
}
}
/// <summary>
/// 导弹自毁
/// </summary>
/// <remarks>
/// 自毁过程:
/// - 记录自毁原因
/// - 停止导弹运动
/// - 触发自毁效果
/// - 结束导弹任务
/// </remarks>
public void SelfDestruct()
{
if (IsActive)
{
string reason = FlightTime >= MissileProperties.MaxFlightTime ? "超出最大飞行时间" :
FlightDistance >= MissileProperties.MaxFlightDistance ? "超出最大飞行距离" :
Position.Y <= 0 ? "高度小于等于0" :
!IsGuidance ? "失去引导" : "未知原因";
Console.WriteLine($"导弹 {Id} 自毁。原因: {reason}");
Deactivate();
}
}
/// <summary>
/// 获取导弹的状态信息字符串
/// </summary>
/// <returns>包含导弹状态的详细描述</returns>
/// <remarks>
/// 返回信息包括:
/// - 导弹ID和类型
/// - 位置和速度信息
/// - 飞行时间和距离
/// - 制导和发动机状态
/// </remarks>
public override string GetStatus()
{
MissileRunningState missileRunningState = GetRunningState();
return $"导弹 {missileRunningState.Id}:\n" +
$" 位置: {missileRunningState.Position}\n" +
$" 速度: {missileRunningState.Speed:F2} m/s\n" +
$" 速度分量: {missileRunningState.Velocity}\n" +
$" 朝向: {missileRunningState.Orientation}\n" +
$" 飞行时间: {missileRunningState.FlightTime:F2}/{MissileProperties.MaxFlightTime:F2}\n" +
$" 飞行距离: {missileRunningState.FlightDistance:F2}/{MissileProperties.MaxFlightDistance:F2}\n" +
$" 发动机工作时间: {missileRunningState.EngineBurnTime:F2}/{MissileProperties.MaxEngineBurnTime:F2}\n" +
$" 有引导: {(missileRunningState.IsGuidance ? "" : "")}\n" +
$" 失去引导时间: {missileRunningState.LostGuidanceTime:F2}\n";
}
/// <summary>
/// 更新导弹的制导状态
/// </summary>
/// <remarks>
/// 基类中的默认实现为空
/// 具体的导弹类型需要重写此方法
/// 实现各自的制导逻辑
/// </remarks>
protected virtual void UpdateGuidanceStatus()
{
// 基类中的默认实现
}
/// <summary>
/// 获取导弹的完整运行状态
/// </summary>
/// <returns>包含导弹所有状态信息的结构体</returns>
/// <remarks>
/// 返回的状态包括:
/// - 基本信息ID、类型
/// - 运动状态(位置、速度、朝向)
/// - 飞行数据(时间、距离)
/// - 工作状态(制导、发动机)
/// </remarks>
public MissileRunningState GetRunningState()
{
return new MissileRunningState
{
Id = Id,
Type = MissileProperties.Type,
Position = Position,
Velocity = Velocity,
Orientation = Orientation,
Speed = Speed,
FlightTime = FlightTime,
FlightDistance = FlightDistance,
IsGuidance = IsGuidance,
LostGuidanceTime = LostGuidanceTime,
EngineBurnTime = EngineBurnTime,
IsActive = IsActive
};
}
}
}

View File

@ -0,0 +1,201 @@
using ThreatSource.Utils;
namespace ThreatSource.Missile
{
/// <summary>
/// 导弹接口,定义了导弹的基本行为和状态
/// </summary>
/// <remarks>
/// 该接口定义了导弹的核心功能:
/// - 制导状态管理
/// - 发射控制
/// - 爆炸和自毁功能
/// - 运行状态查询
/// 所有具体的导弹类型都应实现此接口
/// </remarks>
public interface IMissile
{
/// <summary>
/// 获取导弹是否处于制导状态
/// </summary>
/// <remarks>
/// true表示导弹当前处于制导阶段
/// false表示导弹处于非制导飞行状态
/// 用于控制导弹的制导系统工作状态
/// </remarks>
bool IsGuidance { get; }
/// <summary>
/// 发射导弹,使导弹进入工作状态
/// </summary>
/// <remarks>
/// 发射过程包括:
/// - 点火启动发动机
/// - 初始化制导系统
/// - 开始飞行状态计算
/// - 触发导弹发射事件
/// </remarks>
void Fire();
/// <summary>
/// 引爆导弹,触发爆炸效果
/// </summary>
/// <remarks>
/// 爆炸过程包括:
/// - 计算爆炸范围和伤害
/// - 对周围目标造成伤害
/// - 触发爆炸事件
/// - 导弹自身销毁
/// </remarks>
void Explode();
/// <summary>
/// 执行导弹自毁程序
/// </summary>
/// <remarks>
/// 自毁触发条件:
/// - 超出最大飞行时间
/// - 超出最大飞行距离
/// - 失去制导时间过长
/// - 接收到自毁指令
/// 自毁会立即停止导弹的工作并销毁
/// </remarks>
void SelfDestruct();
/// <summary>
/// 获取导弹的当前运行状态信息
/// </summary>
/// <returns>包含导弹完整状态信息的结构体</returns>
/// <remarks>
/// 返回的状态信息包括:
/// - 基本信息ID、类型
/// - 运动状态(位置、速度、朝向)
/// - 飞行数据(时间、距离)
/// - 工作状态(制导、发动机)
/// </remarks>
MissileRunningState GetRunningState();
}
/// <summary>
/// 导弹运行状态信息结构体,包含导弹的完整状态数据
/// </summary>
/// <remarks>
/// 该结构体用于:
/// - 状态监控和记录
/// - 数据分析和诊断
/// - 仿真状态同步
/// - 导弹行为控制
/// </remarks>
public struct MissileRunningState
{
/// <summary>
/// 获取或设置导弹的唯一标识符
/// </summary>
/// <remarks>
/// 在仿真系统中必须唯一
/// 用于标识和追踪特定的导弹
/// </remarks>
public string Id { get; set; }
/// <summary>
/// 获取或设置导弹的类型
/// </summary>
/// <remarks>
/// 用于区分不同种类的导弹
/// 影响导弹的行为特征和性能参数
/// </remarks>
public MissileType Type { get; set; }
/// <summary>
/// 获取或设置导弹的当前位置
/// </summary>
/// <remarks>
/// 使用三维向量表示空间位置
/// 坐标系右手坐标系X向右Y向上Z向前
/// </remarks>
public Vector3D Position { get; set; }
/// <summary>
/// 获取或设置导弹的当前速度向量
/// </summary>
/// <remarks>
/// 包含速度的大小和方向信息
/// 单位:米/秒
/// </remarks>
public Vector3D Velocity { get; set; }
/// <summary>
/// 获取或设置导弹的当前朝向
/// </summary>
/// <remarks>
/// 使用欧拉角表示导弹的姿态
/// 包含偏航角、俯仰角和滚转角
/// </remarks>
public Orientation Orientation { get; set; }
/// <summary>
/// 获取或设置导弹的当前速度大小
/// </summary>
/// <remarks>
/// 单位:米/秒
/// 表示导弹运动的标量速度
/// </remarks>
public double Speed { get; set; }
/// <summary>
/// 获取或设置导弹的当前飞行时间
/// </summary>
/// <remarks>
/// 单位:秒
/// 从发射时刻开始计时
/// </remarks>
public double FlightTime { get; set; }
/// <summary>
/// 获取或设置导弹的当前飞行距离
/// </summary>
/// <remarks>
/// 单位:米
/// 从发射点到当前位置的累计飞行距离
/// </remarks>
public double FlightDistance { get; set; }
/// <summary>
/// 获取或设置导弹是否处于制导状态
/// </summary>
/// <remarks>
/// true表示导弹当前在制导
/// false表示导弹处于非制导状态
/// </remarks>
public bool IsGuidance { get; set; }
/// <summary>
/// 获取或设置导弹失去制导的持续时间
/// </summary>
/// <remarks>
/// 单位:秒
/// 记录导弹处于非制导状态的累计时间
/// 用于判断是否需要触发自毁
/// </remarks>
public double LostGuidanceTime { get; set; }
/// <summary>
/// 获取或设置发动机的当前燃烧时间
/// </summary>
/// <remarks>
/// 单位:秒
/// 记录发动机工作的累计时间
/// 用于控制推力变化和燃料消耗
/// </remarks>
public double EngineBurnTime { get; set; }
/// <summary>
/// 获取或设置导弹是否处于活动状态
/// </summary>
/// <remarks>
/// true表示导弹正常工作
/// false表示导弹已停止工作销毁或自毁
/// </remarks>
public bool IsActive { get; set; }
}
}

View File

@ -0,0 +1,304 @@
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Guidance;
using ThreatSource.Indicator;
namespace ThreatSource.Missile
{
/// <summary>
/// 红外指令制导导弹类,实现了红外指令制导的导弹功能
/// </summary>
/// <remarks>
/// 该类提供了红外指令制导导弹的核心功能:
/// - 红外热源管理(点亮和熄灭)
/// - 指令制导控制
/// - 飞行阶段管理
/// - 状态监控和事件处理
/// 通过红外测角仪和指令制导系统实现对导弹的制导控制
/// </remarks>
public class InfraredCommandGuidedMissile : BaseMissile
{
/// <summary>
/// 红外指令制导导弹阶段枚举
/// </summary>
/// <remarks>
/// 定义了导弹飞行的四个主要阶段:
/// - Launch发射阶段初始加速
/// - Cruise巡航阶段执行制导
/// - Explode爆炸阶段命中目标
/// - SelfDestruct自毁阶段触发自毁
/// </remarks>
private enum ICGM_Stage
{
Launch, // 发射阶段
Cruise, // 巡航阶段
Explode, // 爆炸阶段
SelfDestruct // 自毁阶段
}
/// <summary>
/// 获取或设置当前飞行阶段
/// </summary>
/// <remarks>
/// 用于控制导弹在不同阶段的行为
/// 影响导弹的运动和制导方式
/// </remarks>
private ICGM_Stage currentStage;
/// <summary>
/// 获取或设置红外热源辐射功率
/// </summary>
/// <value>辐射功率,单位:瓦特</value>
/// <remarks>
/// 影响导弹的红外信号强度
/// 用于红外测角仪的跟踪和制导
/// </remarks>
public double RadiationPower { get; set; }
/// <summary>
/// 红外指令导引系统实例
/// </summary>
/// <remarks>
/// 负责处理制导指令和计算制导律
/// 包含自适应PID参数控制
/// </remarks>
private readonly InfraredCommandGuidanceSystem guidanceSystem;
/// <summary>
/// 红外测角仪实例
/// </summary>
/// <remarks>
/// 用于跟踪导弹的红外信号
/// 提供角度测量数据给制导系统
/// </remarks>
private InfraredTracker infraredTracker;
/// <summary>
/// 初始化红外指令制导导弹的新实例
/// </summary>
/// <param name="config">导弹配置参数</param>
/// <param name="manager">仿真管理器实例</param>
/// <remarks>
/// 构造过程:
/// - 初始化基本属性
/// - 设置红外辐射功率
/// - 创建指令导引系统
/// - 配置PID参数
/// </remarks>
public InfraredCommandGuidedMissile(MissileProperties config, ISimulationManager manager) : base(config, manager)
{
infraredTracker = null!;
RadiationPower = 1000;
// 初始化红外指令导引系统,包括自适应 PID 参数
guidanceSystem = new InfraredCommandGuidanceSystem(
maxAcceleration: config.MaxAcceleration,
guidanceCoefficient: config.ProportionalNavigationCoefficient
);
}
/// <summary>
/// 更新导弹运动状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 点亮红外热源
/// - 根据当前阶段更新状态
/// - 调用基类的运动更新
/// </remarks>
protected override void UpdateMotionState(double deltaTime)
{
// 点亮红外热源
LightInfraredSource();
switch (currentStage)
{
case ICGM_Stage.Launch:
UpdateLaunchStage(deltaTime);
break;
case ICGM_Stage.Cruise:
UpdateCruiseStage(deltaTime);
break;
case ICGM_Stage.Explode:
UpdateExplodeStage(deltaTime);
break;
case ICGM_Stage.SelfDestruct:
UpdateSelfDestructStage(deltaTime);
break;
}
base.UpdateMotionState(deltaTime);
}
/// <summary>
/// 更新发射阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 发射阶段处理:
/// - 清除制导加速度
/// - 检查发射时间
/// - 转换到巡航阶段
/// </remarks>
private void UpdateLaunchStage(double deltaTime)
{
// 发射阶段
GuidanceAcceleration = Vector3D.Zero;
if (FlightTime >= 0.1)
{
currentStage = ICGM_Stage.Cruise;
}
}
/// <summary>
/// 更新巡航阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 巡航阶段处理:
/// - 启用制导控制
/// - 更新制导系统
/// - 计算制导加速度
/// - 检查自毁条件
/// </remarks>
private void UpdateCruiseStage(double deltaTime)
{
IsGuidance = true;
guidanceSystem.Update(deltaTime, Position, Velocity);
GuidanceAcceleration = guidanceSystem.GetGuidanceAcceleration();
if(ShouldSelfDestruct())
{
currentStage = ICGM_Stage.SelfDestruct;
}
}
/// <summary>
/// 更新爆炸阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 爆炸阶段处理:
/// - 触发爆炸效果
/// - 结束导弹任务
/// </remarks>
private void UpdateExplodeStage(double deltaTime)
{
// 爆炸阶段
Explode();
}
/// <summary>
/// 更新自毁阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 自毁阶段处理:
/// - 触发自毁效果
/// - 结束导弹任务
/// </remarks>
private void UpdateSelfDestructStage(double deltaTime)
{
// 自毁阶段
SelfDestruct();
}
/// <summary>
/// 处理制导指令事件
/// </summary>
/// <remarks>
/// 处理过程:
/// - 验证指令目标
/// - 获取红外测角仪
/// - 更新制导指令
/// </remarks>
private void HandleGuidanceCommand(InfraredGuidanceCommandEvent evt)
{
if (evt.TargetMissileId == Id)
{
if (infraredTracker == null && evt.SenderId != null)
{
if (SimulationManager.GetEntityById(evt.SenderId) is InfraredTracker tracker)
{
infraredTracker = tracker;
}
}
guidanceSystem.ReceiveGuidanceCommand(evt.TrackerToMissileVector, evt.TrackerToTargetVector);
}
}
/// <summary>
/// 点亮红外热源
/// </summary>
/// <remarks>
/// 发布红外热源点亮事件
/// 包含当前辐射功率信息
/// </remarks>
public void LightInfraredSource()
{
SimulationManager.PublishEvent(new InfraredGuidanceMissileLightEvent { RadiationPower = this.RadiationPower, SenderId = this.Id });
}
/// <summary>
/// 熄灭红外热源
/// </summary>
/// <remarks>
/// 发布红外热源熄灭事件
/// 停止红外信号发射
/// </remarks>
public void LightOffInfraredSource()
{
SimulationManager.PublishEvent(new InfraredGuidanceMissileLightOffEvent { SenderId = this.Id });
}
/// <summary>
/// 激活导弹
/// </summary>
/// <remarks>
/// 激活过程:
/// - 调用基类激活方法
/// - 订阅制导指令事件
/// - 准备接收制导指令
/// </remarks>
public override void Activate()
{
base.Activate();
// 订阅红外指令制导事件
SimulationManager.SubscribeToEvent<InfraredGuidanceCommandEvent>(HandleGuidanceCommand);
}
/// <summary>
/// 停用导弹
/// </summary>
/// <remarks>
/// 停用过程:
/// - 调用基类停用方法
/// - 熄灭红外热源
/// - 取消订阅制导事件
/// </remarks>
public override void Deactivate()
{
base.Deactivate();
// 熄灭红外热源
LightOffInfraredSource();
// 取消订阅红外指令制导事件
SimulationManager.UnsubscribeFromEvent<InfraredGuidanceCommandEvent>(HandleGuidanceCommand);
}
/// <summary>
/// 获取导弹状态信息
/// </summary>
/// <returns>包含导弹状态的详细描述</returns>
/// <remarks>
/// 返回信息包括:
/// - 基本状态信息
/// - 当前飞行阶段
/// - 制导系统状态
/// </remarks>
public override string GetStatus()
{
return base.GetStatus() + $"\n 当前阶段:{currentStage}\n 导引系统状态: {guidanceSystem.GetStatus()}";
}
}
}

View File

@ -0,0 +1,219 @@
using ThreatSource.Simulation;
using ThreatSource.Guidance;
namespace ThreatSource.Missile
{
/// <summary>
/// 红外成像末制导导弹类,继承自基础导弹类
/// </summary>
/// <remarks>
/// 该类提供了红外成像末制导导弹的完整实现:
/// - 继承自BaseMissile具备基本的导弹功能
/// - 实现了红外成像制导系统
/// - 支持多阶段飞行控制
/// - 具备红外目标识别能力
/// - 提供精确的末制导打击能力
///
/// 工作流程:
/// 1. 导弹发射并进入发射阶段
/// 2. 切换到巡航阶段,进行中程飞行
/// 3. 进入末制导阶段,启动红外成像制导
/// 4. 接近目标后引爆或达到自毁条件后自毁
/// </remarks>
public class InfraredImagingTerminalGuidedMissile : BaseMissile
{
/// <summary>
/// 红外成像末制导导弹的飞行阶段枚举
/// </summary>
/// <remarks>
/// 定义了导弹的五个工作阶段:
/// - Launch: 发射阶段,初始加速
/// - Cruise: 巡航阶段,中程飞行
/// - TerminalGuidance: 末制导阶段,红外制导
/// - Explode: 爆炸阶段,执行毁伤
/// - SelfDestruct: 自毁阶段,紧急处置
/// </remarks>
private enum IRTG_Stage
{
Launch, // 发射阶段
Cruise, // 巡航阶段
TerminalGuidance, // 末制导阶段
Explode, // 爆炸阶段
SelfDestruct // 自毁阶段
}
/// <summary>
/// 导弹当前的飞行阶段
/// </summary>
/// <remarks>
/// 用于控制导弹的行为状态
/// 在不同阶段执行不同的更新逻辑
/// </remarks>
private IRTG_Stage currentStage;
/// <summary>
/// 红外成像制导系统实例
/// </summary>
/// <remarks>
/// 负责处理红外图像信息
/// 计算制导指令
/// 控制导弹的飞行路径
/// </remarks>
private readonly InfraredImagingGuidanceSystem guidanceSystem;
/// <summary>
/// 末制导开始距离,单位:米
/// </summary>
/// <remarks>
/// 当导弹与目标的距离小于此值时
/// 导弹将进入末制导阶段
/// 启动红外成像制导系统
/// </remarks>
private const double TERMINAL_GUIDANCE_DISTANCE = 1000;
/// <summary>
/// 初始化红外成像末制导导弹的新实例
/// </summary>
/// <param name="config">导弹的配置参数</param>
/// <param name="manager">仿真管理器实例</param>
/// <remarks>
/// 构造过程:
/// 1. 调用基类构造函数
/// 2. 创建制导系统实例
/// 3. 设置初始飞行阶段
/// </remarks>
public InfraredImagingTerminalGuidedMissile(MissileProperties config, ISimulationManager manager)
: base(config, manager)
{
currentStage = IRTG_Stage.Launch;
guidanceSystem = new InfraredImagingGuidanceSystem(config.MaxAcceleration, config.ProportionalNavigationCoefficient, manager);
}
/// <summary>
/// 更新导弹的状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 更新过程:
/// 1. 调用基类的更新方法
/// 2. 根据当前阶段选择更新方法
/// 3. 执行相应阶段的更新逻辑
/// 4. 检查是否需要自毁
/// </remarks>
public override void Update(double deltaTime)
{
base.Update(deltaTime);
switch (currentStage)
{
case IRTG_Stage.Launch:
UpdateLaunchStage(deltaTime);
break;
case IRTG_Stage.Cruise:
UpdateCruiseStage(deltaTime);
break;
case IRTG_Stage.TerminalGuidance:
UpdateTerminalGuidanceStage(deltaTime);
break;
case IRTG_Stage.Explode:
Explode();
break;
case IRTG_Stage.SelfDestruct:
SelfDestruct();
break;
}
if (ShouldSelfDestruct())
{
currentStage = IRTG_Stage.SelfDestruct;
}
}
/// <summary>
/// 更新发射阶段的状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 发射阶段特点:
/// - 不使用制导加速度
/// - 仅依靠发动机推力
/// - 持续时间为1秒
/// - 结束后进入巡航阶段
/// </remarks>
private void UpdateLaunchStage(double deltaTime)
{
if (FlightTime > 1) // 假设发射阶段持续1秒
{
currentStage = IRTG_Stage.Cruise;
}
}
/// <summary>
/// 更新巡航阶段的状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 巡航阶段特点:
/// - 保持稳定飞行
/// - 不使用制导系统
/// - 持续时间为3秒
/// - 结束后进入末制导阶段
/// </remarks>
private void UpdateCruiseStage(double deltaTime)
{
if (FlightTime > 4) // 假设巡航阶段持续3秒
{
currentStage = IRTG_Stage.TerminalGuidance;
}
}
/// <summary>
/// 更新末制导阶段的状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 末制导阶段特点:
/// - 开启红外成像制导
/// - 计算制导加速度
/// - 精确跟踪目标
/// - 持续到命中目标
/// </remarks>
private void UpdateTerminalGuidanceStage(double deltaTime)
{
IsGuidance = true;
guidanceSystem.Update(deltaTime, Position, Velocity);
GuidanceAcceleration = guidanceSystem.GetGuidanceAcceleration();
}
/// <summary>
/// 执行导弹爆炸
/// </summary>
/// <remarks>
/// 爆炸过程:
/// 1. 调用基类的爆炸方法
/// 2. 切换到爆炸阶段
/// 3. 结束导弹任务
/// </remarks>
public override void Explode()
{
base.Explode();
currentStage = IRTG_Stage.Explode;
}
/// <summary>
/// 获取导弹的状态信息字符串
/// </summary>
/// <returns>包含导弹状态的详细描述</returns>
/// <remarks>
/// 返回信息包括:
/// - 基类状态信息
/// - 当前飞行阶段
/// - 制导系统状态
/// - 目标跟踪信息
/// </remarks>
public override string GetStatus()
{
return base.GetStatus() + $"\n 当前阶段: {currentStage}" + guidanceSystem.GetStatus();
}
}
}

View File

@ -0,0 +1,287 @@
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Guidance;
using ThreatSource.Indicator;
namespace ThreatSource.Missile
{
/// <summary>
/// 激光波束制导导弹类,实现了激光波束跟踪制导的导弹功能
/// </summary>
/// <remarks>
/// 该类提供了激光波束制导导弹的核心功能:
/// - 激光波束跟踪
/// - 波束制导控制
/// - 飞行阶段管理
/// - 状态监控和事件处理
/// 通过跟踪激光波束的中心线实现对导弹的制导控制
/// </remarks>
public class LaserBeamRiderMissile : BaseMissile
{
/// <summary>
/// 激光驾束制导导弹阶段枚举
/// </summary>
/// <remarks>
/// 定义了导弹飞行的四个主要阶段:
/// - Launch发射阶段初始加速
/// - Cruise巡航阶段跟踪波束
/// - Explode爆炸阶段命中目标
/// - SelfDestruct自毁阶段触发自毁
/// </remarks>
private enum LBRM_Stage
{
Launch, // 发射阶段
Cruise, // 巡航阶段
Explode, // 爆炸阶段
SelfDestruct // 自毁阶段
}
/// <summary>
/// 获取或设置当前飞行阶段
/// </summary>
/// <remarks>
/// 用于控制导弹在不同阶段的行为
/// 影响导弹的运动和制导方式
/// </remarks>
private LBRM_Stage currentStage;
/// <summary>
/// 激光波束制导系统实例
/// </summary>
/// <remarks>
/// 负责处理波束跟踪和制导计算
/// 包含波束偏差修正和制导律计算
/// </remarks>
private readonly LaserBeamRiderGuidanceSystem LaserBeamRiderGuidanceSystem;
/// <summary>
/// 初始化激光波束制导导弹的新实例
/// </summary>
/// <param name="config">导弹配置参数</param>
/// <param name="manager">仿真管理器实例</param>
/// <remarks>
/// 构造过程:
/// - 初始化基本属性
/// - 创建波束制导系统
/// - 配置制导参数
/// - 设置初始飞行阶段
/// </remarks>
public LaserBeamRiderMissile(MissileProperties config, ISimulationManager manager)
: base(config, manager)
{
LaserBeamRiderGuidanceSystem = new LaserBeamRiderGuidanceSystem(config.MaxAcceleration, config.ProportionalNavigationCoefficient);
currentStage = LBRM_Stage.Launch;
}
/// <summary>
/// 处理激光束开启事件
/// </summary>
/// <param name="evt">激光束开启事件数据</param>
/// <remarks>
/// 处理过程:
/// - 验证激光驾束仪
/// - 更新波束参数
/// - 开始波束跟踪
/// </remarks>
private void OnLaserBeamStart(LaserBeamStartEvent evt)
{
if (evt?.LaserBeamRiderId != null)
{
LaserBeamRider laserBeamRider = SimulationManager.GetEntityById(evt.LaserBeamRiderId) as LaserBeamRider ?? throw new Exception("激光驾束仪不存在");
LaserBeamRiderGuidanceSystem?.UpdateLaserBeamRider(laserBeamRider.Position, laserBeamRider.LaserDirection, laserBeamRider.LaserPower);
}
}
/// <summary>
/// 处理激光束更新事件
/// </summary>
/// <param name="evt">激光束更新事件数据</param>
/// <remarks>
/// 处理过程:
/// - 验证激光驾束仪
/// - 更新波束位置和方向
/// - 更新制导参数
/// </remarks>
private void OnLaserBeamUpdate(LaserBeamUpdateEvent evt)
{
if (evt?.LaserBeamRiderId != null)
{
LaserBeamRider laserBeamRider = SimulationManager.GetEntityById(evt.LaserBeamRiderId) as LaserBeamRider ?? throw new Exception("激光驾束仪不存在");
LaserBeamRiderGuidanceSystem?.UpdateLaserBeamRider(laserBeamRider.Position, laserBeamRider.LaserDirection, laserBeamRider.LaserPower);
}
}
/// <summary>
/// 处理激光束停止事件
/// </summary>
/// <param name="evt">激光束停止事件数据</param>
/// <remarks>
/// 处理过程:
/// - 验证事件数据
/// - 停止波束跟踪
/// - 清理制导状态
/// </remarks>
private void OnLaserBeamStop(LaserBeamStopEvent evt)
{
if (evt?.LaserBeamRiderId != null)
{
LaserBeamRiderGuidanceSystem?.DeactivateLaserBeam();
}
}
/// <summary>
/// 更新导弹状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 根据当前阶段更新状态
/// - 处理阶段转换
/// - 调用基类更新
/// </remarks>
public override void Update(double deltaTime)
{
switch (currentStage)
{
case LBRM_Stage.Launch:
UpdateLaunchStage(deltaTime);
break;
case LBRM_Stage.Cruise:
UpdateCruiseStage(deltaTime);
break;
case LBRM_Stage.Explode:
UpdateExplodeStage(deltaTime);
break;
case LBRM_Stage.SelfDestruct:
UpdateSelfDestructStage(deltaTime);
break;
}
base.Update(deltaTime);
}
/// <summary>
/// 更新发射阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 发射阶段处理:
/// - 清除制导加速度
/// - 检查发射时间
/// - 转换到巡航阶段
/// </remarks>
private void UpdateLaunchStage(double deltaTime)
{
// 发射阶段
GuidanceAcceleration = Vector3D.Zero;
if (FlightTime >= 0.01)
{
currentStage = LBRM_Stage.Cruise;
}
}
/// <summary>
/// 更新巡航阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 巡航阶段处理:
/// - 启用波束跟踪
/// - 更新制导系统
/// - 计算制导加速度
/// - 检查自毁条件
/// </remarks>
private void UpdateCruiseStage(double deltaTime)
{
// 巡航阶段
IsGuidance = true;
LaserBeamRiderGuidanceSystem.Update(deltaTime, Position, Velocity);
GuidanceAcceleration = LaserBeamRiderGuidanceSystem.GetGuidanceAcceleration();
if(ShouldSelfDestruct())
{
currentStage = LBRM_Stage.SelfDestruct;
}
}
/// <summary>
/// 更新爆炸阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 爆炸阶段处理:
/// - 触发爆炸效果
/// - 结束导弹任务
/// </remarks>
private void UpdateExplodeStage(double deltaTime)
{
// 爆炸阶段
Explode();
}
/// <summary>
/// 更新自毁阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 自毁阶段处理:
/// - 触发自毁效果
/// - 结束导弹任务
/// </remarks>
private void UpdateSelfDestructStage(double deltaTime)
{
// 自毁阶段
SelfDestruct();
}
/// <summary>
/// 获取导弹状态信息
/// </summary>
/// <returns>包含导弹状态的详细描述</returns>
/// <remarks>
/// 返回信息包括:
/// - 基本状态信息
/// - 波束跟踪状态
/// - 制导系统状态
/// </remarks>
public override string GetStatus()
{
string baseStatus = base.GetStatus().Replace("导弹", "激光驾束制导导弹");
string additionalStatus = LaserBeamRiderGuidanceSystem.HasGuidance ? LaserBeamRiderGuidanceSystem.GetStatus() : "";
return baseStatus + additionalStatus;
}
/// <summary>
/// 激活导弹
/// </summary>
/// <remarks>
/// 激活过程:
/// - 调用基类激活方法
/// - 订阅激光波束事件
/// - 准备波束跟踪
/// </remarks>
public override void Activate()
{
base.Activate();
SimulationManager.SubscribeToEvent<LaserBeamStartEvent>(OnLaserBeamStart);
SimulationManager.SubscribeToEvent<LaserBeamStopEvent>(OnLaserBeamStop);
SimulationManager.SubscribeToEvent<LaserBeamUpdateEvent>(OnLaserBeamUpdate);
}
/// <summary>
/// 停用导弹
/// </summary>
/// <remarks>
/// 停用过程:
/// - 调用基类停用方法
/// - 取消订阅波束事件
/// - 清理制导状态
/// </remarks>
public override void Deactivate()
{
base.Deactivate();
SimulationManager.UnsubscribeFromEvent<LaserBeamStartEvent>(OnLaserBeamStart);
SimulationManager.UnsubscribeFromEvent<LaserBeamStopEvent>(OnLaserBeamStop);
SimulationManager.UnsubscribeFromEvent<LaserBeamUpdateEvent>(OnLaserBeamUpdate);
}
}
}

View File

@ -0,0 +1,295 @@
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Guidance;
using ThreatSource.Indicator;
using ThreatSource.Target;
namespace ThreatSource.Missile
{
/// <summary>
/// 激光半主动制导导弹类,实现了激光半主动寻的制导功能
/// </summary>
/// <remarks>
/// 该类提供了激光半主动制导导弹的核心功能:
/// - 激光照射目标跟踪
/// - 半主动制导控制
/// - 飞行阶段管理
/// - 状态监控和事件处理
/// 通过跟踪目标反射的激光能量实现对导弹的制导控制
/// </remarks>
public class LaserSemiActiveGuidedMissile : BaseMissile
{
/// <summary>
/// 激光半主动制导导弹阶段枚举
/// </summary>
/// <remarks>
/// 定义了导弹飞行的四个主要阶段:
/// - Launch发射阶段初始加速
/// - Cruise巡航阶段执行制导
/// - Explode爆炸阶段命中目标
/// - SelfDestruct自毁阶段触发自毁
/// </remarks>
private enum LSAGM_Stage
{
Launch, // 发射阶段
Cruise, // 巡航阶段
Explode, // 爆炸阶段
SelfDestruct // 自毁阶段
}
/// <summary>
/// 获取或设置当前飞行阶段
/// </summary>
/// <remarks>
/// 用于控制导弹在不同阶段的行为
/// 影响导弹的运动和制导方式
/// </remarks>
private LSAGM_Stage currentStage;
/// <summary>
/// 激光半主动制导系统实例
/// </summary>
/// <remarks>
/// 负责处理目标反射激光信号的跟踪和制导计算
/// 包含制导律计算和目标跟踪逻辑
/// </remarks>
private LaserSemiActiveGuidanceSystem LaserGuidanceSystem;
/// <summary>
/// 获取或设置激光指示器ID
/// </summary>
/// <value>激光指示器的唯一标识符</value>
/// <remarks>
/// 用于识别和关联激光照射源
/// 影响导弹的制导精度
/// </remarks>
public string LaserDesignatorId { get; set; } = "";
/// <summary>
/// 初始化激光半主动制导导弹的新实例
/// </summary>
/// <param name="config">导弹配置参数</param>
/// <param name="manager">仿真管理器实例</param>
/// <remarks>
/// 构造过程:
/// - 初始化基本属性
/// - 创建制导系统
/// - 配置制导参数
/// - 设置初始飞行阶段
/// </remarks>
public LaserSemiActiveGuidedMissile(MissileProperties config, ISimulationManager manager)
: base(config, manager)
{
LaserGuidanceSystem = new LaserSemiActiveGuidanceSystem(config.MaxAcceleration, config.ProportionalNavigationCoefficient);
currentStage = LSAGM_Stage.Launch;
}
/// <summary>
/// 处理激光照射开始事件
/// </summary>
/// <param name="evt">激光照射事件数据</param>
/// <remarks>
/// 处理过程:
/// - 验证激光指示器和目标
/// - 更新制导系统参数
/// - 开始目标跟踪
/// </remarks>
private void OnLaserIlluminationStart(LaserIlluminationStartEvent evt)
{
if (evt?.LaserDesignatorId != null && evt?.TargetId != null)
{
LaserDesignator laserDesignator = SimulationManager.GetEntityById(evt.LaserDesignatorId) as LaserDesignator ?? throw new Exception("激光指示器不存在");
SimulationElement target = SimulationManager.GetEntityById(evt.TargetId) as SimulationElement ?? throw new Exception("目标不存在");
LaserGuidanceSystem.UpdateLaserDesignator(laserDesignator.Position, target.Position, target.Velocity,
laserDesignator.LaserPower, laserDesignator.LaserDivergenceAngle);
}
}
/// <summary>
/// 处理激光照射更新事件
/// </summary>
/// <param name="evt">激光照射更新事件数据</param>
/// <remarks>
/// 处理过程:
/// - 验证激光指示器和目标
/// - 更新目标位置和速度
/// - 更新制导参数
/// </remarks>
private void OnLaserIlluminationUpdate(LaserIlluminationUpdateEvent evt)
{
if (evt?.LaserDesignatorId != null && evt?.TargetId != null)
{
LaserDesignator laserDesignator = SimulationManager.GetEntityById(evt.LaserDesignatorId) as LaserDesignator ?? throw new Exception("激光指示器不存在");
SimulationElement target = SimulationManager.GetEntityById(evt.TargetId) as SimulationElement ?? throw new Exception("目标不存在");
LaserGuidanceSystem.UpdateLaserDesignator(laserDesignator.Position, target.Position, target.Velocity,
laserDesignator.LaserPower, laserDesignator.LaserDivergenceAngle);
}
}
/// <summary>
/// 处理激光照射停止事件
/// </summary>
/// <param name="evt">激光照射停止事件数据</param>
/// <remarks>
/// 处理过程:
/// - 停止目标跟踪
/// - 清理制导状态
/// - 准备进入无制导状态
/// </remarks>
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
{
LaserGuidanceSystem.DeactivateLaserDesignator();
}
/// <summary>
/// 激活导弹
/// </summary>
/// <remarks>
/// 激活过程:
/// - 调用基类激活方法
/// - 订阅激光照射事件
/// - 准备目标跟踪
/// </remarks>
public override void Activate()
{
base.Activate();
SimulationManager.SubscribeToEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
SimulationManager.SubscribeToEvent<LaserIlluminationUpdateEvent>(OnLaserIlluminationUpdate);
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
}
/// <summary>
/// 停用导弹
/// </summary>
/// <remarks>
/// 停用过程:
/// - 调用基类停用方法
/// - 取消订阅激光照射事件
/// - 清理制导状态
/// </remarks>
public override void Deactivate()
{
base.Deactivate();
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
SimulationManager.UnsubscribeFromEvent<LaserIlluminationUpdateEvent>(OnLaserIlluminationUpdate);
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
}
/// <summary>
/// 更新导弹状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 根据当前阶段更新状态
/// - 处理阶段转换
/// - 调用基类更新
/// </remarks>
public override void Update(double deltaTime)
{
switch (currentStage)
{
case LSAGM_Stage.Launch:
UpdateLaunchStage(deltaTime);
break;
case LSAGM_Stage.Cruise:
UpdateCruiseStage(deltaTime);
break;
case LSAGM_Stage.Explode:
UpdateExplodeStage(deltaTime);
break;
case LSAGM_Stage.SelfDestruct:
UpdateSelfDestructStage(deltaTime);
break;
}
base.Update(deltaTime);
}
/// <summary>
/// 更新发射阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 发射阶段处理:
/// - 清除制导加速度
/// - 检查发射时间
/// - 转换到巡航阶段
/// </remarks>
private void UpdateLaunchStage(double deltaTime)
{
// 发射阶段
GuidanceAcceleration = Vector3D.Zero;
if (FlightTime >= 0.1)
{
currentStage = LSAGM_Stage.Cruise;
}
}
/// <summary>
/// 更新巡航阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 巡航阶段处理:
/// - 启用制导控制
/// - 更新制导系统
/// - 计算制导加速度
/// - 检查自毁条件
/// </remarks>
private void UpdateCruiseStage(double deltaTime)
{
IsGuidance = true;
LaserGuidanceSystem.Update(deltaTime, Position, Velocity);
GuidanceAcceleration = LaserGuidanceSystem.GetGuidanceAcceleration();
if(ShouldSelfDestruct())
{
currentStage = LSAGM_Stage.SelfDestruct;
}
}
/// <summary>
/// 更新爆炸阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 爆炸阶段处理:
/// - 触发爆炸效果
/// - 结束导弹任务
/// </remarks>
private void UpdateExplodeStage(double deltaTime)
{
base.Explode();
}
/// <summary>
/// 更新自毁阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 自毁阶段处理:
/// - 触发自毁效果
/// - 结束导弹任务
/// </remarks>
private void UpdateSelfDestructStage(double deltaTime)
{
SelfDestruct();
}
/// <summary>
/// 获取导弹状态信息
/// </summary>
/// <returns>包含导弹状态的详细描述</returns>
/// <remarks>
/// 返回信息包括:
/// - 基本状态信息
/// - 制导系统状态
/// - 目标跟踪状态
/// </remarks>
public override string GetStatus()
{
string baseStatus = base.GetStatus().Replace("导弹", "激光半主动制导导弹");
string additionalStatus = LaserGuidanceSystem.HasGuidance ? LaserGuidanceSystem.GetStatus() : "";
return baseStatus + additionalStatus;
}
}
}

View File

@ -0,0 +1,221 @@
using ThreatSource.Simulation;
using ThreatSource.Guidance;
namespace ThreatSource.Missile
{
/// <summary>
/// 毫米波末制导导弹类,继承自基础导弹类
/// </summary>
/// <remarks>
/// 该类提供了毫米波末制导导弹的完整实现:
/// - 继承自BaseMissile具备基本的导弹功能
/// - 实现了毫米波制导系统
/// - 支持多阶段飞行控制
/// - 具备全天候目标探测能力
/// - 提供精确的末制导打击能力
///
/// 工作流程:
/// 1. 导弹发射并进入发射阶段
/// 2. 切换到巡航阶段,进行中程飞行
/// 3. 进入末制导阶段,启动毫米波制导
/// 4. 接近目标后引爆或达到自毁条件后自毁
/// </remarks>
public class MillimeterWaveTerminalGuidedMissile : BaseMissile
{
/// <summary>
/// 毫米波末制导导弹的飞行阶段枚举
/// </summary>
/// <remarks>
/// 定义了导弹的五个工作阶段:
/// - Launch: 发射阶段,初始加速
/// - Cruise: 巡航阶段,中程飞行
/// - TerminalGuidance: 末制导阶段,毫米波制导
/// - Explode: 爆炸阶段,执行毁伤
/// - SelfDestruct: 自毁阶段,紧急处置
/// </remarks>
private enum MWTG_Stage
{
Launch, // 发射阶段
Cruise, // 巡航阶段
TerminalGuidance, // 末制导阶段
Explode, // 爆炸阶段
SelfDestruct // 自毁阶段
}
/// <summary>
/// 导弹当前的飞行阶段
/// </summary>
/// <remarks>
/// 用于控制导弹的行为状态
/// 在不同阶段执行不同的更新逻辑
/// </remarks>
private MWTG_Stage currentStage;
/// <summary>
/// 毫米波制导系统实例
/// </summary>
/// <remarks>
/// 负责处理毫米波雷达信号
/// 计算制导指令
/// 控制导弹的飞行路径
/// </remarks>
private readonly MillimeterWaveGuidanceSystem guidanceSystem;
/// <summary>
/// 末制导开始距离,单位:米
/// </summary>
/// <remarks>
/// 当导弹与目标的距离小于此值时
/// 导弹将进入末制导阶段
/// 启动毫米波制导系统
/// </remarks>
private const double TERMINAL_GUIDANCE_DISTANCE = 8000;
/// <summary>
/// 初始化毫米波末制导导弹的新实例
/// </summary>
/// <param name="properties">导弹的配置参数</param>
/// <param name="manager">仿真管理器实例</param>
/// <remarks>
/// 构造过程:
/// 1. 调用基类构造函数
/// 2. 创建制导系统实例
/// 3. 设置初始飞行阶段
/// </remarks>
public MillimeterWaveTerminalGuidedMissile(MissileProperties properties, ISimulationManager manager)
: base(properties, manager)
{
currentStage = MWTG_Stage.Launch;
guidanceSystem = new MillimeterWaveGuidanceSystem(properties.MaxAcceleration, properties.ProportionalNavigationCoefficient, manager);
}
/// <summary>
/// 更新导弹的状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 更新过程:
/// 1. 调用基类的更新方法
/// 2. 根据当前阶段选择更新方法
/// 3. 执行相应阶段的更新逻辑
/// 4. 检查是否需要自毁
/// </remarks>
public override void Update(double deltaTime)
{
base.Update(deltaTime);
switch (currentStage)
{
case MWTG_Stage.Launch:
UpdateLaunchStage(deltaTime);
break;
case MWTG_Stage.Cruise:
UpdateCruiseStage(deltaTime);
break;
case MWTG_Stage.TerminalGuidance:
UpdateTerminalGuidanceStage(deltaTime);
break;
case MWTG_Stage.Explode:
Explode();
break;
case MWTG_Stage.SelfDestruct:
SelfDestruct();
break;
}
if (ShouldSelfDestruct())
{
currentStage = MWTG_Stage.SelfDestruct;
}
}
/// <summary>
/// 更新发射阶段的状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 发射阶段特点:
/// - 不使用制导加速度
/// - 仅依靠发动机推力
/// - 持续时间为0.1秒
/// - 结束后进入巡航阶段
/// </remarks>
private void UpdateLaunchStage(double deltaTime)
{
if (FlightTime > 0.1)
{
currentStage = MWTG_Stage.Cruise;
Console.WriteLine($"导弹 {Id} 进入巡航阶段");
}
}
/// <summary>
/// 更新巡航阶段的状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 巡航阶段特点:
/// - 保持稳定飞行
/// - 不使用制导系统
/// - 持续时间为3秒
/// - 结束后进入末制导阶段
/// </remarks>
private void UpdateCruiseStage(double deltaTime)
{
if (FlightTime > 3)
{
currentStage = MWTG_Stage.TerminalGuidance;
Console.WriteLine($"导弹 {Id} 进入末制导阶段");
}
}
/// <summary>
/// 更新末制导阶段的状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 末制导阶段特点:
/// - 开启毫米波制导
/// - 计算制导加速度
/// - 精确跟踪目标
/// - 持续到命中目标
/// </remarks>
private void UpdateTerminalGuidanceStage(double deltaTime)
{
IsGuidance = true;
guidanceSystem.Update(deltaTime, Position, Velocity);
GuidanceAcceleration = guidanceSystem.GetGuidanceAcceleration();
}
/// <summary>
/// 执行导弹爆炸
/// </summary>
/// <remarks>
/// 爆炸过程:
/// 1. 调用基类的爆炸方法
/// 2. 切换到爆炸阶段
/// 3. 结束导弹任务
/// </remarks>
public override void Explode()
{
base.Explode();
currentStage = MWTG_Stage.Explode;
}
/// <summary>
/// 获取导弹的状态信息字符串
/// </summary>
/// <returns>包含导弹状态的详细描述</returns>
/// <remarks>
/// 返回信息包括:
/// - 基类状态信息
/// - 当前飞行阶段
/// - 制导系统状态
/// - 目标跟踪信息
/// </remarks>
public override string GetStatus()
{
return base.GetStatus() + $"\n 当前阶段: {currentStage}, " + guidanceSystem.GetStatus();
}
}
}

View File

@ -0,0 +1,228 @@
using ThreatSource.Utils;
namespace ThreatSource.Missile
{
/// <summary>
/// 导弹类型枚举,定义了系统支持的所有导弹类型
/// </summary>
/// <remarks>
/// 包含以下导弹类型:
/// - 标准导弹:基础型号导弹
/// - 激光半主动制导:利用目标反射的激光能量进行制导
/// - 激光驾束制导:沿着激光束路径飞行
/// - 红外指令制导:通过红外信号接收指令进行制导
/// - 红外成像末制导:末段使用红外成像进行制导
/// - 毫米波末制导:末段使用毫米波雷达进行制导
/// - 末敏弹:末段敏感引信的导弹
/// </remarks>
public enum MissileType
{
StandardMissile, // 标准导弹
LaserSemiActiveGuidance, // 激光半主动制导
LaserBeamRiderGuidance, // 激光驾束制导
InfraredCommandGuidance, // 红外指令制导
InfraredImagingTerminalGuidance, // 红外成像末制导
MillimeterWaveTerminalGuidance, // 毫米波末制导
TerminalSensitiveMissile // 末敏弹
}
/// <summary>
/// 导弹配置类,定义了导弹的所有基本属性和性能参数
/// </summary>
/// <remarks>
/// 该类用于:
/// - 初始化导弹的基本参数
/// - 配置导弹的性能限制
/// - 设置导弹的物理特性
/// - 定义导弹的作战能力
/// 所有导弹实例都基于此配置进行初始化
/// </remarks>
public class MissileProperties
{
/// <summary>
/// 获取或设置导弹的唯一标识符
/// </summary>
/// <remarks>
/// 在仿真系统中必须唯一
/// 用于标识和追踪特定的导弹实例
/// </remarks>
public string Id { get; set; }
/// <summary>
/// 获取或设置导弹的初始位置
/// </summary>
/// <remarks>
/// 使用三维向量表示发射位置
/// 坐标系右手坐标系X向右Y向上Z向前
/// </remarks>
public Vector3D InitialPosition { get; set; }
/// <summary>
/// 获取或设置导弹的初始朝向
/// </summary>
/// <remarks>
/// 使用欧拉角表示初始姿态
/// 包含偏航角、俯仰角和滚转角
/// </remarks>
public Orientation InitialOrientation { get; set; }
/// <summary>
/// 获取或设置导弹的初始速度
/// </summary>
/// <remarks>
/// 单位:米/秒
/// 发射时的初始运动速度
/// </remarks>
public double InitialSpeed { get; set; }
/// <summary>
/// 获取或设置导弹的最大速度限制
/// </summary>
/// <remarks>
/// 单位:米/秒
/// 导弹在飞行过程中不能超过此速度
/// </remarks>
public double MaxSpeed { get; set; }
/// <summary>
/// 获取或设置导弹的最大飞行时间
/// </summary>
/// <remarks>
/// 单位:秒
/// 超过此时间导弹将自毁
/// 用于防止导弹无限飞行
/// </remarks>
public double MaxFlightTime { get; set; }
/// <summary>
/// 获取或设置导弹的最大飞行距离
/// </summary>
/// <remarks>
/// 单位:米
/// 超过此距离导弹将自毁
/// 基于导弹的燃料容量和设计射程
/// </remarks>
public double MaxFlightDistance { get; set; }
/// <summary>
/// 获取或设置导弹的最大加速度
/// </summary>
/// <remarks>
/// 单位:米/秒²
/// 导弹机动时的最大加速度限制
/// 基于导弹的结构强度和推进系统能力
/// </remarks>
public double MaxAcceleration { get; set; }
/// <summary>
/// 获取或设置导弹的比例导引系数
/// </summary>
/// <remarks>
/// 无量纲参数
/// 用于计算制导指令的增益
/// 影响导弹的制导精度和稳定性
/// </remarks>
public double ProportionalNavigationCoefficient { get; set; }
/// <summary>
/// 获取或设置导弹的发射推力加速度
/// </summary>
/// <remarks>
/// 单位:米/秒²
/// 发射阶段的推进加速度
/// 影响导弹的起飞性能
/// </remarks>
public double LaunchAcceleration { get; set; }
/// <summary>
/// 获取或设置发动机的最大燃烧时间
/// </summary>
/// <remarks>
/// 单位:秒
/// 发动机能够持续工作的最长时间
/// 基于燃料容量和燃烧速率
/// </remarks>
public double MaxEngineBurnTime { get; set; }
/// <summary>
/// 获取或设置导弹的质量
/// </summary>
/// <remarks>
/// 单位:千克
/// 导弹的总质量,包括弹体和燃料
/// 影响导弹的运动性能和惯性特性
/// </remarks>
public double Mass { get; set; }
/// <summary>
/// 获取或设置导弹的爆炸半径
/// </summary>
/// <remarks>
/// 单位:米
/// 爆炸效果的有效作用范围
/// 用于计算对目标的伤害
/// </remarks>
public double ExplosionRadius { get; set; }
/// <summary>
/// 获取或设置导弹的命中概率
/// </summary>
/// <remarks>
/// 范围0-1
/// 表示在理想条件下的命中可能性
/// 用于评估导弹的作战效能
/// </remarks>
public double HitProbability { get; set; }
/// <summary>
/// 获取或设置导弹的类型
/// </summary>
/// <remarks>
/// 决定导弹的制导方式和行为特征
/// 影响导弹的性能参数和作战能力
/// </remarks>
public MissileType Type { get; set; }
/// <summary>
/// 初始化导弹配置类的新实例
/// </summary>
/// <remarks>
/// 构造过程:
/// - 设置所有数值参数的默认值
/// - 初始化基本属性ID、位置、朝向
/// - 设置默认导弹类型
/// </remarks>
public MissileProperties()
{
SetDefaultValues();
Id = "";
InitialPosition = new Vector3D(0, 0, 0);
InitialOrientation = new Orientation(0, 0, 0);
Type = MissileType.LaserSemiActiveGuidance;
}
/// <summary>
/// 将所有数值参数设置为默认值
/// </summary>
/// <remarks>
/// 重置以下参数:
/// - 速度相关参数
/// - 时间和距离限制
/// - 加速度参数
/// - 性能参数
/// 用于初始化或重置导弹配置
/// </remarks>
public void SetDefaultValues(){
InitialSpeed = 0;
MaxSpeed = 0;
MaxFlightTime = 0;
MaxFlightDistance = 0;
LaunchAcceleration = 0;
MaxEngineBurnTime = 0;
MaxAcceleration = 0;
ExplosionRadius = 0;
ProportionalNavigationCoefficient = 0;
}
}
}

View File

@ -0,0 +1,299 @@
using ThreatSource.Simulation;
using ThreatSource.Utils;
using System.Diagnostics;
namespace ThreatSource.Missile
{
/// <summary>
/// 末敏导弹类,实现了末端敏感引信的导弹功能
/// </summary>
/// <remarks>
/// 该类提供了末敏导弹的完整实现:
/// - 继承自BaseMissile具备基本的导弹功能
/// - 实现了末端敏感引信的特殊功能
/// - 支持子弹药分离和释放
/// - 具备高度和距离控制能力
/// - 提供精确的目标打击能力
///
/// 工作流程:
/// 1. 导弹发射并飞向预定分离点
/// 2. 到达分离高度时释放子弹药
/// 3. 子弹药独立制导飞向目标
/// 4. 母弹完成任务后自动销毁
/// </remarks>
public class TerminalSensitiveMissile : BaseMissile
{
/// <summary>
/// 子弹药分离的高度阈值
/// </summary>
/// <remarks>
/// 单位:米
/// 当导弹上升到此高度时会触发分离
/// 默认设置为1000米
/// </remarks>
private const double SeparationHeight = 1000;
/// <summary>
/// 分离点与目标的水平距离
/// </summary>
/// <remarks>
/// 单位:米
/// 分离点在目标上方的水平投影距离
/// 默认设置为1000米
/// </remarks>
private const double SeparationDistance = 1000;
/// <summary>
/// 触发分离的距离阈值
/// </summary>
/// <remarks>
/// 单位:米
/// 当导弹距离分离点小于此距离时触发分离
/// 默认设置为50米
/// 注意:此值必须大于导弹速度乘以时间步长的一半
/// </remarks>
private const double SeparationRange = 50;
/// <summary>
/// 子弹药的数量
/// </summary>
/// <remarks>
/// 155口径母弹默认携带2个子弹药
/// 可根据需要调整数量
/// </remarks>
private const int SubmunitionCount = 1;
/// <summary>
/// 子弹药数组,存储所有分离后的子弹药
/// </summary>
/// <remarks>
/// 数组大小由SubmunitionCount决定
/// 每个元素都是一个独立的子弹药实例
/// </remarks>
private TerminalSensitiveSubmunition[] submunitions;
/// <summary>
/// 分离点的三维坐标
/// </summary>
/// <remarks>
/// 在构造时计算确定
/// 基于目标位置、分离高度和分离距离计算
/// 作为导弹的第一阶段目标点
/// </remarks>
private readonly Vector3D separationPoint;
/// <summary>
/// 目标的唯一标识符
/// </summary>
/// <remarks>
/// 用于在仿真系统中识别和追踪目标
/// 在导弹的整个生命周期中保持不变
/// </remarks>
private readonly string TargetId;
/// <summary>
/// 初始化末敏导弹的新实例
/// </summary>
/// <param name="targetId">目标的唯一标识符</param>
/// <param name="properties">导弹的配置参数</param>
/// <param name="manager">仿真管理器实例</param>
/// <exception cref="Exception">当目标不存在时抛出</exception>
/// <exception cref="InvalidOperationException">当无法计算发射方向时抛出</exception>
/// <remarks>
/// 构造过程:
/// 1. 初始化基本属性
/// 2. 创建子弹药数组
/// 3. 计算分离点位置
/// 4. 计算最佳发射角度
/// 5. 设置初始速度和方向
/// </remarks>
public TerminalSensitiveMissile(string targetId, MissileProperties properties, ISimulationManager manager)
: base(properties, manager)
{
TargetId = targetId;
submunitions = new TerminalSensitiveSubmunition[SubmunitionCount];
//计算分离点坐标高度为SeparationHeight距离目标的距离为SeparationDistance
SimulationElement target = SimulationManager.GetEntityById(TargetId) as SimulationElement ?? throw new Exception("目标不存在");
separationPoint = Vector3D.PointOnLine(target.Position, base.Position, SeparationDistance) + new Vector3D(0, SeparationHeight, 0);
//计算导弹发射角度
(Orientation? launchOrientation, Vector3D? launchVelocity) = MotionAlgorithm.CalculateBestLaunchOrientation(Position, separationPoint, Speed);
if (!launchOrientation.HasValue || launchVelocity is null)
{
// 处理错误情况
throw new InvalidOperationException("无法计算发射方向");
}
else
{
Orientation = launchOrientation.Value;
Velocity = launchVelocity;
}
}
/// <summary>
/// 更新导弹的状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 更新过程:
/// 1. 检查导弹是否处于活动状态
/// 2. 验证自毁条件(时间、距离、高度)
/// 3. 更新基本运动状态
/// 4. 计算与分离点的距离
/// 5. 记录状态信息
/// 6. 必要时触发分离动作
///
/// 自毁条件:
/// - 超出最大飞行时间
/// - 超出最大飞行距离
/// - 高度低于地面
/// </remarks>
public override void Update(double deltaTime)
{
if (!IsActive) return;
// 检查自毁条件
if (FlightTime >= MissileProperties.MaxFlightTime)
{
Console.WriteLine($"母弹 {Id} 超出最大飞行时间,自毁");
SelfDestruct();
return;
}
if (FlightDistance >= MissileProperties.MaxFlightDistance)
{
Console.WriteLine($"母弹 {Id} 超出最大飞行距离,自毁");
SelfDestruct();
return;
}
if (Position.Y < 0)
{
Console.WriteLine($"母弹 {Id} 落地,自毁");
SelfDestruct();
return;
}
base.Update(deltaTime);
double distanceToSeparationPoint = (separationPoint - Position).Magnitude();
Vector3D deltaToSeparation = separationPoint - Position;
Console.WriteLine($"导弹 {Id} 状态:");
Console.WriteLine($"当前位置: {Position}");
Console.WriteLine($"分离点位置: {separationPoint}");
Console.WriteLine($"距离分离点: dx={deltaToSeparation.X:F1}m, dy={deltaToSeparation.Y:F1}m, dz={deltaToSeparation.Z:F1}m");
Console.WriteLine($"与分离点直线距离: {distanceToSeparationPoint:F1}米");
Console.WriteLine($"速度: {Velocity.Magnitude():F1}米/秒");
Console.WriteLine($"速度方向: {Velocity.Normalize()}");
Console.WriteLine($"飞行时间: {FlightTime:F1}秒");
Console.WriteLine($"分离范围阈值: {SeparationRange}米");
Console.WriteLine("-------------------");
//距离分离点距离小于50米则分离
if (distanceToSeparationPoint <= SeparationRange)
{
Console.WriteLine("分离");
Debug.WriteLine("分离");
PerformSeparation();
}
}
/// <summary>
/// 执行子弹药分离动作
/// </summary>
/// <remarks>
/// 分离过程:
/// 1. 获取目标的当前位置
/// 2. 计算子弹药的发射方向
/// 3. 创建指定数量的子弹药
/// 4. 为每个子弹药设置初始参数
/// 5. 将子弹药注册到仿真系统
/// 6. 激活所有子弹药
/// 7. 停用母弹
///
/// 子弹药参数设置:
/// - 初始位置:母弹当前位置
/// - 初始速度200米/秒
/// - 最大速度2000米/秒
/// - 最大飞行时间50秒
/// - 最大飞行距离1000米
/// - 最大加速度50米/秒²
/// - 比例导引系数3
/// - 质量10千克
/// </remarks>
private void PerformSeparation()
{
Console.WriteLine($"开始分离,当前位置:{Position},分离点:{separationPoint}");
Debug.WriteLine($"开始分离,当前位置:{Position},分离点:{separationPoint}");
// 获取目标位置
SimulationElement target = SimulationManager.GetEntityById(TargetId) as SimulationElement ?? throw new Exception("目标不存在");
Vector3D targetPosition = target.Position;
Console.WriteLine($"目标位置:{targetPosition}");
Debug.WriteLine($"目标位置:{targetPosition}");
// 计算子弹朝向目标的方向
Vector3D directionToTarget = (targetPosition - this.Position).Normalize();
Orientation orientationToTarget = Orientation.FromVector(directionToTarget);
Console.WriteLine($"子弹朝向:{directionToTarget}");
Debug.WriteLine($"子弹朝向:{directionToTarget}");
// 创建并释子弹
for (int i = 0; i < SubmunitionCount; i++)
{
Console.WriteLine($"创建子弹 {i}");
Debug.WriteLine($"创建子弹 {i}");
submunitions[i] = new TerminalSensitiveSubmunition(
TargetId,
new MissileProperties
{
Id = $"{Id}_Sub_{i}",
InitialPosition = Position,
InitialOrientation = orientationToTarget,
InitialSpeed = 200, // 子弹初始速度
MaxSpeed = 2000,
MaxFlightTime = 50,
MaxFlightDistance = 1000,
MaxAcceleration = 50,
ProportionalNavigationCoefficient = 3,
Mass = 10,
ExplosionRadius = MissileProperties.ExplosionRadius,
HitProbability = MissileProperties.HitProbability
},
SimulationManager);
Console.WriteLine($"注册子弹 {submunitions[i].Id}");
Debug.WriteLine($"注册子弹 {submunitions[i].Id}");
SimulationManager.RegisterEntity(submunitions[i].Id, submunitions[i]);
Console.WriteLine($"激活子弹 {submunitions[i].Id}");
Debug.WriteLine($"激活子弹 {submunitions[i].Id}");
submunitions[i].Activate();
// 验证注册是否成功
var registered = SimulationManager.GetEntityById(submunitions[i].Id);
Console.WriteLine($"子弹注册状态:{registered != null},激活状态:{(registered as SimulationElement)?.IsActive}");
Debug.WriteLine($"子弹注册状态:{registered != null},激活状态:{(registered as SimulationElement)?.IsActive}");
}
// 母弹完成任务,可以被移除
IsActive = false;
Console.WriteLine("分离完成,母弹停用");
Debug.WriteLine("分离完成,母弹停用");
}
/// <summary>
/// 获取导弹的状态信息字符串
/// </summary>
/// <returns>包含导弹状态的详细描述</returns>
/// <remarks>
/// 返回信息包括:
/// - 基类状态信息
/// - 分离点位置
/// - 母弹特有的状态信息
/// </remarks>
public override string GetStatus()
{
return $"{base.GetStatus()}\n母弹, 分离点: {separationPoint}";
}
}
}

View File

@ -0,0 +1,559 @@
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Sensor;
namespace ThreatSource.Missile
{
/// <summary>
/// 末敏子弹类,实现了多传感器融合的末端制导功能
/// </summary>
/// <remarks>
/// 该类提供了末敏子弹的核心功能:
/// - 多传感器融合(红外、毫米波、激光)
/// - 螺旋扫描搜索
/// - 自主目标识别
/// - 末端精确制导
/// 通过多种传感器的协同工作实现对目标的精确打击
/// </remarks>
public class TerminalSensitiveSubmunition : BaseMissile
{
/// <summary>
/// 子弹飞行阶段枚举
/// </summary>
/// <remarks>
/// 定义了子弹飞行的六个主要阶段:
/// - Separation分离阶段从母弹分离
/// - Deceleration减速阶段调整速度
/// - SpiralScan螺旋扫描阶段搜索目标
/// - Attack攻击阶段末端制导
/// - Explode爆炸阶段命中目标
/// - SelfDestruct自毁阶段触发自毁
/// </remarks>
private enum SubmunitionStage
{
Separation, // 分离阶段
Deceleration, // 减速阶段
SpiralScan, // 螺旋扫描阶段
Attack, // 攻击阶段
Explode, // 爆炸阶段
SelfDestruct // 自毁阶段
}
/// <summary>
/// 获取或设置当前飞行阶段
/// </summary>
/// <remarks>
/// 用于控制子弹在不同阶段的行为
/// 影响传感器工作模式和制导方式
/// </remarks>
private SubmunitionStage currentStage;
/// <summary>
/// 螺旋扫描旋转速度,单位:弧度/秒
/// </summary>
/// <remarks>
/// 定义了螺旋扫描时的旋转角速度
/// 4转/秒 = 8π弧度/秒
/// </remarks>
private const double SpiralRotationSpeed = 8 * Math.PI;
/// <summary>
/// 垂直下降速度,单位:米/秒
/// </summary>
/// <remarks>
/// 定义了扫描和攻击阶段的垂直下降速度
/// </remarks>
private const double VerticalDescentSpeed = 10;
/// <summary>
/// 扫描角度,单位:弧度
/// </summary>
/// <remarks>
/// 定义了螺旋扫描的锥角
/// 30度 = π/6弧度
/// </remarks>
private const double ScanAngle = 30 * Math.PI / 180;
/// <summary>
/// 减速高度,单位:米
/// </summary>
/// <remarks>
/// 开始减速的高度阈值
/// 影响减速阶段的触发时机
/// </remarks>
private const double DecelerationHeight = 400;
/// <summary>
/// 减速加速度,单位:米/秒²
/// </summary>
/// <remarks>
/// 减速阶段的减速度大小
/// 影响速度调整的快慢
/// </remarks>
private const double DecelerationAcceleration = 50;
/// <summary>
/// 扫描高度,单位:米
/// </summary>
/// <remarks>
/// 开始螺旋扫描的高度阈值
/// 影响扫描阶段的触发时机
/// </remarks>
private const double ScanningHeight = 200;
/// <summary>
/// 自毁高度,单位:米
/// </summary>
/// <remarks>
/// 触发自毁的高度阈值
/// 保证子弹不会危及友方
/// </remarks>
private const double SelfDestructHeight = 20;
/// <summary>
/// 攻击速度,单位:米/秒
/// </summary>
/// <remarks>
/// 攻击阶段的期望速度
/// 影响末端制导的精度
/// </remarks>
private const double AttackSpeed = 500;
/// <summary>
/// 获取或设置最后一次检测到目标的时间
/// </summary>
/// <remarks>
/// 用于目标确认和跟踪
/// null表示尚未检测到目标
/// </remarks>
private double? lastDetectionTime = null;
/// <summary>
/// 获取或设置螺旋扫描的当前角度
/// </summary>
/// <remarks>
/// 用于控制螺旋扫描的方向
/// 影响传感器的指向
/// </remarks>
private double spiralAngle;
/// <summary>
/// 获取或设置扫描方向向量
/// </summary>
/// <remarks>
/// 表示传感器的当前指向
/// 用于目标探测和跟踪
/// </remarks>
private Vector3D scanDirection;
/// <summary>
/// 获取或设置目标检测角度
/// </summary>
/// <remarks>
/// 记录检测到目标时的角度
/// 用于目标确认和重获
/// </remarks>
private double detectionAngle;
/// <summary>
/// 红外探测器实例
/// </summary>
/// <remarks>
/// 用于探测目标的红外辐射
/// 提供目标方位信息
/// </remarks>
private readonly InfraredDetector infraredDetector;
/// <summary>
/// 毫米波辐射计实例
/// </summary>
/// <remarks>
/// 用于探测目标的毫米波辐射
/// 提供目标特征信息
/// </remarks>
private readonly MillimeterWaveRadiometer radiometer;
/// <summary>
/// 毫米波测高仪实例
/// </summary>
/// <remarks>
/// 用于测量对地高度
/// 控制飞行阶段转换
/// </remarks>
private readonly MillimeterWaveAltimeter altimeter;
/// <summary>
/// 激光测距仪实例
/// </summary>
/// <remarks>
/// 用于精确测量目标距离
/// 提供攻击阶段的制导信息
/// </remarks>
private readonly LaserRangefinder rangefinder;
/// <summary>
/// 目标ID
/// </summary>
/// <remarks>
/// 记录目标的唯一标识符
/// 用于目标识别和跟踪
/// </remarks>
private readonly string TargetId;
/// <summary>
/// 初始化末敏子弹的新实例
/// </summary>
/// <param name="targetId">目标ID</param>
/// <param name="properties">子弹配置参数</param>
/// <param name="manager">仿真管理器实例</param>
/// <remarks>
/// 构造过程:
/// - 初始化基本属性
/// - 创建传感器系统
/// - 配置传感器参数
/// - 设置初始状态
/// </remarks>
public TerminalSensitiveSubmunition(string targetId, MissileProperties properties, ISimulationManager manager)
: base(properties, manager)
{
TargetId = targetId;
currentStage = SubmunitionStage.Separation;
spiralAngle = 0;
scanDirection = new Vector3D(0, 0, 0);
detectionAngle = 0;
// 初始化传感器
infraredDetector = new InfraredDetector(this, 500, 5); // 红外探测器,探测距离 500 米视场角5度
radiometer = new MillimeterWaveRadiometer(this, 3, 5); // 毫米波辐射计工作波段3mm扫描视场角5度
altimeter = new MillimeterWaveAltimeter(this, 1000, 0.1); // 毫米波测高仪测量精度0.1米
rangefinder = new LaserRangefinder(Position, Orientation, 1000, 1000);
}
/// <summary>
/// 更新子弹状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 更新所有传感器
/// - 根据当前阶段更新状态
/// - 处理阶段转换
/// - 调用基类更新
/// </remarks>
public override void Update(double deltaTime)
{
base.Update(deltaTime);
// 更新传感器
infraredDetector.Update(deltaTime);
radiometer.Update(deltaTime);
altimeter.Update(deltaTime);
rangefinder.Update(deltaTime);
switch (currentStage)
{
case SubmunitionStage.Separation:
UpdateSeparationStage(deltaTime);
break;
case SubmunitionStage.Deceleration:
UpdateDecelerationStage(deltaTime);
break;
case SubmunitionStage.SpiralScan:
UpdateSpiralScanStage(deltaTime);
break;
case SubmunitionStage.Attack:
UpdateAttackStage(deltaTime);
break;
case SubmunitionStage.Explode:
UpdateExplodeStage(deltaTime);
break;
case SubmunitionStage.SelfDestruct:
UpdateSelfDestructStage(deltaTime);
break;
}
}
/// <summary>
/// 更新分离阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 分离阶段处理:
/// - 施加重力加速度
/// - 更新位置和速度
/// - 激活测高仪
/// - 检查高度条件
/// </remarks>
private void UpdateSeparationStage(double deltaTime)
{
// 分离阶段
Vector3D deceleration = new(0, 9.8, 0);
Velocity += deceleration * deltaTime;
Position += Velocity * deltaTime;
if(!altimeter.IsActive)
{
// 激活毫米波测高雷达
altimeter.Activate();
}
// 检查高度是否小于等于减速高度
if(((AltimeterSensorData)altimeter.GetSensorData()).Altitude <= DecelerationHeight)
{
// 如果是,则进入减速阶段
currentStage = SubmunitionStage.Deceleration;
}
}
/// <summary>
/// 更新减速阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 减速阶段处理:
/// - 启用制导控制
/// - 计算减速加速度
/// - 更新速度和位置
/// - 检查高度条件
/// </remarks>
private void UpdateDecelerationStage(double deltaTime)
{
IsGuidance = true;
// 减速减旋,垂直速度减小
Vector3D deceleration = - Velocity.Normalize() * DecelerationAcceleration;
Velocity += deceleration * deltaTime;
if (Velocity.Magnitude() <= VerticalDescentSpeed)
{
Velocity = new Vector3D(0, -VerticalDescentSpeed, 0);
GuidanceAcceleration = Vector3D.Zero;
}
if (((AltimeterSensorData)altimeter.GetSensorData()).Altitude <= ScanningHeight)
{
currentStage = SubmunitionStage.SpiralScan;
}
}
/// <summary>
/// 更新螺旋扫描阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 扫描阶段处理:
/// - 激活传感器系统
/// - 执行螺旋扫描
/// - 处理目标探测
/// - 检查目标确认条件
/// </remarks>
private void UpdateSpiralScanStage(double deltaTime)
{
if(!radiometer.IsActive)
{
// 激活毫米波辐射计
radiometer.Activate();
}
if(!infraredDetector.IsActive)
{
// 激活红外探测器
infraredDetector.Activate();
}
Velocity = new Vector3D(0, -VerticalDescentSpeed, 0);
GuidanceAcceleration = Vector3D.Zero;
// 更新螺旋角度
spiralAngle = (spiralAngle + SpiralRotationSpeed * deltaTime) % (2 * Math.PI);
// 计算水平速度分量
double horizontalSpeed = VerticalDescentSpeed * Math.Tan(ScanAngle);
Vector3D horizontalVelocity = new(
Math.Cos(spiralAngle) * horizontalSpeed,
0,
Math.Sin(spiralAngle) * horizontalSpeed
);
// 更新速度
Velocity = new(horizontalVelocity.X, -VerticalDescentSpeed, horizontalVelocity.Z);
// 计算扫描方向
scanDirection = new(
Math.Cos(spiralAngle) * Math.Sin(ScanAngle),
-Math.Cos(ScanAngle),
Math.Sin(spiralAngle) * Math.Sin(ScanAngle)
);
bool isRadiationDetected = radiometer.GetSensorData() is RadiometerSensorData radiometerData && radiometerData.IsTargetDetected;
bool isInfraredDetected = infraredDetector.GetSensorData() is InfraredSensorData infraredData && infraredData.IsTargetDetected;
if (isRadiationDetected || isInfraredDetected)
{
double currentTime = DateTime.Now.Ticks;
if (lastDetectionTime == null)
{
lastDetectionTime = currentTime;
}
else
{
double timeSinceLastDetection = currentTime - lastDetectionTime.Value;
// 重新检测到目标的时间大于等于螺旋周期的90%,则二次确认目标
if (timeSinceLastDetection >= 0.9 * 2 * Math.PI / SpiralRotationSpeed)
{
Console.WriteLine($"目标确认,进入攻击阶段。距离上次检测时间:{timeSinceLastDetection:F2}秒");
currentStage = SubmunitionStage.Attack;
return;
}
}
}
// 使用模式匹配简化类型转换
if (altimeter.GetSensorData() is AltimeterSensorData altimeterData &&
altimeterData.Altitude <= SelfDestructHeight)
{
currentStage = SubmunitionStage.SelfDestruct;
}
}
/// <summary>
/// 更新攻击阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 攻击阶段处理:
/// - 获取目标位置
/// - 计算制导指令
/// - 更新速度和方向
/// - 检查命中条件
/// </remarks>
private void UpdateAttackStage(double deltaTime)
{
Console.WriteLine("攻击阶段");
// 攻击逻辑
SimulationElement target = SimulationManager.GetEntityById(TargetId) as SimulationElement ?? throw new Exception("目标不存在");
Vector3D targetPosition = target.Position;
Vector3D direction = (targetPosition - Position).Normalize();
Velocity = direction * AttackSpeed;
if ((targetPosition - Position).Magnitude() <= MissileProperties.ExplosionRadius)
{
currentStage = SubmunitionStage.Explode;
}
}
/// <summary>
/// 更新爆炸阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 爆炸阶段处理:
/// - 触发爆炸效果
/// - 结束子弹任务
/// </remarks>
private void UpdateExplodeStage(double deltaTime)
{
Explode();
}
/// <summary>
/// 更新自毁阶段状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 自毁阶段处理:
/// - 触发自毁效果
/// - 结束子弹任务
/// </remarks>
private void UpdateSelfDestructStage(double deltaTime)
{
SelfDestruct();
}
/// <summary>
/// 检测目标是否在视场内
/// </summary>
/// <param name="fieldOfView">视场角,单位:度</param>
/// <returns>如果目标在视场内返回true否则返回false</returns>
/// <remarks>
/// 检测过程:
/// - 获取目标位置
/// - 计算目标方向
/// - 判断是否在视场内
/// </remarks>
public bool DetectTarget(double fieldOfView)
{
SimulationElement target = SimulationManager.GetEntityById(TargetId) as SimulationElement ?? throw new Exception("目标不存在");
Vector3D targetPosition = target.Position;
Vector3D toTarget = (targetPosition - Position).Normalize();
// 检查目标是否在扫描视场内
return Vector3D.DotProduct(scanDirection, toTarget) > Math.Cos(fieldOfView * Math.PI / 180);
}
/// <summary>
/// 激活子弹
/// </summary>
/// <remarks>
/// 激活过程:
/// - 调用基类激活方法
/// - 订阅目标辐射事件
/// - 准备传感器系统
/// </remarks>
public override void Activate()
{
base.Activate();
SimulationManager.SubscribeToEvent<TankRadiationEvent>(OnTankRadiationEvent);
}
/// <summary>
/// 停用子弹
/// </summary>
/// <remarks>
/// 停用过程:
/// - 调用基类停用方法
/// - 停用所有传感器
/// - 清理制导状态
/// </remarks>
public override void Deactivate()
{
base.Deactivate();
infraredDetector.Deactivate();
radiometer.Deactivate();
altimeter.Deactivate();
rangefinder.Deactivate();
}
/// <summary>
/// 处理坦克辐射事件
/// </summary>
/// <param name="evt">坦克辐射事件数据</param>
/// <remarks>
/// 处理过程:
/// - 验证目标ID
/// - 记录辐射信息
/// - 更新目标状态
/// </remarks>
private void OnTankRadiationEvent(TankRadiationEvent evt)
{
if (evt.SenderId == TargetId)
{
Console.WriteLine("检测到目标辐射");
}
}
/// <summary>
/// 获取子弹状态信息
/// </summary>
/// <returns>包含子弹状态的详细描述</returns>
/// <remarks>
/// 返回信息包括:
/// - 基本状态信息
/// - 当前飞行阶段
/// - 扫描和检测状态
/// - 传感器工作状态
/// </remarks>
public override string GetStatus()
{
return $"{base.GetStatus()}\n运行状态: {currentStage}\n检测角度: {detectionAngle * 180 / Math.PI:F2}°\n螺旋角度: {spiralAngle * 180 / Math.PI:F2}°\n目标检测: {lastDetectionTime != null}";
}
}
}

View File

@ -0,0 +1,149 @@
using ThreatSource.Missile;
namespace ThreatSource.Sensor
{
/// <summary>
/// 红外探测器类,实现了红外辐射的探测和目标识别功能
/// </summary>
/// <remarks>
/// 该类提供了红外探测器的核心功能:
/// - 红外辐射强度测量
/// - 目标存在性判断
/// - 视场角范围探测
/// - 实时状态更新
/// 用于末敏子弹的目标探测和跟踪
/// </remarks>
public class InfraredDetector : Sensor
{
/// <summary>
/// 探测辐射强度阈值,单位:瓦特/球面度
/// </summary>
/// <remarks>
/// 定义了目标识别的最小辐射强度
/// 大于此阈值表示探测到有效目标
/// 用于目标存在性判断
/// </remarks>
private const double DetectionRadiationIntensityThreshold = 50;
/// <summary>
/// 获取或设置探测范围,单位:米
/// </summary>
/// <remarks>
/// 定义了探测器的最大作用距离
/// 影响目标探测的有效范围
/// </remarks>
public double DetectionRange { get; set; }
/// <summary>
/// 获取或设置视场角,单位:度
/// </summary>
/// <remarks>
/// 定义了探测器的视场范围
/// 影响目标探测的空间覆盖
/// </remarks>
public double FieldOfView { get; set; }
/// <summary>
/// 末敏子弹实例
/// </summary>
/// <remarks>
/// 关联的末敏子弹对象
/// 用于获取位置和姿态信息
/// </remarks>
private readonly TerminalSensitiveSubmunition submunition;
/// <summary>
/// 红外探测器数据实例
/// </summary>
/// <remarks>
/// 存储探测器的测量结果
/// 包含温度和目标探测状态
/// </remarks>
private InfraredSensorData sensorData;
/// <summary>
/// 初始化红外探测器的新实例
/// </summary>
/// <param name="submunition">末敏子弹实例</param>
/// <param name="detectionRange">探测范围,单位:米</param>
/// <param name="fieldOfView">视场角,单位:度</param>
/// <remarks>
/// 构造过程:
/// - 设置探测参数
/// - 关联末敏子弹
/// - 初始化传感器数据
/// - 继承基类位置和姿态
/// </remarks>
public InfraredDetector(TerminalSensitiveSubmunition submunition, double detectionRange, double fieldOfView)
: base(submunition.Position, submunition.Orientation)
{
DetectionRange = detectionRange;
FieldOfView = fieldOfView;
this.submunition = submunition;
sensorData = new InfraredSensorData();
}
/// <summary>
/// 更新红外探测器的工作状态
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 检查激活状态
/// - 测量辐射强度
/// - 判断目标存在
/// - 更新传感器数据
/// </remarks>
public override void Update(double deltaTime)
{
// 实现红外探测器的更新逻辑
if (IsActive)
{
// 获取当前方向上的红外辐射强度
double currentDirectionRadiationIntensity = GetCurrentDirectionRadiationIntensity();
// 如果辐射强度大于探测阈值,则认为检测到目标
if (currentDirectionRadiationIntensity >= DetectionRadiationIntensityThreshold)
{
sensorData.IsTargetDetected = true;
}
else
{
sensorData.IsTargetDetected = false;
}
}
}
/// <summary>
/// 获取当前方向上的红外辐射强度
/// </summary>
/// <returns>当前方向上的红外辐射强度,单位:瓦特/球面度</returns>
/// <remarks>
/// 测量过程:
/// - 检查目标是否在视场内
/// - 计算辐射强度
/// - 返回测量结果
/// 目标存在时返回100不存在时返回0
/// </remarks>
private double GetCurrentDirectionRadiationIntensity()
{
// 获取当前方向上的辐射强度如果检测到目标则返回目标的辐射强度否则返回0
return submunition.DetectTarget(FieldOfView) ? 100 : 0;
}
/// <summary>
/// 获取红外探测器的最新数据
/// </summary>
/// <returns>包含探测结果的数据对象</returns>
/// <remarks>
/// 返回数据:
/// - 目标探测状态
/// - 温度测量结果
/// - 时间戳信息
/// </remarks>
public override SensorData GetSensorData()
{
// 返回红外探测器的数据
return sensorData;
}
}
}

View File

@ -0,0 +1,91 @@
using ThreatSource.Utils;
namespace ThreatSource.Sensor
{
/// <summary>
/// 激光测距仪类,实现了目标距离测量和数据采集功能
/// </summary>
/// <remarks>
/// 该类提供了激光测距仪的核心功能:
/// - 实时距离测量
/// - 脉冲频率控制
/// - 量程范围控制
/// - 数据采集
/// 用于目标距离的精确测量和跟踪
/// </remarks>
public class LaserRangefinder : Sensor
{
/// <summary>
/// 获取或设置最大测量距离,单位:米
/// </summary>
/// <remarks>
/// 定义了测距仪的量程上限
/// 超出此距离的测量可能不准确
/// 受大气条件和目标反射率影响
/// </remarks>
public double MaxRange { get; set; }
/// <summary>
/// 获取或设置脉冲频率,单位:赫兹
/// </summary>
/// <remarks>
/// 定义了激光发射的重复频率
/// 影响测量的更新速率和精度
/// 需要根据目标运动特性选择
/// </remarks>
public double PulseRate { get; set; }
/// <summary>
/// 初始化激光测距仪的新实例
/// </summary>
/// <param name="position">测距仪的位置坐标</param>
/// <param name="orientation">测距仪的朝向</param>
/// <param name="maxRange">最大测量距离,单位:米</param>
/// <param name="pulseRate">脉冲频率,单位:赫兹</param>
/// <remarks>
/// 构造过程:
/// - 设置位置和姿态
/// - 配置测量参数
/// - 初始化工作状态
/// </remarks>
public LaserRangefinder(Vector3D position, Orientation orientation, double maxRange, double pulseRate)
: base(position, orientation)
{
MaxRange = maxRange;
PulseRate = pulseRate;
}
/// <summary>
/// 更新激光测距仪的工作状态
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 发射激光脉冲
/// - 接收回波信号
/// - 计算目标距离
/// - 更新测量数据
/// </remarks>
public override void Update(double deltaTime)
{
// 实现激光测距仪的更新逻辑
}
/// <summary>
/// 获取激光测距仪的最新数据
/// </summary>
/// <returns>包含距离测量结果的数据对象</returns>
/// <remarks>
/// 返回数据:
/// - 目标距离值
/// - 信号强度
/// - 测量时间戳
/// - 数据可靠性
/// </remarks>
public override SensorData GetSensorData()
{
// 返回激光测距仪的数据
return new RangefinderSensorData();
}
}
}

View File

@ -0,0 +1,127 @@
using ThreatSource.Missile;
namespace ThreatSource.Sensor
{
/// <summary>
/// 毫米波测高雷达类,实现了高度测量和数据采集功能
/// </summary>
/// <remarks>
/// 该类提供了毫米波测高雷达的核心功能:
/// - 实时高度测量
/// - 精度控制
/// - 干扰监测
/// - 数据采集
/// 用于末敏子弹的高度测量和地形跟踪
/// </remarks>
public class MillimeterWaveAltimeter : Sensor
{
/// <summary>
/// 当前测量高度,单位:米
/// </summary>
/// <remarks>
/// 存储最新的高度测量值
/// 包含测量精度引入的随机误差
/// </remarks>
private double currentAltitude;
/// <summary>
/// 末敏子弹实例
/// </summary>
/// <remarks>
/// 关联的末敏子弹对象
/// 用于获取位置和姿态信息
/// </remarks>
private readonly TerminalSensitiveSubmunition submunition;
/// <summary>
/// 获取或设置最大测量高度,单位:米
/// </summary>
/// <remarks>
/// 定义了测高雷达的量程上限
/// 超出此高度的测量可能不准确
/// </remarks>
public double MaxAltitude { get; set; }
/// <summary>
/// 获取或设置测量精度,单位:米
/// </summary>
/// <remarks>
/// 定义了高度测量的误差范围
/// 实际测量值在真实高度±精度范围内
/// </remarks>
public double Accuracy { get; set; }
/// <summary>
/// 初始化毫米波测高雷达的新实例
/// </summary>
/// <param name="submunition">末敏子弹实例</param>
/// <param name="maxAltitude">最大测量高度,单位:米</param>
/// <param name="accuracy">测量精度,单位:米</param>
/// <remarks>
/// 构造过程:
/// - 设置量程参数
/// - 初始化高度记录
/// - 继承基类位置和姿态
/// </remarks>
public MillimeterWaveAltimeter(TerminalSensitiveSubmunition submunition, double maxAltitude, double accuracy)
: base(submunition.Position, submunition.Orientation)
{
MaxAltitude = maxAltitude;
Accuracy = accuracy;
currentAltitude = 0;
this.submunition = submunition;
}
/// <summary>
/// 更新毫米波测高雷达的工作状态
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 获取当前位置高度
/// - 添加测量精度误差
/// - 更新高度记录
/// </remarks>
public override void Update(double deltaTime)
{
// 更新当前高度,考虑测量精度
currentAltitude = submunition.Position.Y + Accuracy * new Random().NextDouble();
}
/// <summary>
/// 处理毫米波干扰事件
/// </summary>
/// <param name="sender">事件源对象</param>
/// <param name="e">事件参数</param>
/// <remarks>
/// 当检测到毫米波干扰时:
/// - 输出警告信息
/// - 可能影响测量精度
/// - 需要采取抗干扰措施
/// </remarks>
public void OnMillimeterWaveJamming(object sender, EventArgs e)
{
Console.WriteLine("毫米波测高雷达受到干扰");
}
/// <summary>
/// 获取毫米波测高雷达的最新数据
/// </summary>
/// <returns>包含高度测量结果的数据对象</returns>
/// <remarks>
/// 返回数据:
/// - 当前高度值
/// - 测量时间戳
/// - 数据可靠性
/// </remarks>
public override SensorData GetSensorData()
{
// 返回毫米波测高雷达的数据
AltimeterSensorData altimeterSensorData = new AltimeterSensorData
{
Altitude = currentAltitude
};
return altimeterSensorData;
}
}
}

View File

@ -0,0 +1,172 @@
using ThreatSource.Missile;
namespace ThreatSource.Sensor
{
/// <summary>
/// 毫米波辐射计类,实现了目标辐射温度测量和目标识别功能
/// </summary>
/// <remarks>
/// 该类提供了毫米波辐射计的核心功能:
/// - 辐射温度测量
/// - 温差阈值检测
/// - 目标识别判断
/// - 实时状态更新
/// 用于末敏子弹的目标探测和识别
/// </remarks>
public class MillimeterWaveRadiometer : Sensor
{
/// <summary>
/// 获取或设置工作波段,单位:毫米
/// </summary>
/// <remarks>
/// 可选波段3mm 或 8mm
/// 影响辐射计的探测性能和大气衰减
/// </remarks>
public double Wavelength { get; set; }
/// <summary>
/// 扫描视场角,单位:度
/// </summary>
/// <remarks>
/// 定义了辐射计的扫描范围
/// 默认值为5度
/// 影响目标探测的空间覆盖
/// </remarks>
private double FieldOfView;
/// <summary>
/// 获取或设置辐射温度差检测阈值,单位:开尔文
/// </summary>
/// <remarks>
/// 辐射计高温物体与低温物体的检测温差
/// 默认值为100K
/// 典型温差值:
/// - 金属目标与草地170~230K
/// - 金属目标与砂石地120~150K
/// 辐射率说明:
/// - 草地辐射率1.0
/// - 砂石地辐射率0.83
/// - 金属辐射率0
/// 坦克辐射温度等于天空背景辐射的反射温度天顶角30度时约为90K
/// </remarks>
public double DetectionTemperatureDifferenceThreshold { get; set; } = 100;
/// <summary>
/// 上次检测的辐射温度,单位:开尔文
/// </summary>
/// <remarks>
/// 用于计算温度差值
/// 与当前测量温度比较判断目标存在
/// </remarks>
private double lastDetectionTemperature;
/// <summary>
/// 毫米波辐射计传感器数据实例
/// </summary>
/// <remarks>
/// 存储辐射计的测量结果
/// 包含温度和目标探测状态
/// </remarks>
private readonly RadiometerSensorData sensorData;
/// <summary>
/// 末敏子弹实例
/// </summary>
/// <remarks>
/// 关联的末敏子弹对象
/// 用于获取位置和姿态信息
/// </remarks>
private readonly TerminalSensitiveSubmunition submunition;
/// <summary>
/// 初始化毫米波辐射计的新实例
/// </summary>
/// <param name="submunition">末敏子弹实例</param>
/// <param name="wavelength">工作波段,单位:毫米</param>
/// <param name="fieldOfView">视场角,单位:度</param>
/// <remarks>
/// 构造过程:
/// - 设置工作参数
/// - 初始化温度记录
/// - 创建传感器数据
/// - 继承基类位置和姿态
/// </remarks>
public MillimeterWaveRadiometer(TerminalSensitiveSubmunition submunition, double wavelength, double fieldOfView)
: base(submunition.Position, submunition.Orientation)
{
Wavelength = wavelength;
FieldOfView = fieldOfView;
lastDetectionTemperature = 0;
sensorData = new RadiometerSensorData();
this.submunition = submunition;
}
/// <summary>
/// 更新毫米波辐射计的工作状态
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 检查激活状态
/// - 测量辐射温度
/// - 计算温度差值
/// - 判断目标存在
/// - 更新历史温度
/// </remarks>
public override void Update(double deltaTime)
{
// 实现毫米波辐射计的更新逻辑
if (IsActive)
{
// 获取当前方向上的辐射温度
double currentDirectionRadiationTemperature = GetCurrentDirectionRadiationTemperature();
// 计算辐射温度差
double temperatureDifference = Math.Abs(currentDirectionRadiationTemperature - lastDetectionTemperature);
// 如果温度差大于检测阈值,则认为检测到目标
if (temperatureDifference >= DetectionTemperatureDifferenceThreshold)
{
sensorData.IsTargetDetected = true;
}
else
{
sensorData.IsTargetDetected = false;
}
// 更新上次检测温度
lastDetectionTemperature = currentDirectionRadiationTemperature;
}
}
/// <summary>
/// 获取当前方向上的辐射温度
/// </summary>
/// <returns>当前方向上的辐射温度,单位:开尔文</returns>
/// <remarks>
/// 测量过程:
/// - 检查目标是否在视场内
/// - 返回对应的辐射温度
/// 目标存在时返回90K天空背景
/// 目标不存在时返回300K地面温度
/// </remarks>
private double GetCurrentDirectionRadiationTemperature()
{
// 获取当前方向上的辐射温度如果检测到目标则返回天空背景辐射的反射温度否则返回300K
return submunition.DetectTarget(FieldOfView) ? 90 : 300;
}
/// <summary>
/// 获取毫米波辐射计的最新数据
/// </summary>
/// <returns>包含探测结果的数据对象</returns>
/// <remarks>
/// 返回数据:
/// - 目标探测状态
/// - 温度测量结果
/// - 时间戳信息
/// </remarks>
public override SensorData GetSensorData()
{
// 返回毫米波辐射计的数据
return sensorData;
}
}
}

View File

@ -0,0 +1,126 @@
namespace ThreatSource.Sensor
{
/// <summary>
/// 传感器数据的抽象基类,定义了所有传感器数据的通用属性
/// </summary>
/// <remarks>
/// 该类作为所有传感器数据类型的基础:
/// - 提供基本的时间戳信息
/// - 统一数据接口规范
/// - 支持数据类型扩展
/// 用于传感器数据的采集和处理
/// </remarks>
public abstract class SensorData
{
/// <summary>
/// 获取或设置数据采集的时间戳
/// </summary>
/// <remarks>
/// 记录传感器数据的采集时间
/// 用于数据时序分析和同步处理
/// </remarks>
public DateTime Timestamp { get; set; }
}
/// <summary>
/// 红外传感器数据类,包含红外探测的具体数据
/// </summary>
/// <remarks>
/// 该类封装了红外传感器的测量结果:
/// - 目标温度信息
/// - 目标探测状态
/// 用于红外目标的探测和跟踪
/// </remarks>
public class InfraredSensorData : SensorData
{
/// <summary>
/// 获取或设置探测到的温度,单位:开尔文
/// </summary>
/// <remarks>
/// 记录目标的红外辐射温度
/// 用于目标特征识别和状态评估
/// </remarks>
public double Temperature { get; set; }
/// <summary>
/// 获取或设置是否检测到目标
/// </summary>
/// <remarks>
/// true表示探测到有效目标
/// false表示未探测到目标
/// 用于目标存在性判断
/// </remarks>
public bool IsTargetDetected { get; set; }
}
/// <summary>
/// 辐射计传感器数据类,包含毫米波辐射探测的具体数据
/// </summary>
/// <remarks>
/// 该类封装了毫米波辐射计的测量结果:
/// - 辐射强度信息
/// - 目标探测状态
/// 用于目标特征识别和态势评估
/// </remarks>
public class RadiometerSensorData : SensorData
{
/// <summary>
/// 获取或设置探测到的辐射强度,单位:瓦特/平方米
/// </summary>
/// <remarks>
/// 记录目标的毫米波辐射强度
/// 用于目标特征分析和识别判断
/// </remarks>
public double RadiationIntensity { get; set; }
/// <summary>
/// 获取或设置是否检测到目标
/// </summary>
/// <remarks>
/// true表示探测到有效目标
/// false表示未探测到目标
/// 用于目标存在性判断
/// </remarks>
public bool IsTargetDetected { get; set; }
}
/// <summary>
/// 测高仪传感器数据类,包含高度测量的具体数据
/// </summary>
/// <remarks>
/// 该类封装了毫米波测高仪的测量结果:
/// - 对地高度信息
/// 用于飞行器高度控制和地形跟随
/// </remarks>
public class AltimeterSensorData : SensorData
{
/// <summary>
/// 获取或设置测量的高度,单位:米
/// </summary>
/// <remarks>
/// 记录当前对地高度
/// 用于高度保持和地形跟随
/// </remarks>
public double Altitude { get; set; }
}
/// <summary>
/// 测距仪传感器数据类,包含距离测量的具体数据
/// </summary>
/// <remarks>
/// 该类封装了激光测距仪的测量结果:
/// - 目标距离信息
/// 用于目标定位和距离测量
/// </remarks>
public class RangefinderSensorData : SensorData
{
/// <summary>
/// 获取或设置测量的距离,单位:米
/// </summary>
/// <remarks>
/// 记录到目标的直线距离
/// 用于目标定位和制导控制
/// </remarks>
public double Distance { get; set; }
}
}

View File

@ -0,0 +1,186 @@
using ThreatSource.Utils;
namespace ThreatSource.Sensor
{
/// <summary>
/// 定义传感器的基本接口,规范了所有传感器的通用功能
/// </summary>
/// <remarks>
/// 该接口提供了传感器的基本功能规范:
/// - 激活和停用控制
/// - 状态更新机制
/// - 数据采集接口
/// 是所有具体传感器实现的基础
/// </remarks>
public interface ISensor
{
/// <summary>
/// 获取或设置传感器是否处于激活状态
/// </summary>
/// <remarks>
/// true表示传感器正在工作
/// false表示传感器处于待机状态
/// 用于控制传感器的工作状态
/// </remarks>
bool IsActive { get; set; }
/// <summary>
/// 激活传感器,使其开始工作
/// </summary>
/// <remarks>
/// 激活过程:
/// - 初始化工作参数
/// - 启动数据采集
/// - 开始状态监控
/// </remarks>
void Activate();
/// <summary>
/// 停用传感器,使其停止工作
/// </summary>
/// <remarks>
/// 停用过程:
/// - 停止数据采集
/// - 清理工作状态
/// - 释放相关资源
/// </remarks>
void Deactivate();
/// <summary>
/// 更新传感器的工作状态
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 采集最新数据
/// - 更新内部状态
/// - 处理异常情况
/// </remarks>
void Update(double deltaTime);
/// <summary>
/// 获取传感器采集的最新数据
/// </summary>
/// <returns>包含传感器测量结果的数据对象</returns>
/// <remarks>
/// 返回数据:
/// - 测量的物理量
/// - 时间戳信息
/// - 状态标志
/// </remarks>
SensorData GetSensorData();
}
/// <summary>
/// 传感器的抽象基类实现了ISensor接口的基本功能
/// </summary>
/// <remarks>
/// 该类提供了传感器的通用实现:
/// - 位置和姿态管理
/// - 激活状态控制
/// - 数据采集框架
/// 是具体传感器类的实现基础
/// </remarks>
public abstract class Sensor : ISensor
{
/// <summary>
/// 获取或设置传感器是否处于激活状态
/// </summary>
/// <remarks>
/// true表示传感器正在工作
/// false表示传感器处于待机状态
/// 控制传感器的工作模式
/// </remarks>
public bool IsActive { get; set; }
/// <summary>
/// 获取或设置传感器的位置
/// </summary>
/// <remarks>
/// 传感器在三维空间中的位置向量
/// 用于空间定位和测量计算
/// </remarks>
protected Vector3D Position { get; set; }
/// <summary>
/// 获取或设置传感器的朝向
/// </summary>
/// <remarks>
/// 传感器在三维空间中的姿态
/// 影响传感器的探测方向和精度
/// </remarks>
protected Orientation Orientation { get; set; }
/// <summary>
/// 初始化传感器的新实例
/// </summary>
/// <param name="position">传感器的初始位置</param>
/// <param name="orientation">传感器的初始朝向</param>
/// <remarks>
/// 构造过程:
/// - 设置初始位置
/// - 设置初始朝向
/// - 初始化工作状态
/// </remarks>
protected Sensor(Vector3D position, Orientation orientation)
{
Position = position;
Orientation = orientation;
IsActive = false;
}
/// <summary>
/// 激活传感器,使其开始工作
/// </summary>
/// <remarks>
/// 激活过程:
/// - 设置激活标志
/// - 准备数据采集
/// - 开始工作循环
/// </remarks>
public virtual void Activate()
{
IsActive = true;
}
/// <summary>
/// 停用传感器,使其停止工作
/// </summary>
/// <remarks>
/// 停用过程:
/// - 清除激活标志
/// - 停止数据采集
/// - 清理工作状态
/// </remarks>
public virtual void Deactivate()
{
IsActive = false;
}
/// <summary>
/// 更新传感器状态(需要在子类中实现)
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔,单位:秒</param>
/// <remarks>
/// 更新要求:
/// - 检查工作状态
/// - 采集最新数据
/// - 更新内部状态
/// - 处理异常情况
/// </remarks>
public abstract void Update(double deltaTime);
/// <summary>
/// 获取传感器数据(需要在子类中实现)
/// </summary>
/// <returns>包含传感器测量结果的数据对象</returns>
/// <remarks>
/// 数据要求:
/// - 包含最新测量结果
/// - 附加时间戳信息
/// - 提供状态标志
/// - 确保数据有效性
/// </remarks>
public abstract SensorData GetSensorData();
}
}

View File

@ -0,0 +1,131 @@
using System;
using System.Collections.Generic;
namespace ThreatSource.Simulation
{
/// <summary>
/// 第三方仿真环境适配器接口
/// </summary>
/// <remarks>
/// 该接口用于与外部仿真环境进行集成,提供实体查询和事件交互功能。
/// 实现此接口可以将威胁源仿真库与其他仿真系统对接。
/// </remarks>
public interface ISimulationAdapter
{
/// <summary>
/// 从外部仿真环境获取实体
/// </summary>
/// <param name="id">实体ID</param>
/// <returns>实体对象如果不存在则返回null</returns>
object? GetEntity(string id);
/// <summary>
/// 发布事件到第三方仿真环境
/// </summary>
/// <typeparam name="T">事件类型</typeparam>
/// <param name="evt">要发布的事件</param>
/// <remarks>
/// 用于将威胁源仿真库中的事件同步到外部仿真环境
/// </remarks>
void PublishToExternalSimulation<T>(T evt);
/// <summary>
/// 从第三方仿真环境接收事件
/// </summary>
/// <typeparam name="T">事件类型</typeparam>
/// <param name="evt">接收到的事件</param>
/// <remarks>
/// 用于接收外部仿真环境的事件并在威胁源仿真库中处理
/// </remarks>
void ReceiveFromExternalSimulation<T>(T evt);
}
/// <summary>
/// 仿真管理器接口,提供仿真系统的核心功能
/// </summary>
/// <remarks>
/// 该接口定义了仿真系统的主要功能,包括:
/// - 事件系统:用于实体间的通信和状态同步
/// - 实体管理:负责实体的注册、注销和查询
/// - 第三方集成:支持与其他仿真环境的对接
/// </remarks>
public interface ISimulationManager
{
#region
/// <summary>
/// 发布事件到仿真系统
/// </summary>
/// <typeparam name="T">事件类型</typeparam>
/// <param name="evt">要发布的事件</param>
void PublishEvent<T>(T evt);
/// <summary>
/// 订阅特定类型的事件
/// </summary>
/// <typeparam name="T">事件类型</typeparam>
/// <param name="handler">事件处理函数</param>
void SubscribeToEvent<T>(Action<T> handler);
/// <summary>
/// 取消订阅特定类型的事件
/// </summary>
/// <typeparam name="T">事件类型</typeparam>
/// <param name="handler">要取消的事件处理函数</param>
void UnsubscribeFromEvent<T>(Action<T> handler);
#endregion
#region
/// <summary>
/// 注册实体到仿真系统
/// </summary>
/// <param name="id">实体ID</param>
/// <param name="entity">实体对象</param>
/// <returns>注册是否成功</returns>
bool RegisterEntity(string id, object entity);
/// <summary>
/// 从仿真系统注销实体
/// </summary>
/// <param name="id">要注销的实体ID</param>
/// <returns>注销是否成功</returns>
bool UnregisterEntity(string id);
/// <summary>
/// 根据ID获取实体
/// </summary>
/// <param name="id">实体ID</param>
/// <returns>实体对象如果不存在则返回null</returns>
object? GetEntityById(string id);
/// <summary>
/// 获取特定类型的所有实体
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <returns>指定类型的实体列表</returns>
IReadOnlyList<T> GetEntitiesByType<T>() where T : class;
/// <summary>
/// 获取仿真系统中的所有实体
/// </summary>
/// <returns>所有实体的列表</returns>
IReadOnlyList<object> GetAllEntities();
#endregion
#region 仿
/// <summary>
/// 设置第三方仿真环境适配器
/// </summary>
/// <param name="adapter">要设置的适配器实例</param>
/// <remarks>
/// 用于配置与外部仿真环境的集成
/// </remarks>
void SetSimulationAdapter(ISimulationAdapter adapter);
/// <summary>
/// 获取当前的仿真环境适配器
/// </summary>
/// <returns>当前配置的适配器实例如果未配置则返回null</returns>
ISimulationAdapter? GetSimulationAdapter();
#endregion
}
}

View File

@ -0,0 +1,603 @@
using ThreatSource.Utils;
namespace ThreatSource.Simulation
{
/// <summary>
/// 激光指示器配置类,用于设置激光半主动导引系统中的激光指示器参数
/// </summary>
/// <remarks>
/// 该类定义了激光指示器的关键参数:
/// - 设备标识
/// - 空间位置
/// - 激光功率
/// - 光束发散角
/// 这些参数影响激光指示器的性能和工作特性
/// </remarks>
public class LaserDesignatorConfig
{
/// <summary>
/// 获取或设置激光指示器的唯一标识符
/// </summary>
/// <remarks>
/// 在仿真系统中必须唯一
/// 用于标识和查找特定的激光指示器
/// </remarks>
public string Id { get; set; }
/// <summary>
/// 获取或设置激光指示器的初始位置
/// </summary>
/// <remarks>
/// 使用三维向量表示空间位置
/// 坐标系右手坐标系X向右Y向上Z向前
/// </remarks>
public Vector3D InitialPosition { get; set; }
/// <summary>
/// 获取或设置激光功率
/// </summary>
/// <remarks>
/// 单位:瓦特
/// 影响激光照射的有效距离和目标反射强度
/// </remarks>
public double LaserPower { get; set; }
/// <summary>
/// 获取或设置激光发散角
/// </summary>
/// <remarks>
/// 单位:弧度
/// 影响激光束的扩散特性和照射面积
/// </remarks>
public double LaserDivergenceAngle { get; set; }
/// <summary>
/// 初始化激光指示器配置的新实例
/// </summary>
/// <remarks>
/// 设置默认值:
/// - ID为空字符串
/// - 初始位置为原点(0,0,0)
/// - 激光功率为0瓦特
/// - 发散角为0弧度
/// </remarks>
public LaserDesignatorConfig()
{
Id = "";
InitialPosition = new Vector3D(0, 0, 0);
LaserPower = 0;
LaserDivergenceAngle = 0;
}
}
/// <summary>
/// 激光波束制导仪配置类,用于设置激光波束制导系统的参数
/// </summary>
/// <remarks>
/// 该类定义了波束制导系统的关键参数:
/// - 设备标识
/// - 发射位置
/// - 激光功率
/// - 控制场尺寸
/// - 最大制导距离
/// 这些参数决定了波束制导系统的性能和工作范围
/// </remarks>
public class LaserBeamRiderConfig
{
/// <summary>
/// 获取或设置激光波束制导仪的唯一标识符
/// </summary>
/// <remarks>
/// 在仿真系统中必须唯一
/// 用于标识和查找特定的波束制导仪
/// </remarks>
public string Id { get; set; }
/// <summary>
/// 获取或设置波束制导仪的初始位置
/// </summary>
/// <remarks>
/// 使用三维向量表示空间位置
/// 坐标系右手坐标系X向右Y向上Z向前
/// </remarks>
public Vector3D InitialPosition { get; set; }
/// <summary>
/// 获取或设置激光功率
/// </summary>
/// <remarks>
/// 单位:瓦特
/// 影响制导波束的有效距离和导引精度
/// </remarks>
public double LaserPower { get; set; }
/// <summary>
/// 获取或设置控制场直径
/// </summary>
/// <remarks>
/// 单位:米
/// 定义了导弹可以接收制导信号的横向范围
/// </remarks>
public double ControlFieldDiameter { get; set; }
/// <summary>
/// 获取或设置最大导引距离
/// </summary>
/// <remarks>
/// 单位:米
/// 定义了波束制导系统的最大有效工作距离
/// </remarks>
public double MaxGuidanceDistance { get; set; }
/// <summary>
/// 初始化激光波束制导仪配置的新实例
/// </summary>
/// <remarks>
/// 设置默认值:
/// - ID为空字符串
/// - 初始位置为原点(0,0,0)
/// - 激光功率为0瓦特
/// - 控制场直径为0米
/// </remarks>
public LaserBeamRiderConfig()
{
Id = "";
InitialPosition = new Vector3D(0, 0, 0);
LaserPower = 0;
ControlFieldDiameter = 0;
}
}
/// <summary>
/// 激光告警器配置类,用于设置激光探测和告警系统的参数
/// </summary>
/// <remarks>
/// 该类定义了激光告警器的关键参数:
/// - 设备标识
/// - 灵敏度阈值
/// - 警报持续时间
/// - 探测波长范围
/// 这些参数决定了告警器的探测能力和响应特性
/// </remarks>
public class LaserWarnerConfig
{
/// <summary>
/// 获取或设置激光告警器的唯一标识符
/// </summary>
/// <remarks>
/// 在仿真系统中必须唯一
/// 用于标识和查找特定的告警器
/// </remarks>
public string Id { get; set; }
/// <summary>
/// 获取或设置告警灵敏度阈值
/// </summary>
/// <remarks>
/// 单位:瓦特/平方米
/// 当接收到的激光功率密度超过此阈值时触发告警
/// </remarks>
public double SensitivityThreshold { get; set; }
/// <summary>
/// 获取或设置警报持续时间
/// </summary>
/// <remarks>
/// 单位:秒
/// 定义了每次告警的持续时间
/// </remarks>
public double AlarmDuration { get; set; }
/// <summary>
/// 获取或设置最小探测波长
/// </summary>
/// <remarks>
/// 单位:纳米
/// 定义了告警器可以探测的最短波长
/// </remarks>
public double WavelengthMin { get; set; }
/// <summary>
/// 获取或设置最大探测波长
/// </summary>
/// <remarks>
/// 单位:纳米
/// 定义了告警器可以探测的最长波长
/// </remarks>
public double WavelengthMax { get; set; }
/// <summary>
/// 初始化激光告警器配置的新实例
/// </summary>
/// <remarks>
/// 设置默认值:
/// - ID为空字符串
/// - 灵敏度阈值为0
/// - 警报持续时间为5秒
/// - 波长范围为0-0纳米
/// </remarks>
public LaserWarnerConfig()
{
Id = "";
SensitivityThreshold = 0;
AlarmDuration = 5.0; // 默认警报持续5秒
WavelengthMin = 0;
WavelengthMax = 0;
}
}
/// <summary>
/// 紫外告警器配置类,用于设置紫外探测和告警系统的参数
/// </summary>
/// <remarks>
/// 该类定义了紫外告警器的关键参数:
/// - 设备标识
/// - 灵敏度阈值
/// - 警报持续时间
/// - 探测波长范围
/// 这些参数决定了告警器对紫外辐射的探测能力
/// </remarks>
public class UltravioletWarnerConfig
{
/// <summary>
/// 获取或设置紫外告警器的唯一标识符
/// </summary>
/// <remarks>
/// 在仿真系统中必须唯一
/// 用于标识和查找特定的告警器
/// </remarks>
public string Id { get; set; }
/// <summary>
/// 获取或设置告警灵敏度阈值
/// </summary>
/// <remarks>
/// 单位:瓦特/平方米
/// 当接收到的紫外辐射强度超过此阈值时触发告警
/// </remarks>
public double SensitivityThreshold { get; set; }
/// <summary>
/// 获取或设置警报持续时间
/// </summary>
/// <remarks>
/// 单位:秒
/// 定义了每次告警的持续时间
/// </remarks>
public double AlarmDuration { get; set; }
/// <summary>
/// 获取或设置最小探测波长
/// </summary>
/// <remarks>
/// 单位:纳米
/// 定义了告警器可以探测的最短紫外波长
/// </remarks>
public double WavelengthMin { get; set; }
/// <summary>
/// 获取或设置最大探测波长
/// </summary>
/// <remarks>
/// 单位:纳米
/// 定义了告警器可以探测的最长紫外波长
/// </remarks>
public double WavelengthMax { get; set; }
/// <summary>
/// 初始化紫外告警器配置的新实例
/// </summary>
/// <remarks>
/// 设置默认值:
/// - ID为空字符串
/// - 灵敏度阈值为0
/// - 警报持续时间为5秒
/// - 波长范围为0-0纳米
/// </remarks>
public UltravioletWarnerConfig()
{
Id = "";
SensitivityThreshold = 0;
AlarmDuration = 5.0; // 默认警报持续5秒
WavelengthMin = 0;
WavelengthMax = 0;
}
}
/// <summary>
/// 红外告警器配置类,用于设置红外探测和告警系统的参数
/// </summary>
/// <remarks>
/// 该类定义了红外告警器的关键参数:
/// - 设备标识
/// - 灵敏度阈值
/// - 警报持续时间
/// - 探测波长范围
/// 这些参数决定了告警器对红外辐射的探测能力
/// </remarks>
public class InfraredWarnerConfig
{
/// <summary>
/// 获取或设置红外告警器的唯一标识符
/// </summary>
/// <remarks>
/// 在仿真系统中必须唯一
/// 用于标识和查找特定的告警器
/// </remarks>
public string Id { get; set; }
/// <summary>
/// 获取或设置告警灵敏度阈值
/// </summary>
/// <remarks>
/// 单位:瓦特/平方米
/// 当接收到的红外辐射强度超过此阈值时触发告警
/// </remarks>
public double SensitivityThreshold { get; set; }
/// <summary>
/// 获取或设置警报持续时间
/// </summary>
/// <remarks>
/// 单位:秒
/// 定义了每次告警的持续时间
/// </remarks>
public double AlarmDuration { get; set; }
/// <summary>
/// 获取或设置最小探测波长
/// </summary>
/// <remarks>
/// 单位:纳米
/// 定义了告警器可以探测的最短红外波长
/// </remarks>
public double WavelengthMin { get; set; }
/// <summary>
/// 获取或设置最大探测波长
/// </summary>
/// <remarks>
/// 单位:纳米
/// 定义了告警器可以探测的最长红外波长
/// </remarks>
public double WavelengthMax { get; set; }
/// <summary>
/// 初始化红外告警器配置的新实例
/// </summary>
/// <remarks>
/// 设置默认值:
/// - ID为空字符串
/// - 灵敏度阈值为0
/// - 警报持续时间为5秒
/// - 波长范围为0-0纳米
/// </remarks>
public InfraredWarnerConfig()
{
Id = "";
SensitivityThreshold = 0;
AlarmDuration = 5.0; // 默认警报持续5秒
WavelengthMin = 0;
WavelengthMax = 0;
}
}
/// <summary>
/// 毫米波告警器配置类,用于设置毫米波探测和告警系统的参数
/// </summary>
/// <remarks>
/// 该类定义了毫米波告警器的关键参数:
/// - 设备标识
/// - 灵敏度阈值
/// - 警报持续时间
/// - 探测波长范围
/// 这些参数决定了告警器对毫米波辐射的探测能力
/// </remarks>
public class MillimeterWaveWarnerConfig
{
/// <summary>
/// 获取或设置毫米波告警器的唯一标识符
/// </summary>
/// <remarks>
/// 在仿真系统中必须唯一
/// 用于标识和查找特定的告警器
/// </remarks>
public string Id { get; set; }
/// <summary>
/// 获取或设置告警灵敏度阈值
/// </summary>
/// <remarks>
/// 单位:瓦特/平方米
/// 当接收到的毫米波辐射强度超过此阈值时触发告警
/// </remarks>
public double SensitivityThreshold { get; set; }
/// <summary>
/// 获取或设置警报持续时间
/// </summary>
/// <remarks>
/// 单位:秒
/// 定义了每次告警的持续时间
/// </remarks>
public double AlarmDuration { get; set; }
/// <summary>
/// 获取或设置最小探测波长
/// </summary>
/// <remarks>
/// 单位:纳米
/// 定义了告警器可以探测的最短毫米波波长
/// </remarks>
public double WavelengthMin { get; set; }
/// <summary>
/// 获取或设置最大探测波长
/// </summary>
/// <remarks>
/// 单位:纳米
/// 定义了告警器可以探测的最长毫米波波长
/// </remarks>
public double WavelengthMax { get; set; }
/// <summary>
/// 初始化毫米波告警器配置的新实例
/// </summary>
/// <remarks>
/// 设置默认值:
/// - ID为空字符串
/// - 灵敏度阈值为0
/// - 警报持续时间为5秒
/// - 波长范围为0-0纳米
/// </remarks>
public MillimeterWaveWarnerConfig()
{
Id = "";
SensitivityThreshold = 0;
AlarmDuration = 5.0; // 默认警报持续5秒
WavelengthMin = 0;
WavelengthMax = 0;
}
}
/// <summary>
/// 激光干扰器配置类
/// </summary>
public class LaserJammerConfig
{
/// <summary>
/// 激光干扰器ID
/// </summary>
public string Id { get; set; }
/// <summary>
/// 最大干扰冷却时间(秒)
/// </summary>
public double MaxJammingCooldown { get; set; }
/// <summary>
/// 最大干扰功率(瓦特)
/// </summary>
public double MaxJammingPower { get; set; }
/// <summary>
/// 初始干扰功率(瓦特)
/// </summary>
public double InitialJammingPower { get; set; }
/// <summary>
/// 功率增加速率(瓦特/秒)
/// </summary>
public double PowerIncreaseRate { get; set; }
/// <summary>
/// 构造函数,设置默认值
/// </summary>
public LaserJammerConfig()
{
Id = "";
MaxJammingCooldown = 5.0;
MaxJammingPower = 10000.0;
InitialJammingPower = 4000.0;
PowerIncreaseRate = 2000.0; // 每秒增加的功率
}
}
/// <summary>
/// 红外测角仪配置类
/// </summary>
public class InfraredTrackerConfig
{
/// <summary>
/// 红外测角仪ID
/// </summary>
public string Id { get; set; }
/// <summary>
/// 初始位置
/// </summary>
public Vector3D InitialPosition { get; set; }
/// <summary>
/// 初始朝向
/// </summary>
public Orientation InitialOrientation { get; set; }
/// <summary>
/// 最大跟踪距离(米)
/// </summary>
public double MaxTrackingRange { get; set; }
/// <summary>
/// 视场角(弧度)
/// </summary>
public double FieldOfView { get; set; }
/// <summary>
/// 角度测量精度(弧度)
/// </summary>
public double AngleMeasurementAccuracy { get; set; }
/// <summary>
/// 更新频率(赫兹)
/// </summary>
public double UpdateFrequency { get; set; }
/// <summary>
/// 构造函数,设置默认值
/// </summary>
public InfraredTrackerConfig()
{
Id = "";
InitialPosition = new Vector3D(0, 0, 0);
InitialOrientation = new Orientation(0, 0, 0);
MaxTrackingRange = 10000; // 10公里
FieldOfView = Math.PI / 3; // 60度
AngleMeasurementAccuracy = 0.001; // 0.001弧度 (约0.057度)
UpdateFrequency = 10; // 10赫兹
}
}
/// <summary>
/// 毫米波干扰器配置类
/// </summary>
public class MillimeterWaveJammerConfig
{
/// <summary>
/// 干扰器ID
/// </summary>
public string Id { get; set; }
/// <summary>
/// 最大干扰功率(瓦特)
/// </summary>
public double MaxJammingPower { get; set; }
/// <summary>
/// 初始干扰功率(瓦特)
/// </summary>
public double InitialJammingPower { get; set; }
/// <summary>
/// 功率增长率(瓦特/秒)
/// </summary>
public double PowerIncreaseRate { get; set; }
/// <summary>
/// 最大冷却时间(秒)
/// </summary>
public double MaxJammingCooldown { get; set; }
/// <summary>
/// 构造函数
/// </summary>
public MillimeterWaveJammerConfig()
{
Id = "";
MaxJammingPower = 1000;
InitialJammingPower = 400;
PowerIncreaseRate = 200;
MaxJammingCooldown = 5;
}
}
}

View File

@ -0,0 +1,185 @@
using System;
using System.Reflection.Metadata.Ecma335;
using ThreatSource.Utils;
namespace ThreatSource.Simulation
{
/// <summary>
/// 仿真元素的抽象基类,所有仿真中的实体都继承自此类
/// </summary>
/// <remarks>
/// 该类提供了仿真实体的基本功能:
/// - 位置和运动状态管理
/// - 生命周期管理(激活/停用)
/// - 事件发布机制
/// - 状态更新机制
/// 所有具体的仿真实体(如导弹、目标等)都应继承此类并实现其抽象方法。
/// </remarks>
public abstract class SimulationElement
{
/// <summary>
/// 获取或设置仿真元素的唯一标识符
/// </summary>
/// <remarks>
/// ID在仿真系统中必须唯一用于标识和查找实体
/// </remarks>
public virtual string Id { get; set; }
/// <summary>
/// 获取或设置仿真元素的当前位置
/// </summary>
/// <remarks>
/// 使用三维向量表示实体在空间中的位置
/// 坐标系右手坐标系X向右Y向上Z向前
/// </remarks>
public virtual Vector3D Position { get; set; }
/// <summary>
/// 获取或设置仿真元素的当前速度大小
/// </summary>
/// <remarks>
/// 单位:米/秒
/// 此属性仅表示速度的标量值方向信息需要结合Velocity属性
/// </remarks>
public virtual double Speed { get; set; }
/// <summary>
/// 获取或设置仿真元素的当前速度向量
/// </summary>
/// <remarks>
/// 单位:米/秒
/// 包含速度的大小和方向信息
/// 向量的模等于Speed属性值
/// </remarks>
public virtual Vector3D Velocity { get; set; }
/// <summary>
/// 获取或设置仿真元素的当前朝向
/// </summary>
/// <remarks>
/// 使用欧拉角表示实体的朝向
/// 包含偏航角、俯仰角和滚转角
/// </remarks>
public virtual Orientation Orientation { get; set; }
/// <summary>
/// 获取仿真元素是否处于活动状态
/// </summary>
/// <remarks>
/// true表示实体当前处于活动状态可以参与仿真
/// false表示实体已停用不再参与仿真计算
/// </remarks>
public virtual bool IsActive { get; protected set; }
/// <summary>
/// 获取或设置仿真管理器的引用
/// </summary>
/// <remarks>
/// 用于访问仿真系统的核心功能,如事件发布、实体查询等
/// 在构造函数中初始化,整个生命周期内保持不变
/// </remarks>
protected ISimulationManager SimulationManager { get; set; }
/// <summary>
/// 初始化仿真元素的新实例
/// </summary>
/// <param name="id">仿真元素的唯一标识符</param>
/// <param name="position">初始位置坐标</param>
/// <param name="orientation">初始朝向角度</param>
/// <param name="speed">初始速度大小,单位:米/秒</param>
/// <param name="simulationManager">仿真管理器实例</param>
/// <remarks>
/// 构造函数设置实体的初始状态:
/// - 根据ID、位置、朝向和速度初始化实体
/// - 计算初始速度向量
/// - 设置初始状态为未激活
/// </remarks>
protected SimulationElement(string id, Vector3D position, Orientation orientation, double speed, ISimulationManager simulationManager)
{
Id = id;
Position = position;
Orientation = orientation;
Speed = speed;
Velocity = orientation.ToVector() * speed;
this.SimulationManager = simulationManager;
IsActive = false;
}
/// <summary>
/// 更新仿真元素的状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 抽象方法,需要在派生类中实现具体的更新逻辑:
/// - 更新位置和朝向
/// - 计算新的速度和加速度
/// - 处理碰撞和其他物理效果
/// - 触发相关事件
/// </remarks>
public abstract void Update(double deltaTime);
/// <summary>
/// 获取仿真元素的状态信息
/// </summary>
/// <returns>包含实体当前状态的字符串描述</returns>
/// <remarks>
/// 返回的字符串包含:
/// - 实体类型
/// - 实体ID
/// - 当前位置
/// - 当前朝向
/// - 活动状态
/// </remarks>
public virtual string GetStatus()
{
return $"{GetType().Name} {Id} at {Position}, Orientation: {Orientation}, Active: {IsActive}";
}
/// <summary>
/// 发布仿真事件到事件系统
/// </summary>
/// <param name="evt">要发布的事件实例</param>
/// <remarks>
/// 在发布事件前会:
/// - 设置事件的发送者ID
/// - 添加时间戳
/// - 通过仿真管理器发布到事件系统
/// </remarks>
protected void PublishEvent(SimulationEvent evt)
{
evt.SenderId = Id;
evt.Timestamp = DateTime.UtcNow.Ticks;
SimulationManager.PublishEvent(evt);
}
/// <summary>
/// 激活仿真元素,使其参与仿真
/// </summary>
/// <remarks>
/// 激活操作会:
/// - 将IsActive设置为true
/// - 发布实体激活事件
/// - 允许实体参与仿真计算
/// </remarks>
public virtual void Activate()
{
IsActive = true;
PublishEvent(new EntityActivatedEvent { ActivatedEntityId = Id });
}
/// <summary>
/// 停用仿真元素,将其从仿真中移除
/// </summary>
/// <remarks>
/// 停用操作会:
/// - 将IsActive设置为false
/// - 发布实体停用事件
/// - 停止实体参与仿真计算
/// </remarks>
public virtual void Deactivate()
{
IsActive = false;
PublishEvent(new EntityDeactivatedEvent { DeactivatedEntityId = Id });
}
}
}

View File

@ -0,0 +1,600 @@
using ThreatSource.Utils;
namespace ThreatSource.Simulation
{
/// <summary>
/// 仿真事件的基类,定义所有仿真事件的共同属性
/// </summary>
/// <remarks>
/// 所有仿真事件都继承自此类,提供:
/// - 事件发送者标识
/// - 事件发生时间戳
/// 用于在仿真系统中追踪和处理各类事件
/// </remarks>
public class SimulationEvent
{
/// <summary>
/// 获取或设置事件发送者的ID
/// </summary>
/// <remarks>
/// 用于标识事件的来源实体
/// 可以为null表示系统事件
/// </remarks>
public string? SenderId { get; set; }
/// <summary>
/// 获取或设置事件发生的时间戳
/// </summary>
/// <remarks>
/// 使用UTC时间的Ticks值
/// 用于事件的时序管理和同步
/// </remarks>
public double Timestamp { get; set; }
}
/// <summary>
/// 导弹发射事件,表示导弹被发射的状态变化
/// </summary>
/// <remarks>
/// 在导弹发射时触发,包含目标信息
/// 用于通知其他实体和系统导弹已发射
/// </remarks>
public class MissileFireEvent : SimulationEvent
{
/// <summary>
/// 获取或设置目标实体的ID
/// </summary>
/// <remarks>
/// 标识导弹的预定目标
/// 可以为null表示无预定目标
/// </remarks>
public string? TargetId { get; set; }
}
/// <summary>
/// 激光照射开始事件,表示激光定位器开始照射目标
/// </summary>
/// <remarks>
/// 用于激光半主动导引系统
/// 触发时机:激光定位器开始照射目标时
/// </remarks>
public class LaserIlluminationStartEvent : SimulationEvent
{
/// <summary>
/// 获取或设置激光定位器的ID
/// </summary>
/// <remarks>
/// 标识发出激光的定位器设备
/// </remarks>
public string? LaserDesignatorId { get; set; }
/// <summary>
/// 获取或设置被照射目标的ID
/// </summary>
/// <remarks>
/// 标识被激光照射的目标实体
/// </remarks>
public string? TargetId { get; set; }
}
/// <summary>
/// 激光照射更新事件,表示激光照射状态的更新
/// </summary>
/// <remarks>
/// 用于实时更新激光照射的状态
/// 在照射过程中周期性触发
/// </remarks>
public class LaserIlluminationUpdateEvent : SimulationEvent
{
/// <summary>
/// 获取或设置激光定位器的ID
/// </summary>
/// <remarks>
/// 标识正在照射的定位器设备
/// </remarks>
public string? LaserDesignatorId { get; set; }
/// <summary>
/// 获取或设置被照射目标的ID
/// </summary>
/// <remarks>
/// 标识正在被照射的目标实体
/// </remarks>
public string? TargetId { get; set; }
}
/// <summary>
/// 激光照射停止事件,表示激光定位器停止照射目标
/// </summary>
/// <remarks>
/// 用于通知系统激光照射已结束
/// 触发时机:激光定位器停止照射或照射中断时
/// </remarks>
public class LaserIlluminationStopEvent : SimulationEvent
{
/// <summary>
/// 获取或设置激光定位器的ID
/// </summary>
public string? LaserDesignatorId { get; set; }
/// <summary>
/// 获取或设置被照射目标的ID
/// </summary>
public string? TargetId { get; set; }
}
/// <summary>
/// 激光干扰事件,表示对激光制导系统的干扰
/// </summary>
/// <remarks>
/// 用于模拟激光干扰效果
/// 包含干扰功率信息
/// </remarks>
public class LaserJammingEvent : SimulationEvent
{
/// <summary>
/// 获取或设置被干扰目标的ID
/// </summary>
/// <remarks>
/// 标识受到激光干扰的目标实体
/// </remarks>
public string? TargetId { get; set; }
/// <summary>
/// 获取或设置干扰功率值
/// </summary>
/// <remarks>
/// 单位:瓦特
/// 表示干扰源的输出功率
/// </remarks>
public double JammingPower { get; set; }
}
/// <summary>
/// 实体销毁事件,表示仿真实体被销毁
/// </summary>
/// <remarks>
/// 用于通知系统某个实体已被销毁
/// 触发时机:实体被摧毁或移除时
/// </remarks>
public class EntityDestroyedEvent : SimulationEvent
{
/// <summary>
/// 获取或设置被销毁实体的ID
/// </summary>
/// <remarks>
/// 标识已被销毁的实体
/// </remarks>
public string? DestroyedEntityId { get; set; }
}
/// <summary>
/// 激光告警器警报事件,表示检测到激光照射
/// </summary>
/// <remarks>
/// 用于模拟激光告警器的响应
/// 触发时机:检测到激光照射时
/// </remarks>
public class LaserWarnerAlarmEvent : SimulationEvent
{
/// <summary>
/// 获取或设置被照射目标的ID
/// </summary>
/// <remarks>
/// 标识检测到激光照射的实体
/// </remarks>
public string? TargetId { get; set; }
}
/// <summary>
/// 激光告警器警报停止事件,表示激光照射结束
/// </summary>
/// <remarks>
/// 用于模拟激光告警器停止报警
/// 触发时机:激光照射结束或低于警戒阈值时
/// </remarks>
public class LaserWarnerAlarmStopEvent : SimulationEvent
{
/// <summary>
/// 获取或设置目标的ID
/// </summary>
/// <remarks>
/// 标识激光照射已结束的实体
/// </remarks>
public string? TargetId { get; set; }
}
/// <summary>
/// 实体激活事件,表示仿真实体被激活
/// </summary>
/// <remarks>
/// 用于通知系统某个实体已进入活动状态
/// 触发时机:实体被创建或重新激活时
/// </remarks>
public class EntityActivatedEvent : SimulationEvent
{
/// <summary>
/// 获取或设置被激活实体的ID
/// </summary>
/// <remarks>
/// 标识已被激活的实体
/// </remarks>
public string? ActivatedEntityId { get; set; }
}
/// <summary>
/// 实体停用事件,表示仿真实体被停用
/// </summary>
/// <remarks>
/// 用于通知系统某个实体已停止活动
/// 触发时机:实体被停用或暂时移除时
/// </remarks>
public class EntityDeactivatedEvent : SimulationEvent
{
/// <summary>
/// 获取或设置被停用实体的ID
/// </summary>
/// <remarks>
/// 标识已被停用的实体
/// </remarks>
public string? DeactivatedEntityId { get; set; }
}
/// <summary>
/// 激光波束开始事件,表示激光波束制导开始
/// </summary>
/// <remarks>
/// 用于激光波束制导系统
/// 触发时机:开始发射制导激光波束时
/// </remarks>
public class LaserBeamStartEvent : SimulationEvent
{
/// <summary>
/// 获取或设置激光波束制导器的ID
/// </summary>
public string? LaserBeamRiderId { get; set; }
}
/// <summary>
/// 激光波束更新事件,表示激光波束位置更新
/// </summary>
/// <remarks>
/// 用于实时更新激光波束的位置和方向
/// 在制导过程中周期性触发
/// </remarks>
public class LaserBeamUpdateEvent : SimulationEvent
{
/// <summary>
/// 获取或设置激光波束制导器的ID
/// </summary>
public string? LaserBeamRiderId { get; set; }
}
/// <summary>
/// 激光波束停止事件,表示激光波束制导结束
/// </summary>
/// <remarks>
/// 用于通知系统激光波束制导已结束
/// 触发时机:停止发射制导激光波束时
/// </remarks>
public class LaserBeamStopEvent : SimulationEvent
{
/// <summary>
/// 获取或设置激光波束制导器的ID
/// </summary>
public string? LaserBeamRiderId { get; set; }
}
/// <summary>
/// 红外指令制导事件,表示发送制导指令
/// </summary>
/// <remarks>
/// 用于红外指令制导系统
/// 包含目标和导弹的视线向量信息
/// </remarks>
public class InfraredGuidanceCommandEvent : SimulationEvent
{
/// <summary>
/// 获取或设置目标导弹的ID
/// </summary>
/// <remarks>
/// 标识接收制导指令的导弹
/// </remarks>
public string? TargetMissileId { get; set; }
/// <summary>
/// 获取或设置跟踪器到目标的视线向量
/// </summary>
/// <remarks>
/// 表示从跟踪器到目标的方向
/// 单位:米
/// </remarks>
public Vector3D TrackerToTargetVector { get; set; } = Vector3D.Zero;
/// <summary>
/// 获取或设置跟踪器到导弹的视线向量
/// </summary>
/// <remarks>
/// 表示从跟踪器到导弹的方向
/// 单位:米
/// </remarks>
public Vector3D TrackerToMissileVector { get; set; } = Vector3D.Zero;
}
/// <summary>
/// 红外指令制导导弹点亮红外热源事件
/// </summary>
/// <remarks>
/// 用于模拟导弹尾部红外热源的激活
/// 触发时机:导弹发动机点火时
/// </remarks>
public class InfraredGuidanceMissileLightEvent : SimulationEvent
{
/// <summary>
/// 获取或设置红外热源辐射功率
/// </summary>
/// <remarks>
/// 单位:瓦特
/// 表示导弹尾焰的红外辐射强度
/// </remarks>
public double RadiationPower { get; set; }
}
/// <summary>
/// 红外指令制导导弹熄灭红外热源事件
/// </summary>
/// <remarks>
/// 用于模拟导弹尾部红外热源的关闭
/// 触发时机:导弹发动机关闭时
/// </remarks>
public class InfraredGuidanceMissileLightOffEvent : SimulationEvent
{
}
/// <summary>
/// 毫米波干扰事件,表示对毫米波雷达的干扰
/// </summary>
/// <remarks>
/// 用于模拟对毫米波制导系统的干扰
/// 包含干扰功率信息
/// </remarks>
public class MillimeterWaveJammingEvent : SimulationEvent
{
/// <summary>
/// 获取或设置被干扰目标的ID
/// </summary>
/// <remarks>
/// 标识受到毫米波干扰的目标实体
/// </remarks>
public string? TargetId { get; set; }
/// <summary>
/// 获取或设置干扰功率值
/// </summary>
/// <remarks>
/// 单位:瓦特
/// 表示毫米波干扰源的输出功率
/// </remarks>
public double JammingPower { get; set; }
}
/// <summary>
/// 坦克辐射事件,表示坦克的多波段辐射特性
/// </summary>
/// <remarks>
/// 用于模拟坦克在不同波段的辐射特征
/// 包含激光、毫米波和红外波段的信息
/// </remarks>
public class TankRadiationEvent : SimulationEvent
{
/// <summary>
/// 获取或设置激光漫反射强度
/// </summary>
/// <remarks>
/// 单位:相对单位
/// 表示坦克表面对激光的反射能力
/// </remarks>
public double LaserReflectionIntensity { get; set; }
/// <summary>
/// 获取或设置毫米波反射强度
/// </summary>
/// <remarks>
/// 单位:相对单位
/// 表示坦克对毫米波雷达的反射特性
/// </remarks>
public double MillimeterWaveReflectionIntensity { get; set; }
/// <summary>
/// 获取或设置毫米波辐射温度
/// </summary>
/// <remarks>
/// 单位:开尔文
/// 表示坦克在毫米波波段的辐射温度
/// </remarks>
public double MillimeterWaveRadiationTemperature { get; set; }
/// <summary>
/// 获取或设置红外辐射强度
/// </summary>
/// <remarks>
/// 单位:瓦特/平方米
/// 表示坦克的红外辐射强度
/// </remarks>
public double InfraredRadiationIntensity { get; set; }
}
/// <summary>
/// 目标被击中事件
/// </summary>
public class TargetHitEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
/// <summary>
/// 导弹ID
/// </summary>
public string? MissileId { get; set; }
}
/// <summary>
/// 目标被摧毁事件
/// </summary>
public class TargetDestroyedEvent : SimulationEvent
{
public string? TargetId { get; set; }
}
/// <summary>
/// 红外探测事件
/// </summary>
public class InfraredDetectionEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
/// <summary>
/// 红外辐射强度
/// </summary>
public double Intensity { get; set; }
}
/// <summary>
/// 红外告警器警报事件
/// </summary>
public class InfraredWarnerAlarmEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
}
/// <summary>
/// 红外告警器警报停止事件
/// </summary>
public class InfraredWarnerAlarmStopEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
}
/// <summary>
/// 紫外探测事件
/// </summary>
public class UltravioletDetectionEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
/// <summary>
/// 紫外辐射强度
/// </summary>
public double Intensity { get; set; }
}
/// <summary>
/// 紫外告警器警报事件
/// </summary>
public class UltravioletWarnerAlarmEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
}
/// <summary>
/// 紫外告警器警报停止事件
/// </summary>
public class UltravioletWarnerAlarmStopEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
}
/// <summary>
/// 毫米波探测事件
/// </summary>
public class MillimeterWaveDetectionEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
/// <summary>
/// 毫米波辐射强度
/// </summary>
public double Intensity { get; set; }
/// <summary>
/// 毫米波频率(GHz)
/// </summary>
public double Frequency { get; set; }
}
/// <summary>
/// 毫米波告警器警报事件
/// </summary>
public class MillimeterWaveWarnerAlarmEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
/// <summary>
/// 探测到的频率(GHz)
/// </summary>
public double DetectedFrequency { get; set; }
}
/// <summary>
/// 毫米波告警器警报停止事件
/// </summary>
public class MillimeterWaveWarnerAlarmStopEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
}
/// <summary>
/// 红外干扰事件
/// </summary>
public class InfraredJammingEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
/// <summary>
/// 干扰功率(瓦特)
/// </summary>
public double JammingPower { get; set; }
/// <summary>
/// 最小波长(微米)
/// </summary>
public double WavelengthMin { get; set; }
/// <summary>
/// 最大波长(微米)
/// </summary>
public double WavelengthMax { get; set; }
}
}

View File

@ -0,0 +1,248 @@
using System;
using System.Collections.Generic;
namespace ThreatSource.Simulation
{
/// <summary>
/// 仿真管理器的默认实现,提供仿真系统的核心功能
/// </summary>
/// <remarks>
/// 该类实现了ISimulationManager接口提供
/// - 事件系统:支持发布/订阅模式的事件处理
/// - 实体管理:实体的注册、注销和查询
/// - 第三方集成:支持与外部仿真环境的对接
///
/// 线程安全说明:
/// - 实体管理相关操作使用锁机制确保线程安全
/// - 事件系统的操作不保证线程安全,应在单线程环境中使用
/// </remarks>
public class SimulationManager : ISimulationManager
{
/// <summary>
/// 事件处理器集合,按事件类型分类存储
/// </summary>
private readonly Dictionary<Type, List<Delegate>> eventHandlers = new();
/// <summary>
/// 实体集合使用ID作为键存储所有注册的实体
/// </summary>
private readonly Dictionary<string, object> entities = new();
/// <summary>
/// 用于实体管理操作的同步锁对象
/// </summary>
private readonly object _lock = new();
/// <summary>
/// 第三方仿真环境适配器实例
/// </summary>
private ISimulationAdapter? _simulationAdapter;
#region
/// <summary>
/// 发布事件到仿真系统
/// </summary>
/// <typeparam name="T">事件类型</typeparam>
/// <param name="evt">要发布的事件实例</param>
/// <remarks>
/// 发布过程:
/// 1. 查找并调用所有注册的事件处理器
/// 2. 如果配置了外部仿真适配器,同时发布到外部系统
/// </remarks>
public void PublishEvent<T>(T evt)
{
if (eventHandlers.TryGetValue(typeof(T), out var handlers))
{
foreach (var handler in handlers)
{
((Action<T>)handler)?.Invoke(evt);
}
}
_simulationAdapter?.PublishToExternalSimulation(evt);
}
/// <summary>
/// 订阅特定类型的事件
/// </summary>
/// <typeparam name="T">事件类型</typeparam>
/// <param name="handler">事件处理函数</param>
/// <remarks>
/// 如果是首次订阅该类型事件,会创建新的处理器列表
/// 同一个处理器可以多次订阅,会被多次调用
/// </remarks>
public void SubscribeToEvent<T>(Action<T> handler)
{
if (!eventHandlers.ContainsKey(typeof(T)))
{
eventHandlers[typeof(T)] = new List<Delegate>();
}
eventHandlers[typeof(T)].Add(handler);
}
/// <summary>
/// 取消订阅特定类型的事件
/// </summary>
/// <typeparam name="T">事件类型</typeparam>
/// <param name="handler">要取消的事件处理函数</param>
/// <remarks>
/// 如果取消订阅后该类型没有其他处理器,会删除整个处理器列表
/// 如果处理器不存在,操作会被忽略
/// </remarks>
public void UnsubscribeFromEvent<T>(Action<T> handler)
{
if (eventHandlers.TryGetValue(typeof(T), out var handlers))
{
handlers.Remove(handler);
if (handlers.Count == 0)
{
eventHandlers.Remove(typeof(T));
}
}
}
#endregion
#region
/// <summary>
/// 注册实体到仿真系统
/// </summary>
/// <param name="id">实体ID</param>
/// <param name="entity">实体对象</param>
/// <returns>注册是否成功</returns>
/// <remarks>
/// 注册失败的情况:
/// - ID为空或实体为null
/// - ID已被其他实体使用
///
/// 线程安全:使用锁保护注册操作
/// </remarks>
public bool RegisterEntity(string id, object entity)
{
if (string.IsNullOrEmpty(id) || entity == null)
return false;
lock (_lock)
{
if (entities.ContainsKey(id))
return false;
entities[id] = entity;
return true;
}
}
/// <summary>
/// 从仿真系统注销实体
/// </summary>
/// <param name="id">要注销的实体ID</param>
/// <returns>注销是否成功</returns>
/// <remarks>
/// 如果实体不存在返回false
/// 线程安全:使用锁保护注销操作
/// </remarks>
public bool UnregisterEntity(string id)
{
lock (_lock)
{
return entities.Remove(id);
}
}
/// <summary>
/// 根据ID获取实体
/// </summary>
/// <param name="id">实体ID</param>
/// <returns>实体对象如果不存在则返回null</returns>
/// <remarks>
/// 查找顺序:
/// 1. 在本地实体集合中查找
/// 2. 如果未找到且配置了外部适配器,尝试从外部系统获取
///
/// 线程安全:使用锁保护查询操作
/// </remarks>
public object? GetEntityById(string id)
{
lock (_lock)
{
if (entities.TryGetValue(id, out var entity))
{
return entity;
}
return _simulationAdapter?.GetEntity(id);
}
}
/// <summary>
/// 获取特定类型的所有实体
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <returns>指定类型的实体列表</returns>
/// <remarks>
/// 只返回本地注册的实体,不包括外部系统的实体
/// 返回的列表是原始集合的副本,可以安全地遍历
///
/// 线程安全:使用锁保护查询操作
/// </remarks>
public IReadOnlyList<T> GetEntitiesByType<T>() where T : class
{
lock (_lock)
{
var result = new List<T>();
foreach (var entity in entities.Values)
{
if (entity is T typedEntity)
{
result.Add(typedEntity);
}
}
return result;
}
}
/// <summary>
/// 获取仿真系统中的所有实体
/// </summary>
/// <returns>所有实体的列表</returns>
/// <remarks>
/// 只返回本地注册的实体,不包括外部系统的实体
/// 返回的列表是原始集合的副本,可以安全地遍历
///
/// 线程安全:使用锁保护查询操作
/// </remarks>
public IReadOnlyList<object> GetAllEntities()
{
lock (_lock)
{
return new List<object>(entities.Values);
}
}
#endregion
#region 仿
/// <summary>
/// 设置第三方仿真环境适配器
/// </summary>
/// <param name="adapter">要设置的适配器实例</param>
/// <exception cref="ArgumentNullException">适配器参数为null时抛出</exception>
/// <remarks>
/// 设置适配器后,仿真系统将:
/// - 在发布事件时同步到外部系统
/// - 在查询实体时同时查询外部系统
/// </remarks>
public void SetSimulationAdapter(ISimulationAdapter adapter)
{
_simulationAdapter = adapter ?? throw new ArgumentNullException(nameof(adapter));
}
/// <summary>
/// 获取当前的仿真环境适配器
/// </summary>
/// <returns>当前配置的适配器实例如果未配置则返回null</returns>
public ISimulationAdapter? GetSimulationAdapter()
{
return _simulationAdapter;
}
#endregion
}
}

View File

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using ThreatSource.Simulation;
namespace ThreatSource.Simulation.Testing
{
/// <summary>
/// 用于测试的仿真环境适配器
/// </summary>
public class TestSimulationAdapter : ISimulationAdapter
{
private readonly Dictionary<string, object> _testEntities = new();
private readonly List<object> _receivedEvents = new();
private readonly List<object> _publishedEvents = new();
private ISimulationManager? _simulationManager;
public TestSimulationAdapter(ISimulationManager simulationManager)
{
_simulationManager = simulationManager;
}
public object? GetEntity(string id)
{
return _testEntities.TryGetValue(id, out var entity) ? entity : null;
}
public void PublishToExternalSimulation<T>(T evt)
{
ArgumentNullException.ThrowIfNull(evt);
_publishedEvents.Add(evt);
}
public void ReceiveFromExternalSimulation<T>(T evt)
{
ArgumentNullException.ThrowIfNull(evt);
_receivedEvents.Add(evt);
_simulationManager?.PublishEvent(evt);
}
// 测试辅助方法
public void AddTestEntity(string id, object entity)
{
_testEntities[id] = entity;
}
public void ClearTestEntities()
{
_testEntities.Clear();
}
public IReadOnlyList<object> GetPublishedEvents()
{
return _publishedEvents;
}
public IReadOnlyList<object> GetReceivedEvents()
{
return _receivedEvents;
}
public void ClearEvents()
{
_publishedEvents.Clear();
_receivedEvents.Clear();
}
}
}

View File

@ -0,0 +1,46 @@
using ThreatSource.Utils;
namespace ThreatSource.Target
{
/// <summary>
/// 定义目标对象的基本接口,提供目标的基本特征和属性
/// </summary>
/// <remarks>
/// 该接口定义了目标的关键特征:
/// - 目标类型标识
/// - 雷达散射截面积
/// - 红外辐射特征
/// 用于在仿真系统中表示和识别不同类型的目标
/// </remarks>
public interface ITarget
{
/// <summary>
/// 获取目标的类型标识
/// </summary>
/// <remarks>
/// 用于区分不同种类的目标,如坦克、装甲车等
/// 在仿真系统中用于目标识别和分类
/// </remarks>
string Type { get; }
/// <summary>
/// 获取目标的雷达散射截面积
/// </summary>
/// <remarks>
/// 单位:平方米
/// 表示目标对雷达波的反射能力
/// 影响目标在雷达系统中的探测距离和识别概率
/// </remarks>
double RadarCrossSection { get; }
/// <summary>
/// 获取目标的红外辐射强度
/// </summary>
/// <remarks>
/// 单位:瓦特/平方米
/// 表示目标的热辐射特征
/// 影响红外制导系统的探测和跟踪能力
/// </remarks>
double InfraredRadiationIntensity { get; }
}
}

View File

@ -0,0 +1,106 @@
using ThreatSource.Simulation;
using ThreatSource.Utils;
namespace ThreatSource.Target
{
/// <summary>
/// 坦克类,实现了目标接口的具体坦克目标
/// </summary>
/// <remarks>
/// 该类提供了坦克目标的完整实现:
/// - 继承自SimulationElement具备基本的仿真功能
/// - 实现ITarget接口提供目标特征
/// - 包含生命值系统,可以响应伤害
/// - 支持位置更新和状态同步
/// </remarks>
public class Tank : SimulationElement, ITarget
{
/// <summary>
/// 获取坦克的类型标识
/// </summary>
/// <remarks>
/// 固定返回"Tank",用于标识这是一个坦克目标
/// </remarks>
public string Type => "Tank";
/// <summary>
/// 获取坦克的雷达散射截面积
/// </summary>
/// <remarks>
/// 单位:平方米
/// 固定值10.0,表示标准坦克的雷达反射特性
/// </remarks>
public double RadarCrossSection => 10.0;
/// <summary>
/// 获取坦克的红外辐射强度
/// </summary>
/// <remarks>
/// 单位:瓦特/平方米
/// 固定值100.0,表示坦克发动机和装甲的热辐射特性
/// </remarks>
public double InfraredRadiationIntensity => 100.0;
/// <summary>
/// 获取或设置坦克的当前生命值
/// </summary>
/// <remarks>
/// 范围0-100
/// 初始值为100
/// 当生命值降至0或以下时坦克被销毁
/// </remarks>
public double Health { get; set; } = 100.0;
/// <summary>
/// 初始化坦克类的新实例
/// </summary>
/// <param name="id">坦克的唯一标识符</param>
/// <param name="position">初始位置坐标</param>
/// <param name="speed">初始速度,单位:米/秒</param>
/// <param name="simulationManager">仿真管理器实例</param>
/// <remarks>
/// 构造函数设置坦克的初始状态:
/// - 使用默认朝向
/// - 设置初始位置和速度
/// - 生命值初始化为100
/// </remarks>
public Tank(string id, Vector3D position, double speed, ISimulationManager simulationManager)
: base(id, position, new Orientation(), speed, simulationManager)
{
}
/// <summary>
/// 更新坦克的状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 根据当前速度更新位置
/// - 位置更新使用简单的线性运动模型
/// </remarks>
public override void Update(double deltaTime)
{
// 更新坦克的位置
Position += Velocity * deltaTime;
}
/// <summary>
/// 对坦克造成伤害
/// </summary>
/// <param name="damage">伤害值</param>
/// <remarks>
/// 伤害处理过程:
/// - 从当前生命值中扣除伤害值
/// - 如果生命值降至0或以下触发目标销毁事件
/// - 销毁事件会通知仿真系统移除该目标
/// </remarks>
public void TakeDamage(double damage)
{
Health -= damage;
if (Health <= 0)
{
SimulationManager.PublishEvent(new TargetDestroyedEvent { TargetId = Id });
}
}
}
}

View File

@ -0,0 +1,442 @@
using System;
using System.Numerics;
namespace ThreatSource.Utils
{
/// <summary>
/// 表示三维空间中的向量,提供基本的向量运算功能
/// </summary>
/// <remarks>
/// 该类实现了三维向量的基本运算,包括:
/// - 向量的加减乘除运算
/// - 向量的点积和叉积
/// - 向量的归一化
/// - 向量的旋转变换
/// 所有计算都使用双精度浮点数double以保证精度
/// </remarks>
public class Vector3D
{
/// <summary>
/// X轴单位向量 (1, 0, 0)
/// </summary>
public static Vector3D UnitX => new Vector3D(1, 0, 0);
/// <summary>
/// Y轴单位向量 (0, 1, 0)
/// </summary>
public static Vector3D UnitY => new Vector3D(0, 1, 0);
/// <summary>
/// Z轴单位向量 (0, 0, 1)
/// </summary>
public static Vector3D UnitZ => new Vector3D(0, 0, 1);
/// <summary>
/// 零向量 (0, 0, 0)
/// </summary>
public static Vector3D Zero => new Vector3D(0, 0, 0);
/// <summary>
/// 获取或设置向量的X分量
/// </summary>
public double X { get; set; }
/// <summary>
/// 获取或设置向量的Y分量
/// </summary>
public double Y { get; set; }
/// <summary>
/// 获取或设置向量的Z分量
/// </summary>
public double Z { get; set; }
/// <summary>
/// 初始化三维向量的新实例
/// </summary>
/// <param name="x">X分量的值</param>
/// <param name="y">Y分量的值</param>
/// <param name="z">Z分量的值</param>
public Vector3D(double x, double y, double z)
{
X = x;
Y = y;
Z = z;
}
/// <summary>
/// 计算两个向量之间的距离
/// </summary>
/// <param name="v1">第一个向量</param>
/// <param name="v2">第二个向量</param>
/// <returns>两个向量之间的距离</returns>
public static double Distance(Vector3D v1, Vector3D v2)
{
return Math.Sqrt(Math.Pow(v1.X - v2.X, 2) + Math.Pow(v1.Y - v2.Y, 2) + Math.Pow(v1.Z - v2.Z, 2));
}
/// <summary>
/// 将向量转换为字符串表示
/// </summary>
/// <returns>向量的字符串表示</returns>
public override string ToString()
{
return $"({X:F2}, {Y:F2}, {Z:F2})";
}
/// <summary>
/// 向量减法运算符重载
/// </summary>
public static Vector3D operator -(Vector3D a, Vector3D b)
{
return new Vector3D(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
}
/// <summary>
/// 向量加法运算符重载
/// </summary>
public static Vector3D operator +(Vector3D a, Vector3D b)
{
return new Vector3D(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
}
/// <summary>
/// 向量与标量乘法运算符重载
/// </summary>
public static Vector3D operator *(Vector3D a, double scalar)
{
return new Vector3D(a.X * scalar, a.Y * scalar, a.Z * scalar);
}
/// <summary>
/// 向量与标量除法运算符重载
/// </summary>
public static Vector3D operator /(Vector3D a, double scalar)
{
return new Vector3D(a.X / scalar, a.Y / scalar, a.Z / scalar);
}
/// <summary>
/// 向量反向
/// </summary>
public static Vector3D operator -(Vector3D a)
{
return new Vector3D(-a.X, -a.Y, -a.Z);
}
/// <summary>
/// 向量相等运算符重载
/// </summary>
public static bool operator ==(Vector3D left, Vector3D right)
{
return left.X == right.X && left.Y == right.Y && left.Z == right.Z;
}
/// <summary>
/// 向量不相等运算符重载
/// </summary>
public static bool operator !=(Vector3D left, Vector3D right)
{
return !(left == right);
}
/// <summary>
/// 判断两个向量是否相等
/// </summary>
public override bool Equals(object? obj)
{
if (obj is Vector3D other)
{
return this == other;
}
return false;
}
/// <summary>
/// 获取向量的哈希码
/// </summary>
/// <returns>向量的哈希码</returns>
public override int GetHashCode()
{
return HashCode.Combine(X, Y, Z);
}
/// <summary>
/// 计算向量的模长
/// </summary>
/// <returns>向量的模长</returns>
public double Magnitude()
{
return Math.Sqrt(X * X + Y * Y + Z * Z);
}
/// <summary>
/// 计算向量模长的平方
/// </summary>
/// <returns>向量模长的平方</returns>
public double MagnitudeSquared()
{
return X * X + Y * Y + Z * Z;
}
/// <summary>
/// 向量归一化
/// </summary>
/// <returns>归一化后的向量</returns>
public Vector3D Normalize()
{
double mag = Magnitude();
if (mag > 0)
{
return new Vector3D(X / mag, Y / mag, Z / mag);
}
return new Vector3D(0, 0, 0);
}
/// <summary>
/// 计算两个向量的叉积
/// </summary>
/// <param name="a">第一个向量</param>
/// <param name="b">第二个向量</param>
/// <returns>叉积结果</returns>
public static Vector3D CrossProduct(Vector3D a, Vector3D b)
{
return new Vector3D(
a.Y * b.Z - a.Z * b.Y,
a.Z * b.X - a.X * b.Z,
a.X * b.Y - a.Y * b.X
);
}
/// <summary>
/// 计算两个向量的点积
/// </summary>
/// <param name="a">第一个向量</param>
/// <param name="b">第二个向量</param>
/// <returns>点积结果</returns>
public static double DotProduct(Vector3D a, Vector3D b)
{
return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
}
/// <summary>
/// 向量取反
/// </summary>
/// <param name="a">输入向量</param>
/// <returns>取反后的向量</returns>
public static Vector3D Negate(Vector3D a)
{
return new Vector3D(-a.X, -a.Y, -a.Z);
}
/// <summary>
/// 计算AB两点之间距离 A 点一定距离的点的坐标
/// </summary>
/// <param name="a">直线起点</param>
/// <param name="b">直线终点</param>
/// <param name="distance">距离起点距离</param>
/// <returns>直线上的点</returns>
public static Vector3D PointOnLine(Vector3D a, Vector3D b, double distance)
{
Vector3D direction = b - a;
Vector3D unitDirection = direction.Normalize();
return a + unitDirection * distance;
}
internal Vector3D Rotate(Orientation orientation, double misalignmentAngle)
{
// 首先,根据方向和失调角计算出旋转矩阵
Matrix4x4 rotationMatrix = CalculateRotationMatrix(orientation, misalignmentAngle);
// 然后,使用旋转矩阵对当前向量进行旋转
Vector3D rotatedVector = ApplyRotationMatrix(this, rotationMatrix);
return rotatedVector;
}
private static Matrix4x4 CalculateRotationMatrix(Orientation orientation, double misalignmentAngle)
{
// 创建旋转矩阵
Matrix4x4 yawRotation = Matrix4x4.CreateRotationY((float)orientation.Yaw);
Matrix4x4 pitchRotation = Matrix4x4.CreateRotationX((float)orientation.Pitch);
Matrix4x4 rollRotation = Matrix4x4.CreateRotationZ((float)orientation.Roll);
Matrix4x4 misalignmentRotation = Matrix4x4.CreateRotationY((float)misalignmentAngle);
// 组合旋转矩阵
return misalignmentRotation * yawRotation * pitchRotation * rollRotation;
}
private static Vector3D ApplyRotationMatrix(Vector3D vector, Matrix4x4 matrix)
{
double x = vector.X * matrix.M11 + vector.Y * matrix.M21 + vector.Z * matrix.M31 + matrix.M41;
double y = vector.X * matrix.M12 + vector.Y * matrix.M22 + vector.Z * matrix.M32 + matrix.M42;
double z = vector.X * matrix.M13 + vector.Y * matrix.M23 + vector.Z * matrix.M33 + matrix.M43;
return new Vector3D(x, y, z);
}
}
/// <summary>
/// 表示三维空间中的方向,使用欧拉角表示
/// </summary>
/// <remarks>
/// 使用欧拉角(偏航角、俯仰角、滚转角)来表示三维空间中的方向:
/// - 偏航角Yaw绕Y轴旋转的角度
/// - 俯仰角Pitch绕X轴旋转的角度
/// - 滚转角Roll绕Z轴旋转的角度
/// 所有角度均使用弧度制
/// </remarks>
public struct Orientation
{
/// <summary>
/// 获取或设置偏航角绕Y轴旋转的角度单位弧度
/// </summary>
public double Yaw { get; set; }
/// <summary>
/// 获取或设置俯仰角绕X轴旋转的角度单位弧度
/// </summary>
public double Pitch { get; set; }
/// <summary>
/// 获取或设置滚转角绕Z轴旋转的角度单位弧度
/// </summary>
public double Roll { get; set; }
/// <summary>
/// 初始化方向的新实例
/// </summary>
/// <param name="yaw">偏航角,单位:弧度</param>
/// <param name="pitch">俯仰角,单位:弧度</param>
/// <param name="roll">滚转角,单位:弧度</param>
public Orientation(double yaw, double pitch, double roll)
{
Yaw = yaw;
Pitch = pitch;
Roll = roll;
}
/// <summary>
/// 将方向转换为字符串表示
/// </summary>
/// <returns>方向的字符串表示</returns>
public override readonly string ToString()
{
return $"(Yaw: {Yaw:F2}, Pitch: {Pitch:F2}, Roll: {Roll:F2})";
}
/// <summary>
/// 将角度归一化到 [-π, π] 范围内
/// </summary>
public void Normalize()
{
Yaw = NormalizeAngle(Yaw);
Pitch = NormalizeAngle(Pitch);
Roll = NormalizeAngle(Roll);
}
/// <summary>
/// 将单个角度归一化到 [-π, π] 范围内
/// </summary>
/// <param name="angle">输入角度</param>
/// <returns>归一化后的角度</returns>
private static double NormalizeAngle(double angle)
{
while (angle > Math.PI) angle -= 2 * Math.PI;
while (angle <= -Math.PI) angle += 2 * Math.PI;
return angle;
}
internal Vector3D Rotate(Vector3D vector, double misalignmentAngle)
{
throw new NotImplementedException();
}
/// <summary>
/// 根据给定的方向向量创建方向
/// </summary>
/// <param name="direction">方向向量</param>
/// <returns>对应的方向</returns>
public static Orientation LookAt(Vector3D direction)
{
double yaw = Math.Atan2(direction.Z, direction.X);
double pitch = Math.Atan2(direction.Y, Math.Sqrt(direction.X * direction.X + direction.Z * direction.Z));
return new Orientation(yaw, pitch, 0);
}
/// <summary>
/// 将方向转换为单位向量
/// </summary>
/// <returns>对应的单位向量</returns>
public readonly Vector3D ToVector()
{
double cosYaw = Math.Cos(Yaw);
double sinYaw = Math.Sin(Yaw);
double cosPitch = Math.Cos(Pitch);
double sinPitch = Math.Sin(Pitch);
return new Vector3D(
cosYaw * cosPitch,
sinPitch,
sinYaw * cosPitch
);
}
/// <summary>
/// 从向量创建方向
/// </summary>
/// <param name="vector">输入向量</param>
/// <returns>对应的方向</returns>
public static Orientation FromVector(Vector3D vector)
{
Vector3D normalized = vector.Normalize();
double pitch = Math.Asin(normalized.Y);
double yaw;
if (Math.Abs(normalized.Y) > 0.9999) // 接近垂直
{
yaw = 0; // 或者保持之前的偏航角
}
else
{
yaw = Math.Atan2(normalized.Z, normalized.X);
}
return new Orientation(yaw, pitch, 0);
}
}
/// <summary>
/// 表示二维平面上的向量
/// </summary>
/// <remarks>
/// 用于处理二维平面上的计算,如目标投影等
/// </remarks>
public struct Vector2D
{
/// <summary>
/// 获取或设置向量的X分量
/// </summary>
public double X { get; set; }
/// <summary>
/// 获取或设置向量的Y分量
/// </summary>
public double Y { get; set; }
/// <summary>
/// 初始化二维向量的新实例
/// </summary>
/// <param name="x">X分量的值</param>
/// <param name="y">Y分量的值</param>
public Vector2D(double x, double y)
{
X = x;
Y = y;
}
/// <summary>
/// 零向量 (0, 0)
/// </summary>
public static Vector2D Zero => new Vector2D(0, 0);
}
}

View File

@ -0,0 +1,250 @@
using System;
using System.Numerics;
namespace ThreatSource.Utils
{
/// <summary>
/// 运动算法静态类,提供各种运动计算方法
/// </summary>
/// <remarks>
/// 该类包含了导弹运动相关的各种算法,包括:
/// - 弹道计算
/// - 运动学计算
/// - 制导算法
/// - 扰动计算
/// 所有方法都是静态的,可以直接调用。
/// </remarks>
public static class MotionAlgorithm
{
/// <summary>
/// 计算抛物线弹道最佳发射方向(选择较小的仰角)
/// </summary>
/// <param name="startPos">发射位置坐标</param>
/// <param name="targetPos">目标位置坐标</param>
/// <param name="initialSpeed">发射初速度,单位:米/秒</param>
/// <returns>包含最佳发射方向和初始速度向量的元组如果无解则返回null</returns>
/// <remarks>
/// 该方法使用弹道方程计算两个可能的发射角度,并选择较小的仰角作为最佳发射方向。
/// 计算考虑了重力影响,但未考虑空气阻力。
/// </remarks>
public static (Orientation? orientation, Vector3D? velocity) CalculateBestLaunchOrientation(Vector3D startPos, Vector3D targetPos, double initialSpeed)
{
// 计算水平距离
double dx = targetPos.X - startPos.X;
double dz = targetPos.Z - startPos.Z;
double horizontalDistance = Math.Sqrt(dx * dx + dz * dz);
// 计算高度差
double dy = targetPos.Y - startPos.Y;
double[]? angles = CalculateLaunchAngles(initialSpeed, horizontalDistance, dy);
if (angles == null)
{
Console.WriteLine("无法计算发射角度");
return (null, null);
}
double bestAngle = Math.Min(angles[0], angles[1]);
double azimuth = Math.Atan2(dz, dx);
// 计算初始速度分量
double vx = initialSpeed * Math.Cos(bestAngle) * Math.Cos(azimuth);
double vy = initialSpeed * Math.Sin(bestAngle);
double vz = initialSpeed * Math.Cos(bestAngle) * Math.Sin(azimuth);
// 返回方向和速度
return (new Orientation(bestAngle, azimuth, 0), new Vector3D(vx, vy, vz));
}
/// <summary>
/// 计算抛物线弹道发射角度
/// </summary>
/// <param name="v0">初始速度,单位:米/秒</param>
/// <param name="x">目标水平距离,单位:米</param>
/// <param name="y">目标高度差,单位:米</param>
/// <param name="g">重力加速度默认9.81米/秒²</param>
/// <returns>两个可能的发射角度弧度如果无解则返回null</returns>
/// <remarks>
/// 使用标准弹道方程计算发射角度,会返回两个解:
/// - 一个是低角度解(较小仰角)
/// - 一个是高角度解(较大仰角)
/// 如果目标距离超出武器射程则返回null。
/// </remarks>
public static double[]? CalculateLaunchAngles(double v0, double x, double y, double g = 9.81)
{
double v0_2 = v0 * v0;
double v0_4 = v0_2 * v0_2;
double discriminant = v0_4 - g * (g * x * x + 2 * y * v0_2);
if (discriminant < 0)
{
Console.WriteLine("无实数解 - 目标不可达");
return null;
}
double angle1 = Math.Atan((v0_2 + Math.Sqrt(discriminant)) / (g * x));
double angle2 = Math.Atan((v0_2 - Math.Sqrt(discriminant)) / (g * x));
//Console.WriteLine($"计算得到的两个角度: {angle1 * 180 / Math.PI:F2}° 和 {angle2 * 180 / Math.PI:F2}°");
return new[] { angle1, angle2 };
}
/// <summary>
/// 使用运动学定律计算导弹运动状态
/// </summary>
/// <param name="currentPosition">当前位置坐标</param>
/// <param name="currentVelocity">当前速度向量</param>
/// <param name="acceleration">加速度向量(包含重力加速度)</param>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <returns>包含新位置和新速度的元组</returns>
/// <remarks>
/// 该方法适用于无制导状态下的导弹运动计算,使用标准运动学方程:
/// - 位置更新p = p0 + v0*t + 0.5*a*t^2
/// - 速度更新v = v0 + a*t
/// </remarks>
public static (Vector3D newPosition, Vector3D newVelocity) CalculateBallisticMotion(
Vector3D currentPosition,
Vector3D currentVelocity,
Vector3D acceleration,
double deltaTime)
{
// 使用标准运动学方程
Vector3D newPosition = new(
currentPosition.X + currentVelocity.X * deltaTime + 0.5 * acceleration.X * deltaTime * deltaTime,
currentPosition.Y + currentVelocity.Y * deltaTime + 0.5 * acceleration.Y * deltaTime * deltaTime,
currentPosition.Z + currentVelocity.Z * deltaTime + 0.5 * acceleration.Z * deltaTime * deltaTime
);
Vector3D newVelocity = new(
currentVelocity.X + acceleration.X * deltaTime,
currentVelocity.Y + acceleration.Y * deltaTime,
currentVelocity.Z + acceleration.Z * deltaTime
);
return (newPosition, newVelocity);
}
/// <summary>
/// 使用四阶龙格库塔法计算导弹运动状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <param name="position">当前位置坐标</param>
/// <param name="velocity">当前速度向量</param>
/// <param name="acceleration">当前加速度向量</param>
/// <returns>包含新位置和新速度的元组</returns>
/// <remarks>
/// 四阶龙格库塔法提供了更高精度的数值解:
/// - 适用于有制导状态下的导弹运动计算
/// - 考虑了加速度随时间的变化
/// - 比简单欧拉法具有更高的精度
/// </remarks>
public static (Vector3D newPosition, Vector3D newVelocity) RungeKutta4(double deltaTime, Vector3D position, Vector3D velocity, Vector3D acceleration)
{
// 定义一个局部函数来计算加速度
Vector3D AccelerationFunction(Vector3D pos, Vector3D vel)
{
// 这里可以添加更复杂的加速度计算,比如考虑空气阻力等
return acceleration;
}
// 第一步
Vector3D k1v = AccelerationFunction(position, velocity) * deltaTime;
Vector3D k1r = velocity * deltaTime;
// 第二步
Vector3D k2v = AccelerationFunction(position + k1r * 0.5, velocity + k1v * 0.5) * deltaTime;
Vector3D k2r = (velocity + k1v * 0.5) * deltaTime;
// 第三步
Vector3D k3v = AccelerationFunction(position + k2r * 0.5, velocity + k2v * 0.5) * deltaTime;
Vector3D k3r = (velocity + k2v * 0.5) * deltaTime;
// 第四步
Vector3D k4v = AccelerationFunction(position + k3r, velocity + k3v) * deltaTime;
Vector3D k4r = (velocity + k3v) * deltaTime;
// 计算新的位置和速度
Vector3D newPosition = position + (k1r + k2r * 2 + k3r * 2 + k4r) / 6;
Vector3D newVelocity = velocity + (k1v + k2v * 2 + k3v * 2 + k4v) / 6;
return (newPosition, newVelocity);
}
/// <summary>
/// 计算比例导引加速度
/// </summary>
/// <param name="proportionalNavigationCoefficient">比例导引系数</param>
/// <param name="missilePosition">导弹当前位置</param>
/// <param name="missileVelocity">导弹当前速度</param>
/// <param name="targetPosition">目标当前位置</param>
/// <param name="targetVelocity">目标当前速度</param>
/// <returns>比例导引产生的加速度向量</returns>
/// <remarks>
/// 使用比例导引法计算制导加速度:
/// - 预测目标未来位置
/// - 计算视线角速率
/// - 根据比例导引公式计算所需加速度
/// 加速度方向垂直于导弹速度方向。
/// </remarks>
public static Vector3D CalculateProportionalNavigation(double proportionalNavigationCoefficient, Vector3D missilePosition, Vector3D missileVelocity, Vector3D targetPosition, Vector3D targetVelocity)
{
// 预测时间(预测目标前进方向该时间后到达的位置,可以调整)
double predictionTime = 0.01;
// 预测目标位置
Vector3D predictedTargetPosition = targetPosition + targetVelocity * predictionTime;
Vector3D r = predictedTargetPosition - missilePosition;
Vector3D v = targetVelocity - missileVelocity;
Vector3D LOS = r.Normalize();
Vector3D LOSRate = (v - (LOS * Vector3D.DotProduct(v, LOS))) / r.Magnitude();
Vector3D acceleration = Vector3D.CrossProduct(Vector3D.CrossProduct(LOS, LOSRate), missileVelocity.Normalize()) * proportionalNavigationCoefficient * missileVelocity.Magnitude();
return acceleration;
}
/// <summary>
/// 为向量添加高斯噪声
/// </summary>
/// <param name="vector">原始向量</param>
/// <returns>添加高斯噪声后的向量</returns>
/// <remarks>
/// 使用Box-Muller变换生成高斯随机数
/// - 为向量的每个分量添加独立的高斯噪声
/// - 噪声强度由标准差控制默认0.1
/// - 用于模拟传感器误差和环境扰动
/// </remarks>
public static Vector3D AddRandomPerturbation(Vector3D vector)
{
Random random = new();
// 添加高斯噪声
double sigma = 0.1; // 扰动标准差
// 使用Box-Muller变换来生成高斯随机数
double u1 = random.NextDouble(); // 生成[0, 1)之间的随机数
double u2 = random.NextDouble(); // 生成[0, 1)之间的随机数
double r = Math.Sqrt(-2.0 * Math.Log(u1));
double theta = 2.0 * Math.PI * u2;
double gaussianX = r * Math.Cos(theta);
double gaussianY = r * Math.Sin(theta);
// 由于我们需要三个高斯随机数,我们将再次生成
u1 = random.NextDouble(); // 生成[0, 1)之间的随机数
u2 = random.NextDouble(); // 生成[0, 1)之间的随机数
r = Math.Sqrt(-2.0 * Math.Log(u1));
theta = 2.0 * Math.PI * u2;
double gaussianZ = r * Math.Cos(theta);
// 将高斯随机数转换为指定标准差的高斯随机数
gaussianX *= sigma;
gaussianY *= sigma;
gaussianZ *= sigma;
return new Vector3D(
vector.X + gaussianX,
vector.Y + gaussianY,
vector.Z + gaussianZ
);
}
}
}

87
docfx.json Normal file
View File

@ -0,0 +1,87 @@
{
"metadata": [
{
"src": [
{
"src": "./",
"files": [
"ThreatSource/ThreatSource.csproj"
],
"exclude": [
"**/obj/**",
"**/bin/**",
"**/ThreatSource.Tests/**",
"_site/**"
]
}
],
"dest": "docs/api",
"disableGitFeatures": false,
"disableDefaultFilter": false,
"properties": {
"TargetFramework": "net8.0"
}
}
],
"build": {
"content": [
{
"files": [
"docs/api/**.yml",
"docs/api/index.md"
]
},
{
"files": [
"docs/articles/**.md",
"docs/articles/**/toc.yml",
"docs/toc.yml",
"docs/*.md",
"docs/examples/**/*.md",
"docs/examples/**/*.cs"
],
"exclude": [
"docs/obj/**",
"docs/_site/**"
]
}
],
"resource": [
{
"files": [
"docs/images/**"
]
}
],
"overwrite": [
{
"files": [
"docs/apidoc/**.md"
],
"exclude": [
"docs/obj/**",
"docs/_site/**"
]
}
],
"dest": "docs/_site",
"globalMetadata": {
"_appTitle": "威胁源仿真库",
"_appFooter": "威胁源仿真库文档",
"_enableSearch": true,
"_language": "zh-cn",
"_disableContribution": true
},
"globalMetadataFiles": [],
"fileMetadataFiles": [],
"template": [
"default"
],
"postProcessors": [],
"markdownEngineName": "markdig",
"noLangKeyword": false,
"keepFileLink": false,
"cleanupCacheHistory": false,
"disableGitFeatures": false
}
}

103
docs/README.md Normal file
View File

@ -0,0 +1,103 @@
# ThreatSource Library
## 项目描述
ThreatSource Library 是一个专门用于军事目标和武器系统模拟的 C# 类库。该库提供了一套完整的类和接口,用于模拟各种军事目标(如坦克)、指示器(如激光指示器)以及不同类型的导弹系统。
## 主要功能
- 目标模拟Target
- 坦克Tank等地面目标的模拟
- 指示器系统Indicator
- 激光指示器LaserDesignator
- 激光波束制导LaserBeamRider
- 红外追踪器InfraredTracker
- 导弹系统Missile
- 基础导弹类BaseMissile
- 激光波束制导导弹LaserBeamRiderMissile
- 红外指令制导导弹InfraredCommandGuidedMissile
- 激光半主动制导导弹LaserSemiActiveGuidedMissile
- 红外成像末制导导弹InfraredImagingTerminalGuidedMissile
- 毫米波末制导导弹MillimeterWaveTerminalGuidedMissile
- 末敏导弹TerminalSensitiveMissile
- 末敏子弹药TerminalSensitiveSubmunition
## 使用说明
1. 引用项目
```csharp
using ThreatSource;
```
2. 创建目标实例
```csharp
var tank = new Tank();
```
3. 创建指示器
```csharp
var laserDesignator = new LaserDesignator();
```
4. 创建导弹
```csharp
var missile = new LaserBeamRiderMissile();
```
## 项目结构
```text
ThreatSource/
├── Target/
│ └── Tank.cs
├── Indicator/
│ ├── LaserDesignator.cs
│ ├── LaserBeamRider.cs
│ └── InfraredTracker.cs
└── Missile/
├── BaseMissile.cs
├── LaserBeamRiderMissile.cs
├── InfraredCommandGuidedMissile.cs
├── LaserSemiActiveGuidedMissile.cs
├── InfraredImagingTerminalGuidedMissile.cs
├── MillimeterWaveTerminalGuidedMissile.cs
├── TerminalSensitiveMissile.cs
└── TerminalSensitiveSubmunition.cs
```
## 开发环境
- .NET 6.0 或更高版本
- Visual Studio 2022 或更高版本
- xUnit用于单元测试
## 测试
项目使用 xUnit 作为测试框架。所有测试文件都位于 `ThreatSource.Tests` 目录下。
运行测试:
1. 在 Visual Studio 中打开测试资源管理器
2. 点击"运行所有测试"或选择特定测试运行
或使用命令行:
```bash
dotnet test
```
## 贡献指南
1. Fork 项目
2. 创建特性分支
3. 提交更改
4. 推送到分支
5. 创建 Pull Request
## 许可证
MIT License

View File

@ -0,0 +1,192 @@
# DocFX 文档生成指南
本指南说明如何使用 DocFX 为 ThreatSource 库生成 API 文档。
## 环境准备
1. 安装 .NET SDK需要 .NET 8.0 或更高版本)
2. 安装 DocFX
```bash
dotnet tool install -g docfx
```
## 文档结构
```text
docs/
├── api/ # API 文档(自动生成)
├── articles/ # 手写文档
├── examples/ # 示例代码
├── images/ # 图片资源
├── _site/ # 生成的静态网站
├── docfx.json # DocFX 配置文件
└── toc.yml # 文档目录结构
```
## 生成文档步骤
1. 清理旧的生成文件
```bash
rm -rf docs/_site/
rm -rf docs/api/
```
2. 生成 API 文档元数据
```bash
cd docs
docfx metadata
```
3. 构建网站
```bash
docfx build
```
4. (可选)本地预览
```bash
docfx serve _site
```
然后访问 <http://localhost:8080>
## docfx.json 配置说明
```json
{
"metadata": [
{
"src": [
{
"src": "../", // 源代码根目录
"files": [
"ThreatSource/**.csproj" // 项目文件
]
}
],
"dest": "api", // API文档输出目录
"disableGitFeatures": false,
"disableDefaultFilter": false
}
],
"build": {
"content": [
{
"files": [
"api/**.yml", // API文档
"api/index.md"
]
},
{
"files": [
"articles/**.md", // 文章
"articles/**/toc.yml",
"examples/**.md", // 示例
"examples/**/toc.yml",
"toc.yml",
"*.md"
]
}
],
"resource": [
{
"files": [
"images/**" // 资源文件
]
}
],
"dest": "_site", // 网站输出目录
"globalMetadataFiles": [],
"fileMetadataFiles": [],
"template": [
"default" // 使用默认模板
],
"postProcessors": [],
"markdownEngineName": "markdig",
"noLangKeyword": false,
"keepFileLink": false,
"cleanupCacheHistory": false,
"disableGitFeatures": false
}
}
```
## 注意事项
1. 代码注释规范
- 使用 XML 文档注释
- 为公开的类、方法、属性添加注释
- 使用 `<summary>`、`<param>`、`<returns>` 等标签
```csharp
/// <summary>
/// 类的功能描述
/// </summary>
public class MyClass
{
/// <summary>
/// 方法的功能描述
/// </summary>
/// <param name="input">参数说明</param>
/// <returns>返回值说明</returns>
public string MyMethod(string input)
{
// ...
}
}
```
2. 文档组织
- 使用 `toc.yml` 组织文档结构
- 保持文档层次清晰
- 适当使用交叉引用
3. 图片和资源
- 图片放在 `images` 目录
- 使用相对路径引用
- 控制图片大小适中
4. 常见问题
- 如果生成失败,检查项目引用是否正确
- 确保所有必要的源代码文件都被包含
- 检查文档注释的格式是否正确
## 自动化脚本
可以创建以下脚本来简化文档生成过程:
```bash
#!/bin/bash
# generate-docs.sh
# 清理旧文件
rm -rf docs/_site/
rm -rf docs/api/
# 生成文档
cd docs
docfx metadata
docfx build
# 启动预览(可选)
# docfx serve _site
```
## 更新文档
1. 修改源代码注释后:
- 重新生成 API 文档
- 检查生成的文档是否正确
2. 修改手写文档后:
- 直接重新构建网站
- 不需要重新生成 API 元数据
## 相关资源
- [DocFX 官方文档](https://dotnet.github.io/docfx/)
- [XML 文档注释指南](https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/xmldoc/)

207
docs/articles/intro.md Normal file
View File

@ -0,0 +1,207 @@
# 入门指南
## 安装
### C#版本
通过NuGet包管理器安装威胁源仿真库
```bash
dotnet add package ThreatSource
```
### C++版本
有两种使用方式:
#### 方式一C++/CLI推荐
1. 创建C++/CLI项目Visual Studio -> 新建项目 -> CLR类库
2. 通过NuGet包管理器安装ThreatSource
3. 配置项目属性:
- 公共语言运行时支持:/clr
- 平台工具集Visual Studio 2022 (v143)
- .NET目标框架net8.0
#### 方式二原生C++
1. 下载对应版本的 ThreatSource.dll
2. 将DLL放置在项目输出目录
3. 确保DLL版本与项目平台配置匹配x86/x64
## C#基本用法
### 初始化仿真管理器
```csharp
var simulationManager = new SimulationManager();
```
### 创建导弹
```csharp
// 创建导弹配置
var missileProperties = new MissileProperties
{
Id = "missile1",
InitialPosition = new Vector3D(0, 0, 0),
InitialOrientation = new Orientation(0, 0, 0),
InitialSpeed = 800,
MaxSpeed = 1000,
MaxFlightTime = 30,
MaxFlightDistance = 5000,
MaxAcceleration = 10,
Mass = 50
};
// 创建导弹实例
var missile = new TerminalSensitiveMissile("target1", missileProperties, simulationManager);
```
### 创建目标
```csharp
// 创建目标
var tank = new Tank(
"target1",
new Vector3D(1000, 0, 0),
Math.PI/4,
simulationManager
);
```
### 注册实体
```csharp
simulationManager.RegisterEntity(missile.Id, missile);
simulationManager.RegisterEntity(tank.Id, tank);
```
### 运行仿真
```csharp
// 激活实体
missile.Activate();
tank.Activate();
// 发射导弹
missile.Fire();
// 仿真主循环
double deltaTime = 0.01;
while (missile.IsActive)
{
missile.Update(deltaTime);
tank.Update(deltaTime);
}
```
## C++使用指南
在C++项目中使用威胁源仿真库有两种方式C++/CLI和原生C++。以下重点介绍推荐的C++/CLI方式
### C++/CLI方式推荐
#### 1. 创建包装类
```cpp
using namespace System;
using namespace ThreatSource::Simulation;
public ref class SimulationWrapper
{
private:
SimulationManager^ manager;
public:
SimulationWrapper()
{
manager = gcnew SimulationManager();
}
void CreateAndRunSimulation()
{
try
{
// 创建导弹配置
auto properties = gcnew MissileProperties();
properties->Id = "missile1";
properties->InitialPosition = Vector3D(0, 0, 0);
properties->InitialSpeed = 800;
properties->MaxSpeed = 1000;
properties->MaxFlightTime = 30;
properties->MaxFlightDistance = 5000;
properties->MaxAcceleration = 10;
properties->Mass = 50;
// 创建导弹
auto missile = gcnew TerminalSensitiveMissile("target1", properties, manager);
// 注册和激活
manager->RegisterEntity(missile->Id, missile);
missile->Activate();
missile->Fire();
// 仿真主循环
double deltaTime = 0.01;
while (missile->IsActive)
{
missile->Update(deltaTime);
}
}
catch (Exception^ e)
{
Console::WriteLine("错误: {0}", e->Message);
}
}
};
```
#### 2. 在原生C++代码中使用
```cpp
int main()
{
try
{
auto simulation = gcnew SimulationWrapper();
simulation->CreateAndRunSimulation();
return 0;
}
catch (Exception^ e)
{
Console::WriteLine("错误: {0}", e->Message);
return 1;
}
}
```
### 原生C++方式
如果必须使用原生C++(不推荐),请参考以下方式:
### 注意事项
1. C++/CLI vs 原生C++
- C++/CLI方式更简单直接使用.NET类型
- 原生C++方式需要更多的封装和转换工作
- C++/CLI性能可能略低但开发效率更高
2. 内存管理
- C++/CLI使用垃圾回收
- 使用gcnew创建托管对象
- 注意托管和非托管资源的混合使用
3. 错误处理
- 使用托管异常处理try/catch
- 异常信息更详细,更容易调试
- 可以直接使用.NET的日志机制
4. 类型系统
- 使用托管类型(^
- 注意值类型和引用类型的区别
- 使用安全的类型转换
## 更多示例
更多示例请参考[示例代码](../examples/Simulation/README.md)。

View File

@ -0,0 +1,56 @@
# 第三方引擎集成示例
本目录包含了将仿真系统与第三方引擎集成的示例代码。这些示例展示了如何使用适配器模式将不同的游戏引擎与仿真系统进行集成。
## 示例文件
### [UEExample.cs](UEExample.cs)
虚幻引擎(Unreal Engine)集成示例,展示了:
- 虚幻引擎与仿真系统的双向通信
- 实体信息的同步和转换
- 事件的发布和订阅
- 数据的适配和转换
### [UnityExample.cs](UnityExample.cs)
Unity引擎集成示例展示了
- Unity引擎与仿真系统的双向通信
- GameObject与实体的映射和转换
- MonoBehaviour生命周期管理
- 事件系统的使用
## 使用说明
1. 这些文件仅作为参考示例,不参与实际编译(使用 `#if NEVER` 编译指令)
2. 实际项目中需要根据具体需求修改和扩展
3. 示例中的接口和类名仅供参考,应根据实际项目规范调整
## 关键概念
### 适配器模式
- 实现 `ISimulationAdapter` 接口
- 转换不同引擎的数据格式
- 处理事件的发布和订阅
### 实体映射
- 在仿真系统和游戏引擎之间建立实体对应关系
- 同步实体状态和属性
- 处理实体的创建和销毁
### 事件系统
- 定义统一的事件数据结构
- 处理事件的双向转换
- 确保事件的正确分发
## 注意事项
1. 需要处理线程安全问题
2. 注意性能优化,特别是在状态同步时
3. 合理处理资源的加载和释放
4. 确保异常处理的完整性

View File

@ -0,0 +1,242 @@
#if NEVER // 使用编译指令确保此文件永远不会被编译
// 第三方系统实现适配器示例代码
// 以虚幻引擎为例
// 需要实现的方法: GetEntity, PublishToExternalSimulation, ReceiveFromExternalSimulation
using ThreatSource.Simulation;
/// <summary>
/// 虚幻引擎适配器类,演示如何将第三方系统集成到仿真系统中
/// </summary>
/// <remarks>
/// 该类提供了以下功能:
/// - 虚幻引擎与仿真系统的双向通信
/// - 实体信息的同步和转换
/// - 事件的发布和订阅
/// - 数据的适配和转换
/// 本示例代码仅作为参考,展示了基本的集成方法
/// </remarks>
public class UnrealEngineAdapter : ISimulationAdapter
{
/// <summary>
/// 虚幻引擎API接口定义了与虚幻引擎交互的基本方法
/// </summary>
/// <remarks>
/// 该接口包含:
/// - 获取Actor对象
/// - 生成导弹实体
/// 实际项目中需要根据具体需求扩展
/// </remarks>
public interface IUnrealEngine
{
/// <summary>
/// 根据ID获取虚幻引擎中的Actor对象
/// </summary>
/// <param name="id">Actor的唯一标识符</param>
/// <returns>对应的Actor对象如果未找到则返回null</returns>
object? GetActor(string id);
/// <summary>
/// 在虚幻引擎中生成导弹实体
/// </summary>
/// <param name="senderId">发射者ID</param>
/// <param name="targetId">目标ID</param>
void SpawnMissile(string senderId, string targetId);
}
/// <summary>
/// 虚幻引擎实例
/// </summary>
/// <remarks>
/// 用于与虚幻引擎进行实际交互
/// 通过依赖注入方式提供
/// </remarks>
private readonly IUnrealEngine _unrealEngine;
/// <summary>
/// 仿真管理器实例
/// </summary>
/// <remarks>
/// 用于管理仿真系统的核心功能
/// 处理事件分发和状态同步
/// </remarks>
private readonly ISimulationManager _simulationManager;
/// <summary>
/// 初始化虚幻引擎适配器的新实例
/// </summary>
/// <param name="unrealEngine">虚幻引擎实例</param>
/// <param name="simulationManager">仿真管理器实例</param>
/// <remarks>
/// 构造过程:
/// - 验证参数有效性
/// - 初始化引擎实例
/// - 初始化管理器实例
/// </remarks>
public UnrealEngineAdapter(IUnrealEngine unrealEngine, ISimulationManager simulationManager)
{
_unrealEngine = unrealEngine ?? throw new ArgumentNullException(nameof(unrealEngine));
_simulationManager = simulationManager ?? throw new ArgumentNullException(nameof(simulationManager));
}
/// <summary>
/// 获取指定ID的实体对象
/// </summary>
/// <param name="id">实体的唯一标识符</param>
/// <returns>对应的实体对象如果未找到则返回null</returns>
/// <remarks>
/// 该方法将仿真系统的实体ID转换为虚幻引擎中的实体
/// </remarks>
public object? GetEntity(string id)
{
return _unrealEngine.GetActor(id);
}
/// <summary>
/// 将事件发布到外部仿真系统(虚幻引擎)
/// </summary>
/// <typeparam name="T">事件类型</typeparam>
/// <param name="evt">要发布的事件对象</param>
/// <remarks>
/// 处理过程:
/// - 识别事件类型
/// - 转换为虚幻引擎事件
/// - 调用相应的引擎API
/// </remarks>
public void PublishToExternalSimulation<T>(T evt)
{
if (evt is MissileFireEvent missileEvt)
{
_unrealEngine.SpawnMissile(missileEvt.SenderId, missileEvt.TargetId);
}
// ... 处理其他事件类型
}
/// <summary>
/// 接收来自外部仿真系统(虚幻引擎)的事件
/// </summary>
/// <typeparam name="T">事件类型</typeparam>
/// <param name="evt">接收到的事件对象</param>
/// <remarks>
/// 处理过程:
/// - 接收虚幻引擎事件
/// - 转换为仿真系统事件
/// - 分发到相应的处理器
/// </remarks>
public void ReceiveFromExternalSimulation<T>(T evt)
{
// 处理来自虚幻引擎的事件
}
/// <summary>
/// 处理来自虚幻引擎的事件
/// </summary>
/// <param name="eventType">事件类型标识符</param>
/// <param name="data">事件数据对象</param>
/// <remarks>
/// 处理过程:
/// - 解析事件类型
/// - 转换事件数据
/// - 调用相应的处理方法
/// </remarks>
public void OnUnrealEvent(string eventType, UnrealEventData data)
{
if (eventType == "MissileFired")
{
var evt = new MissileFireEvent
{
SenderId = data.SenderId,
TargetId = data.TargetId
};
_simulationManager.GetSimulationAdapter()?.ReceiveFromExternalSimulation(evt);
}
}
}
/// <summary>
/// 虚幻引擎事件数据结构
/// </summary>
/// <remarks>
/// 用于封装虚幻引擎事件的相关数据
/// 包含事件发送者和目标的标识信息
/// </remarks>
public class UnrealEventData
{
/// <summary>
/// 获取或设置事件发送者的ID
/// </summary>
public string? SenderId { get; set; }
/// <summary>
/// 获取或设置事件目标的ID
/// </summary>
public string? TargetId { get; set; }
}
/// <summary>
/// 虚幻引擎仿真示例类
/// </summary>
/// <remarks>
/// 该类演示了:
/// - 仿真系统的初始化
/// - 适配器的配置
/// - 事件的处理流程
/// 用于指导实际项目中的集成实现
/// </remarks>
public class UnrealSimulation
{
/// <summary>
/// 仿真管理器实例
/// </summary>
private readonly ISimulationManager _simulationManager;
/// <summary>
/// 虚幻引擎实例
/// </summary>
private readonly UnrealEngineAdapter.IUnrealEngine _unrealEngine;
/// <summary>
/// 初始化虚幻引擎仿真的新实例
/// </summary>
/// <remarks>
/// 初始化过程:
/// - 创建仿真管理器
/// - 创建引擎实例
/// - 配置适配器
/// </remarks>
public UnrealSimulation()
{
_simulationManager = new SimulationManager();
_unrealEngine = new UnrealEngineImplementation(); // 实际项目中需要实现这个类
_simulationManager.SetSimulationAdapter(
new UnrealEngineAdapter(_unrealEngine, _simulationManager)
);
}
/// <summary>
/// 处理虚幻引擎事件
/// </summary>
/// <param name="eventType">事件类型标识符</param>
/// <param name="data">事件数据对象</param>
/// <remarks>
/// 处理过程:
/// - 识别事件类型
/// - 转换事件数据
/// - 通过适配器分发事件
/// </remarks>
public void OnUnrealEvent(string eventType, UnrealEventData data)
{
if (eventType == "MissileFired")
{
var evt = new MissileFireEvent
{
SenderId = data.SenderId,
TargetId = data.TargetId
};
_simulationManager.GetSimulationAdapter()?.ReceiveFromExternalSimulation(evt);
}
}
}
#endif // 结束编译指令块

View File

@ -0,0 +1,337 @@
#if NEVER // 使用编译指令确保此文件永远不会被编译
// 第三方系统实现适配器示例代码
// 以Unity引擎为例
// 需要实现的方法: GetEntity, PublishToExternalSimulation, ReceiveFromExternalSimulation
using ThreatSource.Simulation;
using UnityEngine; // 仅用于示例实际项目中需要引用真实的Unity命名空间
/// <summary>
/// Unity引擎适配器类演示如何将Unity引擎集成到仿真系统中
/// </summary>
/// <remarks>
/// 该类提供了以下功能:
/// - Unity引擎与仿真系统的双向通信
/// - GameObject与实体的映射和转换
/// - MonoBehaviour生命周期管理
/// - 事件的发布和订阅
/// - 数据的适配和转换
/// 本示例代码仅作为参考,展示了基本的集成方法
/// </remarks>
public class UnityEngineAdapter : MonoBehaviour, ISimulationAdapter
{
/// <summary>
/// Unity引擎API接口定义了与Unity引擎交互的基本方法
/// </summary>
/// <remarks>
/// 该接口包含:
/// - 获取GameObject对象
/// - 生成导弹预制体
/// - 场景管理
/// 实际项目中需要根据具体需求扩展
/// </remarks>
public interface IUnityEngine
{
/// <summary>
/// 根据ID获取Unity场景中的GameObject对象
/// </summary>
/// <param name="id">GameObject的唯一标识符</param>
/// <returns>对应的GameObject对象如果未找到则返回null</returns>
GameObject GetGameObject(string id);
/// <summary>
/// 在Unity场景中实例化导弹预制体
/// </summary>
/// <param name="prefabPath">预制体资源路径</param>
/// <param name="position">生成位置</param>
/// <param name="rotation">生成朝向</param>
/// <returns>生成的导弹GameObject实例</returns>
GameObject InstantiateMissile(string prefabPath, Vector3 position, Quaternion rotation);
}
/// <summary>
/// Unity引擎实例
/// </summary>
/// <remarks>
/// 用于与Unity引擎进行实际交互
/// 通过依赖注入方式提供
/// </remarks>
private readonly IUnityEngine _unityEngine;
/// <summary>
/// 仿真管理器实例
/// </summary>
/// <remarks>
/// 用于管理仿真系统的核心功能
/// 处理事件分发和状态同步
/// </remarks>
private readonly ISimulationManager _simulationManager;
/// <summary>
/// 导弹预制体路径
/// </summary>
private const string MissilePrefabPath = "Prefabs/Missile";
/// <summary>
/// 初始化Unity引擎适配器的新实例
/// </summary>
/// <param name="unityEngine">Unity引擎实例</param>
/// <param name="simulationManager">仿真管理器实例</param>
/// <remarks>
/// 构造过程:
/// - 验证参数有效性
/// - 初始化引擎实例
/// - 初始化管理器实例
/// - 注册Unity生命周期事件
/// </remarks>
public UnityEngineAdapter(IUnityEngine unityEngine, ISimulationManager simulationManager)
{
_unityEngine = unityEngine ?? throw new ArgumentNullException(nameof(unityEngine));
_simulationManager = simulationManager ?? throw new ArgumentNullException(nameof(simulationManager));
}
/// <summary>
/// 获取指定ID的实体对象
/// </summary>
/// <param name="id">实体的唯一标识符</param>
/// <returns>对应的实体对象如果未找到则返回null</returns>
/// <remarks>
/// 该方法将仿真系统的实体ID转换为Unity场景中的GameObject
/// </remarks>
public object? GetEntity(string id)
{
return _unityEngine.GetGameObject(id);
}
/// <summary>
/// 将事件发布到外部仿真系统Unity引擎
/// </summary>
/// <typeparam name="T">事件类型</typeparam>
/// <param name="evt">要发布的事件对象</param>
/// <remarks>
/// 处理过程:
/// - 识别事件类型
/// - 转换为Unity事件
/// - 在Unity主线程中执行相应操作
/// </remarks>
public void PublishToExternalSimulation<T>(T evt)
{
if (evt is MissileFireEvent missileEvt)
{
// 获取发射者位置和朝向
var sender = _unityEngine.GetGameObject(missileEvt.SenderId);
if (sender != null)
{
// 在Unity主线程中实例化导弹
UnityMainThreadDispatcher.Instance.Enqueue(() =>
{
var missile = _unityEngine.InstantiateMissile(
MissilePrefabPath,
sender.transform.position,
sender.transform.rotation
);
// 设置导弹目标
var missileComponent = missile.GetComponent<MissileController>();
if (missileComponent != null)
{
missileComponent.SetTarget(missileEvt.TargetId);
}
});
}
}
// ... 处理其他事件类型
}
/// <summary>
/// 接收来自外部仿真系统Unity引擎的事件
/// </summary>
/// <typeparam name="T">事件类型</typeparam>
/// <param name="evt">接收到的事件对象</param>
/// <remarks>
/// 处理过程:
/// - 接收Unity事件
/// - 转换为仿真系统事件
/// - 分发到相应的处理器
/// </remarks>
public void ReceiveFromExternalSimulation<T>(T evt)
{
// 处理来自Unity引擎的事件
if (evt is CollisionEvent collisionEvt)
{
// 处理碰撞事件
_simulationManager.HandleCollision(collisionEvt);
}
}
/// <summary>
/// Unity生命周期方法更新
/// </summary>
/// <remarks>
/// 在每一帧执行:
/// - 更新实体状态
/// - 处理输入事件
/// - 同步仿真数据
/// </remarks>
private void Update()
{
// 在Unity的Update循环中同步状态
SyncSimulationState();
}
/// <summary>
/// 同步仿真状态
/// </summary>
/// <remarks>
/// 同步过程:
/// - 更新实体位置和朝向
/// - 同步物理状态
/// - 更新传感器数据
/// </remarks>
private void SyncSimulationState()
{
// 实现仿真状态同步逻辑
}
}
/// <summary>
/// Unity事件数据基类
/// </summary>
/// <remarks>
/// 用于封装Unity事件的基本信息
/// 所有具体的Unity事件类型都应该继承此类
/// </remarks>
public abstract class UnityEventData
{
/// <summary>
/// 获取或设置事件发送者的ID
/// </summary>
public string? SenderId { get; set; }
/// <summary>
/// 获取或设置事件发生的时间戳
/// </summary>
public float TimeStamp { get; set; }
}
/// <summary>
/// Unity碰撞事件数据
/// </summary>
/// <remarks>
/// 用于封装Unity物理碰撞事件的相关数据
/// 包含碰撞的详细信息
/// </remarks>
public class CollisionEvent : UnityEventData
{
/// <summary>
/// 获取或设置碰撞对象的ID
/// </summary>
public string? ColliderId { get; set; }
/// <summary>
/// 获取或设置碰撞点的位置
/// </summary>
public Vector3 CollisionPoint { get; set; }
/// <summary>
/// 获取或设置碰撞的冲量
/// </summary>
public float ImpulseForce { get; set; }
}
/// <summary>
/// Unity仿真示例类
/// </summary>
/// <remarks>
/// 该类演示了:
/// - Unity仿真系统的初始化
/// - MonoBehaviour组件的配置
/// - 事件系统的使用
/// 用于指导实际项目中的集成实现
/// </remarks>
public class UnitySimulation : MonoBehaviour
{
/// <summary>
/// 仿真管理器实例
/// </summary>
private readonly ISimulationManager _simulationManager;
/// <summary>
/// Unity引擎实例
/// </summary>
private readonly UnityEngineAdapter.IUnityEngine _unityEngine;
/// <summary>
/// Unity引擎适配器实例
/// </summary>
private UnityEngineAdapter _adapter;
/// <summary>
/// Unity生命周期方法初始化
/// </summary>
/// <remarks>
/// 初始化过程:
/// - 创建仿真管理器
/// - 创建引擎实例
/// - 配置适配器
/// - 初始化场景
/// </remarks>
private void Awake()
{
_simulationManager = new SimulationManager();
_unityEngine = new UnityEngineImplementation(); // 实际项目中需要实现这个类
// 创建并配置适配器
_adapter = gameObject.AddComponent<UnityEngineAdapter>();
_simulationManager.SetSimulationAdapter(_adapter);
// 初始化场景
InitializeScene();
}
/// <summary>
/// 初始化Unity场景
/// </summary>
/// <remarks>
/// 初始化过程:
/// - 加载必要的资源
/// - 创建初始实体
/// - 设置场景参数
/// </remarks>
private void InitializeScene()
{
// 实现场景初始化逻辑
}
/// <summary>
/// Unity生命周期方法销毁
/// </summary>
/// <remarks>
/// 清理过程:
/// - 释放资源
/// - 清理事件订阅
/// - 保存必要数据
/// </remarks>
private void OnDestroy()
{
// 清理资源和状态
CleanupSimulation();
}
/// <summary>
/// 清理仿真系统
/// </summary>
/// <remarks>
/// 清理过程:
/// - 停止所有协程
/// - 移除事件监听
/// - 销毁动态创建的对象
/// </remarks>
private void CleanupSimulation()
{
// 实现清理逻辑
}
}
#endif // 结束编译指令块

View File

@ -0,0 +1,128 @@
/**
* C++/CLI示例C++使ThreatSource库
*
* 1. C++/CLI项目
* 2. ThreatSource.dll
* 3.
*/
using namespace System;
using namespace ThreatSource::Simulation;
using namespace ThreatSource::Guidance;
using namespace ThreatSource::Sensor;
namespace ThreatSourceWrapper {
// 包装类用于在C++中使用仿真系统
public ref class IRMissileSimulationWrapper
{
private:
TestSimulationAdapter^ adapter;
SimulationEntity^ missile;
SimulationEntity^ target;
InfraredImagingGuidanceSystem^ guidanceSystem;
public:
IRMissileSimulationWrapper()
{
adapter = gcnew TestSimulationAdapter();
}
void RunSimulationExample()
{
try {
// 步骤1创建导弹实体
missile = gcnew SimulationEntity();
missile->Id = "missile_001";
missile->Position = Vector3(0, 0, 0);
missile->Velocity = Vector3(0, 0, 0);
missile->Mass = 100.0f; // kg
// 步骤2配置红外成像制导系统
guidanceSystem = gcnew InfraredImagingGuidanceSystem();
guidanceSystem->FieldOfView = 60.0f; // 视场角(度)
guidanceSystem->TrackingRange = 20000.0f; // 最大跟踪距离(米)
guidanceSystem->UpdateRate = 50; // 制导更新频率Hz
missile->GuidanceSystem = guidanceSystem;
// 步骤3设置目标
target = gcnew SimulationEntity();
target->Id = "target_001";
target->Position = Vector3(10000.0f, 1000.0f, 1000.0f); // 目标在10km外
target->Velocity = Vector3(-100.0f, 0.0f, 0.0f); // 目标以100m/s速度移动
InfraredSignature^ signature = gcnew InfraredSignature();
signature->Temperature = 400.0f; // 目标温度(开尔文)
signature->EmissivityFactor = 0.8f;
target->Signature = signature;
// 步骤4配置仿真参数
SimulationConfig^ config = gcnew SimulationConfig();
config->TimeStep = 0.02f; // 仿真步长(秒)
config->MaxSimulationTime = 60.0f; // 最大仿真时间(秒)
EnvironmentConditions^ env = gcnew EnvironmentConditions();
env->Temperature = 288.15f; // 环境温度(开尔文)
env->Pressure = 101325.0f; // 大气压力(帕)
env->Humidity = 0.5f; // 相对湿度
config->EnvironmentConditions = env;
// 步骤5注册事件处理
adapter->EntityUpdated += gcnew EntityUpdateHandler(this, &IRMissileSimulationWrapper::OnEntityUpdated);
adapter->GuidanceUpdate += gcnew GuidanceUpdateHandler(this, &IRMissileSimulationWrapper::OnGuidanceUpdate);
// 步骤6初始化仿真
adapter->Initialize(config);
adapter->AddEntity(missile);
adapter->AddEntity(target);
// 步骤7启动仿真
adapter->StartSimulation();
// 步骤8等待仿真结束
while (adapter->IsRunning)
{
System::Threading::Thread::Sleep(100);
}
// 步骤9获取仿真结果
SimulationResults^ results = adapter->GetSimulationResults();
Console::WriteLine(String::Format("仿真结束,命中精度: {0:F2}米", results->MissDistance));
}
catch (Exception^ e) {
Console::WriteLine(String::Format("仿真过程出错: {0}", e->Message));
}
}
private:
void OnEntityUpdated(SimulationEntity^ entity)
{
Console::WriteLine(String::Format("实体 {0} 位置更新: ({1:F2}, {2:F2}, {3:F2})",
entity->Id,
entity->Position.X,
entity->Position.Y,
entity->Position.Z));
}
void OnGuidanceUpdate(GuidanceInfo^ info)
{
Console::WriteLine(String::Format("制导更新: 距离目标 {0:F2}米", info->DistanceToTarget));
}
};
}
// 示例如何在原生C++代码中使用包装类
int main()
{
try {
auto simulation = gcnew ThreatSourceWrapper::IRMissileSimulationWrapper();
simulation->RunSimulationExample();
return 0;
}
catch (Exception^ e) {
Console::WriteLine(String::Format("错误: {0}", e->Message));
return 1;
}
}

View File

@ -0,0 +1,111 @@
using System;
using System.Threading.Tasks;
using ThreatSource.Simulation;
using ThreatSource.Guidance;
using ThreatSource.Sensor;
namespace ThreatSource.Examples
{
/// <summary>
/// 红外成像制导导弹仿真示例
/// 本示例展示了如何:
/// 1. 创建和配置一个红外成像制导导弹
/// 2. 设置仿真环境和参数
/// 3. 运行仿真并获取结果
/// </summary>
public class IRMissileSimulationExample
{
private TestSimulationAdapter _adapter;
private SimulationEntity _missile;
private SimulationEntity _target;
private InfraredImagingGuidanceSystem _guidanceSystem;
public async Task RunSimulationExample()
{
try
{
// 步骤1创建导弹实体
_missile = new SimulationEntity
{
Id = "missile_001",
Position = new Vector3(0, 0, 0),
Velocity = new Vector3(0, 0, 0),
Mass = 100.0f // kg
};
// 步骤2配置红外成像制导系统
_guidanceSystem = new InfraredImagingGuidanceSystem
{
FieldOfView = 60.0f, // 视场角(度)
TrackingRange = 20000.0f, // 最大跟踪距离(米)
UpdateRate = 50 // 制导更新频率Hz
};
_missile.GuidanceSystem = _guidanceSystem;
// 步骤3设置目标
_target = new SimulationEntity
{
Id = "target_001",
Position = new Vector3(10000.0f, 1000.0f, 1000.0f), // 目标在10km外
Velocity = new Vector3(-100.0f, 0.0f, 0.0f), // 目标以100m/s速度移动
Signature = new InfraredSignature
{
Temperature = 400.0f, // 目标温度(开尔文)
EmissivityFactor = 0.8f
}
};
// 步骤4配置仿真参数
var config = new SimulationConfig
{
TimeStep = 0.02f, // 仿真步长(秒)
MaxSimulationTime = 60.0f, // 最大仿真时间(秒)
EnvironmentConditions = new EnvironmentConditions
{
Temperature = 288.15f, // 环境温度(开尔文)
Pressure = 101325.0f, // 大气压力(帕)
Humidity = 0.5f // 相对湿度
}
};
// 步骤5创建仿真适配器并注册事件
_adapter = new TestSimulationAdapter();
_adapter.EntityUpdated += OnEntityUpdated;
_adapter.GuidanceUpdate += OnGuidanceUpdate;
// 步骤6初始化仿真
await _adapter.Initialize(config);
await _adapter.AddEntity(_missile);
await _adapter.AddEntity(_target);
// 步骤7启动仿真
await _adapter.StartSimulation();
// 步骤8等待仿真结束
while (_adapter.IsRunning)
{
await Task.Delay(100);
}
// 步骤9获取仿真结果
var results = await _adapter.GetSimulationResults();
Console.WriteLine($"仿真结束,命中精度: {results.MissDistance:F2}米");
}
catch (Exception ex)
{
Console.WriteLine($"仿真过程出错: {ex.Message}");
}
}
private void OnEntityUpdated(SimulationEntity entity)
{
Console.WriteLine($"实体 {entity.Id} 位置更新: ({entity.Position.X:F2}, {entity.Position.Y:F2}, {entity.Position.Z:F2})");
}
private void OnGuidanceUpdate(GuidanceInfo info)
{
Console.WriteLine($"制导更新: 距离目标 {info.DistanceToTarget:F2}米");
}
}
}

View File

@ -0,0 +1,123 @@
# 导弹仿真示例
本目录包含了使用仿真系统进行导弹仿真的示例代码。这些示例展示了如何配置和运行不同类型的导弹仿真。
## 关于本库
ThreatSource 是一个基于 .NET 8.0 的类库,提供了完整的导弹仿真功能。
## 系统要求
### C#/.NET 用户
- .NET 8.0 或更高版本
- 通过 NuGet 包管理器安装或直接引用 ThreatSource.dll
### C++用户
本库是一个 .NET 类库C++用户需要通过 C++/CLI 包装层来使用:
- Windows 操作系统
- Visual Studio 2019 或更高版本
- 创建 C++/CLI 项目并引用 ThreatSource.dll
## 示例文件
### C#示例 ([IRMissileSimulation.cs](IRMissileSimulation.cs))
红外成像制导导弹仿真示例,展示了:
- 如何创建和配置导弹实体
- 如何设置红外成像制导系统
- 如何配置仿真环境和参数
- 如何运行仿真并获取结果
### C++示例 ([IRMissileSimulation.cpp](IRMissileSimulation.cpp))
这是一个使用C++/CLI的示例代码展示了如何在C++项目中使用本库:
- 如何创建C++/CLI包装层
- 如何配置导弹实体
- 如何设置仿真参数
- 如何运行仿真并获取结果
## 使用说明
### C#/.NET使用方式
1. 创建仿真适配器
```csharp
var adapter = new TestSimulationAdapter();
```
2. 配置导弹和目标
```csharp
var missile = new SimulationEntity
{
Id = "missile_001",
Position = new Vector3(0, 0, 0),
// ... 其他配置
};
```
3. 设置仿真参数
```csharp
var simConfig = new SimulationConfig
{
TimeStep = 0.02f, // 仿真步长(秒)
MaxSimulationTime = 60.0f, // 最大仿真时间(秒)
// ... 其他配置
};
```
4. 运行仿真
```csharp
await adapter.Initialize(simConfig);
await adapter.StartSimulation();
```
### C++使用方式
1. 创建C++/CLI项目
- 在Visual Studio中创建新的C++/CLI项目
- 添加对 ThreatSource.dll 的引用
2. 创建包装类
```cpp
public ref class SimulationWrapper
{
private:
TestSimulationAdapter^ adapter;
public:
SimulationWrapper()
{
adapter = gcnew TestSimulationAdapter();
}
// ... 其他包装方法
};
```
3. 在C++代码中使用
```cpp
auto simulation = gcnew SimulationWrapper();
simulation->Initialize();
simulation->StartSimulation();
```
## 注意事项
1. 确保所有参数单位正确(米、秒、开尔文等)
2. 合理设置仿真时间步长,平衡精度和性能
3. 注意处理异步操作和事件回调
4. C++/CLI注意事项
- 仅支持Windows平台
- 需要正确配置项目的目标框架
- 注意托管和非托管资源的正确释放

51
docs/index.md Normal file
View File

@ -0,0 +1,51 @@
# 威胁源仿真库文档
欢迎使用威胁源仿真库文档。
## 简介
威胁源仿真库是一个用于模拟和仿真各种威胁源的.NET类库。它提供了以下主要功能
- 导弹仿真(包括各种类型的导弹)
- 目标仿真
- 传感器仿真
- 制导系统仿真
## 支持的开发语言
- C# (.NET)原生支持提供完整的API和功能
- C++通过C++/CLI包装层支持可以在C++项目中使用全部功能
## 快速开始
请参阅[入门指南](articles/intro.md)了解如何使用该库。该指南包含了C#和C++两种语言的使用示例。
## API文档
完整的API文档请参阅[API参考](api/toc.yml)。
## 集成示例
### 第三方引擎集成
- [集成示例说明](examples/Integration/README.md) - 第三方引擎集成的详细说明
- [虚幻引擎示例](examples/Integration/UEExample.cs) - 虚幻引擎集成示例代码
- [Unity引擎示例](examples/Integration/UnityExample.cs) - Unity引擎集成示例代码
## 示例说明
这些示例展示了如何将不同的游戏引擎与仿真系统集成:
1. 虚幻引擎(UE)示例
- 虚幻引擎与仿真系统的双向通信
- 实体信息的同步和转换
- 事件的发布和订阅
- 数据的适配和转换
2. Unity引擎示例
- Unity引擎与仿真系统的双向通信
- GameObject与实体的映射和转换
- MonoBehaviour生命周期管理
- 事件系统的使用
所有示例代码都提供了详细的注释和说明,可以作为实际开发的参考。

9
docs/toc.yml Normal file
View File

@ -0,0 +1,9 @@
- name: 文档首页
href: index.md
- name: 入门指南
href: articles/intro.md
- name: API文档
href: api/
homepage: api/toc.yml
- name: DocFX文档生成指南
href: articles/docfx-guide.md