public static Vector3 GetRandomWorldPosistionInBoundaryClosest(GameObject element, GameObject container, GameObject target)
    {
        DatasetObjectInfo elementInfo    = element.GetComponent <DatasetObjectInfo>();
        DatasetObjectInfo containterInfo = container.GetComponent <DatasetObjectInfo>();
        DatasetObjectInfo targetInfo     = target.GetComponent <DatasetObjectInfo>();
        var elementSize  = elementInfo.GetBoundarySize();
        var containerMin = containterInfo.GetMinBoundaryPoint();
        var containerMax = containterInfo.GetMaxBoundaryPoint();

        Vector3 transformedCenterOffset = element.transform.TransformDirection(elementInfo.center);
        Vector3 currentElementPosition  = element.transform.position;

        float x = Random.Range(containerMin.x + elementSize.x / 2f - transformedCenterOffset.x, containerMax.x - elementSize.x / 2f - transformedCenterOffset.x);
        float y = Random.Range(containerMin.y + elementSize.y / 2f - transformedCenterOffset.y, containerMax.y - elementSize.y / 2f - transformedCenterOffset.y);
        float z = Random.Range(containerMin.z + elementSize.z / 2f - transformedCenterOffset.z, containerMax.z - elementSize.z / 2f - transformedCenterOffset.z);

        if (-(containerMin.y + elementSize.y / 2f - transformedCenterOffset.y) + (containerMax.y - elementSize.y / 2f - transformedCenterOffset.y) < 0)
        {
            y = containerMin.y + elementSize.y / 2f - transformedCenterOffset.y;
        }

        Vector3 endPoint = target.transform.TransformPoint(targetInfo.testPoints[Random.Range(0, targetInfo.testPoints.Count)]);
        float   t        = 0f;

        float p = 0f, k = 1f, s;

        for (int i = 0; i < 10; i++)//Bin search
        {
            s = (p + k) / 2f;
            element.transform.position = Vector3.Lerp(new Vector3(x, y, z), endPoint, s);
            if (!BoundaryIsColliding(element, target) && IsInside(element, container))
            {
                p = s;
                t = s;
            }
            else
            {
                k = s;
                t = p;
            }
        }
        float offset = Settings.config.datasetOptions.closestMaxDistanceOffset;

        float dt = 1f / (new Vector3(x, y, z) - endPoint).magnitude * offset * Random.value;

        element.transform.position = Vector3.Lerp(new Vector3(x, y, z), endPoint, t - dt);
        if (!BoundaryIsColliding(element, target) && IsInside(element, container))
        {
            element.transform.position = currentElementPosition;
            return(Vector3.Lerp(new Vector3(x, y, z), endPoint, t - dt));
        }
        else
        {
            element.transform.position = currentElementPosition;
            return(Vector3.Lerp(new Vector3(x, y, z), endPoint, t));
        }
    }
    public static bool AreColliding(GameObject elementA, GameObject elementB)
    {//TODO CHECK
        DatasetObjectInfo infoA = elementA.GetComponent <DatasetObjectInfo>();
        DatasetObjectInfo infoB = elementB.GetComponent <DatasetObjectInfo>();

        Vector3 aMin = infoA.GetMinBoundaryPoint();
        Vector3 aMax = infoA.GetMaxBoundaryPoint();
        Vector3 bMin = infoB.GetMinBoundaryPoint();
        Vector3 bMax = infoB.GetMaxBoundaryPoint();

        return((aMin.x <= bMax.x && aMax.x >= bMin.x) &&
               (aMin.y <= bMax.y && aMax.y >= bMin.y) &&
               (aMin.z <= bMax.z && aMax.z >= bMin.z));
    }
    public static Vector3 GetRandomWorldPosistionInBoundary(GameObject element, GameObject container)
    {
        DatasetObjectInfo elementInfo    = element.GetComponent <DatasetObjectInfo>();
        DatasetObjectInfo containterInfo = container.GetComponent <DatasetObjectInfo>();
        var elementSize  = elementInfo.GetBoundarySize();
        var containerMin = containterInfo.GetMinBoundaryPoint();
        var containerMax = containterInfo.GetMaxBoundaryPoint();

        Vector3 transformedCenterOffset = element.transform.TransformDirection(elementInfo.center);
        float   x = Random.Range(containerMin.x + elementSize.x / 2f - transformedCenterOffset.x, containerMax.x - elementSize.x / 2f - transformedCenterOffset.x);
        float   y = Random.Range(containerMin.y + elementSize.y / 2f - transformedCenterOffset.y, containerMax.y - elementSize.y / 2f - transformedCenterOffset.y);
        float   z = Random.Range(containerMin.z + elementSize.z / 2f - transformedCenterOffset.z, containerMax.z - elementSize.z / 2f - transformedCenterOffset.z);

        if (-(containerMin.y + elementSize.y / 2f - transformedCenterOffset.y) + (containerMax.y - elementSize.y / 2f - transformedCenterOffset.y) < 0)
        {
            y = containerMin.y + elementSize.y / 2f - transformedCenterOffset.y;
        }
        return(new Vector3(x, y, z));
    }
    public static bool BoundaryIsColliding(GameObject boundaryObject, GameObject pointObject)
    {
        DatasetObjectInfo boundaryInfo = boundaryObject.GetComponent <DatasetObjectInfo>();
        DatasetObjectInfo pointInfo    = pointObject.GetComponent <DatasetObjectInfo>();
        Vector3           aMin         = boundaryInfo.GetMinBoundaryPoint();
        Vector3           aMax         = boundaryInfo.GetMaxBoundaryPoint();

        foreach (var pointRaw in pointInfo.testPoints)
        {
            var point = pointObject.transform.TransformPoint(pointRaw);
            if ((aMin.x <= point.x && aMax.x >= point.x) &&
                (aMin.y <= point.y && aMax.y >= point.y) &&
                (aMin.z <= point.z && aMax.z >= point.z))
            {
                return(true);
            }
        }
        return(false);
    }
    public static Vector3 GetRandomWorldPosistionInBoundary(GameObject element, GameObject container, GameObject target)
    {
        DatasetObjectInfo elementInfo    = element.GetComponent <DatasetObjectInfo>();
        DatasetObjectInfo containterInfo = container.GetComponent <DatasetObjectInfo>();
        var elementSize  = elementInfo.GetBoundarySize();
        var containerMin = containterInfo.GetMinBoundaryPoint();
        var containerMax = containterInfo.GetMaxBoundaryPoint();

        Vector3        transformedCenterOffset = element.transform.TransformDirection(elementInfo.center);
        List <Vector3> positions          = new List <Vector3>(10);
        List <float>   distancesToElement = new List <float>(positions.Count);

        for (int i = 0; i < positions.Capacity; i++)
        {
            float x = Random.Range(containerMin.x + elementSize.x / 2f - transformedCenterOffset.x, containerMax.x - elementSize.x / 2f - transformedCenterOffset.x);
            float y = Random.Range(containerMin.y + elementSize.y / 2f - transformedCenterOffset.y, containerMax.y - elementSize.y / 2f - transformedCenterOffset.y);
            float z = Random.Range(containerMin.z + elementSize.z / 2f - transformedCenterOffset.z, containerMax.z - elementSize.z / 2f - transformedCenterOffset.z);
            if (-(containerMin.y + elementSize.y / 2f - transformedCenterOffset.y) + (containerMax.y - elementSize.y / 2f - transformedCenterOffset.y) < 0)
            {
                y = containerMin.y + elementSize.y / 2f - transformedCenterOffset.y;
            }
            positions.Add(new Vector3(x, y, z));
            distancesToElement.Add((target.transform.position - positions[positions.Count - 1]).sqrMagnitude);
        }

        int   index            = -1;
        float smallestDistance = Mathf.Infinity;

        for (int i = 0; i < distancesToElement.Count; i++)
        {
            if (distancesToElement[i] < smallestDistance)
            {
                index            = i;
                smallestDistance = distancesToElement[i];
            }
        }

        return(positions[index]);
    }
Beispiel #6
0
    public void PlaceRobotInStartZone()
    {
        var startZones = GameObject.FindGameObjectsWithTag("StartZone");

        if (startZones.Length > 0)
        {
            System.Random r         = new System.Random();
            int           i         = r.Next(0, startZones.Length);
            var           startZone = startZones[i];

            DatasetObjectInfo elementInfo = robot.GetComponent <DatasetObjectInfo>();
            var elementSize = elementInfo.GetBoundarySize();
            var bounds      = startZone.GetComponent <Collider>().bounds;

            var containerMin = bounds.min;
            var containerMax = bounds.max;

            Vector3 transformedCenterOffset = robot.transform.TransformDirection(elementInfo.center);
            float   x = Random.Range(containerMin.x + elementSize.x / 2f - transformedCenterOffset.x, containerMax.x - elementSize.x / 2f - transformedCenterOffset.x);
            float   y = Random.Range(containerMin.y + elementSize.y / 2f - transformedCenterOffset.y, containerMax.y - elementSize.y / 2f - transformedCenterOffset.y);
            float   z = Random.Range(containerMin.z + elementSize.z / 2f - transformedCenterOffset.z, containerMax.z - elementSize.z / 2f - transformedCenterOffset.z);
            if (-(containerMin.y + elementSize.y / 2f - transformedCenterOffset.y) + (containerMax.y - elementSize.y / 2f - transformedCenterOffset.y) < 0)
            {
                y = containerMin.y + elementSize.y / 2f - transformedCenterOffset.y;
            }
            robot.transform.position = new Vector3(x, 1, z);
            float direction = startZone.GetComponent <StartZoneController>().angle;
            float fov       = startZone.GetComponent <StartZoneController>().fov;
            robot.transform.rotation = Quaternion.Euler(0, Random.Range(direction - fov / 2, direction + fov / 2), 0);
        }

        foreach (var cp in GameObject.FindGameObjectsWithTag("Checkpoint"))
        {
            cp.GetComponent <CheckpointController>().reached = false;
        }

        robotController.rb.velocity        = Vector3.zero;
        robotController.rb.angularVelocity = Vector3.zero;
    }
    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();
        DatasetObjectInfo script = (DatasetObjectInfo)target;

        if (GUILayout.Button("Clear test points") && EditorUtility.DisplayDialog("Confirmation", "Do you want to clear test points?", "Clear", "Cancel"))
        {
            script.testPoints = null;
        }

        if (GUILayout.Button("Regenerate uniform points") && EditorUtility.DisplayDialog("Confirmation", "Do you want to regenerate?", "Regenerate", "Cancel"))
        {
            script.GenerateTestPointsUniform(script.testPointsNum);
            EditorUtility.DisplayDialog("Generation", "Done regenerating test points", "0k");
        }

        if (GUILayout.Button("Regenerate non-uniform points") && EditorUtility.DisplayDialog("Confirmation", "Do you want to regenerate?", "Regenerate", "Cancel"))
        {
            script.GenerateTestPointsNonUniform(script.testPointsNum);
            EditorUtility.DisplayDialog("Generation", "Done regenerating test points", "0k");
        }

        if (script.testPoints == null || script.testPoints.Count == 0)
        {
            EditorGUILayout.HelpBox("Test points should be generated", MessageType.Info);
        }

        int triangles = 0;

        foreach (MeshFilter meshFilter in script.gameObject.GetComponentsInChildren <MeshFilter>())
        {
            triangles += meshFilter.sharedMesh.triangles.Length;
        }
        if (triangles > 9000)
        {
            EditorGUILayout.HelpBox("Triangles count over 9000: " + triangles + "\nPregeneration is essential!", MessageType.Warning);
        }
    }
    public static bool IsInside(GameObject element, GameObject container)
    {
        DatasetObjectInfo elementInfo    = element.GetComponent <DatasetObjectInfo>();
        DatasetObjectInfo containterInfo = container.GetComponent <DatasetObjectInfo>();
        var elementSize  = elementInfo.GetBoundarySize();
        var containerMin = containterInfo.GetMinBoundaryPoint();
        var containerMax = containterInfo.GetMaxBoundaryPoint();

        Vector3 transformedCenterOffset = element.transform.TransformDirection(elementInfo.center);
        Vector3 currentElementPosition  = element.transform.position;

        float x = element.transform.position.x;
        float y = element.transform.position.y;
        float z = element.transform.position.z;

        float minX = containerMin.x + elementSize.x / 2f - transformedCenterOffset.x;
        float maxX = containerMax.x - elementSize.x / 2f - transformedCenterOffset.x;
        float minY = containerMin.y + elementSize.y / 2f - transformedCenterOffset.y;
        float maxY = containerMax.y - elementSize.y / 2f - transformedCenterOffset.y;
        float minZ = containerMin.z + elementSize.z / 2f - transformedCenterOffset.z;
        float maxZ = containerMax.z - elementSize.z / 2f - transformedCenterOffset.z;

        return(x >= minX && x <= maxX && y >= minY && y <= maxY && z >= minZ && z <= maxZ);
    }
    void Update()
    {
        if (debugWaitedFrames++ == debugNumFramesToWait)
        {
            debugWaitedFrames = 0;
        }
        else
        {
            return;
        }

        if (Settings.config.datasetOptions.debugOptions.drawDetectionRect)
        {
            cameraObject.GetComponent <DetectionRectDraw>().doDrawRect = true;
        }

        switch (generationState)
        {
        case GenerationState.SingleObjectsSetup:
        {
            ClearSceneFromObjects();
            if (Settings.config.datasetOptions.classObstacleFrameNum == 0 && Settings.config.datasetOptions.classDetectedFrameNum == 0)
            {
                generationState = GenerationState.MultipleObjectsSetup;
                return;
            }
            Instantiate(selectedObjects[currentObjectIndex]);
            Debug.Log("Clearing scene for S.O. Creating object index: " + currentObjectIndex);
            generationState = GenerationState.SingleObjects;

            var info = selectedObjects[currentObjectIndex].GetComponent <DatasetObjectInfo>();
            if (IncludeInDataset(selectedObjects[currentObjectIndex]))
            {
                counter = Settings.config.datasetOptions.classDetectedFrameNum / objectsNumInClass[info.className];
            }
            else
            {
                counter = Settings.config.datasetOptions.classObstacleFrameNum * Settings.config.datasetOptions.classNames.Count / objectsNumInClass["OBSTACLE"];
            }

            for (int i = 0; i < selectedObjects.Count; i++)
            {
                string className = selectedObjects[i].GetComponent <DatasetObjectInfo>().className;
                if (IncludeInDataset(selectedObjects[i]))
                {
                    Directory.CreateDirectory(Settings.config.datasetOptions.datasetDirPath + @"\" + className);
                }
                else
                {
                    Directory.CreateDirectory(Settings.config.datasetOptions.datasetDirPath + @"\" + "obstacle");
                }
            }

            break;
        }

        case GenerationState.SingleObjects:
        {
            GameObject singleObject = GameObject.FindGameObjectWithTag("ToDetect");
            string     className    = singleObject.GetComponent <DatasetObjectInfo>().className;
            if (!IncludeInDataset(singleObject))
            {
                className = "obstacle";
            }


            singleObject.transform.rotation = Quaternion.Euler(Random.Range(0f, 360f), Random.Range(0f, 360f), Random.Range(0f, 0f));
            singleObject.transform.position = DatasetObjectInfo.GetRandomWorldPosistionInBoundary(singleObject, selectedWaterContainer);
            if (Random.value < Settings.config.datasetOptions.percentClosest)
            {
                cameraObject.transform.position = DatasetObjectInfo.GetRandomWorldPosistionInBoundaryClosest(cameraObject, selectedWaterContainer, singleObject);
            }
            else
            {
                cameraObject.transform.position = DatasetObjectInfo.GetRandomWorldPosistionInBoundary(cameraObject, selectedWaterContainer);
            }
            LookAtTargetRandomly(singleObject, cameraObject, Settings.config.datasetOptions.cameraLookAtObjectPitchOffset, Settings.config.datasetOptions.cameraLookAtObjectYawOffset, Settings.config.datasetOptions.cameraLookAtObjectRollOffset);

            var detector = new Detector();
            detector.Detect(cameraObject.GetComponent <Camera>());
            if (detector.detection[0].visible &&
                detector.detection[0].fill >= Settings.config.datasetOptions.minObjectFill &&
                (singleObject.transform.position - cameraObject.transform.position).magnitude >= Settings.config.datasetOptions.minCameraDistanceToObject &&
                (singleObject.transform.position - cameraObject.transform.position).magnitude <= Settings.config.datasetOptions.maxCameraDistanceToObject &&
                !DatasetObjectInfo.BoundaryIsColliding(cameraObject, singleObject))
            {
                string datasetRootPath = Settings.config.datasetOptions.datasetDirPath;

                string txtFileName   = datasetRootPath + @"/" + className + @"/" + createdFramesPerClass[className].ToString() + ".txt";
                string pngFileName   = datasetRootPath + @"/" + className + @"/" + createdFramesPerClass[className].ToString() + ".png";
                string trainFileName = datasetRootPath + @"/train.txt";
                if (IncludeInDataset(detector.detection[0].gameObject))
                {
                    File.WriteAllText(txtFileName, detector.detection[0].GetTextInfo());
                }
                else
                {
                    File.WriteAllText(txtFileName, "");
                }
                File.AppendAllText(trainFileName, pngFileName + System.Environment.NewLine);
                if (!Settings.config.datasetOptions.debugOptions.disableScreenshot)
                {
                    ScreenCapture.CaptureScreenshot(System.IO.Directory.GetCurrentDirectory() + "/" + pngFileName);
                }
                createdFramesPerClass[className]++;
                // Debug.Log("detected " + createdFramesPerClass[className] + "/" + Settings.config.datasetOptions.objectVisibleFrameNum * selectedObjects.Count);
                Debug.Log("detected " + createdFramesPerClass[className] + "/" + 7 * selectedObjects.Count);
                createdTypeFrames++;
                counter--;
                if (Settings.config.datasetOptions.debugOptions.logDetection)
                {
                    File.AppendAllText(datasetRootPath + @"/log.dat", detector.detection[0].distance + " " + detector.detection[0].fill + System.Environment.NewLine);
                }
            }

            StartCoroutine(RandomizeGraphics(cameraObject.GetComponent <Camera>()));



            if (counter <= 0)
            {
                Debug.Log("Finished object index:" + currentObjectIndex + "  " + (currentObjectIndex + 1) + "/" + selectedObjects.Count);
                generationState = GenerationState.SingleObjectsSetup;
                if (++currentObjectIndex >= selectedObjects.Count)
                {
                    Debug.Log("Finished all single objects");
                    generationState = GenerationState.MultipleObjectsSetup;
                }
            }
        }
        break;

        case GenerationState.MultipleObjectsSetup:
        {
            ClearSceneFromObjects();
            // if (Settings.config.datasetOptions.objectMultipleFrameNum == 0)

            /*   if (1 == 0)
             * {
             *     generationState = GenerationState.NoObjectsSetup;
             *     return; TODO
             * }*/
            Debug.Log("Cleared scene for M.O.");
            randomObjectsInScene = new List <GameObject>();
            int TODOrandomObjectsNum = 20;
            for (int i = 0; i < TODOrandomObjectsNum; i++)
            {
                var randomObject = Instantiate(selectedObjects[Random.Range(0, selectedObjects.Count)]);
                randomObject.transform.rotation = Quaternion.Euler(Random.Range(0f, 360f), Random.Range(0f, 360f), Random.Range(0f, 0f));
                randomObject.transform.position = DatasetObjectInfo.GetRandomWorldPosistionInBoundary(randomObject, selectedWaterContainer);
                randomObjectsInScene.Add(randomObject);
            }
            counter = Settings.config.datasetOptions.classMultipleFrameNum * Settings.config.datasetOptions.classNames.Count;
            if (!Directory.Exists(Settings.config.datasetOptions.datasetDirPath + @"/multiple"))
            {
                Directory.CreateDirectory(Settings.config.datasetOptions.datasetDirPath + @"/multiple");
            }
            generationState = GenerationState.MultipleObjects;
        }
        break;

        case GenerationState.MultipleObjects:
        {
            if (counter <= 0)
            {
                generationState = GenerationState.NoObjectsSetup;
                return;
            }
            //
            int detectedVisibleObjectsNum = 0;
            foreach (var obj in randomObjectsInScene)
            {
                obj.SetActive(Random.value > 0.5f);
                if (!obj.activeSelf)
                {
                    continue;
                }
                obj.transform.rotation = Quaternion.Euler(Random.Range(0f, 360f), Random.Range(0f, 360f), Random.Range(0f, 0f));
                obj.transform.position = DatasetObjectInfo.GetRandomWorldPosistionInBoundary(obj, selectedWaterContainer);
            }

            cameraObject.transform.position = DatasetObjectInfo.GetRandomWorldPosistionInBoundary(cameraObject, selectedWaterContainer);
            LookRandomly(cameraObject, 20f, 180f, 30f);
            StartCoroutine(RandomizeGraphics(cameraObject.GetComponent <Camera>()));
            var detector = new Detector();

            string detectedObjectsText = "";
            foreach (var info in detector.Detect(cameraObject.GetComponent <Camera>()))
            {
                if (!info.visible ||
                    info.fill < Settings.config.datasetOptions.minObjectFill ||
                    DatasetObjectInfo.BoundaryIsColliding(cameraObject, info.gameObject))
                {
                    continue;                                                                              //TODO sprawdz nową kolizję
                }
                if (IncludeInDataset(info.gameObject))
                {
                    detectedObjectsText += info.GetTextInfo() + System.Environment.NewLine;
                }
                detectedVisibleObjectsNum++;
            }

            if (detectedVisibleObjectsNum >= Settings.config.datasetOptions.minVisibleMultipleObjectsNum)
            {
                string datasetRootPath = Settings.config.datasetOptions.datasetDirPath;
                string txtFileName     = datasetRootPath + @"/" + "multiple" + @"/" + createdFramesPerClass["multiple"].ToString() + ".txt";
                string pngFileName     = datasetRootPath + @"/" + "multiple" + @"/" + createdFramesPerClass["multiple"].ToString() + ".png";
                string trainFileName   = datasetRootPath + @"/train.txt";
                File.WriteAllText(txtFileName, detectedObjectsText);
                File.AppendAllText(trainFileName, pngFileName + System.Environment.NewLine);
                ScreenCapture.CaptureScreenshot(System.IO.Directory.GetCurrentDirectory() + "/" + pngFileName);
                createdFramesPerClass["multiple"]++;
                counter--;
            }
            break;
        }

        case GenerationState.NoObjectsSetup:
        {
            ClearSceneFromObjects();
            if (Settings.config.datasetOptions.classBlankFrameNum == 0)
            {
                generationState = GenerationState.Finished;
                return;
            }
            counter         = Settings.config.datasetOptions.classBlankFrameNum * Settings.config.datasetOptions.classNames.Count;
            generationState = GenerationState.NoObjects;
            if (!Directory.Exists(Settings.config.datasetOptions.datasetDirPath + @"/blank"))
            {
                Directory.CreateDirectory(Settings.config.datasetOptions.datasetDirPath + @"/blank");
            }
            break;
        }

        case GenerationState.NoObjects:
        {
            StartCoroutine(RandomizeGraphics(cameraObject.GetComponent <Camera>()));
            cameraObject.transform.position = DatasetObjectInfo.GetRandomWorldPosistionInBoundary(cameraObject, selectedWaterContainer);
            LookRandomly(cameraObject, Settings.config.datasetOptions.cameraLookRandomlyPitchOffset, Random.Range(0f, 360f), Settings.config.datasetOptions.cameraLookRandomlyRollOffset);

            string datasetRootPath = Settings.config.datasetOptions.datasetDirPath;
            string txtFileName     = datasetRootPath + @"/" + "blank" + @"/" + createdFramesPerClass["blank"].ToString() + ".txt";
            string pngFileName     = datasetRootPath + @"/" + "blank" + @"/" + createdFramesPerClass["blank"].ToString() + ".png";
            string trainFileName   = datasetRootPath + @"/train.txt";
            File.WriteAllText(txtFileName, "");
            File.AppendAllText(trainFileName, pngFileName + System.Environment.NewLine);
            ScreenCapture.CaptureScreenshot(System.IO.Directory.GetCurrentDirectory() + "/" + pngFileName);
            createdFramesPerClass["blank"]++;
        }
            // if (createdFramesPerClass["blank"] >= Settings.config.datasetOptions.objectBlankFrameNum)
            if (--counter <= 0)
            {
                Debug.Log("Finished all no objects frames");
                generationState = GenerationState.Finished;
            }
            break;

        case GenerationState.Finished:
        {
            ClearSceneFromObjects();
            Destroy(selectedWaterContainer);
                    #if UNITY_EDITOR
            UnityEditor.EditorApplication.isPlaying = false;
                    #else
            Application.Quit();
                    #endif
            break;
        }

        default:

            break;
        }
    }
Beispiel #10
0
    void Start()
    {
        QualitySettings.vSyncCount  = 0; // VSync must be disabled
        Application.targetFrameRate = 35;


        mainThreadUpdateWorkers = new ConcurrentQueue <MainThreadUpdateWorker>();
        if (Settings.config == null || Settings.config.mode == null)
        {
            SceneManager.LoadScene("Start");
            return;//TODO take config
        }

        string selectedWaterContainer = Settings.config.simulationOptions.selectedWaterContainer;

        if (TryGetObjectByTypeName(selectedWaterContainer, out GameObject waterContainerPrefab))
        {
            waterContainer = Instantiate(waterContainerPrefab, Vector3.zero, Quaternion.identity);
        }

        robot           = Instantiate(robotPrefab, new Vector3(0, 2, 0), Quaternion.identity);
        robotController = robot.GetComponent <RobotController>();
        PlaceRobotInStartZone();

        List <string> selectedRandomObjectsNames = Settings.config.simulationOptions.selectedRandomObjects;

        foreach (string randomObjectName in selectedRandomObjectsNames)
        {
            if (TryGetObjectByTypeName(randomObjectName, out GameObject randomObjectPrefab))
            {
                var randomObject = Instantiate(randomObjectPrefab);
                randomObject.transform.rotation = Quaternion.Euler(UnityEngine.Random.Range(0f, 360f), UnityEngine.Random.Range(0f, 360f), UnityEngine.Random.Range(0f, 0f));
                randomObject.transform.position = DatasetObjectInfo.GetRandomWorldPosistionInBoundary(randomObject, waterContainer);
            }
            else
            {
                Debug.LogError(randomObjectName);
            }
        }
        Time.fixedDeltaTime = Settings.config.simulationOptions.fixedDeltaTime;

        /*
         * camera = Camera.main;
         * postDebug = cameraObject.GetComponent<PostProcessDebug>();
         * postLayer = cameraObject.GetComponent<PostProcessLayer>();
         * postVolume = cameraObject.GetComponent<PostProcessVolume>();
         * SetGraphics();*/

        bool TryGetObjectByTypeName(string typeName, out GameObject obj)
        {
            obj = null;
            for (int i = 0; i < knownObjects.Count; i++)
            {
                if (knownObjects[i].GetComponent <DatasetObjectInfo>().typeName.ToLower() == typeName.ToLower())
                {
                    obj = knownObjects[i];
                    return(true);
                }
            }
            return(false);
        }

        StartCoroutine(StartCapture());

        wapiThread = new Thread(WAPIRecv)
        {
            IsBackground = true
        };
        wapiThread.Start();
        JsonSerializer.ToJsonString(GetDetection()); //No idea why first first call takes 1 second, leave it for performance
    }