2024-09-12 00:17:21 -07:00
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
public class SimManager : MonoBehaviour
|
|
|
|
{
|
|
|
|
[SerializeField]
|
|
|
|
public SimulationConfig simulationConfig;
|
|
|
|
|
|
|
|
|
|
|
|
private List<Missile> missiles = new List<Missile>();
|
|
|
|
private List<Target> targets = new List<Target>();
|
|
|
|
private float currentTime = 0f;
|
|
|
|
private float endTime = 100f; // Set an appropriate end time
|
|
|
|
private bool simulationRunning = false;
|
|
|
|
|
|
|
|
private Assignment _assignment;
|
|
|
|
|
|
|
|
|
|
|
|
void Start() {
|
|
|
|
// Slow down time by simulationConfig.timeScale
|
|
|
|
Time.timeScale = simulationConfig.timeScale;
|
|
|
|
Time.fixedDeltaTime = Time.timeScale * 0.02f;
|
|
|
|
Time.maximumDeltaTime = Time.timeScale * 0.15f;
|
|
|
|
InitializeSimulation();
|
|
|
|
simulationRunning = true;
|
|
|
|
}
|
|
|
|
|
2024-09-12 10:36:45 -07:00
|
|
|
private void InitializeSimulation()
|
2024-09-12 00:17:21 -07:00
|
|
|
{
|
|
|
|
// Create missiles based on config
|
|
|
|
foreach (var swarmConfig in simulationConfig.missile_swarm_configs)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < swarmConfig.num_agents; i++) {
|
|
|
|
var missile = CreateMissile(swarmConfig.agent_config);
|
|
|
|
missiles.Add(missile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
targets.Add(target);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-12 10:36:45 -07:00
|
|
|
_assignment = new ThreatAssignment();
|
2024-09-12 00:17:21 -07:00
|
|
|
// Perform initial assignment
|
|
|
|
AssignMissilesToTargets();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void AssignMissilesToTargets()
|
|
|
|
{
|
|
|
|
// Convert Missile and Target lists to Agent lists
|
|
|
|
List<Agent> missileAgents = new List<Agent>(missiles.ConvertAll(m => m as Agent));
|
|
|
|
List<Agent> targetAgents = new List<Agent>(targets.ConvertAll(t => t as Agent));
|
|
|
|
|
|
|
|
// Perform the assignment
|
|
|
|
_assignment.Assign(missileAgents, targetAgents);
|
|
|
|
|
|
|
|
// Apply the assignments to the missiles
|
|
|
|
foreach (var assignment in _assignment.Assignments)
|
|
|
|
{
|
|
|
|
Missile missile = missiles[assignment.MissileIndex];
|
|
|
|
Target target = targets[assignment.TargetIndex];
|
|
|
|
missile.AssignTarget(target);
|
|
|
|
Debug.Log($"Missile {missile.name} assigned to target {target.name}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private Missile CreateMissile(AgentConfig config)
|
|
|
|
{
|
|
|
|
// Load the missile prefab from Resources
|
|
|
|
GameObject missilePrefab = Resources.Load<GameObject>($"Prefabs/{config.prefabName}");
|
|
|
|
if (missilePrefab == null)
|
|
|
|
{
|
|
|
|
Debug.LogError($"Missile prefab '{config.prefabName}' not found in Resources/Prefabs folder.");
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Apply noise to the initial position
|
|
|
|
Vector3 noiseOffset = Utilities.GenerateRandomNoise(config.standard_deviation.position);
|
|
|
|
Vector3 noisyPosition = config.initial_state.position + noiseOffset;
|
|
|
|
|
|
|
|
// Instantiate the missile with the noisy position
|
|
|
|
GameObject missileObject = Instantiate(missilePrefab, noisyPosition, Quaternion.Euler(config.initial_state.rotation));
|
|
|
|
|
|
|
|
switch(config.dynamic_config.sensor_config.type) {
|
|
|
|
case SensorType.IDEAL:
|
|
|
|
missileObject.AddComponent<IdealSensor>();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Debug.LogError($"Sensor type '{config.dynamic_config.sensor_config.type}' not found.");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set initial velocity
|
|
|
|
Rigidbody missileRigidbody = missileObject.GetComponent<Rigidbody>();
|
|
|
|
// Apply noise to the initial velocity
|
|
|
|
Vector3 velocityNoise = Utilities.GenerateRandomNoise(config.standard_deviation.velocity);
|
|
|
|
Vector3 noisyVelocity = config.initial_state.velocity + velocityNoise;
|
|
|
|
missileRigidbody.velocity = noisyVelocity;
|
|
|
|
|
|
|
|
|
|
|
|
Missile missile = missileObject.GetComponent<Missile>();
|
|
|
|
missile.SetAgentConfig(config);
|
|
|
|
if (missile == null)
|
|
|
|
{
|
|
|
|
Debug.LogError($"Missile component not found on prefab '{config.prefabName}'.");
|
|
|
|
Destroy(missileObject);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize missile properties
|
|
|
|
//missile.Initialize(config);
|
|
|
|
|
|
|
|
return missile;
|
|
|
|
}
|
|
|
|
private Target CreateTarget(AgentConfig config)
|
|
|
|
{
|
|
|
|
// Load the target prefab from Resources
|
|
|
|
GameObject targetPrefab = Resources.Load<GameObject>($"Prefabs/{config.prefabName}");
|
|
|
|
if (targetPrefab == null)
|
|
|
|
{
|
|
|
|
Debug.LogError($"Target prefab '{config.prefabName}' not found in Resources/Prefabs folder.");
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Apply noise to the initial position
|
|
|
|
Vector3 noiseOffset = Utilities.GenerateRandomNoise(config.standard_deviation.position);
|
|
|
|
Vector3 noisyPosition = config.initial_state.position + noiseOffset;
|
|
|
|
|
|
|
|
// Instantiate the target with the noisy position
|
|
|
|
GameObject targetObject = Instantiate(targetPrefab, noisyPosition, Quaternion.Euler(config.initial_state.rotation));
|
|
|
|
|
|
|
|
// Set initial velocity with noise
|
|
|
|
Rigidbody targetRigidbody = targetObject.GetComponent<Rigidbody>();
|
|
|
|
Vector3 velocityNoise = Utilities.GenerateRandomNoise(config.standard_deviation.velocity);
|
|
|
|
Vector3 noisyVelocity = config.initial_state.velocity + velocityNoise;
|
|
|
|
targetRigidbody.velocity = noisyVelocity;
|
|
|
|
|
|
|
|
Target target = targetObject.GetComponent<Target>();
|
|
|
|
target.SetAgentConfig(config);
|
|
|
|
|
|
|
|
if (target == null)
|
|
|
|
{
|
|
|
|
Debug.LogError($"Target component not found on prefab '{config.prefabName}'.");
|
|
|
|
Destroy(targetObject);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize target properties
|
|
|
|
//target.Initialize(config);
|
|
|
|
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void RestartSimulation()
|
|
|
|
{
|
|
|
|
// Reset simulation time
|
|
|
|
currentTime = 0f;
|
|
|
|
simulationRunning = true;
|
|
|
|
|
|
|
|
// Clear existing missiles and targets
|
|
|
|
foreach (var missile in missiles)
|
|
|
|
{
|
|
|
|
if (missile != null)
|
|
|
|
{
|
|
|
|
Destroy(missile.gameObject);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
missiles.Clear();
|
|
|
|
|
|
|
|
foreach (var target in targets)
|
|
|
|
{
|
|
|
|
if (target != null)
|
|
|
|
{
|
|
|
|
Destroy(target.gameObject);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
targets.Clear();
|
|
|
|
|
|
|
|
InitializeSimulation();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Update()
|
|
|
|
{
|
|
|
|
// Check if all missiles have terminated
|
|
|
|
bool allMissilesTerminated = true;
|
|
|
|
foreach (var missile in missiles)
|
|
|
|
{
|
2024-09-12 10:36:45 -07:00
|
|
|
if (missile != null && !missile.IsHit() && !missile.IsMiss())
|
2024-09-12 00:17:21 -07:00
|
|
|
{
|
|
|
|
allMissilesTerminated = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If all missiles have terminated, restart the simulation
|
|
|
|
if (allMissilesTerminated)
|
|
|
|
{
|
|
|
|
RestartSimulation();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (simulationRunning && currentTime < endTime)
|
|
|
|
{
|
|
|
|
currentTime += Time.deltaTime;
|
|
|
|
}
|
|
|
|
else if (currentTime >= endTime)
|
|
|
|
{
|
|
|
|
simulationRunning = false;
|
|
|
|
Debug.Log("Simulation completed.");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|