-
-
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); #endifand it now seems to work. Maybe something changed in the .NET namespace?