/// <summary>
        /// Creates the json representation of the given PendingCapture. Static because this should not depend on any SimulationState members,
        /// which may have changed since the capture was reported.
        /// </summary>
        static JToken JObjectFromPendingCapture(PendingCapture pendingCapture)
        {
            var sensorJObject = new JObject();//new SensorCaptureJson

            sensorJObject["sensor_id"]   = pendingCapture.SensorHandle.Id.ToString();
            sensorJObject["ego_id"]      = pendingCapture.SensorData.egoHandle.Id.ToString();
            sensorJObject["modality"]    = pendingCapture.SensorData.modality;
            sensorJObject["translation"] = DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.SensorPose.position);
            sensorJObject["rotation"]    = DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.SensorPose.rotation);

            if (pendingCapture.AdditionalSensorValues != null)
            {
                foreach (var(name, value) in pendingCapture.AdditionalSensorValues)
                {
                    sensorJObject.Add(name, DatasetJsonUtility.ToJToken(value));
                }
            }

            var egoCaptureJson = new JObject();

            egoCaptureJson["ego_id"]       = pendingCapture.SensorData.egoHandle.Id.ToString();
            egoCaptureJson["translation"]  = DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.EgoPose.position);
            egoCaptureJson["rotation"]     = DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.EgoPose.rotation);
            egoCaptureJson["velocity"]     = pendingCapture.SensorSpatialData.EgoVelocity.HasValue ? DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.EgoVelocity.Value) : null;
            egoCaptureJson["acceleration"] = pendingCapture.SensorSpatialData.EgoAcceleration.HasValue ? DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.EgoAcceleration.Value) : null;

            var capture = new JObject();

            capture["id"]          = pendingCapture.Id.ToString();
            capture["sequence_id"] = pendingCapture.SequenceId.ToString();
            capture["step"]        = pendingCapture.Step;
            capture["timestamp"]   = pendingCapture.Timestamp;
            capture["sensor"]      = sensorJObject;
            capture["ego"]         = egoCaptureJson;
            capture["filename"]    = pendingCapture.Path;
            capture["format"]      = GetFormatFromFilename(pendingCapture.Path);

            if (pendingCapture.Annotations.Any())
            {
                capture["annotations"] = new JArray(pendingCapture.Annotations.Select(JObjectFromAnnotation).ToArray());
            }

            return(capture);
        }
        /// <summary>
        /// Writes sensors.json, egos.json, metric_definitions.json, and annotation_definitions.json
        /// </summary>
        public void WriteReferences()
        {
            var egoReference = new JObject();

            egoReference["version"] = SimulationManager.SchemaVersion;
            egoReference["egos"]    = new JArray(m_Egos.Select(e =>
            {
                var egoObj   = new JObject();
                egoObj["id"] = e.Id.ToString();
                if (e.Description != null)
                {
                    egoObj["description"] = e.Description;
                }

                return(egoObj);
            }).ToArray());

            WriteJObjectToFile(egoReference, "egos.json");

            var sensorReferenceDoc = new JObject();

            sensorReferenceDoc["version"] = SimulationManager.SchemaVersion;
            sensorReferenceDoc["sensors"] = new JArray(m_Sensors.Select(kvp =>
            {
                var sensorReference         = new JObject();
                sensorReference["id"]       = kvp.Key.Id.ToString();
                sensorReference["ego_id"]   = kvp.Value.egoHandle.Id.ToString();
                sensorReference["modality"] = kvp.Value.modality;
                if (kvp.Value.description != null)
                {
                    sensorReference["description"] = kvp.Value.description;
                }

                return(sensorReference);
            }).ToArray());
            WriteJObjectToFile(sensorReferenceDoc, "sensors.json");

            if (m_AdditionalInfoTypeData.Count > 0)
            {
                var annotationDefinitionsJArray = new JArray();
                var metricDefinitionsJArray     = new JArray();
                foreach (var typeInfo in m_AdditionalInfoTypeData)
                {
                    var typeJObject = new JObject();
                    typeJObject.Add("id", new JValue(typeInfo.id.ToString()));
                    typeJObject.Add("name", new JValue(typeInfo.name));
                    if (typeInfo.description != null)
                    {
                        typeJObject.Add("description", new JValue(typeInfo.description));
                    }

                    if (typeInfo.format != null)
                    {
                        typeJObject.Add("format", new JValue(typeInfo.format));
                    }

                    if (typeInfo.specValues != null)
                    {
                        var specValues = new JArray();
                        foreach (var value in typeInfo.specValues)
                        {
                            specValues.Add(DatasetJsonUtility.ToJToken(value));
                        }
                        typeJObject.Add("spec", specValues);
                    }

                    switch (typeInfo.additionalInfoKind)
                    {
                    case AdditionalInfoKind.Annotation:
                        annotationDefinitionsJArray.Add(typeJObject);
                        break;

                    case AdditionalInfoKind.Metric:
                        metricDefinitionsJArray.Add(typeJObject);
                        break;

                    default:
                        throw new NotSupportedException("Unsupported info kind");
                    }
                }

                if (annotationDefinitionsJArray.Count > 0)
                {
                    var annotationDefinitionsJObject = new JObject();
                    annotationDefinitionsJObject.Add("version", SimulationManager.SchemaVersion);
                    annotationDefinitionsJObject.Add("annotation_definitions", annotationDefinitionsJArray);
                    WriteJObjectToFile(annotationDefinitionsJObject, "annotation_definitions.json");
                }

                if (metricDefinitionsJArray.Count > 0)
                {
                    var metricDefinitionsJObject = new JObject();
                    metricDefinitionsJObject.Add("version", SimulationManager.SchemaVersion);
                    metricDefinitionsJObject.Add("metric_definitions", metricDefinitionsJArray);
                    WriteJObjectToFile(metricDefinitionsJObject, "metric_definitions.json");
                }
            }
            Debug.Log($"Dataset written to {Path.GetDirectoryName(OutputDirectory)}");
        }