浏览代码

Old perception format now being produced

/solo_support
Steve Borkman 3 年前
当前提交
27ec65b0
共有 22 个文件被更改,包括 1337 次插入716 次删除
  1. 243
      com.unity.perception/Runtime/GroundTruth/Consumers/OldPerceptionConsumer.cs
  2. 360
      com.unity.perception/Runtime/GroundTruth/Consumers/OldPerceptionJsonFactory.cs
  3. 59
      com.unity.perception/Runtime/GroundTruth/Consumers/SoloConsumer.cs
  4. 72
      com.unity.perception/Runtime/GroundTruth/DataModel.cs
  5. 274
      com.unity.perception/Runtime/GroundTruth/DatasetCapture.cs
  6. 34
      com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBox3DLabeler.cs
  7. 33
      com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBoxLabeler.cs
  8. 140
      com.unity.perception/Runtime/GroundTruth/Labelers/InstanceSegmentationLabeler.cs
  9. 4
      com.unity.perception/Runtime/GroundTruth/Labelers/KeypointLabeler.cs
  10. 55
      com.unity.perception/Runtime/GroundTruth/Labelers/ObjectCountLabeler.cs
  11. 122
      com.unity.perception/Runtime/GroundTruth/Labelers/RenderedObjectInfoLabeler.cs
  12. 6
      com.unity.perception/Runtime/GroundTruth/Labelers/SemanticSegmentationLabeler.cs
  13. 2
      com.unity.perception/Runtime/GroundTruth/Labeling/IdLabelConfig.cs
  14. 17
      com.unity.perception/Runtime/GroundTruth/PerceptionCamera.cs
  15. 472
      com.unity.perception/Runtime/GroundTruth/SimulationState.cs
  16. 49
      com.unity.perception/Runtime/Randomization/Scenarios/PerceptionScenario.cs
  17. 18
      com.unity.perception/Tests/Runtime/GroundTruthTests/BoundingBox3dTests.cs
  18. 26
      com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureSensorSchedulingTests.cs
  19. 29
      com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureTests.cs
  20. 4
      com.unity.perception/Tests/Runtime/GroundTruthTests/PerceptionCameraIntegrationTests.cs
  21. 24
      com.unity.perception/Tests/Runtime/GroundTruthTests/SegmentationGroundTruthTests.cs
  22. 10
      com.unity.perception/Tests/Runtime/GroundTruthTests/VisualizationTests.cs

243
com.unity.perception/Runtime/GroundTruth/Consumers/OldPerceptionConsumer.cs


using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Perception.GroundTruth.DataModel;
using Formatting = Newtonsoft.Json.Formatting;

var contract = base.CreateObjectContract(objectType);
if (objectType == typeof(Vector3) ||
objectType == typeof(Vector2) ||
objectType == typeof(Color32))
objectType == typeof(Color) ||
objectType == typeof(Quaternion))
{
contract.Converter = PerceptionConverter.Instance;
}

writer.WriteEndObject();
break;
}
case Quaternion quaternion:
{
writer.WriteStartObject();
writer.WritePropertyName("x");
writer.WriteValue(quaternion.x);
writer.WritePropertyName("y");
writer.WriteValue(quaternion.y);
writer.WritePropertyName("z");
writer.WriteValue(quaternion.z);
writer.WritePropertyName("w");
writer.WriteValue(quaternion.w);
writer.WriteEndObject();
break;
}
}
}

{
if (objectType == typeof(Vector3)) return true;
if (objectType == typeof(Vector2)) return true;
if (objectType == typeof(Quaternion)) return true;
return objectType == typeof(Color32);
}
}

static readonly string version = "0.1.1";
public string baseDirectory = "D:/PerceptionOutput/KickinItOldSchool";
public int capturesPerFile = 20;
public int capturesPerFile = 150;
public int metricsPerFile = 150;
//JsonSerializer m_JsonSerializer = new JsonSerializer();
JsonSerializer m_JsonSerializer = new JsonSerializer();
string m_CurrentPath;
string m_DatasetPath;
string m_RgbPath;

struct SensorInfo
{
public Guid id;
public string id;
Dictionary<string, (Guid, AnnotationDefinition)> m_RegisteredAnnotations = new Dictionary<string, (Guid, AnnotationDefinition)>();
Dictionary<string, AnnotationDefinition> m_RegisteredAnnotations = new Dictionary<string, AnnotationDefinition>();
Dictionary<string, MetricDefinition> m_RegisteredMetrics = new Dictionary<string, MetricDefinition>();
Dictionary<int, Guid> m_SequenceToGuidMap = new Dictionary<int, Guid>();
List<PerceptionCapture> m_CurrentCaptures = new List<PerceptionCapture>();
protected override bool IsComplete()

return;
}
m_RegisteredAnnotations[annotationDefinition.id] = (Guid.NewGuid(), annotationDefinition);
m_RegisteredAnnotations[annotationDefinition.id] = annotationDefinition;
}
public override void OnMetricRegistered(MetricDefinition metricDefinition)
{
if (m_RegisteredMetrics.ContainsKey(metricDefinition.id))
{
Debug.LogError("Tried to register a metric twice");
return;
}
m_RegisteredMetrics[metricDefinition.id] = metricDefinition;
}
public override void OnSensorRegistered(SensorDefinition sensor)

m_SensorMap[sensor.id] = new SensorInfo
{
id = Guid.NewGuid(),
id = sensor.id,
public string RemoveDatasetPathPrefix(string path)
{
return path.Replace(m_CurrentPath + "\\", string.Empty);
}
public override void OnSimulationStarted(SimulationMetadata metadata)
{
// Create a directory guid...

public override void OnFrameGenerated(Frame frame)
{
if (!m_SequenceToGuidMap.TryGetValue(frame.sequence, out var seqId))
{
seqId = Guid.NewGuid();
m_SequenceToGuidMap[frame.sequence] = seqId;
}
var seqId = frame.sequence.ToString();
var annotations = new JArray();
RgbSensor rgbSensor = null;
if (frame.sensors.Count() == 1)
{

rgbSensor = rgb;
path = WriteOutImageFile(frame.frame, rgb);
}
}
#if false // TODO bring back annotations....
var annotations = new JArray();
foreach (var annotation in frame.annotations)
{
var labelerId = Guid.NewGuid(); // TODO - we need to get this figured out
if (!m_RegisteredAnnotations.TryGetValue(annotation.Id, out var def))
foreach (var annotation in sensor.annotations)
def.Item1 = Guid.Empty;
string defId = null;
if (!m_RegisteredAnnotations.TryGetValue(annotation.Id, out var def))
{
defId = null;
}
defId = def.id;
var json = OldPerceptionJsonFactory.Convert(this, frame, annotation.Id, defId, annotation);
if (json != null) annotations.Add(json);
}
var defId = def.Item1;
var json = OldPerceptionJsonFactory.Convert(this, frame, labelerId, defId, annotation);
if (json != null) annotations.Add(json);
foreach (var metric in frame.metrics)
{
AddMetricToReport(metric);
#endif
id = Guid.NewGuid(),
filename = path,
id = $"frame_{frame.frame}",
filename = RemoveDatasetPathPrefix(path),
sensor = PerceptionRgbSensor.Convert(this, rgbSensor, path),
// annotations = annotations
sensor = PerceptionRgbSensor.Convert(this, rgbSensor, path),
annotations = annotations
if (m_CurrentCaptures.Count >= capturesPerFile)
WriteCaptures();
}
void WriteMetrics(bool flush = false)
{
if (flush || m_MetricsReady.Count > metricsPerFile)
var toRemove = m_CurrentCaptures;
m_CurrentCaptures = new List<PerceptionCapture>();
// Write out a capture file
WriteCaptureFile(m_CurrentCaptureIndex++, toRemove);
toRemove.Clear();
WriteMetricsFile(m_MetricOutCount++, m_MetricsReady);
m_MetricsReady.Clear();
}
}
void WriteCaptures(bool flush = false)
{
if (flush || m_CurrentCaptures.Count >= capturesPerFile)
{
WriteCaptureFile(m_CurrentCaptureIndex++, m_CurrentCaptures);
m_CurrentCaptures.Clear();
}
}

WriteEgosFile();
WriteCaptures(true);
WriteMetrics(true);
int m_CurrentCaptureIndex = 1;
int m_CurrentCaptureIndex = 0;
string WriteOutImageFile(int frame, RgbSensor rgb)
{

WriteJTokenToFile(filePath, JToken.FromObject(json, Serializer));
}
void WriteJTokenToFile(string filePath, MetricsJson json)
{
WriteJTokenToFile(filePath, JToken.FromObject(json, Serializer));
}
static void WriteJTokenToFile(string filePath, JToken json)
{
var stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture);

{
var defs = new JArray();
foreach (var (id, def) in m_RegisteredAnnotations.Values)
foreach (var def in m_RegisteredAnnotations.Values)
defs.Add(OldPerceptionJsonFactory.Convert(this, id, def));
defs.Add(OldPerceptionJsonFactory.Convert(this, def.id, def));
}
var top = new JObject

void WriteMetricsDefinitionsFile()
{
var top = new JObject
var defs = new JArray();
foreach (var def in m_RegisteredMetrics.Values)
["version"] = version,
["metric_definitions"] = new JArray()
};
var path = Path.Combine(m_DatasetPath, "metric_definitions.json");
WriteJTokenToFile(path, top);
}
defs.Add(OldPerceptionJsonFactory.Convert(this, def.id, def));
}
void WriteEgosFile()
{
["egos"] = new JArray()
["metric_definitions"] = defs
var path = Path.Combine(m_DatasetPath, "egos.json");
var path = Path.Combine(m_DatasetPath, "metric_definitions.json");
WriteJTokenToFile(path, top);
}

WriteJTokenToFile(path, top);
}
void WriteCaptureFile(int index, IEnumerable<PerceptionCapture> captures)
JToken ToJtoken(Metric metric)
{
string sensorId = null;
string annotationId = null;
string defId = null;
if (!string.IsNullOrEmpty(metric.sensorId))
{
sensorId = m_SensorMap[metric.sensorId].id;
}
if (!string.IsNullOrEmpty(metric.annotationId))
{
annotationId = m_RegisteredAnnotations[metric.annotationId].id;
}
if (m_RegisteredMetrics.TryGetValue(metric.Id, out var def))
{
defId = def.id;
}
return new JObject
{
["capture_id"] = sensorId,
["annotation_id"] = annotationId,
["sequence_id"] = metric.sequenceId.ToString(),
["step"] = metric.step,
["metric_definition"] = defId,
["values"] = JToken.FromObject(metric.Values)
};
}
void WriteMetricsFile(int index, IEnumerable<JToken> metrics)
var top = new PerceptionJson
var top = new MetricsJson
captures = captures
metrics = metrics
var path = Path.Combine(m_DatasetPath, $"captures_{index}.json");
var path = Path.Combine(m_DatasetPath, $"metrics_{index:000}.json");
public Guid GetIdForSensor(Sensor inSensor)
int m_MetricOutCount = 0;
List<JToken> m_MetricsReady = new List<JToken>();
void AddMetricToReport(Metric metric)
if (!m_SensorMap.TryGetValue(inSensor.Id, out var info))
m_MetricsReady.Add(ToJtoken(metric));
WriteMetrics();
}
void WriteCaptureFile(int index, IEnumerable<PerceptionCapture> captures)
{
var top = new PerceptionJson
Debug.LogError("Sensor Id was not available, it should have already been registered");
return Guid.Empty;
}
version = version,
captures = captures
};
return info.id;
var path = Path.Combine(m_DatasetPath, $"captures_{index:000}.json");
WriteJTokenToFile(path, top);
}
[Serializable]

public IEnumerable<PerceptionCapture> captures;
}
[Serializable]
struct MetricsJson
{
public string version;
public IEnumerable<JToken> metrics;
}
public Guid id;
public Guid sequence_id;
public string id;
public string sequence_id;
public PerceptionRgbSensor sensor;
public PerceptionRgbSensor sensor;
public static float[][] ToFloatArray(float3x3 inF3)
{
return new[]
{
new [] { inF3[0][0], inF3[0][1], inF3[0][2] },
new [] { inF3[1][0], inF3[1][1], inF3[1][2] },
new [] { inF3[2][0], inF3[2][1], inF3[2][2] }
};
}
public Guid sensor_id;
public string sensor_id;
public float[][] camera_intrinsic;
public string projection;
sensor_id = consumer.GetIdForSensor(inRgb),
sensor_id = inRgb.Id,
acceleration = inRgb.acceleration
acceleration = inRgb.acceleration,
projection = inRgb.projection,
camera_intrinsic = ToFloatArray(inRgb.intrinsics)
};
}
}

360
com.unity.perception/Runtime/GroundTruth/Consumers/OldPerceptionJsonFactory.cs


{
public static class OldPerceptionJsonFactory
{
public static JToken Convert(OldPerceptionConsumer consumer, Guid id, AnnotationDefinition def)
public static JToken Convert(OldPerceptionConsumer consumer, string id, AnnotationDefinition def)
return JToken.FromObject(PerceptionBoundingBoxAnnotationDefinition.Convert(id, b));
return JToken.FromObject(LabelConfigurationAnnotationDefinition.Convert(b, "json", b.spec));
case BoundingBox3DLabeler.BoundingBox3DAnnotationDefinition d:
return JToken.FromObject(LabelConfigurationAnnotationDefinition.Convert(d, "json", d.spec));
case InstanceSegmentationLabeler.InstanceSegmentationDefinition d:
return JToken.FromObject(LabelConfigurationAnnotationDefinition.Convert(d, "PNG", d.spec));
case SemanticSegmentationLabeler.SemanticSegmentationDefinition d:
return JToken.FromObject(PerceptionSemanticSegmentationAnnotationDefinition.Convert(consumer, d));
case KeypointLabeler.Definition kp:
return JToken.FromObject(PerceptionKeypointAnnotationDefinition.Convert(consumer, kp));
public static JToken Convert(OldPerceptionConsumer consumer, Frame frame, Guid labelerId, Guid defId, Annotation annotation)
public static JToken Convert(OldPerceptionConsumer consumer, string id, MetricDefinition def)
{
switch (def)
{
case ObjectCountLabeler.ObjectCountMetricDefinition casted:
return JToken.FromObject(LabelConfigMetricDefinition.Convert(id, def, casted.spec));
case RenderedObjectInfoLabeler.MetricDefinition casted:
return JToken.FromObject(LabelConfigMetricDefinition.Convert(id, def, casted.spec));
default:
return JToken.FromObject(GenericMetricDefinition.Convert(id, def));
}
}
public static JToken Convert(OldPerceptionConsumer consumer, Frame frame, string labelerId, string defId, Annotation annotation)
{
switch (annotation)
{

{
return JToken.FromObject(PerceptionBoundingBoxAnnotationValue.Convert(consumer, labelerId, defId, b), consumer.Serializer);
}
case BoundingBox3DLabeler.BoundingBoxAnnotation b:
{
return JToken.FromObject(PerceptionBounding3dBoxAnnotationValue.Convert(consumer, labelerId, defId, b), consumer.Serializer);
}
case SemanticSegmentationLabeler.SemanticSegmentation s:
{
return JToken.FromObject(PerceptionSemanticSegmentationValue.Convert(consumer, frame.frame, s), consumer.Serializer);
}
case KeypointLabeler.Annotation kp:
{
return JToken.FromObject(PerceptionKeyPointValue.Convert(consumer, kp), consumer.Serializer);
}
[Serializable]
struct LabelConfigurationAnnotationDefinition
{
public string id;
public string name;
public string description;
public string format;
public IdLabelConfig.LabelEntrySpec[] spec;
public static LabelConfigurationAnnotationDefinition Convert(AnnotationDefinition def, string format, IdLabelConfig.LabelEntrySpec[] spec)
{
return new LabelConfigurationAnnotationDefinition
{
id = def.id,
name = def.id,
description = def.description,
format = format,
spec = spec
};
}
}
[Serializable]
struct GenericMetricDefinition
{
public string id;
public string name;
public string description;
public static GenericMetricDefinition Convert(string id, MetricDefinition def)
{
return new GenericMetricDefinition
{
id = id,
name = def.id,
description = def.description
};
}
}
struct LabelConfigMetricDefinition
{
public string id;
public string name;
public string description;
public IdLabelConfig.LabelEntrySpec[] spec;
public static LabelConfigMetricDefinition Convert(string id, MetricDefinition def, IdLabelConfig.LabelEntrySpec[] spec)
{
return new LabelConfigMetricDefinition
{
id = id,
name = def.id,
description = def.description,
spec = spec
};
}
}
}
[Serializable]
public struct PerceptionKeyPointValue
{
public string id;
public string annotation_definition;
public List<Entry> values;
[Serializable]
public struct Keypoint
{
public int index;
public Vector2 location;
public int state;
public static Keypoint Convert(KeypointLabeler.Keypoint kp)
{
return new Keypoint
{
index = kp.index,
location = kp.location,
state = kp.state
};
}
}
[Serializable]
public struct Entry
{
public int label_id;
public uint instance_id;
public string template_guid;
public string pose;
public Keypoint[] keypoints;
public static Entry Convert(KeypointLabeler.Annotation.Entry entry)
{
return new Entry
{
label_id = entry.labelId,
instance_id = entry.instanceId,
template_guid = entry.templateGuid,
pose = entry.pose,
keypoints = entry.keypoints.Select(Keypoint.Convert).ToArray()
};
}
}
public static PerceptionKeyPointValue Convert(OldPerceptionConsumer consumer, KeypointLabeler.Annotation kp)
{
return new PerceptionKeyPointValue
{
id = kp.Id,
annotation_definition = kp.description,
values = kp.entries.Select(Entry.Convert).ToList()
};
}
}
[Serializable]
struct PerceptionSemanticSegmentationValue
{
public string id;
public string annotation_definition;
public string filename;
static string CreateFile(OldPerceptionConsumer consumer, int frame, SemanticSegmentationLabeler.SemanticSegmentation annotation)
{
var path = consumer.VerifyDirectoryWithGuidExists("SemanticSegmentation");
path = Path.Combine(path, $"segmentation_{frame}.png");
var file = File.Create(path, 4096);
file.Write(annotation.buffer, 0, annotation.buffer.Length);
file.Close();
return path;
}
public static PerceptionSemanticSegmentationValue Convert(OldPerceptionConsumer consumer, int frame, SemanticSegmentationLabeler.SemanticSegmentation annotation)
{
return new PerceptionSemanticSegmentationValue
{
id = Guid.NewGuid().ToString(),
annotation_definition = Guid.NewGuid().ToString(),
filename = consumer.RemoveDatasetPathPrefix(CreateFile(consumer, frame, annotation)),
};
}
}
[SuppressMessage("ReSharper", "InconsistentNaming")]

}
}
public Guid id;
public Guid annotation_definition;
public string id;
public string annotation_definition;
public string filename;
public List<Entry> values;

{
return new PerceptionInstanceSegmentationValue
{
id = Guid.NewGuid(),
annotation_definition = Guid.NewGuid(),
filename = CreateFile(consumer, frame, annotation),
id = Guid.NewGuid().ToString(),
annotation_definition = Guid.NewGuid().ToString(),
filename = consumer.RemoveDatasetPathPrefix(CreateFile(consumer, frame, annotation)),
values = annotation.instances.Select(Entry.Convert).ToList()
};
}

public string label_name;
}
struct PerceptionBounding3dBoxAnnotationValue
{
[Serializable]
internal struct Entry
{
public int label_id;
public string label_name;
public uint instance_id;
public Vector3 translation;
public Vector3 size;
public Quaternion rotation;
public Vector3 velocity;
public Vector3 acceleration;
internal static Entry Convert(BoundingBox3DLabeler.BoundingBoxAnnotation.Entry entry)
{
return new Entry
{
label_id = entry.labelId,
label_name = entry.labelName,
instance_id = (uint)entry.instanceId,
translation = entry.translation,
size = entry.size,
rotation = entry.rotation,
velocity = entry.velocity,
acceleration = entry.acceleration
};
}
}
public string id;
public string annotation_definition;
public List<Entry> values;
public static PerceptionBounding3dBoxAnnotationValue Convert(OldPerceptionConsumer consumer, string labelerId, string defId, BoundingBox3DLabeler.BoundingBoxAnnotation annotation)
{
return new PerceptionBounding3dBoxAnnotationValue
{
id = labelerId,
annotation_definition = defId,
values = annotation.boxes.Select(Entry.Convert).ToList()
};
}
}
struct PerceptionBoundingBoxAnnotationDefinition
struct PerceptionSemanticSegmentationAnnotationDefinition
public Guid id;
[Serializable]
internal struct Entry
{
public string label_name;
public Color32 pixel_value;
internal static Entry Convert(SemanticSegmentationLabeler.SemanticSegmentationDefinition.DefinitionEntry e)
{
return new Entry
{
label_name = e.labelName,
pixel_value = e.pixelValue
};
}
}
public string id;
public LabelDefinitionEntry[] spec;
public List<Entry> spec;
public static PerceptionBoundingBoxAnnotationDefinition Convert(Guid inId, BoundingBox2DLabeler.BoundingBoxAnnotationDefinition box)
public static PerceptionSemanticSegmentationAnnotationDefinition Convert(OldPerceptionConsumer consumer, SemanticSegmentationLabeler.SemanticSegmentationDefinition def)
var specs = new LabelDefinitionEntry[box.spec.Count()];
var i = 0;
return new PerceptionSemanticSegmentationAnnotationDefinition
{
id = def.id,
name = def.id,
description = def.description,
format = "PNG",
spec = def.spec.Select(Entry.Convert).ToList()
};
}
}
foreach (var e in box.spec)
[Serializable]
struct PerceptionKeypointAnnotationDefinition
{
[Serializable]
public struct JointJson
{
public string label;
public int index;
public Color32 color;
internal static JointJson Convert(KeypointLabeler.Definition.JointDefinition joint)
specs[i++] = new LabelDefinitionEntry
return new JointJson
label_id = e.labelId,
label_name = e.labelName
label = joint.label,
index = joint.index,
color = joint.color
}
}
[Serializable]
public struct SkeletonJson
{
public int joint1;
public int joint2;
public Color32 color;
internal static SkeletonJson Convert(KeypointLabeler.Definition.SkeletonDefinition skel)
{
return new SkeletonJson
{
joint1 = skel.joint1,
joint2 = skel.joint2,
color = skel.color
};
}
return new PerceptionBoundingBoxAnnotationDefinition
[Serializable]
public struct KeypointJson
{
public string template_id;
public string template_name;
public JointJson[] key_points;
public SkeletonJson[] skeleton;
internal static KeypointJson Convert(KeypointLabeler.Definition.Entry e)
id = inId,
name = box.id,
description = box.description,
return new KeypointJson
{
template_id = e.templateId,
template_name = e.templateName,
key_points = e.keyPoints.Select(JointJson.Convert).ToArray(),
skeleton = e.skeleton.Select(SkeletonJson.Convert).ToArray()
};
}
}
public string id;
public string name;
public string description;
public string format;
public List<KeypointJson> spec;
public static PerceptionKeypointAnnotationDefinition Convert(OldPerceptionConsumer consumer, KeypointLabeler.Definition def)
{
return new PerceptionKeypointAnnotationDefinition
{
id = def.id,
name = def.id,
description = def.description,
spec = specs
spec = def.entries.Select(KeypointJson.Convert).ToList()
};
}
}

internal struct Entry
{
public int label_id;
public int frame;
public string label_name;
public uint instance_id;
public float x;

{
return new Entry
{
label_id = entry.labelId, // TODO
frame = -1, // TODO
label_id = entry.labelId,
label_name = entry.labelName,
instance_id = (uint)entry.instanceId,
x = entry.origin.x,

}
}
public Guid id;
public Guid annotation_definition;
public string id;
public string annotation_definition;
public static PerceptionBoundingBoxAnnotationValue Convert(OldPerceptionConsumer consumer, Guid labelerId, Guid defId, BoundingBox2DLabeler.BoundingBoxAnnotation annotation)
public static PerceptionBoundingBoxAnnotationValue Convert(OldPerceptionConsumer consumer, string labelerId, string defId, BoundingBox2DLabeler.BoundingBoxAnnotation annotation)
{
return new PerceptionBoundingBoxAnnotationValue
{

59
com.unity.perception/Runtime/GroundTruth/Consumers/SoloConsumer.cs


return path;
}
void WriteJTokenToFile(string filePath, JToken jToken)
static void WriteJTokenToFile(string filePath, JToken jToken)
{
var stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture);
using (var jsonTextWriter = new JsonTextWriter(stringWriter))

{
var path = Path.Combine(currentDirectory, "metadata.json");
WriteJTokenToFile(path, ToMetadata(metadata));
m_IsComplete = true;
}

};
var captures = new JArray();
var metrics = new JArray();
foreach (var sensor in frame.sensors)
{

}
}
foreach (var metric in frame.metrics)
{
switch (metric)
{
case ObjectCountLabeler.ObjectCountMetric objCount:
metrics.Add(ConvertMetric(frame, objCount));
break;
case RenderedObjectInfoLabeler.RenderedObjectInfoMetric info:
metrics.Add(ConvertMetric(frame, info));
break;
}
}
frameJson["metrics"] = metrics;
return frameJson;
}

return token;
}
static JToken ConvertSensor(Frame frame, RgbSensor sensor)
{
// write out the png data

var file = File.Create(path, 4096);
file.Write(sensor.buffer, 0, sensor.buffer.Length);
file.Close();
#else
var fs = new FileStream(path, FileMode.Create, FileAccess.Write);
allTasks.Add(fs.WriteAsync(sensor.buffer, 0, sensor.buffer.Length));
#endif
var outRgb = ToSensorHeader(frame, sensor);
outRgb["fileName"] = path;

var annotations = new JArray();
var metrics = new JArray();
foreach (var annotation in sensor.annotations)
{

}
}
foreach (var metric in sensor.metrics)
{
switch (metric)
{
case ObjectCountLabeler.ObjectCountMetric objCount:
metrics.Add(ConvertMetric(frame, objCount));
break;
}
}
outRgb["metrics"] = metrics;
return outRgb;
}

}
outCount["object_counts"] = values;
return outCount;
}
static JToken ConvertMetric(Frame frame, RenderedObjectInfoLabeler.RenderedObjectInfoMetric info)
{
var outCount = ToMetricHeader(frame, info);
var values = new JArray();
foreach (var i in info.objectInfo)
{
values.Add(new JObject
{
["label_id"] = i.label_id,
["instance_id"] = i.instance_id,
["instance_color"] = FromColor32(i.instance_color),
["visible_pixels"] = i.visible_pixels
});
}
outCount["object_info"] = values;
return outCount;
}

72
com.unity.perception/Runtime/GroundTruth/DataModel.cs


using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Unity.Mathematics;
using UnityEngine.Perception.GroundTruth.Exporters.Solo;

{
void ToMessage(IMessageBuilder builder);
}
public abstract class DataModelBase : IMessageProducer
{
public abstract void ToMessage(IMessageBuilder builder);
}
/// <summary>

/// metrics are ready to report for a single frame.
/// </summary>
[Serializable]
public class Frame : IMessageProducer
public class Frame : DataModelBase
{
public Frame(int frame, int sequence, int step, float timestamp)
{

/// </summary>
public IEnumerable<Sensor> sensors;
/// <summary>
/// A list of all of the metrics recorded recorded for the frame.
/// </summary>
public List<Metric> metrics = new List<Metric>();
public void ToMessage(IMessageBuilder builder)
public override void ToMessage(IMessageBuilder builder)
{
builder.AddInt("frame", frame);
builder.AddInt("sequence", sequence);

var nested = builder.AddNestedMessageToVector("sensors");
s.ToMessage(nested);
}
foreach (var m in metrics)
{
var nested = builder.AddNestedMessageToVector("metrics");
m.ToMessage(nested);
}
}
}

[Serializable]
public abstract class Sensor : IMessageProducer
public abstract class Sensor : DataModelBase
{
/// <summary>
/// The unique, human readable ID for the sensor.

/// </summary>
public Vector3 acceleration;
// TODO put in camera intrinsic
// TODO put in projection
/// <summary>
/// A list of all of the metrics recorded recorded for the frame.
/// </summary>
public IEnumerable<Metric> metrics = new List<Metric>();
public virtual void ToMessage(IMessageBuilder builder)
public override void ToMessage(IMessageBuilder builder)
{
builder.AddString("id", Id);
builder.AddString("sensor_id", sensorType);

var nested = builder.AddNestedMessageToVector("annotations");
annotation.ToMessage(nested);
}
foreach (var metric in metrics)
{
var nested = builder.AddNestedMessageToVector("metrics");
metric.ToMessage(nested);
}
}
}

{
PNG
};
public string projection;
public float3x3 intrinsics;

builder.AddString("image_format", imageFormat.ToString());
builder.AddFloatVector("dimension", Utils.ToFloatVector(dimension));
builder.AddPngImage("camera", buffer);
builder.AddString("projection", projection);
// TODO intrinsics
}
}

/// data for their specific annotation type.
/// </summary>
public abstract class Annotation : IMessageProducer
public abstract class Annotation : DataModelBase
{
public Annotation() {}

/// </summary>
public string annotationType;
public virtual void ToMessage(IMessageBuilder builder)
public override void ToMessage(IMessageBuilder builder)
{
builder.AddString("id", Id);
builder.AddString("sensor_id", sensorId);

/// data for their specific metric type.
/// </summary>
[Serializable]
public abstract class Metric : IMessageProducer
public abstract class Metric : DataModelBase
{
public string Id;
/// <summary>

/// </summary>
public string description;
public virtual void ToMessage(IMessageBuilder builder)
public int sequenceId;
public int step;
public abstract IEnumerable<object> Values { get; }
public override void ToMessage(IMessageBuilder builder)
{
builder.AddString("id", Id);
builder.AddString("sensor_id", sensorId);

}
}
public class GenericMetric : Metric
{
public GenericMetric(string id, string annotationId, int sequenceId, int step, object[] values)
{
this.Id = id;
this.annotationId = annotationId;
this.sequenceId = sequenceId;
this.step = step;
m_Values = values;
}
object[] m_Values;
public override IEnumerable<object> Values => m_Values;
}
/// <summary>

274
com.unity.perception/Runtime/GroundTruth/DatasetCapture.cs


using UnityEngine;
using UnityEngine.Perception.GroundTruth.Consumers;
using UnityEngine.Perception.GroundTruth.DataModel;
using UnityEngine.Rendering;
#pragma warning disable 649
namespace UnityEngine.Perception.GroundTruth

public static DatasetCapture Instance => s_Instance ?? (s_Instance = new DatasetCapture());
//SimulationState m_SimulationState = null;
//List<SimulationState> m_ShuttingDownSimulationStates = new List<SimulationState>();
Type m_ActiveConsumerType = typeof(SoloConsumer);
public bool CanBeShutdown()
bool CanBeShutdown()
Debug.Log($"DC::CanBeShutdown, ready: {m_ReadyToShutdown}, active: {m_ActiveSimulation.IsNotRunning()}, shutting down #: {m_ShuttingDownSimulations.Count}, shutting down ready: {m_ShuttingDownSimulations.All(s => s.IsNotRunning())}");
return m_ReadyToShutdown && m_ActiveSimulation.IsNotRunning() && m_ShuttingDownSimulations.All(s => s.IsNotRunning());
}

}
class AllCapturesCompleteShutdownCondition : ICondition
{
public bool HasConditionBeenMet()
{
if (Instance.m_ReadyToShutdown)
Debug.Log("In here, but I doubt it");
return Instance.CanBeShutdown();
}
}
bool m_automaticShutdown = true;
public bool automaticShutdown
{
get => m_automaticShutdown;
set
{
switch (value)
{
case true when !m_automaticShutdown:
Manager.Instance.ShutdownCondition = new AllCapturesCompleteShutdownCondition();
break;
case false when m_automaticShutdown:
Manager.Instance.ShutdownCondition = null;
break;
}
m_automaticShutdown = value;
}
}
Debug.Log("Dataset Capture NEW!!!");
if (automaticShutdown)
Manager.Instance.ShutdownCondition = new AllCapturesCompleteShutdownCondition();
internal SimulationState currentSimulation
{
get => m_ActiveSimulation ?? (m_ActiveSimulation = CreateSimulationData());
}
#if false
internal SimulationState simulationState
{
get
{
if (!m_Simulations.Any()) m_Simulations.Add(CreateSimulationData());
return m_Simulations.Last();
}
private set => m_Simulations.Add(value);
}
#endif
internal SimulationState currentSimulation => m_ActiveSimulation ?? (m_ActiveSimulation = CreateSimulationData());
/// <summary>
/// The json metadata schema version the DatasetCapture's output conforms to.
/// </summary>

currentSimulation.RegisterAnnotationDefinition(definition);
}
public (int sequence, int step) GetSequenceAndStepFromFrame(int frame)
{
return currentSimulation.GetSequenceAndStepFromFrame(frame);
}
public void ReportMetric(MetricDefinition definition, object[] values)
{
currentSimulation.ReportMetric(definition, values);
}
/// <summary>
/// Starts a new sequence in the capture.
/// </summary>

static ConsumerEndpoint s_Endpoint;
static Type s_EndpointType = typeof(SoloConsumer);
//static Type s_EndpointType = typeof(SoloConsumer);
static Type s_EndpointType = typeof(OldPerceptionConsumer);
public static void SetEndpoint(ConsumerEndpoint endpoint)
{

public enum FutureType
{
Sensor,
Annotation,
Metric
Metric,
Annotation
public interface IAsyncFuture<T> where T : SimulationState.IPendingId
public class PendingId
T GetId();
public static PendingId CreateSensorId(int sequence, int step, string sensorId)
{
return new PendingId(FutureType.Sensor, sequence, step, sensorId, string.Empty,string.Empty);
}
public static PendingId CreateMetricId(int sequence, int step, string metricId)
{
return new PendingId(FutureType.Metric, sequence, step, string.Empty, string.Empty, metricId);
}
public static PendingId CreateMetricId(int sequence, int step, string sensorId, string metricId)
{
return new PendingId(FutureType.Metric, sequence, step, sensorId, string.Empty, metricId);
}
public static PendingId CreateMetricId(int sequence, int step, string sensorId, string annotationId, string metricId)
{
return new PendingId(FutureType.Metric, sequence, step, sensorId, annotationId, metricId);
}
public static PendingId CreateAnnotationId(int sequence, int step, string sensorId, string annotationId)
{
return new PendingId(FutureType.Annotation, sequence, step, sensorId, annotationId, string.Empty);
}
private PendingId(FutureType futureType, int sequence, int step, string sensorId, string annotationId, string metricId)
{
FutureType = futureType;
Sequence = sequence;
Step = step;
SensorId = sensorId;
AnnotationId = annotationId;
MetricId = metricId;
}
public FutureType FutureType { get; }
public int Sequence { get; }
public int Step { get; }
public string SensorId { get; }
public string AnnotationId { get; }
public string MetricId { get; }
bool isBaseValid => Sequence > -1 && Step > -1;
public bool IsValidSensorId =>
// Do not check if it's a sensor ID because both annotation and (some) metric IDs can be used to
// load sensors
isBaseValid && !string.IsNullOrEmpty(SensorId);
public bool IsValidMetricId =>
isBaseValid &&
FutureType == FutureType.Metric &&
!string.IsNullOrEmpty(MetricId);
public bool IsValidAnnotationId =>
isBaseValid &&
FutureType == FutureType.Annotation &&
!string.IsNullOrEmpty(SensorId) &&
!string.IsNullOrEmpty(AnnotationId);
public override bool Equals(object obj)
{
if (obj is PendingId other)
{
if (other.FutureType != FutureType) return false;
if (other.Sequence != Sequence) return false;
if (other.Step != Step) return false;
switch (FutureType)
{
case FutureType.Metric:
if (other.MetricId != MetricId) return false;
if (other.AnnotationId != AnnotationId) return false;
return other.SensorId == SensorId;
case FutureType.Annotation:
if (other.AnnotationId != AnnotationId) return false;
return other.SensorId == SensorId;
case FutureType.Sensor:
return other.SensorId == SensorId;
default:
return true;
}
}
return false;
}
public override int GetHashCode()
{
var hc = (Sequence * 397) ^ Step;
hc = (SensorId != null ? SensorId.GetHashCode() : 0 * 397) ^ hc;
hc = (AnnotationId != null ? AnnotationId.GetHashCode() : 0 * 397) ^ hc;
return (MetricId != null ? MetricId.GetHashCode() : 0 * 397) ^ hc;
}
}
public struct AsyncFuture<T> where T : DataModelBase
{
public static AsyncFuture<Sensor> CreateSensorFuture(PendingId id, SimulationState simState)
{
return new AsyncFuture<Sensor>(id, simState);
}
public static AsyncFuture<Metric> CreateMetricFuture(PendingId id, SimulationState simState)
{
return new AsyncFuture<Metric>(id, simState);
}
public static AsyncFuture<Annotation> CreateAnnotationFuture(PendingId id, SimulationState simState)
{
return new AsyncFuture<Annotation>(id, simState);
}
AsyncFuture(PendingId id, SimulationState simulationState)
{
pendingId = id;
this.simulationState = simulationState;
}
public SimulationState simulationState { get; private set; }
public PendingId pendingId { get; private set; }
public FutureType FutureType => pendingId.FutureType;
public bool IsValid()
{
return simulationState != null && simulationState.IsRunning();
}
public bool IsPending()
{
return simulationState.IsPending(this);
}
public void Report(T toReport)
{
simulationState.ReportAsyncResult(this, toReport);
}
}
#if false
public interface IAsyncFuture
{
PendingId GetId();
FutureType GetFutureType();

}
public struct AsyncSensorFuture : IAsyncFuture<SimulationState.PendingSensorId>
public struct AsyncSensorFuture : IAsyncFuture
public AsyncSensorFuture(SimulationState.PendingSensorId id, SimulationState simulationState)
public AsyncSensorFuture(PendingId id, SimulationState simulationState)
if (!id.IsValidSensorId) throw new ArgumentException("Passed in wrong ID type");
SimulationState.PendingSensorId m_Id;
PendingId m_Id;
public SimulationState.PendingSensorId GetId()
public PendingId GetId()
{
return m_Id;
}

}
}
public struct AsyncAnnotationFuture : IAsyncFuture<SimulationState.PendingCaptureId>
public struct AsyncAnnotationFuture : IAsyncFuture
public AsyncAnnotationFuture(SimulationState.PendingCaptureId id, SimulationState simulationState)
// TODO I do not like throwing exceptions in constructors, rethink this...
public AsyncAnnotationFuture(PendingId id, SimulationState simulationState)
if (!id.IsValidAnnotationId) throw new ArgumentException("Wrong ID type");
SimulationState.PendingCaptureId m_Id;
PendingId m_Id;
public SimulationState.PendingCaptureId GetId()
public PendingId GetId()
{
return m_Id;
}

}
}
public struct AsyncMetricFuture : IAsyncFuture<SimulationState.PendingCaptureId>
public struct AsyncMetricFuture : IAsyncFuture
public AsyncMetricFuture(SimulationState.PendingCaptureId id, SimulationState simulationState)
// TODO I do not like throwing exceptions in constructors, rethink this...
public AsyncMetricFuture(PendingId id, SimulationState simulationState)
if (!id.IsValidMetricId) throw new ArgumentException("Wrong ID type");
SimulationState.PendingCaptureId m_Id;
PendingId m_Id;
public SimulationState.PendingCaptureId GetId()
public PendingId GetId()
{
return m_Id;
}

m_SimulationState.ReportAsyncResult(this, metric);
}
}
#endif
/// <summary>
/// A handle to a sensor managed by the <see cref="DatasetCapture"/>. It can be used to check whether the sensor
/// is expected to capture this frame and report captures, annotations, and metrics regarding the sensor.

/// <returns>Returns a handle to the <see cref="AsyncAnnotation"/>, which can be used to report annotation data during a subsequent frame.</returns>
/// <exception cref="InvalidOperationException">Thrown if this method is called during a frame where <see cref="ShouldCaptureThisFrame"/> is false.</exception>
/// <exception cref="ArgumentException">Thrown if the given AnnotationDefinition is invalid.</exception>
public AsyncAnnotationFuture ReportAnnotationAsync(AnnotationDefinition annotationDefinition)
public AsyncFuture<Annotation> ReportAnnotationAsync(AnnotationDefinition annotationDefinition)
{
if (!ShouldCaptureThisFrame)
throw new InvalidOperationException("Annotation reported on SensorHandle in frame when its ShouldCaptureThisFrame is false.");

return DatasetCapture.Instance.currentSimulation.ReportAnnotationAsync(annotationDefinition, this);
}
public AsyncSensorFuture ReportSensorAsync()
public AsyncFuture<Sensor> ReportSensorAsync()
{
if (!ShouldCaptureThisFrame)
throw new InvalidOperationException("Annotation reported on SensorHandle in frame when its ShouldCaptureThisFrame is false.");

DatasetCapture.Instance.currentSimulation.ReportMetric(this, definition, metric);
}
#if false
public MetricHandle ReportMetric(MetricDefinition definition, Metric metric)
{

/// <param name="metricDefinition">The <see cref="MetricDefinition"/> of the metric</param>
/// <exception cref="InvalidOperationException">Thrown if <see cref="ShouldCaptureThisFrame"/> is false</exception>
/// <returns>An <see cref="AsyncMetric"/> which should be used to report the metric values, potentially in a later frame</returns>
public AsyncMetricFuture ReportMetricAsync(MetricDefinition metricDefinition)
public AsyncFuture<Metric> ReportMetricAsync(MetricDefinition metricDefinition)
{
if (!ShouldCaptureThisFrame)
throw new InvalidOperationException($"Sensor-based metrics may only be reported when SensorHandle.ShouldCaptureThisFrame is true");

/// <summary>
/// The ID of the annotation which will be used in the json metadata.
/// </summary>
public string Id => m_Definition.id;
public string Id => m_Definition != null ? m_Definition.id : string.Empty;
/// <summary>
/// The SensorHandle on which the annotation was reported

34
com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBox3DLabeler.cs


static readonly string k_Description = "Produces 3D bounding box ground truth data for all visible objects that bear a label defined in this labeler's associated label configuration.";
static readonly string k_AnnotationType = "bounding box 3d";
public BoundingBox3DAnnotationDefinition() : base(k_Id, k_Description, k_AnnotationType) { }
public BoundingBox3DAnnotationDefinition(IEnumerable<DefinitionEntry> spec)
public BoundingBox3DAnnotationDefinition(IdLabelConfig.LabelEntrySpec[] spec)
[Serializable]
public struct DefinitionEntry : IMessageProducer
{
public DefinitionEntry(int id, string name)
{
labelId = id;
labelName = name;
}
public int labelId;
public string labelName;
public void ToMessage(IMessageBuilder builder)
{
builder.AddInt("label_id", labelId);
builder.AddString("label_name", labelName);
}
}
public IEnumerable<DefinitionEntry> spec;
public IdLabelConfig.LabelEntrySpec[] spec;
public override void ToMessage(IMessageBuilder builder)
{

var nested = builder.AddNestedMessageToVector("spec");
e.ToMessage(nested);
// TODO figure out how to generically write the spec to a message builder
//e.ToMessage(nested);
}
}
}

static ProfilerMarker s_BoundingBoxCallback = new ProfilerMarker("OnBoundingBoxes3DReceived");
BoundingBox3DAnnotationDefinition m_AnnotationDefinition;
Dictionary<int, AsyncAnnotationFuture> m_AsyncAnnotations;
Dictionary<int, AsyncFuture<Annotation>> m_AsyncAnnotations;
Dictionary<int, Dictionary<uint, BoundingBoxAnnotation.Entry>> m_BoundingBoxValues;
List<BoundingBoxAnnotation.Entry> m_ToReport;

if (idLabelConfig == null)
throw new InvalidOperationException("BoundingBox3DLabeler's idLabelConfig field must be assigned");
var spec = idLabelConfig.GetAnnotationSpecification().Select(i => new BoundingBox3DAnnotationDefinition.DefinitionEntry { labelId = i.label_id, labelName = i.label_name });
m_AnnotationDefinition = new BoundingBox3DAnnotationDefinition(spec);
m_AnnotationDefinition = new BoundingBox3DAnnotationDefinition(idLabelConfig.GetAnnotationSpecification());
m_AsyncAnnotations = new Dictionary<int, AsyncAnnotationFuture>();
m_AsyncAnnotations = new Dictionary<int, AsyncFuture<Annotation>>();
m_BoundingBoxValues = new Dictionary<int, Dictionary<uint, BoundingBoxAnnotation.Entry>>();
m_ToReport = new List<BoundingBoxAnnotation.Entry>();
}

33
com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBoxLabeler.cs


static readonly string k_Description = "Bounding box for each labeled object visible to the sensor";
static readonly string k_AnnotationType = "bounding box";
public BoundingBoxAnnotationDefinition() : base(k_Id, k_Description, k_AnnotationType) { }
public BoundingBoxAnnotationDefinition(IEnumerable<DefinitionEntry> spec)
public BoundingBoxAnnotationDefinition(IdLabelConfig.LabelEntrySpec[] spec)
[Serializable]
public struct DefinitionEntry : IMessageProducer
{
public DefinitionEntry(int id, string name)
{
labelId = id;
labelName = name;
}
public int labelId;
public string labelName;
public void ToMessage(IMessageBuilder builder)
{
builder.AddInt("label_id", labelId);
builder.AddString("label_name", labelName);
}
}
public IEnumerable<DefinitionEntry> spec;
public IdLabelConfig.LabelEntrySpec[] spec;
public override void ToMessage(IMessageBuilder builder)
{

var nested = builder.AddNestedMessageToVector("spec");
e.ToMessage(nested);
// TODO figure out how to generically write the spec to a message builder
}
}
}

[FormerlySerializedAs("labelingConfiguration")]
public IdLabelConfig idLabelConfig;
Dictionary<int, (AsyncAnnotationFuture annotation, LabelEntryMatchCache labelEntryMatchCache)> m_AsyncData;
Dictionary<int, (AsyncFuture<Annotation> annotation, LabelEntryMatchCache labelEntryMatchCache)> m_AsyncData;
List<BoundingBoxAnnotation.Entry> m_ToVisualize;
Vector2 m_OriginalScreenSize = Vector2.zero;

if (idLabelConfig == null)
throw new InvalidOperationException("BoundingBox2DLabeler's idLabelConfig field must be assigned");
m_AsyncData = new Dictionary<int, (AsyncAnnotationFuture annotation, LabelEntryMatchCache labelEntryMatchCache)>();
m_AsyncData = new Dictionary<int, (AsyncFuture<Annotation> annotation, LabelEntryMatchCache labelEntryMatchCache)>();
var spec = idLabelConfig.GetAnnotationSpecification().Select(i => new BoundingBoxAnnotationDefinition.DefinitionEntry { labelId = i.label_id, labelName = i.label_name });
m_AnnotationDefinition = new BoundingBoxAnnotationDefinition(spec);
m_AnnotationDefinition = new BoundingBoxAnnotationDefinition(idLabelConfig.GetAnnotationSpecification());
DatasetCapture.Instance.RegisterAnnotationDefinition(m_AnnotationDefinition);
#if false

140
com.unity.perception/Runtime/GroundTruth/Labelers/InstanceSegmentationLabeler.cs


using System;
using System.Collections.Concurrent;
using Unity.Simulation;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Perception.GroundTruth.DataModel;

static readonly string k_Description = "You know the deal";
static readonly string k_AnnotationType = "instance segmentation";
public InstanceSegmentationDefinition() : base(k_Id, k_Description, k_AnnotationType) { }
public InstanceSegmentationDefinition(IdLabelConfig.LabelEntrySpec[] spec)
: base(k_Id, k_Description, k_AnnotationType)
{
this.spec = spec;
}
public IdLabelConfig.LabelEntrySpec[] spec;
public override void ToMessage(IMessageBuilder builder)
{
base.ToMessage(builder);
foreach (var e in spec)
{
var nested = builder.AddNestedMessageToVector("spec");
// TODO figure out how to generically write the spec to a message builder
}
}
}
/// <summary>

}
}
InstanceSegmentationDefinition m_Definition = new InstanceSegmentationDefinition();
InstanceSegmentationDefinition m_Definition;
///<inheritdoc/>
public override string description

static ProfilerMarker s_OnObjectInfoReceivedCallback = new ProfilerMarker("OnInstanceSegmentationObjectInformationReceived");
static ProfilerMarker s_OnImageReceivedCallback = new ProfilerMarker("OnInstanceSegmentationImagesReceived");
Dictionary<int, (AsyncAnnotationFuture future, byte[] buffer)> m_AsyncData;
Texture m_CurrentTexture;
/// <inheritdoc cref="IOverlayPanelProvider"/>

string m_InstancePath;
List<InstanceData> m_InstanceData;
#if false
Dictionary<int, AsyncFuture<Annotation>> m_PendingFutures;
ConcurrentDictionary<int, List<InstanceSegmentation.Entry>> m_PendingEntries;
ConcurrentDictionary<int, byte[]> m_PendingEncodedImages;
bool ReportFrameIfReady(int frame)
{
lock (m_PendingEntries)
{
var entriesReady = m_PendingEntries.ContainsKey(frame);
var imgReady = m_PendingEncodedImages.ContainsKey(frame);
if (!entriesReady || !imgReady) return false;
if (!m_PendingEntries.TryRemove(frame, out var entries))
{
throw new InvalidOperationException($"Could not remove entries for {frame} although it said it was ready");
}
if (!m_PendingEncodedImages.TryRemove(frame, out var img))
{
throw new InvalidOperationException($"Could not remove encoded image for {frame} although it said it was ready");
}
var toReport = new InstanceSegmentation
{
sensorId = perceptionCamera.ID,
Id = m_Definition.id,
annotationType = m_Definition.annotationType,
description = m_Definition.description,
imageFormat = "png",
instances = entries,
dimension = new Vector2(Screen.width, Screen.height), // TODO figure out how to get this from the camera
buffer = img
};
if (!m_PendingFutures.TryGetValue(frame, out var future))
{
throw new InvalidOperationException($"Could not get future for {frame}");
}
future.Report(toReport);
m_PendingFutures.Remove(frame);
return true;
}
}
public int frame;
public string path;
#endif
/// <summary>
/// Creates a new InstanceSegmentationLabeler. Be sure to assign <see cref="idLabelConfig"/> before adding to a <see cref="PerceptionCamera"/>.
/// </summary>

void OnRenderedObjectInfosCalculated(int frame, NativeArray<RenderedObjectInfo> renderedObjectInfos)
{
if (!m_AsyncData.TryGetValue(frame, out var asyncData))
return;
m_AsyncData.Remove(frame);
using (s_OnObjectInfoReceivedCallback.Auto())
{
m_InstanceData.Clear();

});
}
var toReport = new InstanceSegmentation
if (!m_PendingEntries.TryAdd(frame, instances))
sensorId = perceptionCamera.ID,
Id = m_Definition.id,
annotationType = m_Definition.annotationType,
description = m_Definition.description,
imageFormat = "png",
instances = instances,
dimension = new Vector2(Screen.width, Screen.height), // TODO figure out how to get this from the camera
buffer = asyncData.buffer
};
throw new InvalidOperationException($"Could not add instances for {frame}");
}
asyncData.future.Report(toReport);
ReportFrameIfReady(frame);
if (!m_AsyncData.TryGetValue(frameCount, out var annotation))
return;
// m_InstancePath = $"{k_Directory}/{k_FilePrefix}{frameCount}.png";
// var localPath = $"{Manager.Instance.GetDirectoryFor(k_Directory)}/{k_FilePrefix}{frameCount}.png";
#if false
frame = frameCount,
path = localPath
Profiler.BeginSample("InstanceSegmentationEncode");
var pngEncoded = ImageConversion.EncodeArrayToPNG(r.data.data.ToArray(), GraphicsFormat.R8G8B8A8_UNorm, (uint)r.data.width, (uint)r.data.height);
Profiler.EndSample();
Profiler.BeginSample("InstanceSegmentationWritePng");
File.WriteAllBytes(r.data.path, pngEncoded);
Manager.Instance.ConsumerFileProduced(r.data.path);
Profiler.EndSample();
var buffer = ImageConversion.EncodeArrayToPNG(r.data.data.ToArray(), GraphicsFormat.R8G8B8A8_UNorm, (uint)r.data.width, (uint)r.data.height);
if (!m_PendingEncodedImages.TryAdd(r.data.frame, buffer))
{
throw new InvalidOperationException("Could not add encoded png to pending encoded images");
}
ReportFrameIfReady(r.data.frame);
#endif
annotation.Item2 = ImageConversion.EncodeArrayToPNG(colors.ToArray(), GraphicsFormat.R8G8B8A8_UNorm, (uint)renderTexture.width, (uint)renderTexture.height);
// Profiler.EndSample();
// Profiler.BeginSample("InstanceSegmentationWritePng");
// File.WriteAllBytes(localPath, annotation.Item2);
// Manager.Instance.ConsumerFileProduced(localPath);
// Profiler.EndSample();
colors.Dispose();
m_AsyncData[frameCount] = annotation;
}
}

m_AsyncData[Time.frameCount] = (perceptionCamera.SensorHandle.ReportAnnotationAsync(m_Definition), null);
m_PendingFutures[Time.frameCount] = perceptionCamera.SensorHandle.ReportAnnotationAsync(m_Definition);
}
/// <inheritdoc/>

throw new InvalidOperationException("InstanceSegmentationLabeler's idLabelConfig field must be assigned");
m_Definition = new InstanceSegmentationDefinition(idLabelConfig.GetAnnotationSpecification());
DatasetCapture.Instance.RegisterAnnotationDefinition(m_Definition);
m_InstanceData = new List<InstanceData>();

m_AsyncData = new Dictionary<int, (AsyncAnnotationFuture, byte[])>();
m_PendingFutures = new Dictionary<int, AsyncFuture<Annotation>>();
m_PendingEntries = new ConcurrentDictionary<int, List<InstanceSegmentation.Entry>>();
m_PendingEncodedImages = new ConcurrentDictionary<int, byte[]>();
visualizationEnabled = supportsVisualization;
}

4
com.unity.perception/Runtime/GroundTruth/Labelers/KeypointLabeler.cs


AnnotationDefinition m_AnnotationDefinition;
Texture2D m_MissingTexture;
Dictionary<int, (AsyncAnnotationFuture annotation, Dictionary<uint, Annotation.Entry> keypoints)> m_AsyncAnnotations;
Dictionary<int, (AsyncFuture<DataModel.Annotation> annotation, Dictionary<uint, Annotation.Entry> keypoints)> m_AsyncAnnotations;
List<Annotation.Entry> m_KeypointEntriesToReport;
int m_CurrentFrame;

m_KnownStatus = new Dictionary<uint, CachedData>();
m_AsyncAnnotations = new Dictionary<int, (AsyncAnnotationFuture, Dictionary<uint, Annotation.Entry>)>();
m_AsyncAnnotations = new Dictionary<int, (AsyncFuture<DataModel.Annotation>, Dictionary<uint, Annotation.Entry>)>();
m_KeypointEntriesToReport = new List<Annotation.Entry>();
m_CurrentFrame = 0;

55
com.unity.perception/Runtime/GroundTruth/Labelers/ObjectCountLabeler.cs


using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using UnityEngine.Perception.GroundTruth.Exporters.Solo;
using UnityEngine.Rendering;
namespace UnityEngine.Perception.GroundTruth

[Serializable]
public sealed class ObjectCountLabeler : CameraLabeler
{
[Serializable]
public class ObjectCountMetricDefinition : MetricDefinition
{
public IdLabelConfig.LabelEntrySpec[] spec;
public ObjectCountMetricDefinition() { }
public ObjectCountMetricDefinition(string id, string description, IdLabelConfig.LabelEntrySpec[] spec)
{
this.id = id;
this.description = description;
this.spec = spec;
}
public override bool IsValid()
{
return base.IsValid() && spec != null;
}
public override void ToMessage(IMessageBuilder builder)
{
// TODO stuff for spec
base.ToMessage(builder);
}
}
/// <summary>
/// The object count metric records how many of a particular object are
/// present in a capture.

{
public struct Entry
public override IEnumerable<object> Values => objectCounts;
public class Entry
{
/// <summary>
/// The label of the category

/// The object counts
/// </summary>
public IEnumerable<Entry> objectCounts;
}
static readonly string k_Id = "ObjectCount";

ObjectCountMetric.Entry[] m_ClassCountValues;
Dictionary<int, AsyncMetricFuture> m_AsyncMetrics;
MetricDefinition m_Definition = new MetricDefinition(k_Id, k_Description);
Dictionary<int, AsyncFuture<Metric>> m_AsyncMetrics;
MetricDefinition m_Definition;
/// <summary>
/// Creates a new ObjectCountLabeler. This constructor should only be used by serialization. For creation from

if (labelConfig == null)
throw new InvalidOperationException("The ObjectCountLabeler idLabelConfig field must be assigned");
m_AsyncMetrics = new Dictionary<int, AsyncMetricFuture>();
m_AsyncMetrics = new Dictionary<int, AsyncFuture<Metric>>();
perceptionCamera.RenderedObjectInfosCalculated += (frameCount, objectInfo) =>
{

};
m_Definition = new MetricDefinition
m_Definition = new ObjectCountMetricDefinition
description = k_Description
description = k_Description,
spec = m_LabelConfig.GetAnnotationSpecification()
};
DatasetCapture.Instance.RegisterMetric(m_Definition);

/// <inheritdoc/>
protected override void OnBeginRendering(ScriptableRenderContext scriptableRenderContext)
{
#if true
#endif
}
NativeArray<uint> ComputeObjectCounts(NativeArray<RenderedObjectInfo> objectInfo)

}
}
var (seq, step) = DatasetCapture.Instance.GetSequenceAndStepFromFrame(frameCount);
sensorId = "",
Id = m_Definition.id,
sensorId = perceptionCamera.ID,
objectCounts = m_ClassCountValues
objectCounts = m_ClassCountValues,
sequenceId = seq,
step = step
};
classCountAsyncMetric.Report(payload);
}

122
com.unity.perception/Runtime/GroundTruth/Labelers/RenderedObjectInfoLabeler.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.Profiling.Memory.Experimental;
using UnityEngine.Perception.GroundTruth.DataModel;
using UnityEngine.Perception.GroundTruth.Exporters.Solo;
using UnityEngine.Rendering;
using UnityEngine.Serialization;
using UnityEngine.UI;

[Serializable]
public sealed class RenderedObjectInfoLabeler : CameraLabeler
{
///<inheritdoc/>
public override string description
[Serializable]
public class MetricDefinition : DataModel.MetricDefinition
get => "Produces label id, instance id, and visible pixel count in a single metric each frame for each object which takes up one or more pixels in the camera's frame, based on this labeler's associated label configuration.";
protected set {}
public IdLabelConfig.LabelEntrySpec[] spec;
public MetricDefinition() { }
public MetricDefinition(string id, string description, IdLabelConfig.LabelEntrySpec[] spec)
{
this.id = id;
this.description = description;
this.spec = spec;
}
public override bool IsValid()
{
return base.IsValid() && spec != null;
}
public override void ToMessage(IMessageBuilder builder)
{
// TODO stuff for spec
base.ToMessage(builder);
}
// ReSharper disable InconsistentNaming
struct RenderedObjectInfoValue
[Serializable]
public class RenderedObjectInfoMetric : Metric
[UsedImplicitly]
public int label_id;
[UsedImplicitly]
public uint instance_id;
[UsedImplicitly]
public Color32 instance_color;
[UsedImplicitly]
public int visible_pixels;
public override IEnumerable<object> Values => objectInfo;
public class Entry
{
[UsedImplicitly]
public int label_id;
[UsedImplicitly]
public uint instance_id;
[UsedImplicitly]
public Color32 instance_color;
[UsedImplicitly]
public int visible_pixels;
}
public IEnumerable<Entry> objectInfo;
// ReSharper restore InconsistentNaming
static ProfilerMarker s_ProduceRenderedObjectInfoMetric = new ProfilerMarker("ProduceRenderedObjectInfoMetric");
static readonly string k_Id = "RenderedObjectInfo";
static readonly string k_Description = "Produces label id, instance id, and visible pixel count in a single metric each frame for each object which takes up one or more pixels in the camera's frame, based on this labeler's associated label configuration.";
/// <summary>
/// The ID to use for visible pixels metrics in the resulting dataset
/// </summary>
public string objectInfoMetricId = "5ba92024-b3b7-41a7-9d3f-c03a6a8ddd01";
///<inheritdoc/>
public override string description
{
get => k_Description;
protected set {}
}
static ProfilerMarker s_ProduceRenderedObjectInfoMetric = new ProfilerMarker("ProduceRenderedObjectInfoMetric");
/// <summary>
/// The <see cref="IdLabelConfig"/> which associates objects with labels.

RenderedObjectInfoValue[] m_VisiblePixelsValues;
Dictionary<int, AsyncMetricFuture> m_ObjectInfoAsyncMetrics;
// MetricDefinition m_RenderedObjectInfoMetricDefinition;
RenderedObjectInfoMetric.Entry[] m_VisiblePixelsValues;
Dictionary<int, AsyncFuture<Metric>> m_ObjectInfoAsyncMetrics;
MetricDefinition m_Definition;
/// <summary>
/// Creates a new RenderedObjectInfoLabeler. Be sure to assign <see cref="idLabelConfig"/> before adding to a <see cref="PerceptionCamera"/>.

}
/// <summary>
/// Creates a new RenderedObjectInfoLabeler with an <see cref="IdLabelConfig"/>.
/// </summary>

if (idLabelConfig == null)
throw new ArgumentNullException(nameof(idLabelConfig));
this.idLabelConfig = idLabelConfig;
}

if (idLabelConfig == null)
throw new InvalidOperationException("RenderedObjectInfoLabeler's idLabelConfig field must be assigned");
m_ObjectInfoAsyncMetrics = new Dictionary<int, AsyncMetricFuture>();
m_ObjectInfoAsyncMetrics = new Dictionary<int, AsyncFuture<Metric>>();
perceptionCamera.RenderedObjectInfosCalculated += (frameCount, objectInfo) =>
{

m_Definition = new MetricDefinition(k_Id, k_Description, idLabelConfig.GetAnnotationSpecification());
DatasetCapture.Instance.RegisterMetric(m_Definition);
visualizationEnabled = supportsVisualization;
}

#if false
if (m_RenderedObjectInfoMetricDefinition.Equals(default))
{
m_RenderedObjectInfoMetricDefinition = DatasetCapture.RegisterMetricDefinition(
"rendered object info",
idLabelConfig.GetAnnotationSpecification(),
"Information about each labeled object visible to the sensor",
id: new Guid(objectInfoMetricId));
}
m_ObjectInfoAsyncMetrics[Time.frameCount] = perceptionCamera.SensorHandle.ReportMetricAsync(m_RenderedObjectInfoMetricDefinition);
#endif
m_ObjectInfoAsyncMetrics[Time.frameCount] = perceptionCamera.SensorHandle.ReportMetricAsync(m_Definition);
}
void ProduceRenderedObjectInfoMetric(NativeArray<RenderedObjectInfo> renderedObjectInfos, int frameCount)

m_ObjectInfoAsyncMetrics.Remove(frameCount);
if (m_VisiblePixelsValues == null || m_VisiblePixelsValues.Length != renderedObjectInfos.Length)
m_VisiblePixelsValues = new RenderedObjectInfoValue[renderedObjectInfos.Length];
m_VisiblePixelsValues = new RenderedObjectInfoMetric.Entry[renderedObjectInfos.Length];
var visualize = visualizationEnabled;

if (!TryGetLabelEntryFromInstanceId(objectInfo.instanceId, out var labelEntry))
continue;
m_VisiblePixelsValues[i] = new RenderedObjectInfoValue
m_VisiblePixelsValues[i] = new RenderedObjectInfoMetric.Entry
{
label_id = labelEntry.id,
instance_id = objectInfo.instanceId,

}
}
// metric.Report(m_VisiblePixelsValues);
var (seq, step) = DatasetCapture.Instance.GetSequenceAndStepFromFrame(frameCount);
var payload = new RenderedObjectInfoMetric
{
Id = m_Definition.id,
sensorId = perceptionCamera.ID,
annotationId = default,
description = m_Definition.description,
objectInfo = m_VisiblePixelsValues,
sequenceId = seq,
step = step
};
metric.Report(payload);
}
}

6
com.unity.perception/Runtime/GroundTruth/Labelers/SemanticSegmentationLabeler.cs


LensDistortionUrpPass m_LensDistortionPass;
#endif
Dictionary<int, AsyncAnnotationFuture> m_AsyncAnnotations;
Dictionary<int, AsyncFuture<Annotation>> m_AsyncAnnotations;
/// <summary>
/// Creates a new SemanticSegmentationLabeler. Be sure to assign <see cref="labelConfig"/> before adding to a <see cref="PerceptionCamera"/>.

struct AsyncSemanticSegmentationWrite
{
public AsyncAnnotationFuture future;
public AsyncFuture<Annotation> future;
public NativeArray<Color32> data;
public int width;
public int height;

"SemanticSegmentationLabeler's LabelConfig must be assigned");
}
m_AsyncAnnotations = new Dictionary<int, AsyncAnnotationFuture>();
m_AsyncAnnotations = new Dictionary<int, AsyncFuture<Annotation>>();
if (targetTexture != null)
{

2
com.unity.perception/Runtime/GroundTruth/Labeling/IdLabelConfig.cs


[CreateAssetMenu(fileName = "IdLabelConfig", menuName = "Perception/ID Label Config", order = 1)]
public class IdLabelConfig : LabelConfig<IdLabelEntry>
{
/// <summary>
/// Whether the inspector will auto-assign ids based on the id of the first element.
/// </summary>

17
com.unity.perception/Runtime/GroundTruth/PerceptionCamera.cs


{
var capture = new RgbSensor
{
Id = "perception_camera",
Id = ID,
sensorType = "rgb_camera",
description = "you know",
position = transform.position,

imageFormat = RgbSensor.ImageFormat.PNG,
dimension = new Vector2(cam.pixelWidth, cam.pixelHeight),
intrinsics = ToProjectionMatrix3x3(cam.projectionMatrix),
projection = cam.orthographic ? "orthographic" : "perspective",
buffer = new byte[0]
};

Profiler.BeginSample("CaptureDataFromLastFrame");
//var width = cam.pixelWidth;
//var height = cam.pixelHeight;
var frameCount = Time.frameCount;
//var captureFilename = $"{Manager.Instance.GetDirectoryFor(rgbDirectory)}/{k_RgbFilePrefix}{frameCount}.png";
// Record the camera's projection matrix
SetPersistentSensorData("camera_intrinsic", ToProjectionMatrix3x3(cam.projectionMatrix));
SetPersistentSensorData("projection", cam.orthographic ? "orthographic" : "perspective");
var asyncSensor = SensorHandle.ReportSensorAsync();

472
com.unity.perception/Runtime/GroundTruth/SimulationState.cs


using System;
using System.Collections;
using System.ComponentModel;
using System.Threading;
using Unity.Simulation;
using System.Runtime.CompilerServices;
using UnityEngine.Rendering;
public static int TimeOutFrameCount = 100;
// TODO I want to find a better way to control this...
public static int TimeOutFrameCount = 1000;
public enum ExecutionStateType
{

int m_Step = -1;
List<AdditionalInfoTypeData> m_AdditionalInfoTypeData = new List<AdditionalInfoTypeData>();
#if false
Dictionary<int, PendingFrameId> m_FrameToPendingIdMap = new Dictionary<int, PendingFrameId>();
//Dictionary<PendingFrameId, PendingFrame> m_PendingFrames = new Dictionary<PendingFrameId, PendingFrame>();
#else
Dictionary<int, FrameId> m_FrameToPendingIdMap = new Dictionary<int, FrameId>();
Dictionary<FrameId, int> m_PendingIdToFrameMap = new Dictionary<FrameId, int>();
SortedDictionary<FrameId, PendingFrame> m_PendingFrames = new SortedDictionary<FrameId, PendingFrame>();
#endif
CustomSampler m_SerializeCapturesSampler = CustomSampler.Create("SerializeCaptures");
CustomSampler m_SerializeCapturesAsyncSampler = CustomSampler.Create("SerializeCapturesAsync");

CustomSampler m_GetOrCreatePendingCaptureForThisFrameSampler = CustomSampler.Create("GetOrCreatePendingCaptureForThisFrame");
float m_LastTimeScale;
struct FrameId : IComparable<FrameId>
{
public FrameId(int sequence, int step)
{
this.sequence = sequence;
this.step = step;
}
public int sequence;
public int step;
public override string ToString()
{
return $"({sequence},{step})";
}
internal static FrameId FromPendingId(PendingId id)
{
return new FrameId
{
sequence = id.Sequence,
step = id.Step
};
}
public int CompareTo(FrameId other)
{
var sequenceComparison = sequence.CompareTo(other.sequence);
return sequenceComparison != 0 ? sequenceComparison : step.CompareTo(other.step);
}
}
//A sensor will be triggered if sequenceTime is within includeThreshold seconds of the next trigger
const float k_SimulationTimingAccuracy = 0.01f;

bool readyToShutdown => !m_PendingFrames.Any();
public (int sequence, int step) GetSequenceAndStepFromFrame(int frame)
{
return m_FrameToPendingIdMap.TryGetValue(frame, out var penId) ? (penId.sequence, penId.step) : (-1, -1);
}
public PendingId ReportMetric(MetricDefinition definition, object[] values)
{
if (definition == null)
throw new ArgumentNullException(nameof(definition));
var metricId = PendingId.CreateMetricId(m_SequenceId, AcquireStep(), definition.id);
var frameId = new FrameId(m_SequenceId, AcquireStep());
var metric = new GenericMetric(definition.id, string.Empty, frameId.sequence, frameId.step, values);
var pendingFrame = GetOrCreatePendingFrame(frameId);
if (pendingFrame == null)
throw new InvalidOperationException($"Could not get or create a pending frame for {frameId}");
pendingFrame.AddMetric(metricId, metric);
return metricId;
}
#if false
public class PendingFrameId2 : Tuple<int, int>
{
public PendingFrameId2(int item1, int item2)
: base(item1, item2) { }
}
public interface IPendingId
{
PendingFrameId AsFrameId();

}
#endif
public PendingSensor(PendingSensorId id)
public PendingSensor(PendingId id)
if (!id.IsValidSensorId) throw new ArgumentException("Passed in wrong ID type");
Annotations = new Dictionary<PendingCaptureId, Annotation>();
Metrics = new Dictionary<PendingCaptureId, Metric>();
Annotations = new Dictionary<PendingId, Annotation>();
public PendingSensor(PendingSensorId id, Sensor sensorData) : this(id)
public PendingSensor(PendingId id, Sensor sensorData) : this(id)
if (!id.IsValidSensorId) throw new ArgumentException("Passed in wrong ID type");
m_SensorData = sensorData;
}

m_SensorData.annotations = Annotations.Select(kvp => kvp.Value);
m_SensorData.metrics = Metrics.Select(kvp => kvp.Value);
PendingSensorId m_Id;
PendingId m_Id;
public Dictionary<PendingCaptureId, Annotation> Annotations { get; private set; }
public Dictionary<PendingCaptureId, Metric> Metrics { get; private set; }
public Dictionary<PendingId, Annotation> Annotations { get; private set; }
public bool IsPending<T>(IAsyncFuture<T> asyncFuture) where T : IPendingId
//public bool IsPending(IAsyncFuture asyncFuture)
public bool IsPending<T>(AsyncFuture<T> asyncFuture) where T : DataModelBase
switch (asyncFuture.GetFutureType())
switch (asyncFuture.FutureType)
return asyncFuture.GetId() is PendingCaptureId captureId && Annotations.ContainsKey(captureId) && Annotations[captureId] == null;
var id = asyncFuture.pendingId;
if (!id.IsValidAnnotationId)
throw new InvalidOperationException("Passed in ID was not correct type for annotation");
if (!Annotations.ContainsKey(id))
throw new InvalidOperationException("");
return
Annotations[id] == null;
return asyncFuture.GetId() is PendingCaptureId captureId && Metrics.ContainsKey(captureId) && Metrics[captureId] == null;
throw new InvalidOperationException("Metrics should not be registered with sensors");
}
default:
throw new ArgumentOutOfRangeException();

public bool ReportAsyncResult<T>(IAsyncFuture<T> asyncFuture, object result) where T : IPendingId
// TODO decide if I should report boolean values or handle it with exceptions
public bool ReportAsyncResult<T>(AsyncFuture<T> asyncFuture, object result) where T : DataModelBase
switch (asyncFuture.GetFutureType())
switch (asyncFuture.FutureType)
if (result is Sensor sensor)
if (!(result is Sensor sensor))
m_SensorData = sensor;
return true;
throw new InvalidOperationException("Tried to report a non-sensor value with an async sensor");
return false;
m_SensorData = sensor;
return true;
if (result is Annotation annotation && asyncFuture.GetId() is PendingCaptureId capId)
var id = asyncFuture.pendingId;
if (!id.IsValidAnnotationId)
throw new InvalidOperationException("Passed in ID was not correct type for annotation");
if (!Annotations.ContainsKey(id))
throw new InvalidOperationException("");
if (!(result is Annotation annotation))
Annotations[capId] = annotation;
return true;
throw new InvalidOperationException("Tried to report a non-annotation value with an async annotation");
return false;
Annotations[id] = annotation;
return true;
if (result is Metric metric && asyncFuture.GetId() is PendingCaptureId capId)
{
Metrics[capId] = metric;
return true;
}
Debug.LogError("Metrics should not be sent to sensors");
return false;
}
default:

{
return
m_SensorData != null &&
Metrics.All(i => i.Value != null) &&
public class PendingFrame
class PendingFrame
SimulationState m_SimulationState;
public FrameId PendingId { get; }
public float Timestamp { get; }
public PendingFrameId PendingId { get; }
public float Timestamp { get; set; }
internal Dictionary<PendingSensorId, PendingSensor> sensors = new Dictionary<PendingSensorId, PendingSensor>();
Dictionary<string, PendingSensor> m_Sensors;
Dictionary<string, Metric> m_Metrics;
public IEnumerable<PendingSensor> sensors => m_Sensors.Values;
public IEnumerable<Metric> metrics => m_Metrics.Values;
public PendingFrame(PendingFrameId pendingFrameId, float timestamp, SimulationState simState)
public PendingFrame(FrameId pendingFrameId, float timestamp)
m_SimulationState = simState;
m_Sensors = new Dictionary<string, PendingSensor>();
m_Metrics = new Dictionary<string, Metric>();
return sensors.All(sensor => sensor.Value.IsReadyToReport());
return
m_Metrics.All(i => i.Value != null) &&
m_Sensors.All(sensor => sensor.Value.IsReadyToReport());
public PendingSensor GetOrCreatePendingSensor(PendingSensorId sensorId)
public PendingSensor GetOrCreatePendingSensor(PendingId sensorId)
if (!sensorId.IsValidSensorId)
throw new ArgumentException("Passed in a non-sensor ID");
public PendingSensor GetOrCreatePendingSensor(PendingSensorId sensorId, out bool created)
PendingSensor GetOrCreatePendingSensor(PendingId pendingId, out bool created)
if (!sensors.TryGetValue(sensorId, out var pendingSensor))
if (!pendingId.IsValidSensorId)
pendingSensor = new PendingSensor(sensorId);
sensors[sensorId] = pendingSensor;
throw new ArgumentException("Passed in an invalid sensor ID");
}
if (!m_Sensors.TryGetValue(pendingId.SensorId, out var pendingSensor))
{
pendingSensor = new PendingSensor(pendingId);
m_Sensors[pendingId.SensorId] = pendingSensor;
created = true;
}

public bool IsPending<T>(IAsyncFuture<T> asyncFuture) where T : IPendingId
public bool IsPending<T>(AsyncFuture<T> asyncFuture) where T : DataModelBase
var sensorId = asyncFuture.GetId().AsSensorId();
if (!sensorId.IsValid()) return false;
var pendingId = asyncFuture.pendingId;
if (pendingId == null)
throw new InvalidOperationException("Async future did not have an ID");
if (asyncFuture.FutureType == FutureType.Metric)
{
if (!pendingId.IsValidMetricId)
{
throw new InvalidEnumArgumentException("AsyncFuture has the wrong ID type for a metric");
}
var metricId = pendingId.MetricId;
return m_Metrics.ContainsKey(metricId) && m_Metrics[metricId] == null;
}
if (!pendingId.IsValidSensorId)
throw new InvalidOperationException("Pending ID is not a valid sensor ID");
sensors.TryGetValue(sensorId, out var pendingSensor) &&
m_Sensors.TryGetValue(pendingId.SensorId, out var pendingSensor) &&
public bool ReportAsyncResult<T>(IAsyncFuture<T> asyncFuture, object result) where T : IPendingId
public bool ReportAsyncResult<T>(AsyncFuture<T> asyncFuture, T result) where T : DataModelBase
var sensorId = asyncFuture.GetId().AsSensorId();
if (!sensorId.IsValid()) return false;
var pendingId = asyncFuture.pendingId;
var sensor = GetOrCreatePendingSensor(sensorId);
sensor.ReportAsyncResult(asyncFuture, result);
if (pendingId == null)
throw new InvalidOperationException("Async future did not have an ID");
return true;
if (asyncFuture.FutureType == FutureType.Metric)
{
if (!(result is Metric metric))
throw new InvalidOperationException("Future is associated with a non-metric result");
if (!pendingId.IsValidMetricId)
{
throw new InvalidEnumArgumentException("AsyncFuture has the wrong ID type for a metric");
}
m_Metrics[pendingId.MetricId] = metric;
return true;
}
if (!pendingId.IsValidSensorId)
throw new InvalidOperationException("Pending ID is not a valid sensor ID");
var sensor = GetOrCreatePendingSensor(pendingId);
return sensor.ReportAsyncResult(asyncFuture, result);
public void AddSensor(PendingId id, Sensor sensor)
{
if (!id.IsValidSensorId) throw new ArgumentException("Passed in ID is not a valid sensor ID");
m_Sensors[id.SensorId] = new PendingSensor(id, sensor);
}
public void AddMetric(PendingId id, Metric metric)
{
if (!id.IsValidMetricId) throw new ArgumentException("Passed in ID is not a valid metric ID");
m_Metrics[id.MetricId] = metric;
}
}
public struct SensorData

}
}
}
#if false
internal void ReportCapture(SensorHandle sensorHandle, string filename, SensorSpatialData sensorSpatialData, params(string, object)[] additionalSensorValues)
{
var sensorData = m_Sensors[sensorHandle];
var pendingCapture = GetOrCreatePendingCaptureForThisFrame(sensorHandle, out _);
if (pendingCapture.CaptureReported)
throw new InvalidOperationException($"Capture for frame {Time.frameCount} already reported for sensor {this}");
pendingCapture.CaptureReported = true;
pendingCapture.AdditionalSensorValues = additionalSensorValues;
pendingCapture.SensorSpatialData = sensorSpatialData;
sensorData.lastCaptureFrameCount = Time.frameCount;
m_Sensors[sensorHandle] = sensorData;
// SB - maybe this can all be moved to the other capture area
var width = -1;
var height = -1;
var fullPath = filename;
var frameCount = 0;
var buffer = new byte[0];
foreach (var i in additionalSensorValues)
{
switch (i.Item1)
{
case "camera_width":
width = (int)i.Item2;
break;
case "camera_height":
height = (int)i.Item2;
break;
case "full_path":
fullPath = (string)i.Item2;
break;
case "frame":
frameCount = (int)i.Item2;
break;
case "":
buffer = (byte[])i.Item2;
break;
}
}
var trans = pendingCapture.SensorSpatialData.EgoPose.position;
var rot = pendingCapture.SensorSpatialData.EgoPose.rotation;
var velocity = pendingCapture.SensorSpatialData.EgoVelocity ?? Vector3.zero;
var accel = pendingCapture.SensorSpatialData.EgoAcceleration ?? Vector3.zero;
}
#endif
/// <summary>
/// Use this to get the current step when it is desirable to ensure the step has been allocated for this frame. Steps should only be allocated in frames where a capture or metric is reported.
/// </summary>

void VerifyNoMorePendingFrames()
{
if (m_PendingFrames.Count > 0)
Debug.LogError($"Simulation ended with pending {m_PendingFrames.Count} annotations (final id): ({m_PendingFrames.Last().Key.Sequence},{m_PendingFrames.Last().Key.Step})");
Debug.LogError($"Simulation ended with pending {m_PendingFrames.Count} annotations (final id): {m_PendingFrames.Last().Key}");
}
public void SetNextCaptureTimeToNowForSensor(SensorHandle sensorHandle)

m_AdditionalInfoTypeData.Add(annotationDefinitionInfo);
}
public PendingSensorId ReportSensor(SensorHandle handle, Sensor sensor)
public PendingId ReportSensor(SensorHandle handle, Sensor sensor)
var pendingSensorId = new PendingSensorId(handle.Id, m_SequenceId, step);
var pendingFrame = GetOrCreatePendingFrame(pendingSensorId.AsFrameId());
pendingFrame.sensors[pendingSensorId] = new PendingSensor(pendingSensorId, sensor);
return pendingSensorId;
var id = PendingId.CreateSensorId(m_SequenceId, step, handle.Id);
var pendingFrame = GetOrCreatePendingFrame(id);
pendingFrame.AddSensor(id, sensor);
return id;
public PendingCaptureId ReportAnnotation(SensorHandle sensorHandle, AnnotationDefinition definition, Annotation annotation)
public PendingId ReportAnnotation(SensorHandle sensorHandle, AnnotationDefinition definition, Annotation annotation)
var sensorId = new PendingCaptureId(sensorHandle.Id, definition.id, m_SequenceId, step);
var pendingFrame = GetOrCreatePendingFrame(sensorId.AsFrameId());
var sensorId = PendingId.CreateSensorId(m_SequenceId, step, sensorHandle.Id);
var pendingFrame = GetOrCreatePendingFrame(sensorId);
var sensor = pendingFrame.GetOrCreatePendingSensor(sensorId);
var sensor = pendingFrame.GetOrCreatePendingSensor(sensorId.SensorId);
var annotationId = PendingId.CreateAnnotationId(m_SequenceId, step, sensorHandle.Id, definition.id);
var annotationId = new PendingCaptureId(sensorHandle.Id, definition.id, m_SequenceId, step);
PendingFrame GetOrCreatePendingFrame(PendingFrameId pendingId)
PendingFrame GetOrCreatePendingFrame(PendingId pendingId)
{
var frameId = FrameId.FromPendingId(pendingId);
return GetOrCreatePendingFrame(frameId);
}
PendingFrame GetOrCreatePendingFrame(FrameId frameId)
return GetOrCreatePendingFrame(pendingId, out var _);
return GetOrCreatePendingFrame(frameId, out var _);
PendingFrame GetOrCreatePendingFrame(PendingFrameId pendingId, out bool created)
PendingFrame GetOrCreatePendingFrame(FrameId frameId, out bool created)
if (!m_PendingFrames.TryGetValue(pendingId, out var pendingFrame))
if (!m_PendingFrames.TryGetValue(frameId, out var pendingFrame))
pendingFrame = new PendingFrame(pendingId, SequenceTime, this);
m_PendingFrames[pendingId] = pendingFrame;
m_PendingIdToFrameMap[pendingId] = Time.frameCount;
pendingFrame = new PendingFrame(frameId, SequenceTime);
m_PendingFrames[frameId] = pendingFrame;
m_PendingIdToFrameMap[frameId] = Time.frameCount;
m_FrameToPendingIdMap[Time.frameCount] = frameId;
created = true;
}

public AsyncAnnotationFuture ReportAnnotationAsync(AnnotationDefinition annotationDefinition, SensorHandle sensorHandle)
public AsyncFuture<Annotation> ReportAnnotationAsync(AnnotationDefinition annotationDefinition, SensorHandle sensorHandle)
return new AsyncAnnotationFuture(ReportAnnotation(sensorHandle, annotationDefinition, null), this);
return AsyncFuture<Annotation>.CreateAnnotationFuture(ReportAnnotation(sensorHandle, annotationDefinition, null), this);
public AsyncSensorFuture ReportSensorAsync(SensorHandle handle)
public AsyncFuture<Sensor> ReportSensorAsync(SensorHandle handle)
return new AsyncSensorFuture(ReportSensor(handle, null), this);
return AsyncFuture<Sensor>.CreateSensorFuture(ReportSensor(handle, null), this);
public bool IsPending<T>(IAsyncFuture<T> asyncFuture) where T : IPendingId
public bool IsPending<T>(AsyncFuture<T> asyncFuture) where T : DataModelBase
var frameId = FrameId.FromPendingId(asyncFuture.pendingId);
m_PendingFrames.TryGetValue(asyncFuture.GetId().AsFrameId(), out var pendingFrame) &&
m_PendingFrames.TryGetValue(frameId, out var pendingFrame) &&
PendingFrame GetPendingFrame<T>(IAsyncFuture<T> future) where T : IPendingId
PendingFrame GetPendingFrame<T>(AsyncFuture<T> future) where T : DataModelBase
return GetPendingFrame(future.GetId().AsFrameId());
return GetPendingFrame(FrameId.FromPendingId(future.pendingId));
PendingFrame GetPendingFrame(PendingFrameId id)
PendingFrame GetPendingFrame(FrameId id)
bool ReportAsyncResultGeneric<T>(IAsyncFuture<T> asyncFuture, object result) where T : IPendingId
public bool ReportAsyncResult<T>(AsyncFuture<T> asyncFuture, T result) where T : DataModelBase
{
if (!asyncFuture.IsPending()) return false;
var pendingFrame = GetPendingFrame(asyncFuture);
if (pendingFrame == null) return false;
return pendingFrame.ReportAsyncResult<T>(asyncFuture, result);
}
#if false
bool ReportAsyncResultGeneric<T>(AsyncFuture<T> asyncFuture, T result) where T : DataModelBase
{
if (!asyncFuture.IsPending()) return false;

return pendingFrame.ReportAsyncResult(asyncFuture, result);
return pendingFrame.ReportAsyncResult<T>(asyncFuture, result);
public bool ReportAsyncResult(AsyncSensorFuture asyncFuture, Sensor sensor)
public bool ReportAsyncResult(AsyncFuture<Sensor> asyncFuture, Sensor sensor)
public bool ReportAsyncResult(AsyncAnnotationFuture asyncFuture, Annotation annotation)
public bool ReportAsyncResult(AsyncFuture<Annotation> asyncFuture, Annotation annotation)
public bool ReportAsyncResult(AsyncMetricFuture asyncFuture, Metric metric)
public bool ReportAsyncResult(AsyncFuture<Metric> asyncFuture, Metric metric)
public AsyncMetricFuture CreateAsyncMetric(MetricDefinition metricDefinition, SensorHandle sensorHandle = default, AnnotationHandle annotationHandle = default)
#endif
public AsyncFuture<Metric> CreateAsyncMetric(MetricDefinition metricDefinition, SensorHandle sensorHandle = default, AnnotationHandle annotationHandle = default)
return new AsyncMetricFuture(pendingId, this);
return AsyncFuture<Metric>.CreateMetricFuture(pendingId, this);
public PendingCaptureId ReportMetric(SensorHandle sensor, MetricDefinition definition, Metric metric)
public PendingId ReportMetric(SensorHandle sensor, MetricDefinition definition, Metric metric)
var pendingId = new PendingCaptureId(sensor.Id, definition.id, m_SequenceId, AcquireStep());
var pendingFrame = GetOrCreatePendingFrame(pendingId.AsFrameId());
var pendingId = PendingId.CreateMetricId(m_SequenceId, AcquireStep(), sensor.Id, definition.id);
var pendingFrame = GetOrCreatePendingFrame(pendingId);
var pendingSensor = pendingFrame.GetOrCreatePendingSensor(pendingId.SensorId);
pendingFrame.AddMetric(pendingId, metric);
pendingSensor.Metrics[pendingId] = metric;
public PendingCaptureId ReportMetric(SensorHandle sensor, MetricDefinition definition, Metric metric, AnnotationHandle annotation)
public PendingId ReportMetric(SensorHandle sensor, MetricDefinition definition, Metric metric, AnnotationHandle annotation)
var pendingId = new PendingCaptureId(sensor.Id, definition.id, m_SequenceId, AcquireStep());
var pendingFrame = GetOrCreatePendingFrame(pendingId.AsFrameId());
var pendingId = PendingId.CreateMetricId(m_SequenceId, AcquireStep(), sensor.Id, annotation.Id, definition.id);
var pendingFrame = GetOrCreatePendingFrame(pendingId);
var pendingSensor = pendingFrame.GetOrCreatePendingSensor(pendingId.SensorId);
pendingFrame.AddMetric(pendingId, metric);
pendingSensor.Metrics[pendingId] = metric;
Sensor ToSensor(PendingFrame pendingFrame, SimulationState simulationState, int captureFileIndex)
{
var sensor = new RgbSensor
{
Id = "camera",
sensorType = "camera",
description = "this is the description of the sensor",
position = Vector3.zero,
rotation = Vector3.zero,
velocity = Vector3.zero,
acceleration = Vector3.zero,
imageFormat = RgbSensor.ImageFormat.PNG,
dimension = Vector2.zero,
buffer = null
};
return sensor;
}
// TODO rename this to 'ReportPendingFrames'
void WritePendingCaptures(bool flush = false, bool writeCapturesFromThisFrame = false)
{

var pendingFramesToWrite = new Queue<KeyValuePair<PendingFrameId,PendingFrame>>(m_PendingFrames.Count);
var timedOutFrames = new List<KeyValuePair<PendingFrameId, PendingFrame>>(m_PendingFrames.Count);
var pendingFramesToWrite = new Queue<KeyValuePair<FrameId,PendingFrame>>(m_PendingFrames.Count);
var timedOutFrames = new List<KeyValuePair<FrameId, PendingFrame>>(m_PendingFrames.Count);
var currentFrame = Time.frameCount;

{
var recordedFrame = m_PendingIdToFrameMap[frame.Value.PendingId];
var recordedFrame = m_PendingIdToFrameMap[frame.Key];
if ((writeCapturesFromThisFrame || recordedFrame < currentFrame) &&
frame.Value.IsReadyToReport())

foreach (var pf in timedOutFrames)
{
Debug.LogError($"A frame has timed out and is being removed: [{pf.Key.Sequence},{pf.Key.Step}]");
Debug.LogError($"A frame has timed out and is being removed: {pf.Key}");
return frame.sensors.Values.Where(s => s.IsReadyToReport()).Select(s => s.ToSensor());
return frame.sensors.Where(s => s.IsReadyToReport()).Select(s => s.ToSensor());
var frame = new Frame(frameId, pendingFrame.PendingId.Sequence, pendingFrame.PendingId.Step, pendingFrame.Timestamp);
var frame = new Frame(frameId, pendingFrame.PendingId.sequence, pendingFrame.PendingId.step, pendingFrame.Timestamp);
#if false
foreach (var annotation in pendingFrame.annotations.Values)
{
frame.annotations.Add(annotation);
}
foreach (var metric in pendingFrame.metrics.Values)
foreach (var metric in pendingFrame.metrics)
#endif
void Write(Queue<KeyValuePair<PendingFrameId, PendingFrame>> frames, SimulationState simulationState)
void Write(Queue<KeyValuePair<FrameId, PendingFrame>> frames, SimulationState simulationState)
{
#if true
// TODO this needs to be done properly, we need to wait on all of the frames to come back so we

49
com.unity.perception/Runtime/Randomization/Scenarios/PerceptionScenario.cs


/// <summary>
/// The metric definition used to report the current scenario iteration
/// </summary>
// MetricDefinition m_IterationMetricDefinition;
MetricDefinition m_IterationMetricDefinition;
/// <summary>
/// The scriptable render pipeline hook used to capture perception data skips the first frame of the simulation

return true;
}
}
#if false
class ShutdownCondition : ICondition
{
public bool HasConditionBeenMet()
{
if (DatasetCapture.Instance.ReadyToShutdown)
{
Debug.Log("Triggered dc ready");
}
return DatasetCapture.Instance.ReadyToShutdown;
}
}
#endif
var md = new MetricDefinition();
DatasetCapture.Instance.RegisterMetric(md);
// Manager.Instance.ShutdownCondition = new ShutdownCondition();
Manager.Instance.ShutdownNotification += () =>

};
#if false
m_IterationMetricDefinition = DatasetCapture.RegisterMetricDefinition(
"scenario_iteration", "Iteration information for dataset sequences",
Guid.Parse(k_ScenarioIterationMetricDefinitionId));
#if true
m_IterationMetricDefinition = new MetricDefinition("scenario_iteration", "Iteration information for dataset sequences");
DatasetCapture.Instance.RegisterMetric(m_IterationMetricDefinition);
var randomSeedMetricDefinition = new MetricDefinition("random-seed", "The random seed used to initialize the random state of the simulation. Only triggered once per simulation.");
DatasetCapture.Instance.RegisterMetric(randomSeedMetricDefinition);
var randomSeedMetricDefinition = DatasetCapture.RegisterMetricDefinition(
"random-seed",
"The random seed used to initialize the random state of the simulation. Only triggered once per simulation.",
Guid.Parse("14adb394-46c0-47e8-a3f0-99e754483b76"));
DatasetCapture.ReportMetric(randomSeedMetricDefinition, new[] { genericConstants.randomSeed });
DatasetCapture.Instance.ReportMetric(randomSeedMetricDefinition, new object[] { genericConstants.randomSeed });
#endif
}

DatasetCapture.Instance.StartNewSequence();
#if false
DatasetCapture.ReportMetric(m_IterationMetricDefinition, new[]
#if true
DatasetCapture.Instance.ReportMetric(m_IterationMetricDefinition, new object[]
{
new IterationMetricData { iteration = currentIteration }
});

static IEnumerator WaitUntilWritesAreComplete()
{
var dcWatcher = new DatasetCapture.WaitUntilComplete();
yield return dcWatcher;
}
/// <inheritdoc/>
#if false

protected override void OnComplete()
{
DatasetCapture.Instance.ResetSimulation();
StartCoroutine(WaitUntilWritesAreComplete());
// Quit();
Quit();
#if false
#if true
/// <summary>
/// Used to report a scenario iteration as a perception metric
/// </summary>

18
com.unity.perception/Tests/Runtime/GroundTruthTests/BoundingBox3dTests.cs


using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.Perception.GroundTruth.DataModel;
using UnityEngine.TestTools;
namespace GroundTruthTests

[UnityTest]
public IEnumerator CameraOffset_ProduceProperTranslationTest()
{
DatasetCapture.Instance.automaticShutdown = false;
var expected = new[]
{
new ExpectedResult

[UnityTest]
public IEnumerator CameraOffsetAndRotated_ProduceProperTranslationTest()
{
DatasetCapture.Instance.automaticShutdown = false;
var expected = new[]
{
new ExpectedResult

[UnityTest]
public IEnumerator SimpleMultiMesh_ProduceProperTranslationTest()
{
DatasetCapture.Instance.automaticShutdown = false;
var expected = new[]
{
new ExpectedResult

[UnityTest]
public IEnumerator ParentedObject_ProduceProperResults([ValueSource(nameof(ParentedObject_ProduceProperResults_Values))] ParentedTestData parentedTestData)
{
DatasetCapture.Instance.automaticShutdown = false;
var expected = new[]
{
new ExpectedResult

[UnityTest]
public IEnumerator MultiInheritedMesh_ProduceProperTranslationTest()
{
DatasetCapture.Instance.automaticShutdown = false;
var expected = new[]
{
new ExpectedResult

[UnityTest]
public IEnumerator MultiInheritedMeshDifferentLabels_ProduceProperTranslationTest()
{
DatasetCapture.Instance.automaticShutdown = false;
var wheelScale = new Vector3(0.7f, 2.0f, 0.7f);
var wheelRot = Quaternion.Euler(0, 0, 90);

[UnityTest]
public IEnumerator TestOcclusion_Seen()
{
DatasetCapture.Instance.automaticShutdown = false;
var target = TestHelper.CreateLabeledCube(scale: 15f, z: 50f);
return ExecuteSeenUnseenTest(target, Vector3.zero, quaternion.identity, 1);
}

{
DatasetCapture.Instance.automaticShutdown = false;
var target = TestHelper.CreateLabeledCube(scale: 15f, z: -50f);
return ExecuteSeenUnseenTest(target, Vector3.zero, quaternion.identity, 0);
}

26
com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureSensorSchedulingTests.cs


internal SimulationStateTestHelper()
{
DatasetCapture.Instance.automaticShutdown = false;
m_State = DatasetCapture.Instance.currentSimulation;
var bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
m_SequenceTimeOfNextCaptureMethod = m_State.GetType().GetMethod("GetSequenceTimeOfNextCapture", bindingFlags);

[UnityTest]
public IEnumerator SequenceTimeOfNextCapture_ReportsCorrectTime()
{
DatasetCapture.Instance.automaticShutdown = false;
var firstCaptureFrame = 2;
var simulationDeltaTime = .4f;

[UnityTest]
public IEnumerator SequenceTimeOfNextCapture_WithInBetweenFrames_ReportsCorrectTime()
{
DatasetCapture.Instance.automaticShutdown = false;
var firstCaptureFrame = 2;
var simulationDeltaTime = .4f;
var framesBetweenCaptures = 2;

[UnityTest]
public IEnumerator FramesScheduledBySensorConfig()
{
DatasetCapture.Instance.automaticShutdown = false;
var firstCaptureFrame = 2;
var simulationDeltaTime = .4f;

[UnityTest]
public IEnumerator FramesScheduled_WithTimeScale_ResultsInProperDeltaTime()
{
DatasetCapture.Instance.automaticShutdown = false;
var firstCaptureFrame = 2;
var simulationDeltaTime = 1f;
var timeScale = 2;

[UnityTest]
public IEnumerator ChangingTimeScale_CausesDebugError()
{
DatasetCapture.Instance.automaticShutdown = false;
DatasetCapture.Instance.RegisterSensor(CreateSensorDefinition("cam", "", "", 2, CaptureTriggerMode.Scheduled, 1, 0));
DatasetCapture.Instance.RegisterSensor(CreateSensorDefinition("cam", "", "", 2, CaptureTriggerMode.Scheduled, 1, 0));
yield return null;
Time.timeScale = 5;

[UnityTest]
public IEnumerator ChangingTimeScale_DuringStartNewSequence_Succeeds()
{
DatasetCapture.Instance.automaticShutdown = false;
DatasetCapture.Instance.RegisterSensor(CreateSensorDefinition("cam", "", "", 2, CaptureTriggerMode.Scheduled, 1, 0));
yield return null;

[UnityTest]
public IEnumerator FramesScheduled_WithChangingTimeScale_ResultsInProperDeltaTime()
{
DatasetCapture.Instance.automaticShutdown = false;
var firstCaptureFrame = 2;
var simulationDeltaTime = 1f;
float[] newTimeScalesPerFrame =

[UnityTest]
public IEnumerator ResetSimulation_ResetsCaptureDeltaTime()
{
DatasetCapture.Instance.automaticShutdown = false;
DatasetCapture.Instance.RegisterSensor(CreateSensorDefinition("cam", "", "", 0, CaptureTriggerMode.Scheduled, 5, 0));
yield return null;
Assert.AreEqual(5, Time.captureDeltaTime);

[UnityTest]
public IEnumerator ShouldCaptureFlagsAndRenderTimesAreCorrectWithMultipleSensors()
{
DatasetCapture.Instance.automaticShutdown = false;
var firstCaptureFrame1 = 2;
var simDeltaTime1 = 4;
var framesBetweenCaptures1 = 2;

[TestCase(235, 10, 2350, 2585, 2820, 3055, ExpectedResult = (IEnumerator)null)]
public IEnumerator SequenceTimeOfNextCapture_ReportsCorrectTime_VariedDeltaTimesAndStartFrames(float simulationDeltaTime, int firstCaptureFrame, float firstCaptureTime, float secondCaptureTime, float thirdCaptureTime, float fourthCaptureTime)
{
DatasetCapture.Instance.automaticShutdown = false;
var sensorHandle = DatasetCapture.Instance.RegisterSensor(CreateSensorDefinition("cam", "", "", firstCaptureFrame, CaptureTriggerMode.Scheduled, simulationDeltaTime, 0));
float[] sequenceTimesExpected =

[UnityTest]
public IEnumerator SequenceTimeOfManualCapture_ReportsCorrectTime_ManualSensorDoesNotAffectTimings()
{
DatasetCapture.Instance.automaticShutdown = false;
var sensorHandle = DatasetCapture.Instance.RegisterSensor(CreateSensorDefinition("cam", "", "", 0, CaptureTriggerMode.Manual, 0, 0, false));
var framesToCaptureOn = new List<int>();

[UnityTest]
public IEnumerator SequenceTimeOfManualCapture_ReportsCorrectTime_ManualSensorAffectsTimings()
{
DatasetCapture.Instance.automaticShutdown = false;
var simulationDeltaTime = 0.05f;
var sensorHandle = DatasetCapture.Instance.RegisterSensor(CreateSensorDefinition("cam", "", "", 0, CaptureTriggerMode.Manual, simulationDeltaTime, 0, true));

29
com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureTests.cs


DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
var sensorHandle = RegisterSensor(id, modality, def, firstFrame, mode, delta, framesBetween);
Assert.IsTrue(sensorHandle.IsValid);

{
var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
SimulationState.TimeOutFrameCount = 5;
var sensorHandle = RegisterSensor("camera", "", "", 0, CaptureTriggerMode.Scheduled, 1, 0);

{
var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
SimulationState.TimeOutFrameCount = 5;
var sensorHandle = RegisterSensor("camera", "", "", 0, CaptureTriggerMode.Scheduled, 1, 0);

var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
yield return null;
DatasetCapture.Instance.ResetSimulation();
var dcWatcher = new DatasetCapture.WaitUntilComplete();

var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
var sensorHandle = RegisterSensor("camera", "", "", 0, CaptureTriggerMode.Scheduled, 2, 0);
var sensor = new RgbSensor();

{
var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
var sensorHandle = RegisterSensor("camera", "", "", 0, CaptureTriggerMode.Scheduled, 1, 0);
var sensor = new RgbSensor();

{
var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
var sensorHandle = RegisterSensor("camera", "", "", 0, CaptureTriggerMode.Scheduled, 1, 0);
var sensor = new RgbSensor();

[UnityTest]
public IEnumerator ReportAnnotationFile_WhenCaptureNotExpected_Throws()
{
DatasetCapture.Instance.automaticShutdown = false;
var def = new TestDef();
DatasetCapture.Instance.RegisterAnnotationDefinition(def);
var sensorHandle = RegisterSensor("camera", "", "", 100, CaptureTriggerMode.Scheduled, 1, 0);

[Test]
public void ReportAnnotationValues_WhenCaptureNotExpected_Throws()
{
DatasetCapture.Instance.automaticShutdown = false;
var def = new TestDef();
DatasetCapture.Instance.RegisterAnnotationDefinition(def);
var ann = new TestAnnotation()

{
var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
SimulationState.TimeOutFrameCount = 100;

{
var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
SimulationState.TimeOutFrameCount = 10;

var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
var sensorHandle = RegisterSensor("camera", "", "", 0, CaptureTriggerMode.Scheduled, 1, 0);
var sensor = new RgbSensor();
sensorHandle.ReportSensor(sensor);

var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
var def = new TestDef();
DatasetCapture.Instance.RegisterAnnotationDefinition(def);

// Confirm that the annotation correctly skips the first pending capture to write to the second
var asyncAnnotation = sensorHandle.ReportAnnotationAsync(def);
Assert.DoesNotThrow(() => asyncAnnotation.Report(ann));
yield return null; // TODO why does removing this cause us to spiral out for eternity
sensorHandle.ReportSensor(sensor);
DatasetCapture.Instance.ResetSimulation();
var dcWatcher = new DatasetCapture.WaitUntilComplete();

var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
var def = new TestMetricDef();
DatasetCapture.Instance.RegisterMetric(def);

var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
// DatasetCapture.Instance.automaticShutdown = false;
var def = new TestMetricDef();
DatasetCapture.Instance.RegisterMetric(def);

var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
// DatasetCapture.Instance.automaticShutdown = false;
var values = new[]
{

var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
// DatasetCapture.Instance.automaticShutdown = false;
if (additionalInfoKind == AdditionalInfoKind.Annotation)
{

4
com.unity.perception/Tests/Runtime/GroundTruthTests/PerceptionCameraIntegrationTests.cs


var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
DatasetCapture.Instance.ResetSimulation();
var dcWatcher = new DatasetCapture.WaitUntilComplete();

var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
SemanticSegmentationLabeler semanticSegmentationLabeler = null;
SetupCamera(pc =>

{
var collector = new CollectEndpoint();
DatasetCapture.SetEndpoint(collector);
DatasetCapture.Instance.automaticShutdown = false;
SemanticSegmentationLabeler semanticSegmentationLabeler = null;
SetupCamera(pc =>

24
com.unity.perception/Tests/Runtime/GroundTruthTests/SegmentationGroundTruthTests.cs


[Values(RendererType.MeshRenderer, RendererType.SkinnedMeshRenderer, RendererType.Terrain)] RendererType rendererType,
[Values(SegmentationKind.Instance, SegmentationKind.Semantic)] SegmentationKind segmentationKind)
{
DatasetCapture.Instance.automaticShutdown = false;
int timesSegmentationImageReceived = 0;
int? frameStart = null;
GameObject cameraObject = null;

[UnityTest]
public IEnumerator SemanticSegmentationPass_WithLensDistortion()
{
DatasetCapture.Instance.automaticShutdown = false;
GameObject cameraObject = null;
PerceptionCamera perceptionCamera;
var fLensDistortionEnabled = false;

[UnityTest]
public IEnumerator SemanticSegmentationPass_WithLabeledButNotMatchingObject_ProducesBlack()
{
DatasetCapture.Instance.automaticShutdown = false;
int timesSegmentationImageReceived = 0;
var expectedPixelValue = new Color32(0, 0, 0, 255);
void OnSegmentationImageReceived(NativeArray<Color32> data)

[UnityTest]
public IEnumerator SemanticSegmentationPass_WithMatchingButDisabledLabel_ProducesBlack()
{
DatasetCapture.Instance.automaticShutdown = false;
int timesSegmentationImageReceived = 0;
var expectedPixelValue = new Color32(0, 0, 0, 255);
void OnSegmentationImageReceived(NativeArray<Color32> data)

[UnityTest]
public IEnumerator InstanceSegmentationPass_WithMatchingButDisabledLabel_ProducesBlack()
{
DatasetCapture.Instance.automaticShutdown = false;
int timesSegmentationImageReceived = 0;
var expectedPixelValue = new Color32(0, 0, 0, 255);
void OnSegmentationImageReceived(NativeArray<Color32> data)

[UnityTest]
public IEnumerator SemanticSegmentationPass_WithEmptyFrame_ProducesSky([Values(false, true)] bool showVisualizations)
{
DatasetCapture.Instance.automaticShutdown = false;
int timesSegmentationImageReceived = 0;
var expectedPixelValue = k_SkyValue;
void OnSegmentationImageReceived(NativeArray<Color32> data)

[UnityTest]
public IEnumerator SemanticSegmentationPass_WithNoObjects_ProducesSky()
{
DatasetCapture.Instance.automaticShutdown = false;
int timesSegmentationImageReceived = 0;
var expectedPixelValue = k_SkyValue;
void OnSegmentationImageReceived(NativeArray<Color32> data)

[UnityTest]
public IEnumerator SemanticSegmentationPass_WithTextureOverride_RendersToOverride([Values(true, false)] bool showVisualizations)
{
DatasetCapture.Instance.automaticShutdown = false;
var expectedPixelValue = new Color32(0, 0, 255, 255);
var targetTextureOverride = new RenderTexture(2, 2, 1, RenderTextureFormat.R8);

[UnityTest]
public IEnumerator SemanticSegmentationPass_WithMultiMaterial_ProducesCorrectValues([Values(true, false)] bool showVisualizations)
{
DatasetCapture.Instance.automaticShutdown = false;
int timesSegmentationImageReceived = 0;
var expectedPixelValue = k_SemanticPixelValue;
void OnSegmentationImageReceived(NativeArray<Color32> data)

[UnityTest]
public IEnumerator SemanticSegmentationPass_WithChangingLabeling_ProducesCorrectValues([Values(true, false)] bool showVisualizations)
{
DatasetCapture.Instance.automaticShutdown = false;
int timesSegmentationImageReceived = 0;
var expectedPixelValue = k_SemanticPixelValue;
void OnSegmentationImageReceived(NativeArray<Color32> data)

[UnityTest]
public IEnumerator InstanceSegmentationPass_WithSeparateDisabledPerceptionCamera_ProducesCorrectValues()
{
DatasetCapture.Instance.automaticShutdown = false;
int timesSegmentationImageReceived = 0;
void OnSegmentationImageReceived(NativeArray<Color32> data)
{

public IEnumerator SegmentationPassProducesCorrectValuesEachFrame(
[Values(SegmentationKind.Instance, SegmentationKind.Semantic)] SegmentationKind segmentationKind)
{
DatasetCapture.Instance.automaticShutdown = false;
int timesSegmentationImageReceived = 0;
Dictionary<int, object> expectedLabelAtFrame = null;

10
com.unity.perception/Tests/Runtime/GroundTruthTests/VisualizationTests.cs


[UnityTest]
public IEnumerator VisualizedCamera_SetsUpCanvas()
{
DatasetCapture.Instance.automaticShutdown = false;
var object1 = SetupCameraSemanticSegmentation(nameof(VisualizedCamera_SetsUpCanvas));
object1.SetActive(true);
AddTestObjectForCleanup(object1);

[UnityTest]
public IEnumerator TwoCamerasVisualizing_CausesWarningAndDisablesVisualization()
{
DatasetCapture.Instance.automaticShutdown = false;
var object1 = new GameObject();
object1.name = nameof(TwoCamerasVisualizing_CausesWarningAndDisablesVisualization);
object1.SetActive(false);

[UnityTest]
public IEnumerator DestroyCamera_RemovesVisualization()
{
DatasetCapture.Instance.automaticShutdown = false;
var object1 = SetupCameraSemanticSegmentation(nameof(DestroyCamera_RemovesVisualization));
object1.SetActive(true);
AddTestObjectForCleanup(object1);

[UnityTest]
public IEnumerator DestroyAndRecreateCamera_ProperlyVisualizes()
{
DatasetCapture.Instance.automaticShutdown = false;
var object1 = SetupCameraSemanticSegmentation(nameof(DestroyAndRecreateCamera_ProperlyVisualizes));
object1.SetActive(true);
AddTestObjectForCleanup(object1);

[UnityTest]
public IEnumerator TwoLabelersOfSameType_ProperlyStoredInHud()
{
DatasetCapture.Instance.automaticShutdown = false;
var label = "label";
var planeObject = TestHelper.CreateLabeledPlane(.1f, label);
AddTestObjectForCleanup(planeObject);

正在加载...
取消
保存