Beispiel #1
0
        public IEnumerator FramesScheduled_WithChangingTimeScale_ResultsInProperDeltaTime()
        {
            var ego = DatasetCapture.RegisterEgo("ego");
            var firstCaptureTime = 2f;
            var period           = 1f;

            float[] newTimeScalesPerFrame =
            {
                2f,
                10f,
                .01f,
                1f
            };
            DatasetCapture.RegisterSensor(ego, "cam", "", period, firstCaptureTime);

            float[] deltaTimeSamplesExpected =
            {
                newTimeScalesPerFrame[0] * firstCaptureTime,
                newTimeScalesPerFrame[1] * period,
                newTimeScalesPerFrame[2] * period,
                newTimeScalesPerFrame[3] * period
            };
            float[] deltaTimeSamples = new float[deltaTimeSamplesExpected.Length];
            for (int i = 0; i < deltaTimeSamples.Length; i++)
            {
                Time.timeScale = newTimeScalesPerFrame[i];
                yield return(null);

                Assert.AreEqual(deltaTimeSamplesExpected[i], Time.deltaTime, 0.0001f);
            }
        }
        public IEnumerator SequenceTimeOfNextCapture_ReportsCorrectTime()
        {
            var ego = DatasetCapture.RegisterEgo("ego");
            var firstCaptureFrame   = 2f;
            var simulationDeltaTime = .4f;
            var sensorHandle        = DatasetCapture.RegisterSensor(ego, "cam", "", firstCaptureFrame, CaptureTriggerMode.Scheduled, simulationDeltaTime, 0);

            var startTime = firstCaptureFrame * simulationDeltaTime;

            float[] sequenceTimesExpected =
            {
                startTime,
                simulationDeltaTime + startTime,
                simulationDeltaTime * 2 + startTime,
                simulationDeltaTime * 3 + startTime
            };

            for (var i = 0; i < firstCaptureFrame; i++)
            {
                //render the non-captured frames before firstCaptureFrame
                yield return(null);
            }

            for (var i = 0; i < sequenceTimesExpected.Length; i++)
            {
                var sensorData         = m_TestHelper.GetSensorData(sensorHandle);
                var sequenceTimeActual = m_TestHelper.CallSequenceTimeOfNextCapture(sensorData);
                Assert.AreEqual(sequenceTimesExpected[i], sequenceTimeActual, 0.0001f);
                yield return(null);
            }
        }
Beispiel #3
0
        void ReportMetrics(IEnumerable <RandomizerTag> tags)
        {
            var infos = new List <MyVolumeInfo>();

            foreach (var tag in tags)
            {
                var taggedObject = tag.gameObject;
                if (!m_PostProcessingVolumeCache.TryGetValue(taggedObject, out var volume))
                {
                    volume = taggedObject.GetComponentInChildren <Volume>();
                    m_PostProcessingVolumeCache.Add(taggedObject, volume);
                }

                var colorAdjustments = (ColorAdjustments)volume.profile.components.Find(comp => comp is ColorAdjustments);
                var depthOfField     = (DepthOfField)volume.profile.components.Find(comp => comp is DepthOfField);
                infos.Add(new MyVolumeInfo()
                {
                    saturation        = colorAdjustments.saturation.value,
                    contrast          = colorAdjustments.contrast.value,
                    gaussianDofStart  = depthOfField.gaussianStart.value,
                    gaussianDofEnd    = depthOfField.gaussianEnd.value,
                    gaussianDofRadius = depthOfField.gaussianMaxRadius.value
                });
            }

            DatasetCapture.ReportMetric(m_CameraPostProcessingMetricDefinition, infos.ToArray());
        }
Beispiel #4
0
        public IEnumerator FramesScheduled_WithTimeScale_ResultsInProperDeltaTime()
        {
            var ego = DatasetCapture.RegisterEgo("ego");
            var firstCaptureTime = 2f;
            var period           = 1f;

            var timeScale = 2;

            Time.timeScale = timeScale;
            DatasetCapture.RegisterSensor(ego, "cam", "", period, firstCaptureTime);

            float[] deltaTimeSamplesExpected =
            {
                timeScale *firstCaptureTime,
                timeScale *period,
                timeScale *period,
                timeScale *period
            };
            float[] deltaTimeSamples = new float[deltaTimeSamplesExpected.Length];
            for (int i = 0; i < deltaTimeSamples.Length; i++)
            {
                yield return(null);

                Assert.AreEqual(deltaTimeSamplesExpected[i], Time.deltaTime, 0.0001f);
            }
        }
Beispiel #5
0
 public void DefineViewPortAnnotation()
 {
     plantAnnotationDefinition = DatasetCapture.RegisterAnnotationDefinition(
         "View_Port_Position",
         "The position relative to the screen",
         id: Guid.Parse("C0B4A22C-0420-4D9F-BAFC-954B8F7B35A7"));
 }
    void ReportObjectStats(PlacementStatics placementStatics, NativeList <PlacedObject> placedObjectBoundingBoxes, GameObject cameraObject)
    {
        var objectStates = new JArray();

        for (int i = 0; i < placedObjectBoundingBoxes.Length; i++)
        {
            var placedObject = placedObjectBoundingBoxes[i];
            var labeling     = m_ParentForeground.transform.GetChild(placedObject.PrefabIndex).GetChild(0).gameObject.GetComponent <Labeling>();
            int labelId;
            if (placementStatics.IdLabelConfig.TryGetMatchingConfigurationEntry(labeling, out IdLabelEntry labelEntry))
            {
                labelId = labelEntry.id;
            }
            else
            {
                labelId = -1;
            }

            var jObject = new JObject();
            jObject["label_id"] = labelId;
            var rotationEulerAngles = (float3)placedObject.Rotation.eulerAngles;
            jObject["rotation"] = new JRaw($"[{rotationEulerAngles.x}, {rotationEulerAngles.y}, {rotationEulerAngles.z}]");
            objectStates.Add(jObject);
        }
        DatasetCapture.ReportMetric(m_ForegroundPlacementInfoDefinition, objectStates.ToString(Formatting.Indented));
    }
    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        if (!m_IsInitialized)
        {
            Initialize();
        }

        if (!m_IsInitialized)
        {
            return(inputDeps);
        }

        m_Light.color = new Color(
            m_Rand.NextFloat(m_InitParams.AppParameters.LightColorMin, 1f), m_Rand.NextFloat(m_InitParams.AppParameters.LightColorMin, 1f), m_Rand.NextFloat(m_InitParams.AppParameters.LightColorMin, 1f));
        var xRotation = m_Rand.NextFloat(-m_InitParams.AppParameters.LightRotationMax, m_InitParams.AppParameters.LightRotationMax);
        var yRotation = m_Rand.NextFloat(-m_InitParams.AppParameters.LightRotationMax, m_InitParams.AppParameters.LightRotationMax);

        m_Light.transform.rotation = Quaternion.Euler(
            xRotation,
            yRotation,
            0f
            );

        DatasetCapture.ReportMetric(m_LightingInfoDefinition, new[]
        {
            new LightInfo()
            {
                color      = m_Light.color,
                x_rotation = xRotation,
                y_rotation = yRotation
            }
        });
        return(inputDeps);
    }
    void Initialize()
    {
        var light = GameObject.Find("Directional Light");

        if (light == null)
        {
            return;
        }

        m_LightingInfoDefinition = DatasetCapture.RegisterMetricDefinition("lighting info", "Per-frame light color and orientation", id: k_LightingInfoGuid);
        m_Light = light.GetComponent <Light>();
        // To simulate phong shading we turn off shadows
        m_Light.shadows = LightShadows.None;
        m_IsInitialized = true;


        // Try to find game object here because scene may not be initialized on Create()
        if (m_InitParams == null)
        {
            m_InitParams = GameObject.Find("Management")?.GetComponentInChildren <ProjectInitialization>();
            if (m_InitParams == null)
            {
                Debug.LogWarning("Unable to find Management object. Will not randomize lighting.");
                return;
            }
        }
    }
        void ReportMetrics(IEnumerable <RandomizerTag> tags)
        {
            var objectStates = new JArray();

            foreach (var tag in tags)
            {
                var taggedObject = tag.gameObject;
                if (!m_LabelingComponentsCache.TryGetValue(taggedObject, out var labeling))
                {
                    labeling = taggedObject.GetComponentInChildren <Labeling>();
                    m_LabelingComponentsCache.Add(taggedObject, labeling);
                }

                int labelId = -1;
                if (labelConfigForObjectPlacementMetrics.TryGetMatchingConfigurationEntry(labeling, out IdLabelEntry labelEntry))
                {
                    labelId = labelEntry.id;
                }

                var jObject = new JObject();
                jObject["label_id"] = labelId;
                var rotationEulerAngles = (float3)taggedObject.transform.rotation.eulerAngles;
                jObject["rotation"] = new JRaw($"[{rotationEulerAngles.x}, {rotationEulerAngles.y}, {rotationEulerAngles.z}]");
                var position = (float3)taggedObject.transform.position;
                jObject["position"] = new JRaw($"[{position.x}, {position.y}, {position.z}]");
                var scale = (float3)taggedObject.transform.localScale;
                jObject["scale"] = new JRaw($"[{scale.x}, {scale.y}, {scale.z}]");
                objectStates.Add(jObject);
            }

            DatasetCapture.ReportMetric(m_ForegroundObjectPlacementMetricDefinition, objectStates.ToString(Formatting.Indented));
        }
        public IEnumerator EnableSemanticSegmentation_GeneratesCorrectDataset([Values(true, false)] bool enabled)
        {
            SemanticSegmentationLabeler semanticSegmentationLabeler = null;

            SetupCamera(pc =>
            {
                semanticSegmentationLabeler = new SemanticSegmentationLabeler(CreateSemanticSegmentationLabelConfig());
                pc.AddLabeler(semanticSegmentationLabeler);
            }, enabled);

            string expectedImageFilename = $"segmentation_{Time.frameCount}.png";

            this.AddTestObjectForCleanup(TestHelper.CreateLabeledPlane());
            yield return(null);

            DatasetCapture.ResetSimulation();

            if (enabled)
            {
                var capturesPath = Path.Combine(DatasetCapture.OutputDirectory, "captures_000.json");
                var capturesJson = File.ReadAllText(capturesPath);
                var imagePath    = $"{semanticSegmentationLabeler.semanticSegmentationDirectory}/{expectedImageFilename}";
                StringAssert.Contains(imagePath, capturesJson);
            }
            else
            {
                DirectoryAssert.DoesNotExist(DatasetCapture.OutputDirectory);
            }
        }
Beispiel #11
0
        /// <inheritdoc/>
        protected override void OnStart()
        {
            var randomSeedMetricDefinition = DatasetCapture.RegisterMetricDefinition(
                "random-seed",
                "The random seed used to initialize the random state of the simulation. Only triggered once per simulation.",
                Guid.Parse("14adb394-46c0-47e8-a3f0-99e754483b76"));

            DatasetCapture.ReportMetric(randomSeedMetricDefinition, new[] { genericConstants.randomSeed });
        }
Beispiel #12
0
 /// <inheritdoc/>
 protected override void OnIterationStart()
 {
     DatasetCapture.StartNewSequence();
     DatasetCapture.ReportMetric(m_IterationMetricDefinition, new[]
     {
         new IterationMetricData {
             iteration = currentIteration
         }
     });
 }
 public override void Create()
 {
     m_RenderPass = new RandomizedPostProcessingPass();
     if (Application.isPlaying)
     {
         m_PostProcessValuesMetric = DatasetCapture.RegisterMetricDefinition(
             "random post processing",
             description: "Some post-processing parameters are randomized each frame. These are the per-frame values used.",
             id: k_PostProcessValuesMetricId);
     }
 }
        public IEnumerator ResetSimulation_ResetsCaptureDeltaTime()
        {
            var ego = DatasetCapture.RegisterEgo("ego");

            DatasetCapture.RegisterSensor(ego, "cam", "", 0, CaptureTriggerMode.Scheduled, 5, 0);
            yield return(null);

            Assert.AreEqual(5, Time.captureDeltaTime);
            DatasetCapture.ResetSimulation();
            Assert.AreEqual(0, Time.captureDeltaTime);
        }
Beispiel #15
0
        public IEnumerator ResetSimulation_ResetsCaptureDeltaTime()
        {
            var ego = DatasetCapture.RegisterEgo("ego");

            DatasetCapture.RegisterSensor(ego, "cam", "", 4, 10);
            yield return(null);

            Assert.AreEqual(10, Time.captureDeltaTime);
            DatasetCapture.ResetSimulation();
            Assert.AreEqual(0, Time.captureDeltaTime);
        }
    // Initialize your operator here
    protected override void OnCreate()
    {
        m_Rand                         = new Random(1);
        m_ForegroundLayer              = LayerMask.NameToLayer("Foreground");
        m_ParentForeground             = new GameObject("ForegroundContainer");
        m_ParentBackgroundInForeground = new GameObject("BackgroundInForegroundContainer");
        m_OccludingLayer               = LayerMask.NameToLayer("Occluding");
        m_ParentOccluding              = new GameObject("OccludingContainer");

        m_CurriculumQuery = EntityManager.CreateEntityQuery(typeof(CurriculumState));
        m_ForegroundPlacementInfoDefinition = DatasetCapture.RegisterMetricDefinition("foreground placement info", description: "Info about each object placed in the foreground layer. Currently only includes label and orientation.", id: new Guid(k_ForegroundPlacementInfoMetricGuid));
    }
Beispiel #17
0
        public IEnumerator ChangingTimeScale_DuringStartNewSequence_Succeeds()
        {
            var ego = DatasetCapture.RegisterEgo("ego");

            DatasetCapture.RegisterSensor(ego, "cam", "", 1f, 2f);

            yield return(null);

            Time.timeScale = 1;
            DatasetCapture.StartNewSequence();
            yield return(null);
        }
 public void Start()
 {
     //Metrics and annotations are registered up-front
     lightMetricDefinition = DatasetCapture.RegisterMetricDefinition(
         "Light position",
         "The world-space position of the light",
         Guid.Parse("1F6BFF46-F884-4CC5-A878-DB987278FE35"));
     boundingBoxAnnotationDefinition = DatasetCapture.RegisterAnnotationDefinition(
         "Target bounding box",
         "The position of the target in the camera's local space",
         id: Guid.Parse("C0B4A22C-0420-4D9F-BAFC-954B8F7B35A7"));
 }
Beispiel #19
0
        /// <summary>
        /// Start is called after Awake but before the first Update method call
        /// </summary>
        protected virtual void Start()
        {
            var randomSeedMetricDefinition = DatasetCapture.RegisterMetricDefinition(
                "random-seed",
                "The random seed used to initialize the random state of the simulation. Only triggered once per simulation.",
                Guid.Parse("14adb394-46c0-47e8-a3f0-99e754483b76"));

            DatasetCapture.ReportMetric(randomSeedMetricDefinition, new[] { genericConstants.randomSeed });
#if !UNITY_EDITOR
            DeserializeFromFile();
#endif
        }
Beispiel #20
0
        public IEnumerator SimpleData_GeneratesFullDataset_OnExitPlaymode()
        {
            yield return(new EnterPlayMode());

            var ego    = DatasetCapture.RegisterEgo("ego");
            var sensor = DatasetCapture.RegisterSensor(ego, "camera", "", 0.1f, 0);

            sensor.ReportCapture("file.txt", new SensorSpatialData());
            expectedDatasetPath = DatasetCapture.OutputDirectory;
            yield return(new ExitPlayMode());

            FileAssert.Exists(Path.Combine(expectedDatasetPath, "sensors.json"));
        }
Beispiel #21
0
        public IEnumerator ChangingTimeScale_CausesDebugError()
        {
            var ego = DatasetCapture.RegisterEgo("ego");

            DatasetCapture.RegisterSensor(ego, "cam", "", 1f, 2f);

            yield return(null);

            Time.timeScale = 5;
            yield return(null);

            LogAssert.Expect(LogType.Error, new Regex("Time\\.timeScale may not change mid-sequence.*"));
        }
 protected override void OnAwake()
 {
     m_ForegroundObjectPlacementMetricDefinition = DatasetCapture.RegisterMetricDefinition("Per Frame Foreground Object Placement Info", $"Reports the world position, scale, rotation, and label id of objects carrying a {nameof(ForegroundObjectMetricReporterTag)} component.", new Guid(k_LayerOneForegroundObjectPlacementInfoMetricGuid));
     m_LabelingComponentsCache = new Dictionary <GameObject, Labeling>();
     if (labelConfigForObjectPlacementMetrics == null)
     {
         var perceptionCamera = Object.FindObjectOfType <PerceptionCamera>();
         if (perceptionCamera && perceptionCamera.labelers.Count > 0 && perceptionCamera.labelers[0] is BoundingBox2DLabeler boundingBox2DLabeler)
         {
             labelConfigForObjectPlacementMetrics = boundingBox2DLabeler.idLabelConfig;
         }
     }
 }
Beispiel #23
0
        public void TearDown()
        {
            foreach (var o in m_ObjectsToDestroy)
            {
                Object.DestroyImmediate(o);
            }

            m_ObjectsToDestroy.Clear();

            DatasetCapture.ResetSimulation();
            Time.timeScale = 1;
            if (Directory.Exists(DatasetCapture.OutputDirectory))
            {
                Directory.Delete(DatasetCapture.OutputDirectory, true);
            }
        }
Beispiel #24
0
        public IEnumerator ShouldCaptureThisFrame_ReturnsTrueOnProperFrames()
        {
            var ego = DatasetCapture.RegisterEgo("ego");
            var firstCaptureTime1 = 10;
            var frequencyInMs1    = 4;
            var sensor1           = DatasetCapture.RegisterSensor(ego, "cam", "1", frequencyInMs1, firstCaptureTime1);

            var firstCaptureTime2 = 10;
            var frequencyInMs2    = 6;
            var sensor2           = DatasetCapture.RegisterSensor(ego, "cam", "2", frequencyInMs2, firstCaptureTime2);

            var sensor3 = DatasetCapture.RegisterSensor(ego, "cam", "3", 1, 1);

            sensor3.Enabled = false;

            (float deltaTime, bool sensor1ShouldCapture, bool sensor2ShouldCapture)[] samplesExpected =
        public IEnumerator EnableBoundingBoxes_GeneratesCorrectDataset()
        {
            //set resolution to ensure we don't have rounding in rendering leading to bounding boxes to change height/width
            Screen.SetResolution(400, 400, false);
            //give the screen a chance to resize
            yield return(null);

            var jsonExpected          = $@"[
            {{
              ""label_id"": 100,
              ""label_name"": ""label"",
              ""instance_id"": 1,
              ""x"": 0.0,
              ""y"": {Screen.height / 4:F1},
              ""width"": {Screen.width:F1},
              ""height"": {Screen.height / 2:F1}
            }}
          ]";
            var labelingConfiguration = CreateLabelingConfiguration();

            SetupCamera(pc =>
            {
                pc.AddLabeler(new BoundingBox2DLabeler(labelingConfiguration));
            });

            var plane = TestHelper.CreateLabeledPlane();

            AddTestObjectForCleanup(plane);
            //a plane is 10x10 by default, so scale it down to be 10x1 to cover the center half of the image
            plane.transform.localScale    = new Vector3(10f, -1f, .1f);
            plane.transform.localPosition = new Vector3(0, 0, 10);

            var plane2 = TestHelper.CreateLabeledPlane(label: "nonmatching");

            AddTestObjectForCleanup(plane2);
            //place a smaller plane in front to test non-matching objects
            plane2.transform.localScale    = new Vector3(.1f, -1f, .1f);
            plane2.transform.localPosition = new Vector3(0, 0, 5);
            yield return(null);

            DatasetCapture.ResetSimulation();

            var capturesPath = Path.Combine(DatasetCapture.OutputDirectory, "captures_000.json");
            var capturesJson = File.ReadAllText(capturesPath);

            StringAssert.Contains(TestHelper.NormalizeJson(jsonExpected, true), TestHelper.NormalizeJson(capturesJson, true));
        }
        public IEnumerator SequenceTimeOfNextCapture_WithInBetweenFrames_ReportsCorrectTime()
        {
            var ego = DatasetCapture.RegisterEgo("ego");
            var firstCaptureFrame     = 2;
            var simulationDeltaTime   = .4f;
            var framesBetweenCaptures = 2;
            var sensorHandle          = DatasetCapture.RegisterSensor(ego, "cam", "", firstCaptureFrame, CaptureTriggerMode.Scheduled, simulationDeltaTime, framesBetweenCaptures);
            var startingFrame         = Time.frameCount;

            var startTime = firstCaptureFrame * simulationDeltaTime;
            var interval  = (framesBetweenCaptures + 1) * simulationDeltaTime;

            float[] sequenceTimesExpected =
            {
                startTime,
                interval + startTime,
                interval * 2 + startTime,
                interval * 3 + startTime
            };

            int[] simulationFramesToCheck =
            {
                firstCaptureFrame,
                firstCaptureFrame + (framesBetweenCaptures + 1),
                firstCaptureFrame + (framesBetweenCaptures + 1) * 2,
                firstCaptureFrame + (framesBetweenCaptures + 1) * 3,
            };

            int checkedFrame    = 0;
            var currentSimFrame = Time.frameCount - startingFrame;

            while (currentSimFrame <= simulationFramesToCheck[simulationFramesToCheck.Length - 1] && checkedFrame < simulationFramesToCheck.Length)
            {
                currentSimFrame = Time.frameCount - startingFrame;
                if (currentSimFrame == simulationFramesToCheck[checkedFrame])
                {
                    var sensorData         = m_TestHelper.GetSensorData(sensorHandle);
                    var sequenceTimeActual = m_TestHelper.CallSequenceTimeOfNextCapture(sensorData);
                    Assert.AreEqual(sequenceTimesExpected[checkedFrame], sequenceTimeActual, 0.0001f);
                    checkedFrame++;
                }
                else
                {
                    yield return(null);
                }
            }
        }
Beispiel #27
0
        public IEnumerator EditorPause_DoesNotLogErrors()
        {
            ResetScene();
            var cameraObject = SetupCamera(p =>
            {
                var idLabelConfig  = ScriptableObject.CreateInstance <IdLabelConfig>();
                p.captureRgbImages = true;
                p.AddLabeler(new BoundingBox2DLabeler(idLabelConfig));
                p.AddLabeler(new RenderedObjectInfoLabeler(idLabelConfig));
            });

            cameraObject.name = "Camera";
            yield return(new EnterPlayMode());

            var expectedFirstFrame = Time.frameCount;

            yield return(null);

            EditorApplication.isPaused = true;
            //Wait a few editor frames to ensure the issue has a chance to trigger.
            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            EditorApplication.isPaused = false;
            var expectedLastFrame = Time.frameCount;

            yield return(null);

            DatasetCapture.ResetSimulation();

            var capturesPath = Path.Combine(DatasetCapture.OutputDirectory, "captures_000.json");
            var capturesJson = File.ReadAllText(capturesPath);

            for (int iFrameCount = expectedFirstFrame; iFrameCount <= expectedLastFrame; iFrameCount++)
            {
                var imagePath = $"{GameObject.Find("Camera").GetComponent<PerceptionCamera>().rgbDirectory}/rgb_{iFrameCount}";
                StringAssert.Contains(imagePath, capturesJson);
            }

            yield return(new ExitPlayMode());
        }
Beispiel #28
0
        public void RegisterSensor_ReportsProperJson()
        {
            var egoDescription    = @"the main car driving in simulation";
            var sensorDescription = "Cam (FL2-14S3M-C)";
            var modality          = "camera";

            var egoJsonExpected =
                $@"{{
  ""version"": ""{DatasetCapture.SchemaVersion}"",
  ""egos"": [
    {{
      ""id"": <guid>,
      ""description"": ""{egoDescription}""
    }}
  ]
}}";
            var sensorJsonExpected =
                $@"{{
  ""version"": ""{DatasetCapture.SchemaVersion}"",
  ""sensors"": [
    {{
      ""id"": <guid>,
      ""ego_id"": <guid>,
      ""modality"": ""{modality}"",
      ""description"": ""{sensorDescription}""
    }}
  ]
}}";

            var ego          = DatasetCapture.RegisterEgo(egoDescription);
            var sensorHandle = DatasetCapture.RegisterSensor(ego, modality, sensorDescription, 1, 1);

            Assert.IsTrue(sensorHandle.IsValid);
            DatasetCapture.ResetSimulation();
            Assert.IsFalse(sensorHandle.IsValid);

            var sensorsPath = Path.Combine(DatasetCapture.OutputDirectory, "sensors.json");
            var egosPath    = Path.Combine(DatasetCapture.OutputDirectory, "egos.json");

            FileAssert.Exists(egosPath);
            FileAssert.Exists(sensorsPath);

            AssertJsonFileEquals(egoJsonExpected, egosPath);
            AssertJsonFileEquals(sensorJsonExpected, sensorsPath);
        }
        public IEnumerator StepFunction_OverridesSimulationDeltaTime_AndRunsSensors()
        {
            yield return(new EnterPlayMode());

            DatasetCapture.ResetSimulation();
            var ego    = DatasetCapture.RegisterEgo("ego");
            var sensor = DatasetCapture.RegisterSensor(ego, "camera", "", 0, CaptureTriggerMode.Scheduled, 2f, 0);

            yield return(null);

            var timeBeforeStep = Time.time;

            EditorApplication.isPaused = true;
            EditorApplication.Step();
            Assert.True(Time.time - timeBeforeStep < .3f);
            Assert.True(sensor.ShouldCaptureThisFrame);
            yield return(new ExitPlayMode());
        }
        public IEnumerator ShouldCaptureFlagsAndRenderTimesAreCorrectWithMultipleSensors()
        {
            var ego = DatasetCapture.RegisterEgo("ego");
            var firstCaptureFrame1     = 2;
            var simDeltaTime1          = 4;
            var framesBetweenCaptures1 = 2;
            var sensor1 = DatasetCapture.RegisterSensor(ego, "cam", "1", firstCaptureFrame1, CaptureTriggerMode.Scheduled, simDeltaTime1, framesBetweenCaptures1);

            var firstCaptureFrame2     = 1;
            var simDeltaTime2          = 6;
            var framesBetweenCaptures2 = 1;
            var sensor2 = DatasetCapture.RegisterSensor(ego, "cam", "2", firstCaptureFrame2, CaptureTriggerMode.Scheduled, simDeltaTime2, framesBetweenCaptures2);

            //Third sensor is a manually triggered one. All it does in this test is affect delta times.
            var simDeltaTime3 = 5;
            var sensor3       = DatasetCapture.RegisterSensor(ego, "cam", "3", 0, CaptureTriggerMode.Manual, simDeltaTime3, 0, true);

            (float deltaTime, bool sensor1ShouldCapture, bool sensor2ShouldCapture, bool sensor3ShouldCapture)[] samplesExpected =