-
-
Save julenka/20ece5141e821cb6d0a9cb530d3dc96d to your computer and use it in GitHub Desktop.
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Text; | |
using System.Threading.Tasks; | |
using UnityEngine; | |
#if WINDOWS_UWP | |
using Windows.Storage; | |
#endif | |
namespace holoutils | |
{ | |
/// <summary> | |
/// Component that Logs data to a CSV. | |
/// Assumes header is fixed. | |
/// Copy and paste this logger to create your own CSV logger. | |
/// CSV Logger breaks data up into settions (starts when application starts) which are folders | |
/// and instances which are files | |
/// A session starts when the application starts, it ends when the session ends. | |
/// | |
/// In Editor, writes to MyDocuments/SessionFolderRoot folder | |
/// On Device, saves data in the Pictures/SessionFolderRoot | |
/// | |
/// How to use: | |
/// Find the csvlogger | |
/// if it has not started a CSV, create one. | |
/// every frame, log stuff | |
/// Flush data regularly | |
/// | |
/// **Important: Requires the PicturesLibrary capability!** | |
/// </summary> | |
public class CSVLogger : MonoBehaviour | |
{ | |
#region Constants to modify | |
private const string DataSuffix = "data"; | |
private const string CSVHeader = "Timestamp,SessionID,RecordingID," + | |
"blah,blah,blah"; | |
private const string SessionFolderRoot = "CSVLogger"; | |
#endregion | |
#region private members | |
private string m_sessionPath; | |
private string m_filePath; | |
private string m_recordingId; | |
private string m_sessionId; | |
private StringBuilder m_csvData; | |
#endregion | |
#region public members | |
public string RecordingInstance => m_recordingId; | |
#endregion | |
// Use this for initialization | |
async void Start() | |
{ | |
await MakeNewSession(); | |
} | |
async Task MakeNewSession() | |
{ | |
m_sessionId = DateTime.Now.ToString("yyyyMMdd_HHmmss"); | |
string rootPath = ""; | |
#if WINDOWS_UWP | |
StorageFolder sessionParentFolder = await KnownFolders.PicturesLibrary | |
.CreateFolderAsync(SessionFolderRoot, | |
CreationCollisionOption.OpenIfExists); | |
rootPath = sessionParentFolder.Path; | |
#else | |
rootPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), SessionFolderRoot); | |
if (!Directory.Exists(rootPath)) Directory.CreateDirectory(rootPath); | |
#endif | |
m_sessionPath = Path.Combine(rootPath, m_sessionId); | |
Directory.CreateDirectory(m_sessionPath); | |
Debug.Log("CSVLogger logging data to " + m_sessionPath); | |
} | |
public void StartNewCSV() | |
{ | |
m_recordingId = DateTime.Now.ToString("yyyyMMdd_HHmmssfff"); | |
var filename = m_recordingId + "-" + DataSuffix + ".csv"; | |
m_filePath = Path.Combine(m_sessionPath, filename); | |
if (m_csvData != null) | |
{ | |
EndCSV(); | |
} | |
m_csvData = new StringBuilder(); | |
m_csvData.AppendLine(CSVHeader); | |
} | |
public void EndCSV() | |
{ | |
if (m_csvData == null) | |
{ | |
return; | |
} | |
using (var csvWriter = new StreamWriter(m_filePath, true)) | |
{ | |
csvWriter.Write(m_csvData.ToString()); | |
} | |
m_recordingId = null; | |
m_csvData = null; | |
} | |
public void OnDestroy() | |
{ | |
EndCSV(); | |
} | |
public void AddRow(List<String> rowData) | |
{ | |
AddRow(string.Join(",", rowData.ToArray())); | |
} | |
public void AddRow(string row) | |
{ | |
m_csvData.AppendLine(row); | |
} | |
/// <summary> | |
/// Writes all current data to current file | |
/// </summary> | |
public void FlushData() | |
{ | |
using (var csvWriter = new StreamWriter(m_filePath, true)) | |
{ | |
csvWriter.Write(m_csvData.ToString()); | |
} | |
m_csvData.Clear(); | |
} | |
/// <summary> | |
/// Returns a row populated with common start data like | |
/// recording id, session id, timestamp | |
/// </summary> | |
/// <returns></returns> | |
public List<String> RowWithStartData() | |
{ | |
List<String> rowData = new List<String>(); | |
rowData.Add(Time.timeSinceLevelLoad.ToString("##.000")); | |
rowData.Add(m_recordingId); | |
rowData.Add(m_recordingId); | |
return rowData; | |
} | |
} | |
} |
Hello, thank you for the code it works well in unity but the data is quite delayed on the Hololens. At first, I didn't include FlushData() in the code, .csv file was created properly in the unity editor but it was not created on the Hololens. But right after I put FlushData(), I can see the file created in Hololens's picture folder but it makes the game and sensor data delayed more than I expected which is around 30sec from the normal 4sec (before adding flush). Do you have any suggestions or recommendations?
Thank you for the code. I have just one question, where should I call the StartNewCSV()
and FlushData()
functions? The code that you provided has a async void Start()
function which does not allow me to have my basic void start(){}
. I'm guessing I should use the FlushData()
in the Update()
function. right?
I think StartNewCSV(
) here is to create a CSV file with the unity editor. If you want to create a CSV file in the Hololens, you need to use the Windows.Storage
for UWP. Referring to https://learn.microsoft.com/en-us/windows/uwp/files/quickstart-reading-and-writing-files
For more file-accessing codes for UWP, I found this helpful:
https://github.com/Microsoft/Windows-universal-samples/tree/main/Samples/FileAccess
Hello, I was using your code for two projects without issues, but recently, the call to
Directory.CreateDirectory(m_sessionPath)
on line 74 stopped working very similar to the above. I updated the MakeNewSession code tom_sessionId = DateTime.Now.ToString("yyyyMMdd_HHmmss"); string rootPath = ""; m_sessionPath = Path.Combine(SessionFolderRoot, m_sessionId); #if WINDOWS_UWP StorageFolder sessionParentFolder = await KnownFolders.PicturesLibrary .CreateFolderAsync(m_sessionPath, CreationCollisionOption.OpenIfExists); rootPath = sessionParentFolder.Path; UnityEngine.Debug.Log("Logger logging data to " + sessionParentFolder.Path); #endif
and it now seems to work. Maybe something changed in the .NET namespace?