New Event monitoring and telemetry optimizations

master
Daniel Lovell 2024-10-02 00:30:21 -07:00
parent 17987c2c5f
commit 05400f318a
1 changed files with 225 additions and 32 deletions

View File

@ -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<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();
}
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<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;
}
}
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;
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];
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);
}
Vector3 vel = agent.GetComponent<Rigidbody>().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}");
}
writer.Flush();
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();
}
}