Refactor "Target" -> "Threat"

This commit is contained in:
Daniel Lovell
2024-09-24 19:24:50 -07:00
parent 4293bfec94
commit 17af733afb
21 changed files with 112 additions and 222 deletions

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: df58f75918cee2c48bb2986daa4c7f8d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,98 +0,0 @@
syntax = "proto3";
package SimulationConfigProto;
message ProtobufConfig {
double step_time = 1;
repeated MissileConfigProto missile_configs = 2;
repeated TargetConfigProto target_configs = 3;
}
enum MissileTypeProto {
HYDRA_70 = 0;
MICROMISSILE = 1;
}
enum TargetTypeProto {
DRONE = 0;
MISSILE = 1;
}
enum ConfigColorProto {
BLUE = 0;
GREEN = 1;
RED = 2;
}
enum LineStyleProto {
DOTTED = 0;
SOLID = 1;
}
enum MarkerProto {
TRIANGLE_UP = 0;
TRIANGLE_DOWN = 1;
SQUARE = 2;
}
enum SensorTypeProto {
IDEAL = 0;
}
message Vector3Proto {
double x = 1;
double y = 2;
double z = 3;
}
message InitialStateProto {
Vector3Proto position = 1;
Vector3Proto velocity = 2;
}
message LaunchConfigProto {
double launch_time = 1;
}
message SensorConfigProto {
SensorTypeProto type = 1;
double frequency = 2;
}
message DynamicConfigProto {
LaunchConfigProto launch_config = 1;
SensorConfigProto sensor_config = 2;
}
message PlottingConfigProto {
ConfigColorProto color = 1;
LineStyleProto linestyle = 2;
MarkerProto marker = 3;
}
message SubmunitionAgentConfigProto {
MissileTypeProto missile_type = 1;
InitialStateProto initial_state = 2;
DynamicConfigProto dynamic_config = 3;
PlottingConfigProto plotting_config = 4;
}
message SubmunitionsConfigProto {
int32 num_submunitions = 1;
LaunchConfigProto launch_config = 2;
SubmunitionAgentConfigProto agent_config = 3;
}
message MissileConfigProto {
MissileTypeProto missile_type = 1;
InitialStateProto initial_state = 2;
DynamicConfigProto dynamic_config = 3;
PlottingConfigProto plotting_config = 4;
SubmunitionsConfigProto submunitions_config = 5;
}
message TargetConfigProto {
TargetTypeProto target_type = 1;
InitialStateProto initial_state = 2;
PlottingConfigProto plotting_config = 3;
}

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: a739996d4385c0f408a96e21ca42a239
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -2,18 +2,18 @@ using System;
using System.Collections.Generic;
using UnityEngine;
// The assignment class is an interface for assigning a target to each missile.
// The assignment class is an interface for assigning a threat to each missile.
public interface IAssignment {
// Assignment item type.
// The first element corresponds to the missile index, and the second element
// corresponds to the target index.
// corresponds to the threat index.
public struct AssignmentItem {
public int MissileIndex;
public int TargetIndex;
public int ThreatIndex;
public AssignmentItem(int missileIndex, int targetIndex) {
public AssignmentItem(int missileIndex, int threatIndex) {
MissileIndex = missileIndex;
TargetIndex = targetIndex;
ThreatIndex = threatIndex;
}
}
@@ -34,13 +34,13 @@ public interface IAssignment {
}
// Get the list of active target indices.
protected static List<int> GetActiveTargetIndices(List<Agent> targets) {
List<int> activeTargetIndices = new List<int>();
for (int targetIndex = 0; targetIndex < targets.Count; targetIndex++) {
if (!targets[targetIndex].IsHit()) {
activeTargetIndices.Add(targetIndex);
protected static List<int> GetActiveThreatIndices(List<Agent> threats) {
List<int> activeThreatIndices = new List<int>();
for (int threatIndex = 0; threatIndex < threats.Count; threatIndex++) {
if (!threats[threatIndex].IsHit()) {
activeThreatIndices.Add(threatIndex);
}
}
return activeTargetIndices;
return activeThreatIndices;
}
}

View File

@@ -17,19 +17,19 @@ public class RoundRobinAssignment : IAssignment {
return assignments;
}
List<int> activeTargetIndices = IAssignment.GetActiveTargetIndices(targets);
if (activeTargetIndices.Count == 0) {
List<int> activeThreatIndices = IAssignment.GetActiveThreatIndices(targets);
if (activeThreatIndices.Count == 0) {
return assignments;
}
foreach (int missileIndex in assignableMissileIndices) {
int nextActiveTargetIndex = activeTargetIndices.FindIndex(index => index > prevTargetIndex);
int nextActiveTargetIndex = activeThreatIndices.FindIndex(index => index > prevTargetIndex);
if (nextActiveTargetIndex == -1) {
nextActiveTargetIndex = 0;
}
int nextTargetIndex = activeTargetIndices[nextActiveTargetIndex];
int nextTargetIndex = activeThreatIndices[nextActiveTargetIndex];
assignments.Add(new IAssignment.AssignmentItem(missileIndex, nextTargetIndex));
prevTargetIndex = nextTargetIndex;
}

View File

@@ -16,14 +16,14 @@ public class ThreatAssignment : IAssignment {
return assignments;
}
List<int> activeTargetIndices = IAssignment.GetActiveTargetIndices(targets);
if (activeTargetIndices.Count == 0) {
List<int> activeThreatIndices = IAssignment.GetActiveThreatIndices(targets);
if (activeThreatIndices.Count == 0) {
return assignments;
}
Vector3 positionToDefend = Vector3.zero;
List<ThreatInfo> threatInfos =
CalculateThreatLevels(targets, activeTargetIndices, positionToDefend);
CalculateThreatLevels(targets, activeThreatIndices, positionToDefend);
foreach (int missileIndex in assignableMissileIndices) {
if (missiles[missileIndex].HasAssignedTarget())
@@ -54,11 +54,11 @@ public class ThreatAssignment : IAssignment {
return assignments;
}
private List<ThreatInfo> CalculateThreatLevels(List<Agent> targets, List<int> activeTargetIndices,
private List<ThreatInfo> CalculateThreatLevels(List<Agent> targets, List<int> activeThreatIndices,
Vector3 missilesMeanPosition) {
List<ThreatInfo> threatInfos = new List<ThreatInfo>();
foreach (int targetIndex in activeTargetIndices) {
foreach (int targetIndex in activeThreatIndices) {
Agent target = targets[targetIndex];
float distanceToMean = Vector3.Distance(target.transform.position, missilesMeanPosition);
float velocityMagnitude = target.GetVelocity().magnitude;

View File

@@ -48,10 +48,10 @@ public static class ConfigLoader {
PrintSwarmConfig(config.missile_swarm_configs[i], $"Missile Swarm {i + 1}");
}
Debug.Log("Target Swarm Configurations:");
Debug.Log("Threat Swarm Configurations:");
for (int i = 0; i < config.target_swarm_configs.Count; i++)
{
PrintSwarmConfig(config.target_swarm_configs[i], $"Target Swarm {i + 1}");
PrintSwarmConfig(config.target_swarm_configs[i], $"Threat Swarm {i + 1}");
}
}
@@ -66,7 +66,7 @@ public static class ConfigLoader {
{
Debug.Log(" Agent Configuration:");
Debug.Log($" Missile Type: {agentConfig.missile_type}");
Debug.Log($" Target Type: {agentConfig.target_type}");
Debug.Log($" Threat Type: {agentConfig.target_type}");
PrintInitialState(agentConfig.initial_state);
PrintStandardDeviation(agentConfig.standard_deviation);
PrintDynamicConfig(agentConfig.dynamic_config);

View File

@@ -13,7 +13,7 @@ public class SimulationConfig {
[Header("Missile Swarm Configurations")]
public List<SwarmConfig> missile_swarm_configs = new List<SwarmConfig>();
[Header("Target Swarm Configurations")]
[Header("Threat Swarm Configurations")]
public List<SwarmConfig> target_swarm_configs = new List<SwarmConfig>();
}
@@ -32,7 +32,7 @@ public class SwarmConfig {
[Serializable]
public class AgentConfig {
public MissileType missile_type;
public TargetType target_type;
public ThreatType target_type;
public InitialState initial_state;
public StandardDeviation standard_deviation;
public DynamicConfig dynamic_config;
@@ -47,7 +47,7 @@ public class AgentConfig {
dynamic_config = submunitionConfig.dynamic_config,
plotting_config = submunitionConfig.plotting_config,
// Set other fields as needed, using default values if not present in SubmunitionAgentConfig
target_type = TargetType.DRONE, // Or another default value
target_type = ThreatType.DRONE, // Or another default value
submunitions_config = null // Or a default value if needed
};
}
@@ -102,7 +102,7 @@ public class SensorConfig {
[Serializable]
public class TargetConfig {
public TargetType target_type;
public ThreatType target_type;
public InitialState initial_state;
public PlottingConfig plotting_config;
public string prefabName;
@@ -112,7 +112,7 @@ public class TargetConfig {
[JsonConverter(typeof(StringEnumConverter))]
public enum MissileType { HYDRA_70, MICROMISSILE }
[JsonConverter(typeof(StringEnumConverter))]
public enum TargetType { DRONE, MISSILE }
public enum ThreatType { DRONE, MISSILE }
[JsonConverter(typeof(StringEnumConverter))]
public enum ConfigColor { BLUE, GREEN, RED }
[JsonConverter(typeof(StringEnumConverter))]

View File

@@ -7,24 +7,24 @@ using System;
public class IADS : MonoBehaviour {
public enum TargetStatus { UNASSIGNED, ASSIGNED, HIT, DEGRADED, DESTROYED }
// Look up target status by unique target ID
// Look up threat status by unique threat ID
public Dictionary<string, TargetStatus> _targetStatusDictionary;
private List<Target> _targets;
private List<Threat> _threats;
private List<Missile> _missiles;
private List<Vessel> _vessels;
public delegate void RegisterNewTargetDelegate(Target target);
public delegate void RegisterNewTargetDelegate(Threat threat);
public event RegisterNewTargetDelegate OnRegisterNewTarget;
void Start() {
_targets = new List<Target>();
_threats = new List<Threat>();
}
public void RegisterNewTarget(Target target) {
_targets.Add(target);
OnRegisterNewTarget?.Invoke(target);
public void RegisterNewTarget(Threat threat) {
_threats.Add(threat);
OnRegisterNewTarget?.Invoke(threat);
}
}

View File

@@ -48,6 +48,6 @@ public class Hydra70 : Missile {
}
break;
}
SimManager.Instance.AssignMissilesToTargets(submunitions);
SimManager.Instance.AssignMissilesToThreats(submunitions);
}
}

View File

@@ -13,19 +13,19 @@ public class Micromissile : Missile {
_elapsedTime += deltaTime;
Vector3 accelerationInput = Vector3.zero;
if (HasAssignedTarget()) {
// Update the target model (assuming we have a target model)
// TODO: Implement target model update logic
// Update the threat model (assuming we have a threat model)
// TODO: Implement threat model update logic
// Correct the state of the target model at the sensor frequency
// Correct the state of the threat model at the sensor frequency
float sensorUpdatePeriod = 1f / _agentConfig.dynamic_config.sensor_config.frequency;
if (_elapsedTime >= sensorUpdatePeriod) {
// TODO: Implement guidance filter to estimate state from sensor output
// For now, we'll use the target's actual state
// For now, we'll use the threat's actual state
_sensorOutput = GetComponent<Sensor>().Sense(_target);
_elapsedTime = 0;
}
// Check whether the target should be considered a miss
// Check whether the threat should be considered a miss
SensorOutput sensorOutput = GetComponent<Sensor>().Sense(_target);
if (sensorOutput.velocity.range > 1000f) {
this.MarkAsMiss();

View File

@@ -78,7 +78,7 @@ public class Missile : Agent {
}
// Check if the collision is with another Agent
Agent otherAgent = other.gameObject.GetComponentInParent<Agent>();
if (otherAgent != null && otherAgent.GetComponent<Target>() != null) {
if (otherAgent != null && otherAgent.GetComponent<Threat>() != null) {
// Check kill probability before marking as hit
float killProbability = _staticConfig.hitConfig.killProbability;
GameObject markerObject = Instantiate(Resources.Load<GameObject>("Prefabs/HitMarkerPrefab"),

View File

@@ -41,14 +41,14 @@ public class SimMonitor : MonoBehaviour
private void ExportTelemetry()
{
float time = (float)SimManager.Instance.GetElapsedSimulationTime();
foreach (var agent in SimManager.Instance.GetActiveTargets().Cast<Agent>().Concat(SimManager.Instance.GetActiveMissiles().Cast<Agent>()))
foreach (var agent in SimManager.Instance.GetActiveThreats().Cast<Agent>().Concat(SimManager.Instance.GetActiveMissiles().Cast<Agent>()))
{
Vector3 pos = agent.transform.position;
if(pos == Vector3.zero) {
continue;
}
Vector3 vel = agent.GetComponent<Rigidbody>().velocity;
string type = agent is Target ? "T" : "M";
string type = agent is Threat ? "T" : "M";
writer.WriteLine($"{time:F2},{agent.name},{pos.x:F2},{pos.y:F2},{pos.z:F2},{vel.x:F2},{vel.y:F2},{vel.z:F2},{(int)agent.GetFlightPhase()},{type}");
}

View File

@@ -21,9 +21,9 @@ public class SimManager : MonoBehaviour {
private List<Missile> _missiles = new List<Missile>();
private List<Missile> _activeMissiles = new List<Missile>();
private List<Target> _unassignedTargets = new List<Target>();
private List<Target> _targets = new List<Target>();
private List<Target> _activeTargets = new List<Target>();
private List<Threat> _unassignedThreats = new List<Threat>();
private List<Threat> _threats = new List<Threat>();
private List<Threat> _activeThreats = new List<Threat>();
private float _elapsedSimulationTime = 0f;
private float endTime = 100f; // Set an appropriate end time
private bool simulationRunning = false;
@@ -46,13 +46,13 @@ public class SimManager : MonoBehaviour {
return _activeMissiles;
}
public List<Target> GetActiveTargets() {
return _activeTargets;
public List<Threat> GetActiveThreats() {
return _activeThreats;
}
public List<Agent> GetActiveAgents() {
return _activeMissiles.ConvertAll(missile => missile as Agent)
.Concat(_activeTargets.ConvertAll(target => target as Agent))
.Concat(_activeThreats.ConvertAll(threat => threat as Agent))
.ToList();
}
@@ -112,22 +112,25 @@ public class SimManager : MonoBehaviour {
}
}
List<Target> targets = new List<Target>();
List<Threat> targets = new List<Threat>();
// Create targets based on config
foreach (var swarmConfig in simulationConfig.target_swarm_configs) {
for (int i = 0; i < swarmConfig.num_agents; i++) {
var target = CreateTarget(swarmConfig.agent_config);
target.OnAgentHit += RegisterTargetHit;
target.OnAgentMiss += RegisterTargetMiss;
var threat = CreateThreat(swarmConfig.agent_config);
threat.OnAgentHit += RegisterThreatHit;
threat.OnAgentMiss += RegisterThreatMiss;
}
}
_assignmentScheme = new ThreatAssignment();
// Invoke the simulation started event to let listeners
// know to invoke their own handler behavior
OnSimulationStarted?.Invoke();
}
public void AssignMissilesToTargets() {
AssignMissilesToTargets(_missiles);
public void AssignMissilesToThreats() {
AssignMissilesToThreats(_missiles);
}
public void RegisterMissileHit(Agent missile) {
@@ -142,15 +145,15 @@ public class SimManager : MonoBehaviour {
}
}
public void RegisterTargetHit(Agent target) {
if (target is Target targetComponent) {
_activeTargets.Remove(targetComponent);
public void RegisterThreatHit(Agent threat) {
if (threat is Threat targetComponent) {
_activeThreats.Remove(targetComponent);
}
}
public void RegisterTargetMiss(Agent target) {
if (target is Target targetComponent) {
_unassignedTargets.Add(targetComponent);
public void RegisterThreatMiss(Agent threat) {
if (threat is Threat targetComponent) {
_unassignedThreats.Add(targetComponent);
}
}
@@ -158,11 +161,11 @@ public class SimManager : MonoBehaviour {
/// Assigns the specified list of missiles to available targets based on the assignment scheme.
/// </summary>
/// <param name="missilesToAssign">The list of missiles to assign.</param>
public void AssignMissilesToTargets(List<Missile> missilesToAssign) {
// Convert Missile and Target lists to Agent lists
public void AssignMissilesToThreats(List<Missile> missilesToAssign) {
// Convert Missile and Threat lists to Agent lists
List<Agent> missileAgents = new List<Agent>(missilesToAssign.ConvertAll(m => m as Agent));
// Convert Target list to Agent list, excluding already assigned targets
List<Agent> targetAgents = _unassignedTargets.ToList<Agent>();
// Convert Threat list to Agent list, excluding already assigned targets
List<Agent> targetAgents = _unassignedThreats.ToList<Agent>();
// Perform the assignment
IEnumerable<IAssignment.AssignmentItem> assignments =
@@ -172,14 +175,14 @@ public class SimManager : MonoBehaviour {
foreach (var assignment in assignments) {
if (assignment.MissileIndex < missilesToAssign.Count) {
Missile missile = missilesToAssign[assignment.MissileIndex];
Target target = _unassignedTargets[assignment.TargetIndex];
missile.AssignTarget(target);
Debug.Log($"Missile {missile.name} assigned to target {target.name}");
Threat threat = _unassignedThreats[assignment.ThreatIndex];
missile.AssignTarget(threat);
Debug.Log($"Missile {missile.name} assigned to threat {threat.name}");
}
}
// TODO this whole function should be optimized
_unassignedTargets.RemoveAll(
target => missilesToAssign.Any(missile => missile.GetAssignedTarget() == target));
_unassignedThreats.RemoveAll(
threat => missilesToAssign.Any(missile => missile.GetAssignedTarget() == threat));
}
/// <summary>
@@ -209,38 +212,38 @@ public class SimManager : MonoBehaviour {
_missiles.Add(missileObject.GetComponent<Missile>());
_activeMissiles.Add(missileObject.GetComponent<Missile>());
// Assign a unique and simple target ID
// Assign a unique and simple ID
int missileId = _missiles.Count;
missileObject.name = $"{config.missile_type}_Missile_{missileId}";
return missileObject.GetComponent<Missile>();
}
/// <summary>
/// Creates a target based on the provided configuration.
/// Creates a threat based on the provided configuration.
/// </summary>
/// <param name="config">Configuration settings for the target.</param>
/// <returns>The created Target instance, or null if creation failed.</returns>
private Target CreateTarget(AgentConfig config) {
/// <param name="config">Configuration settings for the threat.</param>
/// <returns>The created Threat instance, or null if creation failed.</returns>
private Threat CreateThreat(AgentConfig config) {
string prefabName = config.target_type switch {
TargetType.DRONE => "DroneTarget", TargetType.MISSILE => "MissileTarget",
_ => throw new System.ArgumentException($"Unsupported target type: {config.target_type}")
ThreatType.DRONE => "DroneTarget", ThreatType.MISSILE => "MissileTarget",
_ => throw new System.ArgumentException($"Unsupported threat type: {config.target_type}")
};
GameObject targetObject = CreateAgent(config, prefabName);
if (targetObject == null)
GameObject threatObject = CreateAgent(config, prefabName);
if (threatObject == null)
return null;
_targets.Add(targetObject.GetComponent<Target>());
_activeTargets.Add(targetObject.GetComponent<Target>());
_unassignedTargets.Add(targetObject.GetComponent<Target>());
_threats.Add(threatObject.GetComponent<Threat>());
_activeThreats.Add(threatObject.GetComponent<Threat>());
_unassignedThreats.Add(threatObject.GetComponent<Threat>());
// Assign a unique and simple target ID
int targetId = _targets.Count;
targetObject.name = $"{config.target_type}_Target_{targetId}";
return targetObject.GetComponent<Target>();
// Assign a unique and simple ID
int targetId = _threats.Count;
threatObject.name = $"{config.target_type}_Target_{targetId}";
return threatObject.GetComponent<Threat>();
}
/// <summary>
/// Creates an agent (missile or target) based on the provided configuration and prefab name.
/// Creates an agent (missile or threat) based on the provided configuration and prefab name.
/// </summary>
/// <param name="config">Configuration settings for the agent.</param>
/// <param name="prefabName">Name of the prefab to instantiate.</param>
@@ -292,15 +295,15 @@ public class SimManager : MonoBehaviour {
}
}
foreach (var target in _targets) {
if (target != null) {
Destroy(target.gameObject);
foreach (var threat in _threats) {
if (threat != null) {
Destroy(threat.gameObject);
}
}
_missiles.Clear();
_targets.Clear();
_unassignedTargets.Clear();
_threats.Clear();
_unassignedThreats.Clear();
StartSimulation();
}

View File

@@ -2,7 +2,7 @@ using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DroneTarget : Target {
public class DroneTarget : Threat {
// Start is called before the first frame update
protected override void Start() {
base.Start();

View File

@@ -2,7 +2,7 @@ using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class Target : Agent {
public abstract class Threat : Agent {
public override bool IsAssignable() {
return false;
}

View File

@@ -70,7 +70,7 @@ public class CameraController : MonoBehaviour
public bool _autoRotate = false;
/// <summary>
/// Target transform for orbit rotation.
/// Threat transform for orbit rotation.
/// </summary>
public Transform target;

View File

@@ -19,7 +19,7 @@ public class BotStatusDialog : UIDialog
submunitions.SetIsSelectable(false);
UISelectableEntry targets = CreateSelectableEntry();
targets.SetTextContent(new List<string>(new string[] { "Targets" }));
targets.SetTextContent(new List<string>(new string[] { "Threats" }));
targets.SetIsSelectable(false);
SetDialogEntries(new List<UISelectableEntry>(new UISelectableEntry[] { missiles, submunitions, targets }));