Warning
Warning: Unity Simulation is deprecated as of December 2023, and is no longer available.
Set up Data Logging
Now that you have a working simulation, you'll want it to emit some data for analysis. Depending on how you want to do your analysis, you might find it useful to output a CSV file (to load in plotly, for example), or some JSON, or perhaps a custom ROS message for another package to receive.
Writing to CSV
CSV is a very easy file format to generate, especially if you're just logging sets of numbers. Here's a simple C# utility class that receives rows of numbers and saves the results to a CSV file.
using System.IO;
using System.Linq;
class CsvLogger
{
StreamWriter file;
public CsvLogger(string filename)
{
file = new StreamWriter(filename);
}
public CsvLogger(string filename, params string[] columnNames): this(filename)
{
file.WriteLine(string.Join(\",\", columnNames));
}
public void AddRow(params float[] values)
{
file.WriteLine(string.Join(\",\", values.Select(f=>f.ToString())));
}
public void Close()
{
file.Close();
}
}
And here's a simple Unity MonoBehaviour script that demonstrates how to use CsvLogger. You can just attach this component to a GameObject to log that object's height every frame:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CsvLoggerExample : MonoBehaviour
{
CsvLogger logger;
void Start()
{
logger = new CsvLogger(\"example.csv\", \"height\", \"time\");
}
void Update()
{
logger.AddRow(transform.position.y, Time.time);
}
void OnApplicationQuit()
{
logger.Close();
}
}
Writing data as JSON
The JsonUtility class is a fast, convenient way to convert simple data structures into JSON format, although it can't generate all possible Json files.
Here's an example of a MonoBehaviour that collects data about the height of its GameObject over time. When it has collected enough data points, it publishes them as a JSON string embedded in a ROS String message, and then turns itself off.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Simulation.Foundation;
using Unity.Simulation.Foundation.StdMessages;
public class JsonLoggerExample : MonoBehaviour
{
[SerializeField]
string topic = \"jsonlog\";
// This class's fields are the keys of the json dictionary we will generate
class JsonData
{
public List<float> heights = new List<float>();
public List<float> times = new List<float>();
}
JsonData data;
IPublisher publisher;
void Start()
{
data = new JsonData();
publisher = ConnectorInjector.FindConnection(gameObject).RegisterPublisher<StringMsg>(topic);
}
void Update()
{
data.heights.Add(transform.position.y);
data.times.Add(Time.time);
// When we have enough data, generate the json, send it and turn off the logger
if (data.heights.Count >= 100)
{
this.enabled = false; // stop updating
string json = JsonUtility.ToJson(data);
publisher.Publish(new StringMsg(json));
}
}
}