浏览代码

Merge branch 'master' of github.com:Unity-Technologies/com.unity.perception into docs

/docs
Wesley Mareovich Smith 5 年前
当前提交
47d9ea99
共有 54 个文件被更改,包括 837 次插入831 次删除
  1. 4
      TestProjects/PerceptionHDRP/Assets/Rotator.cs
  2. 1
      TestProjects/PerceptionHDRP/Packages/manifest.json
  3. 4
      TestProjects/PerceptionURP/Assets/Rotator.cs
  4. 1
      TestProjects/PerceptionURP/Packages/manifest.json
  5. 8
      com.unity.perception/Editor/GroundTruth/BaseCustomPassDrawer.cs
  6. 9
      com.unity.perception/Editor/GroundTruth/InstanceSegmentationPassEditor.cs
  7. 109
      com.unity.perception/Editor/GroundTruth/LabelingConfigurationEditor.cs
  8. 75
      com.unity.perception/Editor/GroundTruth/LabelingEditor.cs
  9. 7
      com.unity.perception/Editor/GroundTruth/ObjectCountPassEditor.cs
  10. 9
      com.unity.perception/Editor/GroundTruth/SemanticSegmentationPassEditor.cs
  11. 5
      com.unity.perception/Runtime/GroundTruth/BoundingBoxOrigin.cs
  12. 6
      com.unity.perception/Runtime/GroundTruth/DatasetJsonUtility.cs
  13. 158
      com.unity.perception/Runtime/GroundTruth/GroundTruthCrossPipelinePass.cs
  14. 10
      com.unity.perception/Runtime/GroundTruth/GroundTruthInfo.cs
  15. 32
      com.unity.perception/Runtime/GroundTruth/GroundTruthLabelSetupSystem.cs
  16. 3
      com.unity.perception/Runtime/GroundTruth/GroundTruthPass.cs
  17. 91
      com.unity.perception/Runtime/GroundTruth/GroundTruthRendererFeature.cs
  18. 19
      com.unity.perception/Runtime/GroundTruth/IGroundTruthGenerator.cs
  19. 111
      com.unity.perception/Runtime/GroundTruth/InstanceSegmentationCrossPipelinePass.cs
  20. 9
      com.unity.perception/Runtime/GroundTruth/InstanceSegmentationPass.cs
  21. 41
      com.unity.perception/Runtime/GroundTruth/Labeling/Labeling.cs
  22. 35
      com.unity.perception/Runtime/GroundTruth/Labeling/LabelingConfiguration.cs
  23. 33
      com.unity.perception/Runtime/GroundTruth/ObjectCountPass.cs
  24. 112
      com.unity.perception/Runtime/GroundTruth/PerceptionCamera.cs
  25. 21
      com.unity.perception/Runtime/GroundTruth/RenderTextureReader.cs
  26. 24
      com.unity.perception/Runtime/GroundTruth/RenderedObjectInfo.cs
  27. 14
      com.unity.perception/Runtime/GroundTruth/RenderedObjectInfoGenerator.cs
  28. 8
      com.unity.perception/Runtime/GroundTruth/SemanticSegmentationCrossPipelinePass.cs
  29. 4
      com.unity.perception/Runtime/GroundTruth/SemanticSegmentationPass.cs
  30. 4
      com.unity.perception/Runtime/GroundTruth/SimulationManagementComponentSystem.cs
  31. 114
      com.unity.perception/Runtime/GroundTruth/SimulationManager.cs
  32. 25
      com.unity.perception/Runtime/GroundTruth/SimulationState.cs
  33. 14
      com.unity.perception/Runtime/GroundTruth/SimulationState_Json.cs
  34. 66
      com.unity.perception/Tests/Editor/BuildPerceptionPlayer.cs
  35. 15
      com.unity.perception/Tests/Editor/PerceptionCameraEditorTests.cs
  36. 11
      com.unity.perception/Tests/Runtime/GroundTruthTests/BoundingBox2DTests.cs
  37. 4
      com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetJsonUtilityTests.cs
  38. 15
      com.unity.perception/Tests/Runtime/GroundTruthTests/GroundTruthTestBase.cs
  39. 43
      com.unity.perception/Tests/Runtime/GroundTruthTests/ObjectCountTests.cs
  40. 9
      com.unity.perception/Tests/Runtime/GroundTruthTests/PerceptionCameraIntegrationTests.cs
  41. 24
      com.unity.perception/Tests/Runtime/GroundTruthTests/SegmentationGroundTruthTests.cs
  42. 32
      com.unity.perception/Tests/Runtime/GroundTruthTests/SimulationManagerTests.cs
  43. 7
      com.unity.perception/Tests/Runtime/GroundTruthTests/TestHelper.cs
  44. 33
      com.unity.perception/Tests/Runtime/GroundTruthTests/SimulationManagerSensorSchedulingTests.cs
  45. 74
      .editorconfig
  46. 38
      com.unity.perception/Runtime/GroundTruth/Ego.cs
  47. 31
      com.unity.perception/Runtime/GroundTruth/EgoMarker.cs
  48. 135
      com.unity.perception/Runtime/GroundTruth/MetricData.cs
  49. 11
      com.unity.perception/Runtime/GroundTruth/MetricData.cs.meta
  50. 0
      /com.unity.perception/Editor/GroundTruth/SemanticSegmentationPassEditor.cs.meta
  51. 0
      /com.unity.perception/Editor/GroundTruth/SemanticSegmentationPassEditor.cs
  52. 0
      /com.unity.perception/Runtime/GroundTruth/Ego.cs.meta
  53. 0
      /com.unity.perception/Tests/Runtime/GroundTruthTests/SimulationManagerSensorSchedulingTests.cs.meta
  54. 0
      /com.unity.perception/Tests/Runtime/GroundTruthTests/SimulationManagerSensorSchedulingTests.cs

4
TestProjects/PerceptionHDRP/Assets/Rotator.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine;
public class Rotator : MonoBehaviour
{

1
TestProjects/PerceptionHDRP/Packages/manifest.json


"com.unity.ext.nunit": "1.0.0",
"com.unity.ide.rider": "1.1.4",
"com.unity.ide.vscode": "1.1.4",
"com.unity.package-validation-suite": "0.9.1-preview",
"com.unity.perception": "file:../../../com.unity.perception",
"com.unity.render-pipelines.core": "7.3.1",
"com.unity.render-pipelines.high-definition": "7.3.1",

4
TestProjects/PerceptionURP/Assets/Rotator.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine;
public class Rotator : MonoBehaviour
{

1
TestProjects/PerceptionURP/Packages/manifest.json


"com.unity.collab-proxy": "1.2.16",
"com.unity.ide.rider": "1.1.4",
"com.unity.ide.vscode": "1.1.4",
"com.unity.package-validation-suite": "0.9.1-preview",
"com.unity.perception": "file:../../../com.unity.perception",
"com.unity.render-pipelines.universal": "7.3.1",
"com.unity.simulation.capture": "0.0.10-preview.6",

8
com.unity.perception/Editor/GroundTruth/BaseCustomPassDrawer.cs


#if HDRP_PRESENT
#if HDRP_PRESENT
using UnityEditor;
using UnityEngine;
namespace UnityEngine.Perception.Sensors.Editor
namespace UnityEditor.Perception.GroundTruth
{
public class BaseCustomPassDrawer : CustomPassDrawer
{

}
}
}
#endif
#endif

9
com.unity.perception/Editor/GroundTruth/InstanceSegmentationPassEditor.cs


#if HDRP_PRESENT
#if HDRP_PRESENT
using UnityEditor;
using UnityEngine.Perception.GroundTruth;
namespace UnityEngine.Perception.Sensors.Editor
namespace UnityEditor.Perception.GroundTruth
{
[CustomPassDrawer(typeof(InstanceSegmentationPass))]
public class InstanceSegmentationPassEditor : BaseCustomPassDrawer

var targetCameraProperty = customPass.FindPropertyRelative(nameof(GroundTruthPass.targetCamera));
AddProperty(targetCameraProperty);
AddProperty(customPass.FindPropertyRelative(nameof(InstanceSegmentationPass.targetTexture)));
AddProperty(customPass.FindPropertyRelative(nameof(InstanceSegmentationPass.reassignIds)));
AddProperty(customPass.FindPropertyRelative(nameof(InstanceSegmentationPass.idStart)));
AddProperty(customPass.FindPropertyRelative(nameof(InstanceSegmentationPass.idStep)));
base.Initialize(customPass);
}
}

109
com.unity.perception/Editor/GroundTruth/LabelingConfigurationEditor.cs


using UnityEditor;
using UnityEngine.Perception.Sensors;
using UnityEngine.Perception.GroundTruth;
[CustomEditor(typeof(LabelingConfiguration))]
public class LabelingConfigurationEditor : Editor
namespace UnityEditor.Perception.GroundTruth
ReorderableList m_LabelsList;
public void OnEnable()
[CustomEditor(typeof(LabelingConfiguration))]
class LabelingConfigurationEditor : Editor
m_LabelsList = new ReorderableList(this.serializedObject, this.serializedObject.FindProperty(nameof(LabelingConfiguration.LabelingConfigurations)), true, false, true, true);
m_LabelsList.elementHeight = EditorGUIUtility.singleLineHeight * 2;
m_LabelsList.drawElementCallback = DrawElement;
m_LabelsList.onAddCallback += OnAdd;
m_LabelsList.onRemoveCallback += OnRemove;
}
ReorderableList m_LabelsList;
void OnRemove(ReorderableList list)
{
if (list.index != -1)
list.serializedProperty.DeleteArrayElementAtIndex(list.index);
public void OnEnable()
{
m_LabelsList = new ReorderableList(this.serializedObject, this.serializedObject.FindProperty(nameof(LabelingConfiguration.LabelingConfigurations)), true, false, true, true);
m_LabelsList.elementHeight = EditorGUIUtility.singleLineHeight * 2;
m_LabelsList.drawElementCallback = DrawElement;
m_LabelsList.onAddCallback += OnAdd;
m_LabelsList.onRemoveCallback += OnRemove;
}
this.serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(target);
}
void OnRemove(ReorderableList list)
{
if (list.index != -1)
list.serializedProperty.DeleteArrayElementAtIndex(list.index);
LabelingConfiguration config => (LabelingConfiguration)this.target;
this.serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(target);
}
void OnAdd(ReorderableList list)
{
var index = list.serializedProperty.arraySize;
list.serializedProperty.InsertArrayElementAtIndex(index);
var element = list.serializedProperty.GetArrayElementAtIndex(index);
var labelProperty = element.FindPropertyRelative(nameof(LabelingConfigurationEntry.label));
labelProperty.stringValue = "";
var valueProperty = element.FindPropertyRelative(nameof(LabelingConfigurationEntry.value));
valueProperty.intValue = 0;
serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(target);
}
void OnAdd(ReorderableList list)
{
var index = list.serializedProperty.arraySize;
list.serializedProperty.InsertArrayElementAtIndex(index);
var element = list.serializedProperty.GetArrayElementAtIndex(index);
var labelProperty = element.FindPropertyRelative(nameof(LabelingConfigurationEntry.label));
labelProperty.stringValue = "";
var valueProperty = element.FindPropertyRelative(nameof(LabelingConfigurationEntry.value));
valueProperty.intValue = 0;
serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(target);
}
void DrawElement(Rect rect, int index, bool isactive, bool isfocused)
{
var element = m_LabelsList.serializedProperty.GetArrayElementAtIndex(index);
var labelProperty = element.FindPropertyRelative(nameof(LabelingConfigurationEntry.label));
var valueProperty = element.FindPropertyRelative(nameof(LabelingConfigurationEntry.value));
using (var change = new EditorGUI.ChangeCheckScope())
void DrawElement(Rect rect, int index, bool isactive, bool isfocused)
var contentRect = new Rect(rect.position, new Vector2(rect.width, EditorGUIUtility.singleLineHeight));
var newLabel = EditorGUI.TextField(contentRect, nameof(LabelingConfigurationEntry.label), labelProperty.stringValue);
if (change.changed)
labelProperty.stringValue = newLabel;
var element = m_LabelsList.serializedProperty.GetArrayElementAtIndex(index);
var labelProperty = element.FindPropertyRelative(nameof(LabelingConfigurationEntry.label));
var valueProperty = element.FindPropertyRelative(nameof(LabelingConfigurationEntry.value));
using (var change = new EditorGUI.ChangeCheckScope())
{
var contentRect = new Rect(rect.position, new Vector2(rect.width, EditorGUIUtility.singleLineHeight));
var newLabel = EditorGUI.TextField(contentRect, nameof(LabelingConfigurationEntry.label), labelProperty.stringValue);
if (change.changed)
labelProperty.stringValue = newLabel;
}
using (var change = new EditorGUI.ChangeCheckScope())
{
var contentRect = new Rect(rect.position + new Vector2(0, EditorGUIUtility.singleLineHeight), new Vector2(rect.width, EditorGUIUtility.singleLineHeight));
var newValue = EditorGUI.IntField(contentRect, nameof(LabelingConfigurationEntry.value), valueProperty.intValue);
if (change.changed)
valueProperty.intValue = newValue;
}
using (var change = new EditorGUI.ChangeCheckScope())
public override void OnInspectorGUI()
var contentRect = new Rect(rect.position + new Vector2(0, EditorGUIUtility.singleLineHeight), new Vector2(rect.width, EditorGUIUtility.singleLineHeight));
var newValue = EditorGUI.IntField(contentRect, nameof(LabelingConfigurationEntry.value), valueProperty.intValue);
if (change.changed)
valueProperty.intValue = newValue;
m_LabelsList.DoLayoutList();
this.serializedObject.ApplyModifiedProperties();
}
public override void OnInspectorGUI()
{
m_LabelsList.DoLayoutList();
this.serializedObject.ApplyModifiedProperties();
}
}

75
com.unity.perception/Editor/GroundTruth/LabelingEditor.cs


using UnityEditor;
using UnityEngine.Perception.GroundTruth;
[CustomEditor(typeof(Labeling))]
public class LabelingEditor : Editor
namespace UnityEditor.Perception.GroundTruth
const int k_Indent = 7;
ReorderableList m_LabelsList;
public void OnEnable()
[CustomEditor(typeof(Labeling))]
class LabelingEditor : Editor
m_LabelsList = new ReorderableList(this.serializedObject, this.serializedObject.FindProperty(nameof(Labeling.classes)), true, false, true, true);
m_LabelsList.drawElementCallback = DrawElement;
m_LabelsList.onAddCallback += OnAdd;
m_LabelsList.onRemoveCallback += OnRemove;
}
const int k_Indent = 7;
ReorderableList m_LabelsList;
void OnRemove(ReorderableList list)
{
if (list.index != -1)
labeling.classes.RemoveAt(list.index);
}
public void OnEnable()
{
m_LabelsList = new ReorderableList(serializedObject, serializedObject.FindProperty(nameof(global::UnityEngine.Perception.GroundTruth.Labeling.labels)), true, false, true, true);
m_LabelsList.drawElementCallback = DrawElement;
m_LabelsList.onAddCallback += OnAdd;
m_LabelsList.onRemoveCallback += OnRemove;
}
Labeling labeling => (Labeling)this.target;
void OnRemove(ReorderableList list)
{
if (list.index != -1)
Labeling.labels.RemoveAt(list.index);
}
void OnAdd(ReorderableList list)
{
labeling.classes.Add("");
}
Labeling Labeling => (Labeling)target;
void DrawElement(Rect rect, int index, bool isactive, bool isfocused)
{
using (var change = new EditorGUI.ChangeCheckScope())
void OnAdd(ReorderableList list)
var indent = k_Indent * index;
if (indent >= rect.width)
return;
Labeling.labels.Add("");
}
var contentRect = new Rect(rect.x + indent, rect.y, rect.width - indent, rect.height);
var value = EditorGUI.TextField(contentRect, labeling.classes[index]);
if (change.changed)
void DrawElement(Rect rect, int index, bool isactive, bool isfocused)
{
using (var change = new EditorGUI.ChangeCheckScope())
labeling.classes[index] = value;
var indent = k_Indent * index;
if (indent >= rect.width)
return;
var contentRect = new Rect(rect.x + indent, rect.y, rect.width - indent, rect.height);
var value = EditorGUI.TextField(contentRect, Labeling.labels[index]);
if (change.changed)
{
Labeling.labels[index] = value;
}
}
public override void OnInspectorGUI()
{
m_LabelsList.DoLayoutList();
public override void OnInspectorGUI()
{
m_LabelsList.DoLayoutList();
}
}
}

7
com.unity.perception/Editor/GroundTruth/ObjectCountPassEditor.cs


#if HDRP_PRESENT
#if HDRP_PRESENT
using System.Collections.Generic;
using UnityEditor;
using UnityEngine.Perception.GroundTruth;
namespace UnityEngine.Perception.Sensors.Editor
namespace UnityEditor.Perception.GroundTruth
{
[CustomPassDrawer(typeof(ObjectCountPass))]
public class ObjectCountPassEditor : BaseCustomPassDrawer

9
com.unity.perception/Editor/GroundTruth/SemanticSegmentationPassEditor.cs


#if HDRP_PRESENT
#if HDRP_PRESENT
using System.Collections.Generic;
using UnityEditor;
using UnityEngine.Perception.GroundTruth;
namespace UnityEngine.Perception.Sensors.Editor
namespace UnityEditor.Perception.GroundTruth
public class SemanticSegmentationPassEditor : BaseCustomPassDrawer
class SemanticSegmentationPassEditor : BaseCustomPassDrawer
{
protected override void Initialize(SerializedProperty customPass)
{

5
com.unity.perception/Runtime/GroundTruth/BoundingBoxOrigin.cs


using System;
using System;
namespace UnityEngine.Perception {
namespace UnityEngine.Perception.GroundTruth
{
/// <summary>
/// The origin to use for bounding box calculation
/// </summary>

6
com.unity.perception/Runtime/GroundTruth/DatasetJsonUtility.cs


using Newtonsoft.Json.Linq;
using Unity.Mathematics;
namespace UnityEngine.Perception.Sensors
namespace UnityEngine.Perception.GroundTruth
{
/// <summary>
/// Utilities for producing Json for datasets.

obj.Add(value.z);
return obj;
}
public static JToken ToJToken(Quaternion value)
{
var obj = new JArray();

obj.Add(value.w);
return obj;
}
public static JToken ToJToken(float3x3 value)
{
var obj = new JArray();

return obj;
}
public static JToken ToJToken(float3 value)
{
var obj = new JArray();

return obj;
}
public static JToken ToJToken<T>(T value)
{
switch (value)

158
com.unity.perception/Runtime/GroundTruth/GroundTruthCrossPipelinePass.cs


using System;
using System;
using UnityEngine.Perception.Sensors;
public abstract class GroundTruthCrossPipelinePass : IGroundTruthGenerator
namespace UnityEngine.Perception.GroundTruth
public Camera targetCamera;
bool m_IsActivated;
protected GroundTruthCrossPipelinePass(Camera targetCamera)
abstract class GroundTruthCrossPipelinePass : IGroundTruthGenerator
this.targetCamera = targetCamera;
}
public Camera targetCamera;
public virtual void Setup()
{
if (targetCamera == null)
throw new InvalidOperationException("targetCamera may not be null");
bool m_IsActivated;
// If we are forced to activate here we will get zeroes in the first frame.
EnsureActivated();
}
protected GroundTruthCrossPipelinePass(Camera targetCamera)
{
this.targetCamera = targetCamera;
}
public void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, Camera camera, CullingResults cullingResult)
{
// CustomPasses are executed for each camera. We only want to run for the target camera
if (camera != targetCamera)
return;
public virtual void Setup()
{
if (targetCamera == null)
throw new InvalidOperationException("targetCamera may not be null");
ExecutePass(renderContext, cmd, camera, cullingResult);
}
// If we are forced to activate here we will get zeroes in the first frame.
EnsureActivated();
}
protected abstract void ExecutePass(ScriptableRenderContext renderContext, CommandBuffer cmd, Camera camera, CullingResults cullingResult);
public void EnsureActivated()
{
if (!m_IsActivated)
public void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, Camera camera, CullingResults cullingResult)
var labelSetupSystem = World.DefaultGameObjectInjectionWorld?.GetExistingSystem<GroundTruthLabelSetupSystem>();
labelSetupSystem?.Activate(this);
m_IsActivated = true;
// CustomPasses are executed for each camera. We only want to run for the target camera
if (camera != targetCamera)
return;
ExecutePass(renderContext, cmd, camera, cullingResult);
}
public void Cleanup()
{
var labelSetupSystem = World.DefaultGameObjectInjectionWorld?.GetExistingSystem<GroundTruthLabelSetupSystem>();
labelSetupSystem?.Deactivate(this);
}
protected abstract void ExecutePass(ScriptableRenderContext renderContext, CommandBuffer cmd, Camera camera, CullingResults cullingResult);
protected RendererListDesc CreateRendererListDesc(Camera camera, CullingResults cullingResult, string overrideMaterialPassName, int overrideMaterialPassIndex, Material overrideMaterial, LayerMask layerMask/*, PerObjectData perObjectData*/)
{
var shaderPasses = new[]
public void EnsureActivated()
new ShaderTagId("Forward"), // HD Lit shader
new ShaderTagId("ForwardOnly"), // HD Unlit shader
new ShaderTagId("SRPDefaultUnlit"), // Cross SRP Unlit shader
new ShaderTagId("UniversalForward"), // URP Forward
new ShaderTagId("LightweightForward"), // LWRP Forward
new ShaderTagId(overrideMaterialPassName), // The override material shader
};
if (!m_IsActivated)
{
var labelSetupSystem = World.DefaultGameObjectInjectionWorld?.GetExistingSystem<GroundTruthLabelSetupSystem>();
labelSetupSystem?.Activate(this);
m_IsActivated = true;
}
}
var stateBlock = new RenderStateBlock(0)
public void Cleanup()
depthState = new DepthState(true, CompareFunction.LessEqual),
};
var labelSetupSystem = World.DefaultGameObjectInjectionWorld?.GetExistingSystem<GroundTruthLabelSetupSystem>();
labelSetupSystem?.Deactivate(this);
}
var result = new RendererListDesc(shaderPasses, cullingResult, camera)
protected RendererListDesc CreateRendererListDesc(Camera camera, CullingResults cullingResult, string overrideMaterialPassName, int overrideMaterialPassIndex, Material overrideMaterial, LayerMask layerMask /*, PerObjectData perObjectData*/)
rendererConfiguration = PerObjectData.None,
renderQueueRange = new RenderQueueRange { lowerBound = 0, upperBound = 5000 },
sortingCriteria = SortingCriteria.CommonOpaque,
excludeObjectMotionVectors = false,
overrideMaterial = overrideMaterial,
overrideMaterialPassIndex = overrideMaterialPassIndex,
stateBlock = stateBlock,
layerMask = layerMask,
};
return result;
}
var shaderPasses = new[]
{
new ShaderTagId("Forward"), // HD Lit shader
new ShaderTagId("ForwardOnly"), // HD Unlit shader
new ShaderTagId("SRPDefaultUnlit"), // Cross SRP Unlit shader
new ShaderTagId("UniversalForward"), // URP Forward
new ShaderTagId("LightweightForward"), // LWRP Forward
new ShaderTagId(overrideMaterialPassName), // The override material shader
};
var stateBlock = new RenderStateBlock(0)
{
depthState = new DepthState(true, CompareFunction.LessEqual),
};
public static void DrawRendererList(ScriptableRenderContext renderContext, CommandBuffer cmd, RendererList rendererList)
{
if (!rendererList.isValid)
throw new ArgumentException("Invalid renderer list provided to DrawRendererList");
var result = new RendererListDesc(shaderPasses, cullingResult, camera)
{
rendererConfiguration = PerObjectData.None,
renderQueueRange = new RenderQueueRange { lowerBound = 0, upperBound = 5000 },
sortingCriteria = SortingCriteria.CommonOpaque,
excludeObjectMotionVectors = false,
overrideMaterial = overrideMaterial,
overrideMaterialPassIndex = overrideMaterialPassIndex,
stateBlock = stateBlock,
layerMask = layerMask,
};
return result;
}
// This is done here because DrawRenderers API lives outside command buffers so we need to make call this before doing any DrawRenders or things will be executed out of order
renderContext.ExecuteCommandBuffer(cmd);
cmd.Clear();
public static void DrawRendererList(ScriptableRenderContext renderContext, CommandBuffer cmd, RendererList rendererList)
{
if (!rendererList.isValid)
throw new ArgumentException("Invalid renderer list provided to DrawRendererList");
// This is done here because DrawRenderers API lives outside command buffers so we need to make call this before doing any DrawRenders or things will be executed out of order
renderContext.ExecuteCommandBuffer(cmd);
cmd.Clear();
if (rendererList.stateBlock == null)
renderContext.DrawRenderers(rendererList.cullingResult, ref rendererList.drawSettings, ref rendererList.filteringSettings);
else
{
var renderStateBlock = rendererList.stateBlock.Value;
renderContext.DrawRenderers(rendererList.cullingResult, ref rendererList.drawSettings, ref rendererList.filteringSettings, ref renderStateBlock);
if (rendererList.stateBlock == null)
renderContext.DrawRenderers(rendererList.cullingResult, ref rendererList.drawSettings, ref rendererList.filteringSettings);
else
{
var renderStateBlock = rendererList.stateBlock.Value;
renderContext.DrawRenderers(rendererList.cullingResult, ref rendererList.drawSettings, ref rendererList.filteringSettings, ref renderStateBlock);
}
}
public abstract void SetupMaterialProperties(MaterialPropertyBlock mpb, MeshRenderer meshRenderer, Labeling labeling, uint instanceId);
public abstract void SetupMaterialProperties(MaterialPropertyBlock mpb, MeshRenderer meshRenderer, Labeling labeling, uint instanceId);
}
}

10
com.unity.perception/Runtime/GroundTruth/GroundTruthInfo.cs


using Unity.Entities;
using Unity.Entities;
namespace UnityEngine.Perception.Sensors
namespace UnityEngine.Perception.GroundTruth
/// <summary>
/// Information regarding a Labeling instance. Generated by <see cref="GroundTruthLabelSetupSystem"/>
/// </summary>
/// <summary>
/// The instanceId assigned to the <see cref="Labeling"/>
/// </summary>
public uint instanceId;
}
}

32
com.unity.perception/Runtime/GroundTruth/GroundTruthLabelSetupSystem.cs


using System.Collections.Generic;
using System.Collections.Generic;
namespace UnityEngine.Perception.Sensors
namespace UnityEngine.Perception.GroundTruth
{
struct IdAssignmentParameters : IComponentData
{

/// <summary>
/// System which notifies the registered <see cref="IGroundTruthGenerator"/> about <see cref="Labeling"/> additions.
/// </summary>
public class GroundTruthLabelSetupSystem : ComponentSystem
{
List<IGroundTruthGenerator> m_ActiveGenerators = new List<IGroundTruthGenerator>();

/// <inheritdoc/>
GetEntityQuery( ComponentType.Exclude<GroundTruthInfo>(), ComponentType.ReadOnly<Labeling>());
GetEntityQuery( ComponentType.ReadOnly<GroundTruthInfo>(), ComponentType.ReadOnly<Labeling>());
GetEntityQuery(ComponentType.Exclude<GroundTruthInfo>(), ComponentType.ReadOnly<Labeling>());
GetEntityQuery(ComponentType.ReadOnly<GroundTruthInfo>(), ComponentType.ReadOnly<Labeling>());
/// <inheritdoc/>
protected override void OnUpdate()
{
var entityQuery = Entities.WithAll<IdAssignmentParameters>().ToEntityQuery();

}
}
public void Activate(IGroundTruthGenerator pass)
/// <summary>
/// Activates the given <see cref="IGroundTruthGenerator"/>. <see cref="IGroundTruthGenerator.SetupMaterialProperties"/>
/// will be called for all <see cref="MeshRenderer"/> instances under each object containing a <see cref="Labeling"/> component.
/// </summary>
/// <param name="generator">The generator to register</param>
public void Activate(IGroundTruthGenerator generator)
m_ActiveGenerators.Add(pass);
m_ActiveGenerators.Add(generator);
public void Deactivate(IGroundTruthGenerator pass)
/// <summary>
/// Deactivates the given <see cref="IGroundTruthGenerator"/>. It will no longer receive calls when <see cref="Labeling"/> instances are created.
/// </summary>
/// <param name="generator">The generator to deactivate</param>
/// <returns>True if the <see cref="generator"/> was successfully removed. False if <see cref="generator"/> was not active.</returns>
public bool Deactivate(IGroundTruthGenerator generator)
m_ActiveGenerators.Remove(pass);
return m_ActiveGenerators.Remove(generator);
}
}
}

3
com.unity.perception/Runtime/GroundTruth/GroundTruthPass.cs


using System;
using Unity.Entities;
using UnityEngine.Experimental.Rendering;
namespace UnityEngine.Perception.Sensors
namespace UnityEngine.Perception.GroundTruth
{
public abstract class GroundTruthPass : CustomPass, IGroundTruthGenerator
{

91
com.unity.perception/Runtime/GroundTruth/GroundTruthRendererFeature.cs


#if URP_PRESENT
#if URP_PRESENT
using System.Collections.Generic;
using UnityEngine.Perception;
using UnityEngine.Perception.Sensors;
class InstanceSegmentationUrpPass : ScriptableRenderPass
namespace UnityEngine.Perception.GroundTruth
InstanceSegmentationCrossPipelinePass m_InstanceSegmentationPass;
class InstanceSegmentationUrpPass : ScriptableRenderPass
{
InstanceSegmentationCrossPipelinePass m_InstanceSegmentationPass;
public InstanceSegmentationUrpPass(Camera camera, RenderTexture targetTexture)
{
m_InstanceSegmentationPass = new InstanceSegmentationCrossPipelinePass(camera);
ConfigureTarget(targetTexture, targetTexture.depthBuffer);
m_InstanceSegmentationPass.Setup();
}
public InstanceSegmentationUrpPass(Camera camera, RenderTexture targetTexture)
{
m_InstanceSegmentationPass = new InstanceSegmentationCrossPipelinePass(camera);
ConfigureTarget(targetTexture, targetTexture.depthBuffer);
m_InstanceSegmentationPass.Setup();
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
var commandBuffer = CommandBufferPool.Get(nameof(InstanceSegmentationUrpPass));
m_InstanceSegmentationPass.Execute(context, commandBuffer, renderingData.cameraData.camera, renderingData.cullResults);
CommandBufferPool.Release(commandBuffer);
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
class SemanticSegmentationUrpPass : ScriptableRenderPass
var commandBuffer = CommandBufferPool.Get(nameof(InstanceSegmentationUrpPass));
m_InstanceSegmentationPass.Execute(context, commandBuffer, renderingData.cameraData.camera, renderingData.cullResults);
CommandBufferPool.Release(commandBuffer);
}
}
class SemanticSegmentationUrpPass : ScriptableRenderPass
{
SemanticSegmentationCrossPipelinePass m_SemanticSegmentationCrossPipelinePass;
SemanticSegmentationCrossPipelinePass m_SemanticSegmentationCrossPipelinePass;
public SemanticSegmentationUrpPass(Camera camera, RenderTexture targetTexture, LabelingConfiguration labelingConfiguration)
{
m_SemanticSegmentationCrossPipelinePass = new SemanticSegmentationCrossPipelinePass(camera, labelingConfiguration);
ConfigureTarget(targetTexture, targetTexture.depthBuffer);
m_SemanticSegmentationCrossPipelinePass.Setup();
}
public SemanticSegmentationUrpPass(Camera camera, RenderTexture targetTexture, LabelingConfiguration labelingConfiguration)
{
m_SemanticSegmentationCrossPipelinePass = new SemanticSegmentationCrossPipelinePass(camera, labelingConfiguration);
ConfigureTarget(targetTexture, targetTexture.depthBuffer);
m_SemanticSegmentationCrossPipelinePass.Setup();
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
var commandBuffer = CommandBufferPool.Get(nameof(SemanticSegmentationUrpPass));
m_SemanticSegmentationCrossPipelinePass.Execute(context, commandBuffer, renderingData.cameraData.camera, renderingData.cullResults);
CommandBufferPool.Release(commandBuffer);
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
var commandBuffer = CommandBufferPool.Get(nameof(SemanticSegmentationUrpPass));
m_SemanticSegmentationCrossPipelinePass.Execute(context, commandBuffer, renderingData.cameraData.camera, renderingData.cullResults);
CommandBufferPool.Release(commandBuffer);
}
}
public class GroundTruthRendererFeature : ScriptableRendererFeature
{
public override void Create()
public class GroundTruthRendererFeature : ScriptableRendererFeature
}
public override void Create() {}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
var cameraObject = renderingData.cameraData.camera.gameObject;
var perceptionCamera = cameraObject.GetComponent<PerceptionCamera>();
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
var cameraObject = renderingData.cameraData.camera.gameObject;
var perceptionCamera = cameraObject.GetComponent<PerceptionCamera>();
if (perceptionCamera == null)
return;
if (perceptionCamera == null)
return;
if (!EditorApplication.isPlaying)
return;
if (!EditorApplication.isPlaying)
return;
renderer.EnqueuePass(perceptionCamera.instanceSegmentationUrpPass);
renderer.EnqueuePass(perceptionCamera.semanticSegmentationUrpPass);
renderer.EnqueuePass(perceptionCamera.instanceSegmentationUrpPass);
renderer.EnqueuePass(perceptionCamera.semanticSegmentationUrpPass);
}
}
}
#endif

19
com.unity.perception/Runtime/GroundTruth/IGroundTruthGenerator.cs


using UnityEngine;
using UnityEngine;
public interface IGroundTruthGenerator
namespace UnityEngine.Perception.GroundTruth
void SetupMaterialProperties(MaterialPropertyBlock mpb, MeshRenderer meshRenderer, Labeling labeling, uint instanceId);
/// <summary>
/// Interface for setting up MeshRenderers for ground truth generation via <see cref="GroundTruthLabelSetupSystem"/>.
/// </summary>
public interface IGroundTruthGenerator
{
/// <summary>
/// Called by <see cref="GroundTruthLabelSetupSystem"/> when first registered or when a Labeling is created at runtime.
/// </summary>
/// <param name="mpb">The MaterialPropertyBlock for the given meshRenderer. Can be used to set properties for custom rendering.</param>
/// <param name="meshRenderer">The MeshRenderer which exists under the given Labeling.</param>
/// <param name="labeling">The Labeling component created</param>
/// <param name="instanceId">The instanceId assigned to the given Labeling instance.</param>
void SetupMaterialProperties(MaterialPropertyBlock mpb, MeshRenderer meshRenderer, Labeling labeling, uint instanceId);
}
}

111
com.unity.perception/Runtime/GroundTruth/InstanceSegmentationCrossPipelinePass.cs


using System;
using System;
using System.Collections.Generic;
using Unity.Profiling;
using UnityEngine;

public class InstanceSegmentationCrossPipelinePass : GroundTruthCrossPipelinePass
namespace UnityEngine.Perception.GroundTruth
public static readonly int SegmentationIdProperty = Shader.PropertyToID("_SegmentationId");
const string k_SegmentationPassShaderName = "Perception/InstanceSegmentation";
static ProfilerMarker s_ExecuteMarker = new ProfilerMarker("SegmentationPass_Execute");
class InstanceSegmentationCrossPipelinePass : GroundTruthCrossPipelinePass
{
static readonly int k_SegmentationIdProperty = Shader.PropertyToID("_SegmentationId");
const string k_SegmentationPassShaderName = "Perception/InstanceSegmentation";
//Filter settings
public LayerMask layerMask = -1;
static ProfilerMarker s_ExecuteMarker = new ProfilerMarker("SegmentationPass_Execute");
Shader m_SegmentationShader;
Material m_OverrideMaterial;
public bool reassignIds = false;
public uint idStart = 1;
public uint idStep = 1;
int m_NextObjectIndex;
/// <summary>
/// The LayerMask to apply when rendering objects.
/// </summary>
public LayerMask layerMask = -1;
Dictionary<uint, uint> m_Ids;
Shader m_SegmentationShader;
Material m_OverrideMaterial;
int m_NextObjectIndex;
public InstanceSegmentationCrossPipelinePass(Camera targetCamera, uint idStart = 1, uint idStep = 1)
:base(targetCamera)
{
if (targetCamera == null)
throw new ArgumentNullException(nameof(targetCamera));
Dictionary<uint, uint> m_Ids;
//Activating in the constructor allows us to get correct labeling in the first frame.
EnsureActivated();
/// <summary>
/// Create a new <see cref="InstanceSegmentationCrossPipelinePass"/> referencing the given
/// </summary>
/// <param name="targetCamera"></param>
/// <exception cref="ArgumentNullException"></exception>
public InstanceSegmentationCrossPipelinePass(Camera targetCamera)
: base(targetCamera)
{
if (targetCamera == null)
throw new ArgumentNullException(nameof(targetCamera));
this.idStart = idStart;
this.idStep = idStep;
}
//Activating in the constructor allows us to get correct labeling in the first frame.
EnsureActivated();
}
public override void Setup()
{
base.Setup();
m_SegmentationShader = Shader.Find(k_SegmentationPassShaderName);
var shaderVariantCollection = new ShaderVariantCollection();
shaderVariantCollection.Add(new ShaderVariantCollection.ShaderVariant(m_SegmentationShader, PassType.ScriptableRenderPipeline));
shaderVariantCollection.WarmUp();
m_OverrideMaterial = new Material(m_SegmentationShader);
}
//Render all objects to our target RenderTexture using `overrideMaterial` to use our shader
protected override void ExecutePass(ScriptableRenderContext renderContext, CommandBuffer cmd, Camera camera, CullingResults cullingResult)
{
using (s_ExecuteMarker.Auto())
public override void Setup()
cmd.ClearRenderTarget(true, true, Color.clear);
var result = CreateRendererListDesc(camera, cullingResult, "FirstPass", 0, m_OverrideMaterial, layerMask);
base.Setup();
m_SegmentationShader = Shader.Find(k_SegmentationPassShaderName);
var shaderVariantCollection = new ShaderVariantCollection();
shaderVariantCollection.Add(new ShaderVariantCollection.ShaderVariant(m_SegmentationShader, PassType.ScriptableRenderPipeline));
shaderVariantCollection.WarmUp();
DrawRendererList(renderContext, cmd, RendererList.Create(result));
m_OverrideMaterial = new Material(m_SegmentationShader);
}
public override void SetupMaterialProperties(MaterialPropertyBlock mpb, MeshRenderer meshRenderer, Labeling labeling, uint instanceId)
{
if (reassignIds)
//Render all objects to our target RenderTexture using `overrideMaterial` to use our shader
protected override void ExecutePass(ScriptableRenderContext renderContext, CommandBuffer cmd, Camera camera, CullingResults cullingResult)
//Almost all the code here interacts with shared state, so just use a simple lock for now.
lock (this)
using (s_ExecuteMarker.Auto())
if (m_Ids == null)
m_Ids = new Dictionary<uint, uint>();
cmd.ClearRenderTarget(true, true, Color.clear);
var result = CreateRendererListDesc(camera, cullingResult, "FirstPass", 0, m_OverrideMaterial, layerMask);
if (!m_Ids.TryGetValue(instanceId, out var actualId))
{
actualId = (uint)m_NextObjectIndex * idStep + idStart;
m_Ids.Add(instanceId, actualId);
instanceId = actualId;
m_NextObjectIndex++;
}
DrawRendererList(renderContext, cmd, RendererList.Create(result));
mpb.SetInt(SegmentationIdProperty, (int)instanceId);
#if PERCEPTION_DEBUG
Debug.Log($"Assigning id. Frame {Time.frameCount} id {id}");
#endif
public override void SetupMaterialProperties(MaterialPropertyBlock mpb, MeshRenderer meshRenderer, Labeling labeling, uint instanceId)
{
mpb.SetInt(k_SegmentationIdProperty, (int)instanceId);
#if PERCEPTION_DEBUG
Debug.Log($"Assigning id. Frame {Time.frameCount} id {id}");
#endif
}
}
}

9
com.unity.perception/Runtime/GroundTruth/InstanceSegmentationPass.cs


#if HDRP_PRESENT
#if HDRP_PRESENT
using System;
using JetBrains.Annotations;

namespace UnityEngine.Perception.Sensors
namespace UnityEngine.Perception.GroundTruth
{
/// <summary>
/// A CustomPass for creating object instance segmentation images. GameObjects containing Labeling components

InstanceSegmentationCrossPipelinePass m_InstanceSegmentationCrossPipelinePass;
public RenderTexture targetTexture;
public bool reassignIds = false;
public uint idStart = 1;
public uint idStep = 1;
public Camera targetCamera;
[UsedImplicitly]

{
if (m_InstanceSegmentationCrossPipelinePass == null)
{
m_InstanceSegmentationCrossPipelinePass = new InstanceSegmentationCrossPipelinePass(targetCamera, idStart, idStep);
m_InstanceSegmentationCrossPipelinePass = new InstanceSegmentationCrossPipelinePass(targetCamera);
m_InstanceSegmentationCrossPipelinePass.Setup();
}
}

41
com.unity.perception/Runtime/GroundTruth/Labeling/Labeling.cs


using System;
using System.Collections;
using UnityEngine.Serialization;
/// <summary>
/// Defines a set of classes associated with the object and its descendants. Classes can be overwritten
/// </summary>
public class Labeling : MonoBehaviour
namespace UnityEngine.Perception.GroundTruth
public List<string> classes = new List<string>();
/// <summary>
/// Defines a set of labels associated with the object and its descendants. A Labeling component will override any Labeling components on the object's ancestors.
/// </summary>
public class Labeling : MonoBehaviour
{
/// <summary>
/// The label names to associate with the GameObject.
/// </summary>
[FormerlySerializedAs("classes")]
public List<string> labels = new List<string>();
Entity entity;
// Start is called before the first frame update
void Awake()
{
entity = World.DefaultGameObjectInjectionWorld.EntityManager.CreateEntity();
World.DefaultGameObjectInjectionWorld.EntityManager.AddComponentObject(entity, this);
}
Entity m_Entity;
void Awake()
{
m_Entity = World.DefaultGameObjectInjectionWorld.EntityManager.CreateEntity();
World.DefaultGameObjectInjectionWorld.EntityManager.AddComponentObject(m_Entity, this);
}
private void OnDestroy()
{
if (World.DefaultGameObjectInjectionWorld != null)
World.DefaultGameObjectInjectionWorld.EntityManager.DestroyEntity(entity);
void OnDestroy()
{
if (World.DefaultGameObjectInjectionWorld != null)
World.DefaultGameObjectInjectionWorld.EntityManager.DestroyEntity(m_Entity);
}
}
}

35
com.unity.perception/Runtime/GroundTruth/Labeling/LabelingConfiguration.cs


using System;
using System;
namespace UnityEngine.Perception.Sensors
namespace UnityEngine.Perception.GroundTruth
/// <summary>
/// A definition for how a <see cref="Labeling"/> should be resolved to a single label and id for ground truth generation.
/// </summary>
/// <summary>
/// A sequence of <see cref="LabelingConfigurationEntry"/> which defines the labels relevant for this configuration and their values.
/// </summary>
/// <summary>
/// Attempts to find the matching index in <see cref="LabelingConfigurations"/> for the given <see cref="Labeling"/>.
/// </summary>
/// <remarks>
/// The matching index is the first class name in the given Labeling which matches an entry in <see cref="LabelingConfigurations"/>.
/// </remarks>
/// <param name="labeling">The <see cref="Labeling"/> to match </param>
/// <param name="index">When this method returns, contains the index of the matching <see cref="LabelingConfigurationEntry"/>, or -1 if no match was found.</param>
/// <returns>Returns true if a match was found. False if not.</returns>
foreach (var labelingClass in labeling.classes)
foreach (var labelingClass in labeling.labels)
{
for (var i = 0; i < LabelingConfigurations.Count; i++)
{

}
}
/// <summary>
/// Structure defining a label configuration for <see cref="LabelingConfiguration"/>.
/// </summary>
/// <summary>
/// The label string
/// </summary>
/// <summary>
/// The value to use when generating semantic segmentation images.
/// </summary>
/// <summary>
/// Creates a new LabelingConfigurationEntry with the given values.
/// </summary>
/// <param name="label">The label string.</param>
/// <param name="value">The value to use when generating semantic segmentation images.</param>
public LabelingConfigurationEntry(string label, int value)
{
this.label = label;

33
com.unity.perception/Runtime/GroundTruth/ObjectCountPass.cs


#if HDRP_PRESENT
#if HDRP_PRESENT
using Unity.Collections.LowLevel.Unsafe;
using System;

using UnityEngine.Rendering;
namespace UnityEngine.Perception.Sensors
namespace UnityEngine.Perception.GroundTruth
{
/// <summary>
/// CustomPass which computes object count for each label in the given LabelingConfiguration in the frame.

{
}
public bool WriteToLog { get; set; }
public override void SetupMaterialProperties(MaterialPropertyBlock mpb, MeshRenderer meshRenderer, Labeling labeling, uint instanceId)
{
if (!m_InstanceIdToClassIdLookup.IsCreated)

m_InstanceIdToClassIdLookup.Resize((int)instanceId + 1, NativeArrayOptions.ClearMemory);
}
m_IdBuffersNeedUpdating = true;
m_InstanceIdToClassIdLookup[(int) instanceId] = index + 1;
m_InstanceIdToClassIdLookup[(int)instanceId] = index + 1;
}
}

var objectCount = k_StartingObjectCount;
UpdateIdBufferSizes(objectCount);
m_ClassCounts = new ComputeBuffer(LabelingConfiguration.LabelingConfigurations.Count + 1, UnsafeUtility.SizeOf<uint>(), ComputeBufferType.Structured);
m_DataLogger = new Unity.Simulation.Logger("LabelHistogram");
RenderPipelineManager.endCameraRendering += OnEndCameraRendering;
}

internal event Action<NativeSlice<uint>, IReadOnlyList<LabelingConfigurationEntry>, int> ClassCountsReceived;
Unity.Simulation.Logger m_DataLogger;
void OnClassCountReadback(int requestFrameCount, NativeArray<uint> counts)
{
#if PERCEPTION_DEBUG

}
Debug.Log(sb);
#endif
if (WriteToLog)
{
//This is a bad pattern. We need to be able to log a JSON string without tons of allocations
var sensorMetric = new SensorMetric() {
FrameId = Time.frameCount
};
var sensorMetricData = new MetricData<SensorMetric>(
"sensor_metric",
sensorMetric);
for (int i = 0; i < LabelingConfiguration.LabelingConfigurations.Count; i++)
{
sensorMetric.SegmentedHistogram.Add(new ObjectCountEntry
{
Label = LabelingConfiguration.LabelingConfigurations[i].label,
Count = counts[i + 1]
});
}
m_DataLogger.Log(sensorMetricData);
}
ClassCountsReceived?.Invoke(new NativeSlice<uint>(counts, 1), LabelingConfiguration.LabelingConfigurations, requestFrameCount);
}

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


using System;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;

using UnityEngine.Experimental.Rendering;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
using UnityEngine.Serialization;
using UnityEngine.Perception.Sensors;
namespace UnityEngine.Perception
namespace UnityEngine.Perception.GroundTruth
{
/// <summary>
/// Captures ground truth from the associated Camera.

/// <summary>
/// The ID to use for object count annotations in the resulting dataset
/// </summary>
public string m_ObjectCountID = "51DA3C27-369D-4929-AEA6-D01614635CE2";
[FormerlySerializedAs("m_ObjectCountID")]
public string objectCountId = "51DA3C27-369D-4929-AEA6-D01614635CE2";
/// <summary>
/// Whether object bounding boxes should be computed
/// </summary>

/// </summary>
public string m_BoundingBoxID = "F9F22E05-443F-4602-A422-EBE4EA9B55CB";
[FormerlySerializedAs("m_BoundingBoxID")]
public string boundingBoxId = "F9F22E05-443F-4602-A422-EBE4EA9B55CB";
/// <summary>
/// Whether visible pixels should be computed for each labeled object
/// </summary>

/// </summary>
public string m_VisiblePixelsID = "5BA92024-B3B7-41A7-9D3F-C03A6A8DDD01";
[FormerlySerializedAs("m_VisiblePixelsID")]
public string visiblePixelsId = "5BA92024-B3B7-41A7-9D3F-C03A6A8DDD01";
/// <summary>
/// The corner of the image to use as the origin for bounding boxs.
/// </summary>

/// </summary>
public event Action<int, NativeArray<RenderedObjectInfo>> renderedObjectInfosCalculated;
internal event Action<int,NativeArray<uint>> segmentationImageReceived;
internal event Action<int, NativeArray<uint>> segmentationImageReceived;
internal RenderTexture m_LabelingTexture;
internal RenderTexture labelingTexture;
internal RenderTexture m_SegmentationTexture;
internal RenderTexture segmentationTexture;
RenderTextureReader<short> m_ClassLabelingTextureReader;
RenderTextureReader<uint> m_SegmentationReader;

bool m_CapturedLastFrame;
EgoMarker m_EgoMarker;
Ego m_EgoMarker;
/// <summary>
/// The <see cref="SensorHandle"/> associated with this camera. Use this to report additional annotations and metrics at runtime.

{
//CaptureOptions.useAsyncReadbackIfSupported = false;
m_EgoMarker = this.GetComponentInParent<EgoMarker>();
var ego = m_EgoMarker == null ? SimulationManager.RegisterEgo("") : m_EgoMarker.Ego;
m_EgoMarker = this.GetComponentInParent<Ego>();
var ego = m_EgoMarker == null ? SimulationManager.RegisterEgo("") : m_EgoMarker.EgoHandle;
SensorHandle = SimulationManager.RegisterSensor(ego, "camera", description, period, startTime);
var myCamera = GetComponent<Camera>();

produceBoundingBoxAnnotations = false;
}
m_SegmentationTexture = new RenderTexture(new RenderTextureDescriptor(width, height, GraphicsFormat.R8G8B8A8_UNorm, 8));
m_SegmentationTexture.name = "Segmentation";
m_LabelingTexture = new RenderTexture(new RenderTextureDescriptor(width, height, GraphicsFormat.R8G8B8A8_UNorm, 8));
m_LabelingTexture.name = "Labeling";
segmentationTexture = new RenderTexture(new RenderTextureDescriptor(width, height, GraphicsFormat.R8G8B8A8_UNorm, 8));
segmentationTexture.name = "Segmentation";
labelingTexture = new RenderTexture(new RenderTextureDescriptor(width, height, GraphicsFormat.R8G8B8A8_UNorm, 8));
labelingTexture.name = "Labeling";
#if HDRP_PRESENT
var customPassVolume = this.GetComponent<CustomPassVolume>() ?? gameObject.AddComponent<CustomPassVolume>();

{
name = "Segmentation Pass",
targetCamera = myCamera,
targetTexture = m_SegmentationTexture
targetTexture = segmentationTexture
m_SemanticSegmentationPass = new SemanticSegmentationPass(myCamera, m_LabelingTexture, LabelingConfiguration)
m_SemanticSegmentationPass = new SemanticSegmentationPass(myCamera, labelingTexture, LabelingConfiguration)
{
name = "Labeling Pass"
};

#if URP_PRESENT
instanceSegmentationUrpPass = new InstanceSegmentationUrpPass(myCamera, m_SegmentationTexture);
semanticSegmentationUrpPass = new SemanticSegmentationUrpPass(myCamera, m_LabelingTexture, LabelingConfiguration);
instanceSegmentationUrpPass = new InstanceSegmentationUrpPass(myCamera, segmentationTexture);
semanticSegmentationUrpPass = new SemanticSegmentationUrpPass(myCamera, labelingTexture, LabelingConfiguration);
#endif
if (produceSegmentationImages)

m_SegmentationAnnotationDefinition = SimulationManager.RegisterAnnotationDefinition("semantic segmentation", specs, "pixel-wise semantic segmentation label", "PNG");
m_ClassLabelingTextureReader = new RenderTextureReader<short>(m_LabelingTexture, myCamera,
m_ClassLabelingTextureReader = new RenderTextureReader<short>(labelingTexture, myCamera,
(frameCount, data, tex) => OnSemanticSegmentationImageRead(frameCount, data));
}

if (produceObjectCountAnnotations)
{
m_ObjectCountMetricDefinition = SimulationManager.RegisterMetricDefinition("object count", labelingMetricSpec, "Counts of objects for each label in the sensor's view", id: new Guid(m_ObjectCountID));
m_ObjectCountMetricDefinition = SimulationManager.RegisterMetricDefinition("object count", labelingMetricSpec, "Counts of objects for each label in the sensor's view", id: new Guid(objectCountId));
m_BoundingBoxAnnotationDefinition = SimulationManager.RegisterAnnotationDefinition("bounding box", labelingMetricSpec, "Bounding boxe for each labeled object visible to the sensor", id: new Guid(m_BoundingBoxID));
m_BoundingBoxAnnotationDefinition = SimulationManager.RegisterAnnotationDefinition("bounding box", labelingMetricSpec, "Bounding boxe for each labeled object visible to the sensor", id: new Guid(boundingBoxId));
m_VisiblePixelsMetricDefinition = SimulationManager.RegisterMetricDefinition("visible pixels", labelingMetricSpec, "Visible pixels for each visible object", id: new Guid(m_VisiblePixelsID));
m_VisiblePixelsMetricDefinition = SimulationManager.RegisterMetricDefinition("visible pixels", labelingMetricSpec, "Visible pixels for each visible object", id: new Guid(visiblePixelsId));
m_SegmentationReader = new RenderTextureReader<uint>(m_SegmentationTexture, myCamera, (frameCount, data, tex) =>
m_SegmentationReader = new RenderTextureReader<uint>(segmentationTexture, myCamera, (frameCount, data, tex) =>
{
if (segmentationImageReceived != null)
segmentationImageReceived(frameCount, data);

SimulationManager.SimulationEnding += OnSimulationEnding;
}
// ReSharper disable InconsistentNaming
[UsedImplicitly]
[UsedImplicitly]
[UsedImplicitly]
// ReSharper restore InconsistentNaming
void ProduceVisiblePixelsMetric(NativeArray<RenderedObjectInfo> renderedObjectInfos, int frameCount)
{

for (var i = 0; i < renderedObjectInfos.Length; i++)
{
var objectInfo = renderedObjectInfos[i];
if (!TryGetClassIdFromInstanceId(objectInfo.instanceId, out var labelId))
if (!TryGetLabelIdFromInstanceId(objectInfo.instanceId, out var labelId))
continue;
m_VisiblePixelsValues[i] = new VisiblePixelsValue

if (produceSegmentationImages)
customPassVolume.customPasses.Add(m_SemanticSegmentationPass);
}
#endif
void ProduceBoundingBoxesAnnotation(NativeArray<RenderedObjectInfo> renderedObjectInfos, List<LabelingConfigurationEntry> labelingConfigurations, int frameCount)

for (var i = 0; i < renderedObjectInfos.Length; i++)
{
var objectInfo = renderedObjectInfos[i];
if (!TryGetClassIdFromInstanceId(objectInfo.instanceId, out var labelId))
if (!TryGetLabelIdFromInstanceId(objectInfo.instanceId, out var labelId))
continue;
m_BoundingBoxValues[i] = new BoundingBoxValue

}
}
public bool TryGetClassIdFromInstanceId(int instanceId, out int labelId)
/// <summary>
/// Returns the class ID for the given instance ID resolved by <see cref="LabelingConfiguration"/>. Only valid when bounding boxes are being computed.
/// </summary>
/// <param name="instanceId">The instanceId of the object</param>
/// <param name="labelId">When this method returns, contains the labelId associated with the given instanceId, if one exists. -1 otherwise.</param>
/// <returns>True if a valid labelId was found for the given instanceId.</returns>
/// <exception cref="InvalidOperationException">Thrown when <see cref="produceBoundingBoxAnnotations"/> was not true on Start.</exception>
public bool TryGetLabelIdFromInstanceId(int instanceId, out int labelId)
throw new InvalidOperationException($"{nameof(TryGetClassIdFromInstanceId)} can only be used when bounding box capture is enabled");
throw new InvalidOperationException($"{nameof(TryGetLabelIdFromInstanceId)} can only be used when bounding box capture is enabled");
return m_RenderedObjectInfoGenerator.TryGetLabelIdFromInstanceId(instanceId, out labelId);
}

if (!SensorHandle.IsValid)
return;
var camera = this.GetComponent<Camera>();
camera.enabled = SensorHandle.ShouldCaptureThisFrame;
var cam = GetComponent<Camera>();
cam.enabled = SensorHandle.ShouldCaptureThisFrame;
m_AsyncCaptureInfos.RemoveSwapBack(i =>
!i.SegmentationAsyncAnnotation.IsPending &&

}
}
void CaptureRgbData(Camera camera)
void CaptureRgbData(Camera cam)
{
Profiler.BeginSample("CaptureDataFromLastFrame");
if (!captureRgbImages)

SensorHandle.ReportCapture(dxRootPath, SensorSpatialData.FromGameObjects(m_EgoMarker == null ? null : m_EgoMarker.gameObject, gameObject), m_PersistentSensorData.Select(kvp => (kvp.Key, kvp.Value)).ToArray());
Func<AsyncRequest<CaptureCamera.CaptureState>, AsyncRequest.Result> colorFunctor = null;
var width = camera.pixelWidth;
var height = camera.pixelHeight;
var flipY = ShouldFlipY(camera);
var width = cam.pixelWidth;
var height = cam.pixelHeight;
var flipY = ShouldFlipY(cam);
colorFunctor = r =>
{

}
};
CaptureCamera.Capture(camera, colorFunctor);
CaptureCamera.Capture(cam, colorFunctor);
Profiler.EndSample();
}

{
var stride = dataColorBuffer.Length / height;
var buffer = new NativeArray<byte>(stride, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
fixed (byte* colorBufferPtr = &dataColorBuffer[0])
fixed(byte* colorBufferPtr = &dataColorBuffer[0])
{
var unsafePtr = (byte*)buffer.GetUnsafePtr();
for (var row = 0; row < height / 2; row++)

RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering;
}
void OnBeginCameraRendering(ScriptableRenderContext _, Camera camera)
void OnBeginCameraRendering(ScriptableRenderContext _, Camera cam)
if (camera != GetComponent<Camera>())
if (cam != GetComponent<Camera>())
return;
#if UNITY_EDITOR
if (UnityEditor.EditorApplication.isPaused)

CaptureRgbData(camera);
CaptureRgbData(cam);
}
void OnDisable()

m_ClassLabelingTextureReader?.Dispose();
m_ClassLabelingTextureReader = null;
if (m_SegmentationTexture != null)
m_SegmentationTexture.Release();
if (segmentationTexture != null)
segmentationTexture.Release();
m_SegmentationTexture = null;
if (m_LabelingTexture != null)
m_LabelingTexture.Release();
segmentationTexture = null;
if (labelingTexture != null)
labelingTexture.Release();
if (m_RenderedObjectInfoGenerator != null)
{

SensorHandle = default;
m_LabelingTexture = null;
labelingTexture = null;
}
void OnSemanticSegmentationImageRead(int frameCount, NativeArray<short> data)

asyncRequest.data = new AsyncSemanticSegmentationWrite()
{
dataArray = data.ToArray(),
width = m_LabelingTexture.width,
height = m_LabelingTexture.height,
width = labelingTexture.width,
height = labelingTexture.height,
path = path
};
asyncRequest.Start((r) =>

21
com.unity.perception/Runtime/GroundTruth/RenderTextureReader.cs


using System;
using System;
using Unity.Profiling;
using UnityEngine.Assertions;
namespace UnityEngine.Perception.Sensors
namespace UnityEngine.Perception.GroundTruth
/// <typeparam name="T">The type of the raw texture data to be provided.</typeparam>
public class RenderTextureReader<T> : IDisposable where T : struct
{
RenderTexture m_Source;

Texture2D m_CpuTexture;
Camera m_CameraRenderingToSource;
ProfilerMarker m_WaitingForCompletionMarker = new ProfilerMarker("RenderTextureReader_WaitingForCompletion");
/// <summary>
/// Creates a new <see cref="RenderTextureReader{T}"/> for the given <see cref="RenderTexture"/>, <see cref="Camera"/>, and image readback callback
/// </summary>
/// <param name="source">The <see cref="RenderTexture"/> to read from.</param>
/// <param name="cameraRenderingToSource">The <see cref="Camera"/> which renders to the given renderTexture. This is used to determine when to read from the texture.</param>
/// <param name="imageReadCallback">The callback to call after reading the texture</param>
public RenderTextureReader(RenderTexture source, Camera cameraRenderingToSource, Action<int, NativeArray<T>, RenderTexture> imageReadCallback)
{
this.m_Source = source;

}
}
/// <summary>
/// Synchronously wait for all image requests to complete.
/// </summary>
/// <summary>
/// Shut down the reader, waiting for all requests to return.
/// </summary>
public void Dispose()
{
WaitForAllImages();

24
com.unity.perception/Runtime/GroundTruth/RenderedObjectInfo.cs


using System;
using System;
// ReSharper disable NonReadonlyMemberInGetHashCode
namespace UnityEngine.Perception
namespace UnityEngine.Perception.GroundTruth
/// <summary>
/// Describes an instance of an object in an instance segmentation frame. Generated by <see cref="RenderedObjectInfoGenerator"/>.
/// </summary>
/// <summary>
/// The instanceId of the rendered object.
/// </summary>
/// <summary>
/// The labelId of the object resolved by a <see cref="LabelingConfiguration"/>
/// </summary>
/// <summary>
/// The bounding box of the object in pixel coordinates.
/// </summary>
/// <summary>
/// The number of pixels in the image matching this instance.
/// </summary>
/// <inheritdoc />
/// <inheritdoc />
/// <inheritdoc />
/// <inheritdoc />
public override int GetHashCode()
{
unchecked

14
com.unity.perception/Runtime/GroundTruth/RenderedObjectInfoGenerator.cs


using System;
using System;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;

using UnityEngine.Rendering;
using UnityEngine.Perception.Sensors;
namespace UnityEngine.Perception
namespace UnityEngine.Perception.GroundTruth
{
/// <summary>
/// A CPU-based pass which computes bounding box and pixel counts per-object from instance segmentation images

NativeList<int> m_InstanceIdToClassIdLookup;
LabelingConfiguration m_LabelingConfiguration;
// ReSharper disable once InvalidXmlDocComment
/// one used by the <seealso cref="InstanceSegmentationPass"/> generating the input image. See <see cref="Compute"/></param>
/// one used by the <seealso cref="InstanceSegmentationUrpPass"/> generating the input image. See <see cref="Compute"/></param>
public RenderedObjectInfoGenerator(LabelingConfiguration labelingConfiguration)
{
m_LabelingConfiguration = labelingConfiguration;

}
}
// ReSharper disable once InvalidXmlDocComment
/// InstanceSegmentationRawData should be the raw data from a texture filled by <see cref="InstanceSegmentationPass"/>
/// InstanceSegmentationRawData should be the raw data from a texture filled by <see cref="InstanceSegmentationUrpPass"/> or <see cref="InstanceSegmentationPass"/>
/// using the same LabelingConfiguration that was passed into this object.
/// </summary>
/// <param name="instanceSegmentationRawData"></param>

8
com.unity.perception/Runtime/GroundTruth/SemanticSegmentationCrossPipelinePass.cs


using System;
using System;
namespace UnityEngine.Perception.Sensors
namespace UnityEngine.Perception.GroundTruth
public class SemanticSegmentationCrossPipelinePass : GroundTruthCrossPipelinePass
class SemanticSegmentationCrossPipelinePass : GroundTruthCrossPipelinePass
{
const string k_ShaderName = "Perception/SemanticSegmentation";
static readonly int k_LabelingId = Shader.PropertyToID("LabelingId");

var entry = new LabelingConfigurationEntry();
foreach (var l in m_LabelingConfiguration.LabelingConfigurations)
{
if (labeling.classes.Contains(l.label))
if (labeling.labels.Contains(l.label))
{
entry = l;
break;

4
com.unity.perception/Runtime/GroundTruth/SemanticSegmentationPass.cs


#if HDRP_PRESENT
#if HDRP_PRESENT
namespace UnityEngine.Perception.Sensors
namespace UnityEngine.Perception.GroundTruth
{
/// <summary>
/// Custom Pass which renders labeled images where each object with a Labeling component is drawn with the value

4
com.unity.perception/Runtime/GroundTruth/SimulationManagementComponentSystem.cs


using System;
using System;
namespace UnityEngine.Perception
namespace UnityEngine.Perception.GroundTruth
{
class SimulationManagementComponentSystem : ComponentSystem
{

114
com.unity.perception/Runtime/GroundTruth/SimulationManager.cs


using System;
using System;
using JetBrains.Annotations;
using Newtonsoft.Json.Linq;
using Unity.Simulation;

namespace UnityEngine.Perception
namespace UnityEngine.Perception.GroundTruth
{
/// <summary>
/// Global manager for frame scheduling and output capture for simulations.

/// </summary>
public static string SchemaVersion => "0.0.1";
/// <summary>
/// Called when the simulation ends. The simulation ends on playmode exit, application exit, or when <see cref="ResetSimulation"/> is called.
/// </summary>
public static event Action SimulationEnding;
/// <summary>

/// <returns>An <see cref="Ego"/>, which can be used to organize sensors under a common ego.</returns>
public static Ego RegisterEgo(string description)
/// <returns>An <see cref="EgoHandle"/>, which can be used to organize sensors under a common ego.</returns>
public static EgoHandle RegisterEgo(string description)
var ego = new Ego(Guid.NewGuid(), description);
var ego = new EgoHandle(Guid.NewGuid(), description);
SimulationState.AddEgo(ego);
return ego;
}

/// </summary>
/// <param name="ego">The ego container for the sensor. Sensor orientation will be reported in the context of the given ego.</param>
/// <param name="egoHandle">The ego container for the sensor. Sensor orientation will be reported in the context of the given ego.</param>
/// <param name="modality">The kind of the sensor (ex. "camera", "lidar")</param>
/// <param name="description">A human-readable description of the sensor (ex. "front-left rgb camera")</param>
/// <param name="period">The period, in seconds, on which the sensor should capture. Frames will be scheduled in the simulation such that each sensor is triggered every _period_ seconds.</param>

/// <exception cref="ArgumentException">Thrown if ego is invalid.</exception>
public static SensorHandle RegisterSensor(Ego ego, string modality, string description, float period, float firstCaptureTime)
public static SensorHandle RegisterSensor(EgoHandle egoHandle, string modality, string description, float period, float firstCaptureTime)
if (!SimulationState.Contains(ego.Id))
throw new ArgumentException("Supplied ego is not part of the simulation.", nameof(ego));
if (!SimulationState.Contains(egoHandle.Id))
throw new ArgumentException("Supplied ego is not part of the simulation.", nameof(egoHandle));
SimulationState.AddSensor(ego, modality, description, period, firstCaptureTime, sensor);
SimulationState.AddSensor(egoHandle, modality, description, period, firstCaptureTime, sensor);
return sensor;
}

/// </summary>
/// <param name="name">Human readable annotation spec name (e.g. sementic_segmentation, instance_segmentation, etc.)</param>
/// <param name="description">Description of the annotation.</param>
/// <param name="specValues">Format-specific specification for the metric values</param>
/// <param name="specValues">Format-specific specification for the metric values. Will be converted to json automatically.</param>
/// <typeparam name="TSpec">The type of the <see cref="specValues"/> struct to write.</typeparam>
/// <returns>A MetricDefinition, which can be used during this simulation to report metrics.</returns>
public static MetricDefinition RegisterMetricDefinition<TSpec>(string name, TSpec[] specValues, string description = null, Guid id = default)
{

/// </summary>
/// <param name="metricDefinition">The MetricDefinition associated with this metric. <see cref="RegisterMetricDefinition"/></param>
/// <param name="values">An array to be converted to json and put in the "values" field of the metric</param>
/// <typeparam name="T">The type of the <see cref="values"/> array</typeparam>
public static void ReportMetric<T>(MetricDefinition metricDefinition, T[] values)
{
SimulationState.ReportMetric(metricDefinition, values, default, default);

/// <summary>
/// Report a metric not associated with any sensor or annotation.
/// </summary>
/// <param name="metricDefinition"></param>
/// <param name="metricDefinition">The metric definition of the metric being reported</param>
public static AsyncMetric ReportMetricAsync(MetricDefinition metricDefinition) => SimulationState.CreateAsyncMetric(metricDefinition);
/// <summary>

Manager.Instance.ShutdownNotification += ResetSimulation;
}
internal static void ResetSimulation()
/// <summary>
/// Stop the current simulation and start a new one. All pending data is written to disk before returning.
/// </summary>
public static void ResetSimulation()
{
//this order ensures that exceptions thrown by End() do not prevent the state from being reset
SimulationEnding?.Invoke();

/// Report a value-based annotation related to this sensor in this frame.
/// </summary>
/// <param name="annotationDefinition">The AnnotationDefinition of this annotation.</param>
/// <param name="values">The annotation data.</param>
/// <returns>A handle to the reported annotation for reporting annotation-based metrics.</returns>
/// <param name="values">The annotation data, which will be automatically converted to json.</param>
/// <typeparam name="T">The type of the values array.</typeparam>
/// <returns>Returns a handle to the reported annotation for reporting annotation-based metrics.</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 Annotation ReportAnnotationValues<T>(AnnotationDefinition annotationDefinition, T[] values)

/// <summary>
/// Creates an async annotation for reporting the values for an annotation during a future frame.
///
/// <returns>A handle to the <see cref="AsyncAnnotation"/>, which can be used to report annotation data during a subsequent frame.</returns>
/// <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 AsyncAnnotation ReportAnnotationAsync(AnnotationDefinition annotationDefinition)

/// <param name="sensorSpatialData">Spatial data describing the sensor and the ego containing it.</param>
/// <param name="additionalSensorValues">Additional values to be emitted as json name/value pairs on the sensor object under the capture.</param>
/// <exception cref="InvalidOperationException">Thrown if ReportCapture is being called when ShouldCaptureThisFrame is false or it has already been called this frame.</exception>
public void ReportCapture(string filename, SensorSpatialData sensorSpatialData, params (string, object)[] additionalSensorValues)
public void ReportCapture(string filename, SensorSpatialData sensorSpatialData, params(string, object)[] additionalSensorValues)
{
if (!ShouldCaptureThisFrame)
{

/// </summary>
/// <param name="metricDefinition">The <see cref="MetricDefinition"/> of the metric.</param>
/// <param name="valuesJsonArray">A string-based JSON array to be placed in the "values" field of the metric</param>
/// <typeparam name="T">The value type</typeparam>
/// <exception cref="ArgumentNullException">Thrown if values is null</exception>
/// <exception cref="InvalidOperationException">Thrown if <see cref="ShouldCaptureThisFrame"/> is false.</exception>
public void ReportMetric(MetricDefinition metricDefinition, [NotNull] string valuesJsonArray)

/// <summary>
/// Start an async metric for reporting metric values for this frame in a subsequent frame.
/// </summary>
/// <param name="metricDefinition">The <see cref="MetricDefinition"/> of the metric.</param>
/// <exception cref="InvalidOperationException">Thrown if <see cref="ShouldCaptureThisFrame"/> is false.</exception>
/// <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 AsyncMetric ReportMetricAsync(MetricDefinition metricDefinition)
{
if (!ShouldCaptureThisFrame)

throw new InvalidOperationException("SensorHandle has been disposed or its simulation has ended");
}
/// <inheritdoc/>
/// <inheritdoc/>
/// <inheritdoc/>
public static bool operator ==(SensorHandle left, SensorHandle right)
/// <summary>
/// Compares two <see cref="SensorHandle"/> instances for equality.
/// </summary>
/// <param name="left">The first SensorHandle.</param>
/// <param name="right">The second SensorHandle.</param>
/// <returns>Returns true if the two SensorHandles refer to the same sensor.</returns>
public static bool operator==(SensorHandle left, SensorHandle right)
public static bool operator !=(SensorHandle left, SensorHandle right)
/// <summary>
/// Compares two <see cref="SensorHandle"/> instances for inequality.
/// </summary>
/// <param name="left">The first SensorHandle.</param>
/// <param name="right">The second SensorHandle.</param>
/// <returns>Returns false if the two SensorHandles refer to the same sensor.</returns>
public static bool operator!=(SensorHandle left, SensorHandle right)
{
return !left.Equals(right);
}

/// ReportValues may only be called once per AsyncMetric.
/// </summary>
/// <param name="valuesJsonArray">A JSON array in string form.</param>
/// <typeparam name="T">The type of the values</typeparam>
/// <exception cref="ArgumentNullException">Thrown if values is null</exception>
public void ReportValues(string valuesJsonArray)
{

/// Report a value-based data for this annotation.
/// </summary>
/// <param name="values">The annotation data.</param>
/// <typeparam name="T">The type of the data.</typeparam>
/// <exception cref="ArgumentNullException">Thrown if values is null</exception>
public void ReportValues<T>(T[] values)
{

/// <param name="values"></param>
/// <typeparam name="T"></typeparam>
/// <exception cref="ArgumentNullException">Thrown if values is null</exception>
/// <exception cref="InvalidOperationException">Thrown if <see cref="Annotation.SensorHandle"/> reports false for <see cref="UnityEngine.Perception.SensorHandle.ShouldCaptureThisFrame"/>.</exception>
/// <exception cref="InvalidOperationException">Thrown if <see cref="Annotation.SensorHandle"/> reports false for <see cref="UnityEngine.Perception.GroundTruth.SensorHandle.ShouldCaptureThisFrame"/>.</exception>
public void ReportMetric<T>(MetricDefinition metricDefinition, [NotNull] T[] values)
{
if (values == null)

/// <param name="metricDefinition"></param>
/// <param name="valuesJsonArray">A string-based JSON array to be placed in the "values" field of the metric</param>
/// <exception cref="ArgumentNullException">Thrown if values is null</exception>
/// <exception cref="InvalidOperationException">Thrown if <see cref="Annotation.SensorHandle"/> reports false for <see cref="SensorHandle.ShouldCaptureThisFrame"/>.</exception>
/// <exception cref="InvalidOperationException">Thrown if <see cref="Annotation.SensorHandle"/> reports false for
/// <see cref="UnityEngine.Perception.GroundTruth.SensorHandle.ShouldCaptureThisFrame"/>.</exception>
public void ReportMetric(MetricDefinition metricDefinition, [NotNull] string valuesJsonArray)
{
if (valuesJsonArray == null)

/// <returns>A handle to an AsyncMetric, which can be used to report values for this metric in future frames.</returns>
public AsyncMetric ReportMetricAsync(MetricDefinition metricDefinition) => SimulationManager.SimulationState.CreateAsyncMetric(metricDefinition, SensorHandle, this);
/// <inheritdoc/>
/// <inheritdoc/>
/// <inheritdoc/>
public override int GetHashCode()
{
return Id.GetHashCode();

/// <summary>
/// An ego, which is used to group multiple sensors under a single frame of reference.
/// </summary>
public struct Ego : IEquatable<Ego>
public struct EgoHandle : IEquatable<EgoHandle>
{
/// <summary>
/// The ID for this ego. This ID will be used to refer to this ego in the json metadata.

/// </summary>
public readonly string Description;
internal Ego(Guid id, string description)
internal EgoHandle(Guid id, string description)
public bool Equals(Ego other)
/// <inheritdoc/>
public bool Equals(EgoHandle other)
/// <inheritdoc/>
return obj is Ego other && Equals(other);
return obj is EgoHandle other && Equals(other);
/// <inheritdoc/>
public static bool operator ==(Ego left, Ego right)
/// <summary>
/// Compares two <see cref="EgoHandle"/> instances for equality.
/// </summary>
/// <param name="left">The first EgoHandle.</param>
/// <param name="right">The second EgoHandle.</param>
/// <returns>Returns true if the two EgoHandles refer to the same ego.</returns>
public static bool operator==(EgoHandle left, EgoHandle right)
public static bool operator !=(Ego left, Ego right)
/// <summary>
/// Compares two <see cref="EgoHandle"/> instances for inequality.
/// </summary>
/// <param name="left">The first EgoHandle.</param>
/// <param name="right">The second EgoHandle.</param>
/// <returns>Returns true if the two EgoHandles refer to the same ego.</returns>
public static bool operator!=(EgoHandle left, EgoHandle right)
{
return !left.Equals(right);
}

{
Id = id;
}
/// <inheritdoc />
public bool Equals(MetricDefinition other)
{

/// <summary>
/// Create a new SensorSpatialData with the given values.
/// </summary>
/// <param name="egoPose">The pose of the ego.</param>
/// <param name="sensorPose">The pose of the sensor relative to the ego.</param>
/// <param name="egoVelocity">The velocity of the ego.</param>
/// <param name="egoAcceleration">The acceleration of the ego.</param>
public SensorSpatialData(Pose egoPose, Pose sensorPose, Vector3? egoVelocity, Vector3? egoAcceleration)
{
EgoPose = egoPose;

/// </summary>
/// <param name="ego">The ego GameObject.</param>
/// <param name="sensor">The sensor GameObject.</param>
/// <returns></returns>
/// <returns>Returns a SensorSpatialData filled out with EgoPose and SensorPose based on the given objects.</returns>
public static SensorSpatialData FromGameObjects(GameObject ego, GameObject sensor)
{
ego = ego == null ? sensor : ego;

return sensorSpatialData;
}
}
}

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


using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Perception.Sensors;
namespace UnityEngine.Perception
namespace UnityEngine.Perception.GroundTruth
{
partial class SimulationState
{

Dictionary<SensorHandle, SensorData> m_Sensors = new Dictionary<SensorHandle, SensorData>();
HashSet<Ego> m_Egos = new HashSet<Ego>();
HashSet<EgoHandle> m_Egos = new HashSet<EgoHandle>();
HashSet<Guid> m_Ids = new HashSet<Guid>();
Guid m_SequenceId = Guid.NewGuid();

public float Timestamp;
public Guid SequenceId;
public (string, object)[] AdditionalSensorValues;
public List<(Annotation, AnnotationData )> Annotations = new List<(Annotation, AnnotationData)>();
public List<(Annotation, AnnotationData)> Annotations = new List<(Annotation, AnnotationData)>();
public bool CaptureReported;
public PendingCapture(Guid id, SensorHandle sensorHandle, SensorData sensorData, Guid sequenceId, int frameCount, int step, float timestamp)

public float sequenceTimeNextCapture;
public int lastCaptureFrameCount;
public Ego ego;
public EgoHandle egoHandle;
}
struct AnnotationData

}
}
internal void ReportCapture(SensorHandle sensorHandle, string filename, SensorSpatialData sensorSpatialData, params (string, object)[] additionalSensorValues)
internal void ReportCapture(SensorHandle sensorHandle, string filename, SensorSpatialData sensorSpatialData, params(string, object)[] additionalSensorValues)
{
var sensorData = m_Sensors[sensorHandle];
var pendingCapture = GetOrCreatePendingCaptureForThisFrame(sensorHandle, out _);

m_LastTimeScale = Time.timeScale;
}
public void AddSensor(Ego ego, string modality, string description, float period, float firstCaptureTime, SensorHandle sensor)
public void AddSensor(EgoHandle egoHandle, string modality, string description, float period, float firstCaptureTime, SensorHandle sensor)
{
var sensorData = new SensorData()
{

firstCaptureTime = firstCaptureTime,
ego = ego,
egoHandle = egoHandle,
lastCaptureFrameCount = -1
};
sensorData.sequenceTimeNextCapture = SequenceTimeOfNextCapture(sensorData);

public bool Contains(Guid id) => m_Ids.Contains(id);
public void AddEgo(Ego ego)
public void AddEgo(EgoHandle egoHandle)
m_Egos.Add(ego);
m_Ids.Add(ego.Id);
m_Egos.Add(egoHandle);
m_Ids.Add(egoHandle.Id);
}
public bool IsEnabled(SensorHandle sensorHandle) => m_ActiveSensors.Contains(sensorHandle);

do
{
sensorData.sequenceTimeNextCapture += sensorData.period;
} while (sensorData.sequenceTimeNextCapture <= UnscaledSequenceTime);
}
while (sensorData.sequenceTimeNextCapture <= UnscaledSequenceTime);
sensorData.lastCaptureFrameCount = Time.frameCount;
m_Sensors[activeSensor] = sensorData;

14
com.unity.perception/Runtime/GroundTruth/SimulationState_Json.cs


using System;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;

using Newtonsoft.Json.Linq;
using Unity.Simulation;
using UnityEngine.Perception.Sensors;
namespace UnityEngine.Perception
namespace UnityEngine.Perception.GroundTruth
{
partial class SimulationState
{

{
var sensorReference = new JObject();
sensorReference["id"] = kvp.Key.Id.ToString();
sensorReference["ego_id"] = kvp.Value.ego.Id.ToString();
sensorReference["ego_id"] = kvp.Value.egoHandle.Id.ToString();
sensorReference["modality"] = kvp.Value.modality;
if (kvp.Value.description != null)
sensorReference["description"] = kvp.Value.description;

{
var sensorJObject = new JObject();//new SensorCaptureJson
sensorJObject["sensor_id"] = pendingCapture.SensorHandle.Id.ToString();
sensorJObject["ego_id"] = pendingCapture.SensorData.ego.Id.ToString();
sensorJObject["ego_id"] = pendingCapture.SensorData.egoHandle.Id.ToString();
sensorJObject["modality"] = pendingCapture.SensorData.modality;
sensorJObject["translation"] = DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.SensorPose.position);
sensorJObject["rotation"] = DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.SensorPose.rotation);

foreach (var (name, value) in pendingCapture.AdditionalSensorValues)
foreach (var(name, value) in pendingCapture.AdditionalSensorValues)
egoCaptureJson["ego_id"] = pendingCapture.SensorData.ego.Id.ToString();
egoCaptureJson["ego_id"] = pendingCapture.SensorData.egoHandle.Id.ToString();
egoCaptureJson["translation"] = DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.EgoPose.position);
egoCaptureJson["rotation"] = DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.EgoPose.rotation);
egoCaptureJson["velocity"] = pendingCapture.SensorSpatialData.EgoVelocity.HasValue ? DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.EgoVelocity.Value) : null;

66
com.unity.perception/Tests/Editor/BuildPerceptionPlayer.cs


using System;
using System.Collections.Generic;
using System.IO;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Build.Reporting;

{
public class BuildPerceptionPlayer
{
public List<EditorBuildSettingsScene> editorBuildSettingsScenes = new List<EditorBuildSettingsScene>();
public List<string> testScenesPaths = new List<string>();
public string testSceneBase = "default base scene";
private BuildReport report;
private BuildSummary summary;
private string buildPath = "Build/PerceptionBuild";
List<EditorBuildSettingsScene> m_EditorBuildSettingsScenes = new List<EditorBuildSettingsScene>();
BuildSummary m_Summary;
string m_BuildPath = "Build/PerceptionBuild";
[SetUp]
public void SetUp()

[Test]
public void BuildPlayerStandaloneWindows64()
{
BuildPlayer(BuildTargetGroup.Standalone, BuildTarget.StandaloneWindows64, buildPath, BuildOptions.IncludeTestAssemblies, out report, out summary);
Assert.AreEqual(BuildResult.Succeeded, summary.result, " BuildTarget.StandaloneWindows64 failed to build");
BuildPlayer(BuildTargetGroup.Standalone, BuildTarget.StandaloneWindows64, m_BuildPath, BuildOptions.IncludeTestAssemblies, out _, out m_Summary);
Assert.AreEqual(BuildResult.Succeeded, m_Summary.result, " BuildTarget.StandaloneWindows64 failed to build");
}
[RequirePlatformSupport(BuildTarget.StandaloneLinux64)]

BuildPlayer(BuildTargetGroup.Standalone, BuildTarget.StandaloneLinux64, buildPath, BuildOptions.IncludeTestAssemblies, out report, out summary);
Assert.AreEqual(BuildResult.Succeeded, summary.result, "BuildTarget.StandaloneLinux64 failed to build");
BuildPlayer(BuildTargetGroup.Standalone, BuildTarget.StandaloneLinux64, m_BuildPath, BuildOptions.IncludeTestAssemblies, out _, out m_Summary);
Assert.AreEqual(BuildResult.Succeeded, m_Summary.result, "BuildTarget.StandaloneLinux64 failed to build");
}
[UnityPlatform(RuntimePlatform.OSXEditor)]

{
BuildPlayer(BuildTargetGroup.Standalone, BuildTarget.StandaloneOSX, buildPath, BuildOptions.IncludeTestAssemblies, out report, out summary);
Assert.AreEqual(BuildResult.Succeeded, summary.result, "BuildTarget.StandaloneLinux64 failed to build");
BuildPlayer(BuildTargetGroup.Standalone, BuildTarget.StandaloneOSX, m_BuildPath, BuildOptions.IncludeTestAssemblies, out _, out m_Summary);
Assert.AreEqual(BuildResult.Succeeded, m_Summary.result, "BuildTarget.StandaloneLinux64 failed to build");
}
public void TestsScenesPath()

{
if (targetPath.Contains("BaseScene.unity"))
{
testSceneBase = targetPath;
editorBuildSettingsScenes.Add(new EditorBuildSettingsScene(targetPath, true));
m_EditorBuildSettingsScenes.Add(new EditorBuildSettingsScene(targetPath, true));
{
testScenesPaths.Add(targetPath);
Debug.Log("Scenes Path : " + targetPath);
{
Debug.Log("Scenes Path : " + targetPath);
editorBuildSettingsScenes.Add(new EditorBuildSettingsScene(targetPath, true));
}
m_EditorBuildSettingsScenes.Add(new EditorBuildSettingsScene(targetPath, true));
}
EditorBuildSettings.scenes = editorBuildSettingsScenes.ToArray();
EditorBuildSettings.scenes = m_EditorBuildSettingsScenes.ToArray();
public void BuildPlayer(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget, string buildOutputPath, BuildOptions buildOptions,
void BuildPlayer(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget, string buildOutputPath, BuildOptions buildOptions,
out BuildReport buildReport, out BuildSummary buildSummary)
{
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();

buildPlayerOptions.targetGroup = buildTargetGroup;
if (buildTarget == BuildTarget.StandaloneLinux64)
TurnOffBurstCompiler();
public void TurnOffBurstCompiler()
{
var newLine = Environment.NewLine;
const string BurstAOTSettingsFilePath = "ProjectSettings/BurstAotSettings_StandaloneLinux64.json";
string[] BurstAOTSettingsText = new[]
{
"{" + newLine,
@" ""MonoBehaviour"": {" ,
@" ""m_EditorHideFlags"": 0,",
@" ""m_Name"": """",",
@" ""m_EditorClassIdentifier"":""Unity.Burst.Editor:Unity.Burst.Editor:BurstPlatformAotSettings"",",
@" ""DisableOptimisations"": false,",
@" ""DisableSafetyChecks"": true,",
@" ""DisableBurstCompilation"": true",
" }",
"}"
};
File.WriteAllLines(BurstAOTSettingsFilePath, BurstAOTSettingsText);
AssetDatabase.Refresh();
}

15
com.unity.perception/Tests/Editor/PerceptionCameraEditorTests.cs


using System;
using System;
using System.Collections.Generic;
using Unity.Collections;
using UnityEngine.Perception;
using UnityEngine.Perception.Sensors;
using UnityEngine.Perception.GroundTruth;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools;
namespace EditorTests

[UnityTest]
public IEnumerator EditorPause_DoesNotLogErrors()
{
int sceneCount = EditorSceneManager.sceneCount;
int sceneCount = SceneManager.sceneCount;
EditorSceneManager.CloseScene(EditorSceneManager.GetSceneAt(i), true);
EditorSceneManager.CloseScene(SceneManager.GetSceneAt(i), true);
}
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);

yield return new ExitPlayMode();
}
static GameObject SetupCamera(LabelingConfiguration labelingConfiguration)
static void SetupCamera(LabelingConfiguration labelingConfiguration)
{
var cameraObject = new GameObject();
cameraObject.SetActive(false);

perceptionCamera.produceObjectCountAnnotations = true;
cameraObject.SetActive(true);
return cameraObject;
}
}
}

11
com.unity.perception/Tests/Runtime/GroundTruthTests/BoundingBox2DTests.cs


using System;
using System;
using System.Linq;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Perception;
using UnityEngine.Perception.Sensors;
using UnityEngine.Perception.GroundTruth;
using UnityEngine.TestTools;
namespace GroundTruthTests

}, new uint[]
{
1,
0
0
},
2,
BoundingBoxOrigin.BottomLeft,

}
[UnityTest]
public IEnumerator ProducesCorrectBoundingBoxes([ValueSource(nameof(ProducesCorrectBoundingBoxesTestCases))]ProducesCorrectBoundingBoxesData producesCorrectBoundingBoxesData)
public IEnumerator ProducesCorrectBoundingBoxes([ValueSource(nameof(ProducesCorrectBoundingBoxesTestCases))] ProducesCorrectBoundingBoxesData producesCorrectBoundingBoxesData)
{
var label = "label";
var label2 = "label2";

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


using NUnit.Framework;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Perception.Sensors;
using UnityEngine.Perception.GroundTruth;
namespace GroundTruthTests
{

var jsonActual = DatasetJsonUtility.ToJToken(new Vector3(x, y, z));
Assert.AreEqual(jsonExpected, jsonActual.ToString());
}
[Test]
[TestCase(-2f, 0f, 3f, 4f, @"[
-2.0,

var jsonActual = DatasetJsonUtility.ToJToken(new Quaternion(x, y, z, w)).ToString();
Assert.AreEqual(jsonExpected, jsonActual);
}
[Test]
[TestCase(0.1f, 0.2f, 0.3f, 4f, 5f, 6f, 70f, 80f, 90f, @"[
[

15
com.unity.perception/Tests/Runtime/GroundTruthTests/GroundTruthTestBase.cs


using System;
using System;
using Unity.Simulation;
using UnityEngine.Perception;
using UnityEngine.Perception.GroundTruth;
using Object = UnityEngine.Object;
namespace GroundTruthTests

List<GameObject> objectsToDestroy = new List<GameObject>();
List<GameObject> m_ObjectsToDestroy = new List<GameObject>();
foreach (var o in objectsToDestroy)
foreach (var o in m_ObjectsToDestroy)
objectsToDestroy.Clear();
m_ObjectsToDestroy.Clear();
SimulationManager.ResetSimulation();
Time.timeScale = 1;

public void AddTestObjectForCleanup(GameObject @object) => objectsToDestroy.Add(@object);
public void AddTestObjectForCleanup(GameObject @object) => m_ObjectsToDestroy.Add(@object);
objectsToDestroy.Remove(@object);
m_ObjectsToDestroy.Remove(@object);
}
}
}

43
com.unity.perception/Tests/Runtime/GroundTruthTests/ObjectCountTests.cs


using System;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

using UnityEditor;
using UnityEditorInternal;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Perception;
using UnityEngine.Perception.Sensors;
using UnityEngine.Perception.GroundTruth;
using Object = UnityEngine.Object;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering.HighDefinition;
#endif

//TestHelper.LoadAndStartRenderDocCapture(out EditorWindow gameView);
var startFrameCount = Time.frameCount;
var expectedFramesAndCounts= new Dictionary<int, int>()
var expectedFramesAndCounts = new Dictionary<int, int>()
{
{Time.frameCount , 0},
{startFrameCount + 1, 1},

//Put a plane in front of the camera
var planeObject = TestHelper.CreateLabeledPlane(.1f, label);
yield return null;
GameObject.DestroyImmediate(planeObject);
Object.DestroyImmediate(planeObject);
planeObject = TestHelper.CreateLabeledPlane(.1f, label);
yield return null;
var planeObject2 = TestHelper.CreateLabeledPlane(.1f, label);

GameObject.DestroyImmediate(planeObject);
Object.DestroyImmediate(planeObject);
GameObject.DestroyImmediate(planeObject2);
Object.DestroyImmediate(planeObject2);
#if HDRP_PRESENT
//TODO: Remove this when DestroyImmediate properly calls Cleanup on the pass
var labelHistogramPass = (ObjectCountPass)cameraObject.GetComponent<CustomPassVolume>().customPasses.First(p => p is ObjectCountPass);

customPassVolume.isGlobal = true;
var rt = new RenderTexture(128, 128, 1, GraphicsFormat.R8G8B8A8_UNorm);
rt.Create();
var InstanceSegmentationPass = new InstanceSegmentationPass()
var instanceSegmentationPass = new InstanceSegmentationPass()
targetTexture = rt,
idStart = 1,
idStep = 1
targetTexture = rt
InstanceSegmentationPass.name = nameof(InstanceSegmentationPass);
InstanceSegmentationPass.EnsureInit();
customPassVolume.customPasses.Add(InstanceSegmentationPass);
var ObjectCountPass = new ObjectCountPass(camera);
ObjectCountPass.SegmentationTexture = rt;
ObjectCountPass.LabelingConfiguration = labelingConfiguration;
ObjectCountPass.name = nameof(ObjectCountPass);
customPassVolume.customPasses.Add(ObjectCountPass);
instanceSegmentationPass.name = nameof(instanceSegmentationPass);
instanceSegmentationPass.EnsureInit();
customPassVolume.customPasses.Add(instanceSegmentationPass);
var objectCountPass = new ObjectCountPass(camera);
objectCountPass.SegmentationTexture = rt;
objectCountPass.LabelingConfiguration = labelingConfiguration;
objectCountPass.name = nameof(objectCountPass);
customPassVolume.customPasses.Add(objectCountPass);
ObjectCountPass.ClassCountsReceived += onClassCountsReceived;
objectCountPass.ClassCountsReceived += onClassCountsReceived;
#endif
#if URP_PRESENT
var perceptionCamera = cameraObject.AddComponent<PerceptionCamera>();

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


using System;
using System;
using Unity.Collections;
using UnityEngine.Perception;
using UnityEngine.Perception.Sensors;
using UnityEngine.Perception.GroundTruth;
using Object = UnityEngine.Object;
namespace GroundTruthTests
{

""height"": {Screen.height / 2:F1}
}}";
var labelingConfiguration = CreateLabelingConfiguration();
var camera = SetupCamera(labelingConfiguration, pc =>
SetupCamera(labelingConfiguration, pc =>
{
pc.produceBoundingBoxAnnotations = true;
});

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


using System;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

using UnityEngine.Perception.GroundTruth;
using UnityEngine.Perception.Sensors;
using UnityEngine.TestTools;
using Object = UnityEngine.Object;

//Put a plane in front of the camera
var planeObject = GameObject.CreatePrimitive(PrimitiveType.Plane);
planeObject.transform.SetPositionAndRotation(new Vector3(0, 0, 10), Quaternion.Euler(90, 0, 0) );
planeObject.transform.SetPositionAndRotation(new Vector3(0, 0, 10), Quaternion.Euler(90, 0, 0));
planeObject.transform.localScale = new Vector3(10, -1, 10);
planeObject.AddComponent<Labeling>();
AddTestObjectForCleanup(planeObject);

Assert.AreEqual(4, timesSegmentationImageReceived);
}
[UnityTest]
public IEnumerator SegmentationPassProducesCorrectValuesEachFrame()
{

{
CollectionAssert.AreEqual(Enumerable.Repeat(expectedLabelAtFrame[frameCount], data.Length), data);
}
catch (Exception e)
// ReSharper disable once RedundantCatchClause
catch (Exception)
{
//uncomment to get RenderDoc captures while this check is failing
//RenderDoc.EndCaptureRenderDoc(gameView);

customPassVolume.isGlobal = true;
var rt = new RenderTexture(128, 128, 1, GraphicsFormat.R8G8B8A8_UNorm);
rt.Create();
var InstanceSegmentationPass = new InstanceSegmentationPass();
InstanceSegmentationPass.targetCamera = camera;
InstanceSegmentationPass.targetTexture = rt;
customPassVolume.customPasses.Add(InstanceSegmentationPass);
InstanceSegmentationPass.name = nameof(InstanceSegmentationPass);
InstanceSegmentationPass.EnsureInit();
var instanceSegmentationPass = new InstanceSegmentationPass();
instanceSegmentationPass.targetCamera = camera;
instanceSegmentationPass.targetTexture = rt;
customPassVolume.customPasses.Add(instanceSegmentationPass);
instanceSegmentationPass.name = nameof(instanceSegmentationPass);
instanceSegmentationPass.EnsureInit();
var reader = cameraObject.AddComponent<ImageReaderBehaviour>();
reader.source = rt;

#endif
#if URP_PRESENT
var labelingConfiguration = ScriptableObject.CreateInstance<LabelingConfiguration>();
var perceptionCamera = cameraObject.AddComponent<UnityEngine.Perception.PerceptionCamera>();
var perceptionCamera = cameraObject.AddComponent<PerceptionCamera>();
perceptionCamera.LabelingConfiguration = labelingConfiguration;
perceptionCamera.captureRgbImages = false;
perceptionCamera.produceBoundingBoxAnnotations = false;

32
com.unity.perception/Tests/Runtime/GroundTruthTests/SimulationManagerTests.cs


using System;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;

using Newtonsoft.Json.Linq;
using NUnit.Framework;
using Unity.Mathematics;
using Unity.Simulation;
using UnityEngine.Perception;
using UnityEngine.Perception.GroundTruth;
using UnityEngine.TestTools;
// ReSharper disable InconsistentNaming
// ReSharper disable NotAccessedField.Local

[UnityTest]
public IEnumerator StartNewSequence_ProperlyIncrementsSequence()
{
var timingsExpected = new (int step, int timestamp, bool expectNewSequence)[]
var timingsExpected = new(int step, int timestamp, bool expectNewSequence)[]
{
(0, 0, true),
(1, 2, false),

var filename = "my/file.png";
var annotationDefinitionGuid = Guid.NewGuid();
var annotationDefinitionsJsonExpected=
var annotationDefinitionsJsonExpected =
$@"{{
""version"": ""{SimulationManager.SchemaVersion}"",
""annotation_definitions"": [

}}
]
}}";
var annotationsJsonExpected=
var annotationsJsonExpected =
$@" ""annotations"": [
{{
""id"": <guid>,

var ego = SimulationManager.RegisterEgo("");
var annotationDefinition = SimulationManager.RegisterAnnotationDefinition("");
var sensorHandle = SimulationManager.RegisterSensor(ego, "", "", 1, 100);
Assert.Throws<InvalidOperationException>(()=>sensorHandle.ReportAnnotationFile(annotationDefinition, ""));
Assert.Throws<InvalidOperationException>(() => sensorHandle.ReportAnnotationFile(annotationDefinition, ""));
}
[Test]

var annotationDefinition = SimulationManager.RegisterAnnotationDefinition("");
var sensorHandle = SimulationManager.RegisterSensor(ego, "", "", 1, 100);
Assert.Throws<InvalidOperationException>(()=>sensorHandle.ReportAnnotationValues(annotationDefinition, new int[0]));
Assert.Throws<InvalidOperationException>(() => sensorHandle.ReportAnnotationValues(annotationDefinition, new int[0]));
}
[Test]

var annotationDefinition = SimulationManager.RegisterAnnotationDefinition("");
var sensorHandle = SimulationManager.RegisterSensor(ego, "", "", 1, 100);
Assert.Throws<InvalidOperationException>(()=>sensorHandle.ReportAnnotationAsync(annotationDefinition));
Assert.Throws<InvalidOperationException>(() => sensorHandle.ReportAnnotationAsync(annotationDefinition));
}
[Test]

StringAssert.Contains(expectedAnnotation, EscapeGuids(File.ReadAllText(capturesPath)));
}
public struct TestValues
{
public string a;

{
var annotationDefinitionGuid = new Guid(10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
var annotationDefinitionsJsonExpected=
var annotationDefinitionsJsonExpected =
$@"{{
""version"": ""{SimulationManager.SchemaVersion}"",
""annotation_definitions"": [

{
var annotationDefinitionGuid = new Guid(10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
var annotationDefinitionsJsonExpected=
var annotationDefinitionsJsonExpected =
$@"{{
""version"": ""{SimulationManager.SchemaVersion}"",
""annotation_definitions"": [

var ego = SimulationManager.RegisterEgo("");
var metricDefinition = SimulationManager.RegisterMetricDefinition("");
var sensorHandle = SimulationManager.RegisterSensor(ego, "", "", 1, 100);
Assert.Throws<InvalidOperationException>(()=>sensorHandle.ReportMetric(metricDefinition, new int[0]));
Assert.Throws<InvalidOperationException>(() => sensorHandle.ReportMetric(metricDefinition, new int[0]));
}
[Test]

var metricDefinition = SimulationManager.RegisterMetricDefinition("");
var sensorHandle = SimulationManager.RegisterSensor(ego, "", "", 1, 100);
Assert.Throws<InvalidOperationException>(()=>sensorHandle.ReportMetricAsync(metricDefinition));
Assert.Throws<InvalidOperationException>(() => sensorHandle.ReportMetricAsync(metricDefinition));
}
[Test]

{
var metricDefinitionGuid = new Guid(10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
var metricDefinitionsJsonExpected=
var metricDefinitionsJsonExpected =
$@"{{
""version"": ""{SimulationManager.SchemaVersion}"",
""metric_definitions"": [

public void CreateAnnotationOrMetric_WithSpecValues_WritesProperTypes(
[Values(AdditionalInfoKind.Annotation, AdditionalInfoKind.Metric)] AdditionalInfoKind additionalInfoKind)
{
var specValues = new []
var specValues = new[]
{
new TestSpec
{

jsonContainerName = "metric_definitions";
}
var annotationDefinitionsJsonExpected=
var annotationDefinitionsJsonExpected =
$@"{{
""version"": ""{SimulationManager.SchemaVersion}"",
""{jsonContainerName}"": [

7
com.unity.perception/Tests/Runtime/GroundTruthTests/TestHelper.cs


using System;
using System;
using UnityEngine.Perception.GroundTruth;
namespace GroundTruthTests
{

planeObject.transform.SetPositionAndRotation(new Vector3(0, 0, 10), Quaternion.Euler(90, 0, 0));
planeObject.transform.localScale = new Vector3(scale, -1, scale);
var labeling = planeObject.AddComponent<Labeling>();
labeling.classes.Add(label);
labeling.labels.Add(label);
#if UNITY_EDITOR
public static void LoadAndStartRenderDocCapture(out UnityEditor.EditorWindow gameView)
{

gameView = UnityEditor.EditorWindow.GetWindow(type);
UnityEditorInternal.RenderDoc.BeginCaptureRenderDoc(gameView);
}
#endif
}
}

33
com.unity.perception/Tests/Runtime/GroundTruthTests/SimulationManagerSensorSchedulingTests.cs


using System.Collections;
using System.Collections;
using UnityEngine.Assertions.Comparers;
using UnityEngine.Perception;
using UnityEngine.Perception.GroundTruth;
public class SimulationManager_SensorSchedulingTests
public class SimulationManagerSensorSchedulingTests
{
[TearDown]
public void TearDown()

var period = .4f;
SimulationManager.RegisterSensor(ego, "cam", "", period, firstCaptureTime);
float[] deltaTimeSamplesExpected = {
float[] deltaTimeSamplesExpected =
{
firstCaptureTime,
period,
period,

Time.timeScale = timeScale;
SimulationManager.RegisterSensor(ego, "cam", "", period, firstCaptureTime);
float[] deltaTimeSamplesExpected = {
float[] deltaTimeSamplesExpected =
{
timeScale * firstCaptureTime,
timeScale * period,
timeScale * period,

var ego = SimulationManager.RegisterEgo("ego");
var firstCaptureTime = 2f;
var period = 1f;
float[] newTimeScalesPerFrame = {
float[] newTimeScalesPerFrame =
{
2f,
10f,
.01f,

float[] deltaTimeSamplesExpected = {
float[] deltaTimeSamplesExpected =
{
};
float[] unscaledDeltaTimeSamplesExpected = {
firstCaptureTime,
period,
period,
period
};
float[] deltaTimeSamples = new float[deltaTimeSamplesExpected.Length];
for (int i = 0; i < deltaTimeSamples.Length; i++)

Assert.AreEqual(deltaTimeSamplesExpected[i], Time.deltaTime, 0.0001f);
//Assert.AreEqual(unscaledDeltaTimeSamplesExpected[i], Time.unscaledDeltaTime, 0.0001f);
}
}

var sensor3 = SimulationManager.RegisterSensor(ego, "cam", "3", 1, 1);
sensor3.Enabled = false;
(float deltaTime, bool sensor1ShouldCapture, bool sensor2ShouldCapture)[] samplesExpected = {
(float deltaTime, bool sensor1ShouldCapture, bool sensor2ShouldCapture)[] samplesExpected =
{
((float)firstCaptureTime1, true, true),
(4, true, false),
(2, false, true),

var samplesActual = new (float deltaTime, bool sensor1ShouldCapture, bool sensor2ShouldCapture)[samplesExpected.Length];
var samplesActual = new(float deltaTime, bool sensor1ShouldCapture, bool sensor2ShouldCapture)[samplesExpected.Length];
for (int i = 0; i < samplesActual.Length; i++)
{
yield return null;

[Test]
public void Enabled_StartsTrue()
{
var sensor1 = SimulationManager.RegisterSensor(SimulationManager.RegisterEgo(""), "cam", "1", 1,1);
var sensor1 = SimulationManager.RegisterSensor(SimulationManager.RegisterEgo(""), "cam", "1", 1, 1);
Assert.IsTrue(sensor1.Enabled);
}
}

74
.editorconfig


; see http://editorconfig.org/ for docs on this file
root = true
[*]
ignore_if_in_header = This code was generated by a tool|<auto-generated>
indent_style = space
indent_size = 4
; uncomment to help with sharing files across os's (i.e. network share or through local vm)
#end_of_line = lf
; avoid a bom, which causes endless problems with naive text tooling
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
; keeping auto-format enabled helps avoid merge hell for projects without CI-based format validation
#disable_auto_format = true
[*.cs]
; uncomment to enable full formatting of c# files
formatters = generic, uncrustify
[*.asmdef]
scrape_api = true
[**/Tests/**.asmdef]
scrape_api = false
[*.Tests.asmdef]
scrape_api = false
[*.md]
indent_size = 2
; trailing whitespace is unfortunately significant in markdown
trim_trailing_whitespace = false
; uncomment to enable basic formatting of markdown files
#formatters = generic
[{Makefile,makefile}]
; tab characters are part of the Makefile format
indent_style = tab
[*.asmdef]
indent_size = 4
[*.json]
indent_size = 2
[*.{vcproj,bat,cmd,xaml,tt,t4,ttinclude}]
end_of_line = crlf
; this VS-specific stuff is based on experiments to see how VS will modify a file after it has been manually edited.
; the settings are meant to closely match what VS does to minimize unnecessary diffs.
[*.{vcxproj,vcxproj.filters}]
indent_style = space
indent_size = 2
end_of_line = crlf
charset = utf-8-bom
trim_trailing_whitespace = true
insert_final_newline = false
; must be broken out because of 51-char bug (https://github.com/editorconfig/editorconfig-visualstudio/issues/21)
[*.{csproj,pyproj,props,targets}]
indent_style = space
indent_size = 2
end_of_line = crlf
charset = utf-8-bom
trim_trailing_whitespace = true
insert_final_newline = false
[*.{sln,sln.template}]
indent_style = tab
indent_size = 4
end_of_line = crlf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = false

38
com.unity.perception/Runtime/GroundTruth/Ego.cs


using System;
using UnityEngine;
namespace UnityEngine.Perception.GroundTruth
{
/// <summary>
/// Marker indicating the GameObject is the root of the ego for a set of sensors. Works with <see cref="PerceptionCamera"/>.
/// Custom sensors can use the <see cref="EgoHandle"/> property to register themselves under this ego.
/// </summary>
public class Ego : MonoBehaviour
{
/// <summary>
/// A human-readable description for this Ego to be included in the dataset.
/// </summary>
public string Description;
EgoHandle m_EgoHandle;
public EgoHandle EgoHandle
{
get
{
EnsureEgoInitialized();
return m_EgoHandle;
}
}
void Start()
{
EnsureEgoInitialized();
}
void EnsureEgoInitialized()
{
if (m_EgoHandle == default)
m_EgoHandle = SimulationManager.RegisterEgo(Description);
}
}
}

31
com.unity.perception/Runtime/GroundTruth/EgoMarker.cs


using System;
using UnityEngine;
namespace UnityEngine.Perception
{
public class EgoMarker : MonoBehaviour
{
public string Description;
Ego m_Ego;
public Ego Ego
{
get
{
EnsureEgoInitialized();
return m_Ego;
}
}
void Start()
{
EnsureEgoInitialized();
}
void EnsureEgoInitialized()
{
if (m_Ego == default)
m_Ego = SimulationManager.RegisterEgo(Description);
}
}
}

135
com.unity.perception/Runtime/GroundTruth/MetricData.cs


using System;
using System.Collections.Generic;
using UnityEngine;
using USim = Unity.Simulation;
namespace UnityEngine.Perception.Sensors
{
class MetricData<T>
{
public string Name;
public SimulationInfo SimulationInfo;
public CurrentContext CurrentContext;
public T Metric;
public MetricData(string name, T metric)
{
if(string.IsNullOrEmpty(name)) {
throw new ArgumentException("Arg name is null or empty");
}
this.Name = name;
this.Metric = metric;
this.SimulationInfo = SimulationInfo.GetInstance();
this.CurrentContext = CurrentContext.NewCurrentContext();
}
}
[Serializable]
class SensorMetric
{
public string SensorId;
public int FrameId;
public List<ObjectCountEntry> SegmentedHistogram = new List<ObjectCountEntry>();
}
[Serializable]
struct ObjectCountEntry
{
public string Label;
public uint Count;
}
[Serializable]
struct CurrentContext
{
static USim.Manager s_Manager;
public double SimulationElapsedTime;
public double SimulationElapsedTimeUnscaled;
public static CurrentContext NewCurrentContext()
{
if(s_Manager == null) {
s_Manager = USim.Manager.Instance;
}
return new CurrentContext() {
SimulationElapsedTime = s_Manager.SimulationElapsedTime,
SimulationElapsedTimeUnscaled = s_Manager.SimulationElapsedTimeUnscaled,
};
}
}
/// <summary> SimulationInfo - Context that is unchanged for this entire simulation </summary>
[Serializable]
class SimulationInfo
{
public string ProjectId;
public string RunId;
public string ExecutionId;
public string AppParamId;
public string RunInstanceId;
public string AttemptId;
public override string ToString()
{
return string.Format("{0}/{1}/{2}/{3}/{4}/{5}",
this.ProjectId,
this.RunId,
this.ExecutionId,
this.AppParamId,
this.RunInstanceId,
this.AttemptId);
}
static SimulationInfo s_Context;
public static SimulationInfo GetInstance()
{
if(s_Context != null) {
return s_Context;
}
var config = USim.Configuration.Instance;
if(config.IsSimulationRunningInCloud()) {
s_Context = GetInstance(config.GetStoragePath());
} else {
s_Context = new SimulationInfo() {
ProjectId = Guid.NewGuid().ToString(),
AppParamId = "urn:app_param_id:app_param_id",
ExecutionId = "urn:app_param_id:exn_id",
RunId = "urn:app_param_id:run_id",
RunInstanceId = "0",
AttemptId = "0"
};
}
return s_Context;
}
static SimulationInfo GetInstance(string storagePath)
{
if(string.IsNullOrEmpty(storagePath)) {
throw new ArgumentException("Arg storagePath is null or empty");
}
const int expectedTokenCount = 8;
var tokens = storagePath.Split('/');
if (tokens.Length < expectedTokenCount) {
var msg = "Storage path not in the expected format";
Debug.LogError(msg);
throw new ArgumentException(msg);
}
return new SimulationInfo()
{
ProjectId = tokens[1],
RunId = tokens[3],
ExecutionId = tokens[4],
AppParamId = tokens[5],
RunInstanceId = tokens[6],
AttemptId = tokens[7]
};
}
}
}

11
com.unity.perception/Runtime/GroundTruth/MetricData.cs.meta


fileFormatVersion: 2
guid: 21e0b364c4d364d4a8d36cd1b2648bb0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

/com.unity.perception/Editor/GroundTruth/LabelingPassEditor.cs.meta → /com.unity.perception/Editor/GroundTruth/SemanticSegmentationPassEditor.cs.meta

/com.unity.perception/Editor/GroundTruth/LabelingPassEditor.cs → /com.unity.perception/Editor/GroundTruth/SemanticSegmentationPassEditor.cs

/com.unity.perception/Runtime/GroundTruth/EgoMarker.cs.meta → /com.unity.perception/Runtime/GroundTruth/Ego.cs.meta

/com.unity.perception/Tests/Runtime/GroundTruthTests/SimulationManager_SensorSchedulingTests.cs.meta → /com.unity.perception/Tests/Runtime/GroundTruthTests/SimulationManagerSensorSchedulingTests.cs.meta

/com.unity.perception/Tests/Runtime/GroundTruthTests/SimulationManager_SensorSchedulingTests.cs → /com.unity.perception/Tests/Runtime/GroundTruthTests/SimulationManagerSensorSchedulingTests.cs

正在加载...
取消
保存