From 05400f318a3418698ca16778471f2f04df564f2a Mon Sep 17 00:00:00 2001 From: Daniel Lovell Date: Wed, 2 Oct 2024 00:30:21 -0700 Subject: [PATCH] New Event monitoring and telemetry optimizations --- Assets/Scripts/Monitor.cs | 257 +++++++++++++++++++++++++++++++++----- 1 file changed, 225 insertions(+), 32 deletions(-) diff --git a/Assets/Scripts/Monitor.cs b/Assets/Scripts/Monitor.cs index e4fda2a..182068d 100644 --- a/Assets/Scripts/Monitor.cs +++ b/Assets/Scripts/Monitor.cs @@ -3,70 +3,263 @@ using System.Collections; using System.IO; using System; using System.Linq; +using System.Collections.Generic; +using System.Threading; public class SimMonitor : MonoBehaviour { - private const float UpdateRate = 0.01f; // 100 Hz - private StreamWriter writer; - private Coroutine monitorRoutine; + 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 _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(); + } private void Start() { + SimManager.Instance.OnSimulationStarted += RegisterSimulationStarted; SimManager.Instance.OnSimulationEnded += RegisterSimulationEnded; - InitializeFile(); - monitorRoutine = StartCoroutine(MonitorRoutine()); + SimManager.Instance.OnNewThreat += RegisterNewThreat; + SimManager.Instance.OnNewInterceptor += RegisterNewInterceptor; } - private void InitializeFile() + 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() { string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss"); - string fileName = $"sim_telemetry_{timestamp}.csv"; - string directory = Application.persistentDataPath + "/Telemetry/Logs/"; - Directory.CreateDirectory(directory); - string path = Path.Combine(directory, fileName); - writer = new StreamWriter(path, false); - writer.WriteLine("Time,AgentID,AgentX,AgentY,AgentZ,AgentVX,AgentVY,AgentVZ,AgentState,AgentType"); - Debug.Log($"Monitoring simulation data to {path}"); + + _eventLogPath = Path.Combine(_sessionDirectory, $"sim_events_{timestamp}.csv"); + + // Initialize the event log cache + _eventLogCache = new List(); + + _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; + } + } private IEnumerator MonitorRoutine() { while (true) { - ExportTelemetry(); - yield return new WaitForSeconds(UpdateRate); + RecordTelemetry(); + yield return new WaitForSeconds(_updateRate); } } - private void ExportTelemetry() + private void RecordTelemetry() { float time = (float)SimManager.Instance.GetElapsedSimulationTime(); - foreach (var agent in SimManager.Instance.GetActiveAgents()) - { - Vector3 pos = agent.transform.position; - if(pos == Vector3.zero) { - continue; - } - Vector3 vel = agent.GetComponent().linearVelocity; - 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}"); + var agents = SimManager.Instance.GetActiveAgents(); + if(_telemetryBinaryWriter == null) { + Debug.LogWarning("Telemetry binary writer is null"); + return; } + for (int i = 0; i < agents.Count; i++) + { + var agent = agents[i]; - writer.Flush(); + if (!agent.gameObject.activeInHierarchy) + continue; + + Vector3 pos = agent.transform.position; + + if (pos == Vector3.zero) + continue; + + 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}"); + //System.Threading.Thread.Sleep(1000); + //ConvertBinaryTelemetryToCsv(binaryFilePath, csvFilePath); + } + } + + 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}"); + } + } + } + + private void RegisterSimulationStarted() + { + InitializeLogFiles(); + _monitorRoutine = StartCoroutine(MonitorRoutine()); } private void RegisterSimulationEnded() { - writer.Close(); - StopCoroutine(monitorRoutine); + StopCoroutine(_monitorRoutine); + CloseLogFiles(); + WriteEventsToFile(); + StartCoroutine(ConvertBinaryTelemetryToCsvCoroutine(_telemetryBinPath, Path.ChangeExtension(_telemetryBinPath, ".csv"))); } + private IEnumerator ConvertBinaryTelemetryToCsvCoroutine(string binaryFilePath, string csvFilePath) + { + yield return null; // Wait for the next frame to ensure RecordTelemetry() has finished + ConvertBinaryTelemetryToCsv(binaryFilePath, csvFilePath); + } + + 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) + { + float time = (float)SimManager.Instance.GetElapsedSimulationTime(); + Vector3 pos = agent.transform.position; + var record = new EventRecord + { + 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() { - if (writer != null) - { - writer.Close(); - } + CloseLogFiles(); } } \ No newline at end of file