2024-09-14 15:00:35 -07:00
|
|
|
using UnityEngine;
|
|
|
|
using System.Collections;
|
|
|
|
using System.IO;
|
|
|
|
using System;
|
|
|
|
using System.Linq;
|
2024-10-02 00:30:21 -07:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Threading;
|
2024-09-14 15:00:35 -07:00
|
|
|
|
|
|
|
public class SimMonitor : MonoBehaviour
|
|
|
|
{
|
2024-10-02 00:30:21 -07:00
|
|
|
private const float _updateRate = 0.1f; // 100 Hz
|
|
|
|
private string _telemetryBinPath;
|
|
|
|
private string _eventLogPath;
|
|
|
|
private Coroutine _monitorRoutine;
|
|
|
|
|
|
|
|
private string _sessionDirectory;
|
|
|
|
|
|
|
|
|
|
|
|
private FileStream _telemetryFileStream;
|
|
|
|
private BinaryWriter _telemetryBinaryWriter;
|
|
|
|
|
|
|
|
[SerializeField]
|
|
|
|
private List<EventRecord> _eventLogCache;
|
|
|
|
|
|
|
|
[System.Serializable]
|
|
|
|
private class EventRecord
|
|
|
|
{
|
|
|
|
public float Time;
|
|
|
|
public float PositionX;
|
|
|
|
public float PositionY;
|
|
|
|
public float PositionZ;
|
|
|
|
public string EventType;
|
|
|
|
public string Details;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void Awake() {
|
|
|
|
InitializeSessionDirectory();
|
|
|
|
}
|
2024-09-14 15:00:35 -07:00
|
|
|
|
|
|
|
private void Start()
|
|
|
|
{
|
2024-10-02 00:30:21 -07:00
|
|
|
SimManager.Instance.OnSimulationStarted += RegisterSimulationStarted;
|
2024-09-14 15:00:35 -07:00
|
|
|
SimManager.Instance.OnSimulationEnded += RegisterSimulationEnded;
|
2024-10-02 00:30:21 -07:00
|
|
|
SimManager.Instance.OnNewThreat += RegisterNewThreat;
|
|
|
|
SimManager.Instance.OnNewInterceptor += RegisterNewInterceptor;
|
2024-09-14 15:00:35 -07:00
|
|
|
}
|
|
|
|
|
2024-10-02 00:30:21 -07:00
|
|
|
private void InitializeSessionDirectory() {
|
|
|
|
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
|
|
|
|
_sessionDirectory = Application.persistentDataPath + $"\\Telemetry\\Logs\\{timestamp}";
|
|
|
|
Directory.CreateDirectory(_sessionDirectory);
|
|
|
|
Debug.Log($"Monitoring simulation logs to {_sessionDirectory}");
|
|
|
|
}
|
|
|
|
|
|
|
|
private void InitializeLogFiles()
|
2024-09-14 15:00:35 -07:00
|
|
|
{
|
|
|
|
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
|
2024-10-02 00:30:21 -07:00
|
|
|
|
|
|
|
_eventLogPath = Path.Combine(_sessionDirectory, $"sim_events_{timestamp}.csv");
|
|
|
|
|
|
|
|
// Initialize the event log cache
|
|
|
|
_eventLogCache = new List<EventRecord>();
|
|
|
|
|
|
|
|
_telemetryBinPath = Path.Combine(_sessionDirectory, $"sim_telemetry_{timestamp}.bin");
|
|
|
|
|
|
|
|
// Open the file stream and binary writer for telemetry data
|
|
|
|
_telemetryFileStream = new FileStream(_telemetryBinPath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
|
|
|
|
_telemetryBinaryWriter = new BinaryWriter(_telemetryFileStream);
|
|
|
|
|
|
|
|
Debug.Log("Log files initialized successfully.");
|
|
|
|
}
|
|
|
|
|
|
|
|
private void CloseLogFiles() {
|
|
|
|
if (_telemetryBinaryWriter != null)
|
|
|
|
{
|
|
|
|
_telemetryBinaryWriter.Flush();
|
|
|
|
_telemetryBinaryWriter.Close();
|
|
|
|
_telemetryBinaryWriter = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_telemetryFileStream != null)
|
|
|
|
{
|
|
|
|
_telemetryFileStream.Close();
|
|
|
|
_telemetryFileStream = null;
|
|
|
|
}
|
|
|
|
|
2024-09-14 15:00:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private IEnumerator MonitorRoutine()
|
|
|
|
{
|
|
|
|
while (true)
|
|
|
|
{
|
2024-10-02 00:30:21 -07:00
|
|
|
RecordTelemetry();
|
|
|
|
yield return new WaitForSeconds(_updateRate);
|
2024-09-14 15:00:35 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-02 00:30:21 -07:00
|
|
|
private void RecordTelemetry()
|
2024-09-14 15:00:35 -07:00
|
|
|
{
|
|
|
|
float time = (float)SimManager.Instance.GetElapsedSimulationTime();
|
2024-10-02 00:30:21 -07:00
|
|
|
var agents = SimManager.Instance.GetActiveAgents();
|
|
|
|
if(_telemetryBinaryWriter == null) {
|
|
|
|
Debug.LogWarning("Telemetry binary writer is null");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (int i = 0; i < agents.Count; i++)
|
2024-09-14 15:00:35 -07:00
|
|
|
{
|
2024-10-02 00:30:21 -07:00
|
|
|
var agent = agents[i];
|
|
|
|
|
|
|
|
if (!agent.gameObject.activeInHierarchy)
|
|
|
|
continue;
|
|
|
|
|
2024-09-14 15:00:35 -07:00
|
|
|
Vector3 pos = agent.transform.position;
|
2024-10-02 00:30:21 -07:00
|
|
|
|
|
|
|
if (pos == Vector3.zero)
|
2024-09-14 15:37:45 -07:00
|
|
|
continue;
|
2024-10-02 00:30:21 -07:00
|
|
|
|
|
|
|
Vector3 vel = agent.GetVelocity(); // Ensure GetVelocity() doesn't allocate
|
|
|
|
|
|
|
|
int agentID = agent.GetInstanceID();
|
|
|
|
int flightPhase = (int)agent.GetFlightPhase();
|
|
|
|
byte agentType = (byte)(agent is Threat ? 0 : 1);
|
|
|
|
|
|
|
|
// Write telemetry data directly to the binary file
|
|
|
|
_telemetryBinaryWriter.Write(time);
|
|
|
|
_telemetryBinaryWriter.Write(agentID);
|
|
|
|
_telemetryBinaryWriter.Write(pos.x);
|
|
|
|
_telemetryBinaryWriter.Write(pos.y);
|
|
|
|
_telemetryBinaryWriter.Write(pos.z);
|
|
|
|
_telemetryBinaryWriter.Write(vel.x);
|
|
|
|
_telemetryBinaryWriter.Write(vel.y);
|
|
|
|
_telemetryBinaryWriter.Write(vel.z);
|
|
|
|
_telemetryBinaryWriter.Write(flightPhase);
|
|
|
|
_telemetryBinaryWriter.Write(agentType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void ConvertBinaryTelemetryToCsv(string binaryFilePath, string csvFilePath)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
using FileStream fs = new FileStream(binaryFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
|
|
|
using BinaryReader reader = new BinaryReader(fs);
|
|
|
|
using StreamWriter writer = new StreamWriter(csvFilePath, false);
|
|
|
|
{
|
|
|
|
// Write CSV header
|
|
|
|
writer.WriteLine("Time,AgentID,AgentX,AgentY,AgentZ,AgentVX,AgentVY,AgentVZ,AgentState,AgentType");
|
|
|
|
|
|
|
|
while (reader.BaseStream.Position != reader.BaseStream.Length)
|
|
|
|
{
|
|
|
|
float time = reader.ReadSingle();
|
|
|
|
int agentID = reader.ReadInt32();
|
|
|
|
float posX = reader.ReadSingle();
|
|
|
|
float posY = reader.ReadSingle();
|
|
|
|
float posZ = reader.ReadSingle();
|
|
|
|
float velX = reader.ReadSingle();
|
|
|
|
float velY = reader.ReadSingle();
|
|
|
|
float velZ = reader.ReadSingle();
|
|
|
|
int flightPhase = reader.ReadInt32();
|
|
|
|
byte agentTypeByte = reader.ReadByte();
|
|
|
|
string agentType = agentTypeByte == 0 ? "T" : "M";
|
|
|
|
|
|
|
|
// Write the data to CSV
|
|
|
|
writer.WriteLine($"{time:F2},{agentID},{posX:F2},{posY:F2},{posZ:F2},{velX:F2},{velY:F2},{velZ:F2},{flightPhase},{agentType}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (IOException e)
|
|
|
|
{
|
|
|
|
Debug.LogWarning($"An IO error occurred while converting binary telemetry to CSV: {e.Message}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void WriteEventsToFile()
|
|
|
|
{
|
|
|
|
using (StreamWriter writer = new StreamWriter(_eventLogPath, false))
|
|
|
|
{
|
|
|
|
// Write CSV header
|
|
|
|
writer.WriteLine("Time,PositionX,PositionY,PositionZ,Event,Details");
|
|
|
|
|
|
|
|
foreach (var record in _eventLogCache)
|
|
|
|
{
|
|
|
|
writer.WriteLine($"{record.Time:F2},{record.PositionX:F2},{record.PositionY:F2},{record.PositionZ:F2},{record.EventType},{record.Details}");
|
2024-09-14 15:37:45 -07:00
|
|
|
}
|
2024-09-14 15:00:35 -07:00
|
|
|
}
|
2024-10-02 00:30:21 -07:00
|
|
|
}
|
2024-09-14 15:00:35 -07:00
|
|
|
|
2024-10-02 00:30:21 -07:00
|
|
|
private void RegisterSimulationStarted()
|
|
|
|
{
|
|
|
|
InitializeLogFiles();
|
|
|
|
_monitorRoutine = StartCoroutine(MonitorRoutine());
|
2024-09-14 15:00:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private void RegisterSimulationEnded()
|
|
|
|
{
|
2024-10-02 00:30:21 -07:00
|
|
|
StopCoroutine(_monitorRoutine);
|
|
|
|
CloseLogFiles();
|
|
|
|
WriteEventsToFile();
|
|
|
|
StartCoroutine(ConvertBinaryTelemetryToCsvCoroutine(_telemetryBinPath, Path.ChangeExtension(_telemetryBinPath, ".csv")));
|
2024-09-14 15:00:35 -07:00
|
|
|
}
|
|
|
|
|
2024-10-02 00:30:21 -07:00
|
|
|
private IEnumerator ConvertBinaryTelemetryToCsvCoroutine(string binaryFilePath, string csvFilePath)
|
|
|
|
{
|
|
|
|
yield return null; // Wait for the next frame to ensure RecordTelemetry() has finished
|
|
|
|
ConvertBinaryTelemetryToCsv(binaryFilePath, csvFilePath);
|
|
|
|
}
|
2024-09-14 15:00:35 -07:00
|
|
|
|
2024-10-02 00:30:21 -07:00
|
|
|
public void RegisterNewThreat(Threat threat) {
|
|
|
|
RegisterNewAgent(threat, "NEW_THREAT");
|
|
|
|
}
|
|
|
|
|
|
|
|
public void RegisterNewInterceptor(Interceptor interceptor) {
|
|
|
|
RegisterNewAgent(interceptor, "NEW_INTERCEPTOR");
|
|
|
|
interceptor.OnInterceptMiss += RegisterInterceptorMiss;
|
|
|
|
interceptor.OnInterceptHit += RegisterInterceptorHit;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void RegisterNewAgent(Agent agent, string eventType)
|
2024-09-14 15:00:35 -07:00
|
|
|
{
|
2024-10-02 00:30:21 -07:00
|
|
|
float time = (float)SimManager.Instance.GetElapsedSimulationTime();
|
|
|
|
Vector3 pos = agent.transform.position;
|
|
|
|
var record = new EventRecord
|
2024-09-14 15:00:35 -07:00
|
|
|
{
|
2024-10-02 00:30:21 -07:00
|
|
|
Time = time,
|
|
|
|
PositionX = pos.x,
|
|
|
|
PositionY = pos.y,
|
|
|
|
PositionZ = pos.z,
|
|
|
|
EventType = eventType,
|
|
|
|
Details = agent.name
|
|
|
|
};
|
|
|
|
_eventLogCache.Add(record);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void RegisterInterceptorHit(Interceptor interceptor, Threat threat) {
|
|
|
|
RegisterInterceptEvent(interceptor, threat, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void RegisterInterceptorMiss(Interceptor interceptor, Threat threat) {
|
|
|
|
RegisterInterceptEvent(interceptor, threat, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void RegisterInterceptEvent(Interceptor interceptor, Threat threat, bool hit)
|
|
|
|
{
|
|
|
|
float time = (float)SimManager.Instance.GetElapsedSimulationTime();
|
|
|
|
Vector3 pos = interceptor.transform.position;
|
|
|
|
string eventType = hit ? "HIT" : "MISS";
|
|
|
|
var record = new EventRecord
|
|
|
|
{
|
|
|
|
Time = time,
|
|
|
|
PositionX = pos.x,
|
|
|
|
PositionY = pos.y,
|
|
|
|
PositionZ = pos.z,
|
|
|
|
EventType = eventType,
|
|
|
|
Details = $"{interceptor.name} and {threat.name}"
|
|
|
|
};
|
|
|
|
_eventLogCache.Add(record);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnDestroy()
|
|
|
|
{
|
|
|
|
CloseLogFiles();
|
2024-09-14 15:00:35 -07:00
|
|
|
}
|
|
|
|
}
|