예제 #1
0
        private async Task MapAlignmentSave(int mapId, Matrix4x4 m)
        {
            //
            // Updates map metadata to the Cloud Service and reloads to keep local files in sync
            //
            Vector3    pos = m.GetColumn(3);
            Quaternion rot = m.rotation;
            float      scl = (m.lossyScale.x + m.lossyScale.y + m.lossyScale.z) / 3f; // Only uniform scale metadata is supported

            // IMPORTANT
            // Switching coordinate system handedness from Unity's left-handed system to Immersal Cloud Service's default right-handed system
            Matrix4x4 a;
            Matrix4x4 b = Matrix4x4.TRS(pos, rot, transform.localScale);

            ARHelper.SwitchHandedness(out a, b);
            pos = a.GetColumn(3);
            rot = a.rotation;

            // Update map alignment metadata to Immersal Cloud Service
            JobMapAlignmentSetAsync j = new JobMapAlignmentSetAsync();

            j.id    = mapId;
            j.tx    = pos.x;
            j.ty    = pos.y;
            j.tz    = pos.z;
            j.qx    = rot.x;
            j.qy    = rot.y;
            j.qz    = rot.z;
            j.qw    = rot.w;
            j.scale = scl;

            j.OnResult += (SDKMapAlignmentSetResult result) =>
            {
                Debug.Log(string.Format("Alignment for map {0} saved", mapId));
            };

            j.OnError += (e) =>
            {
                Immersal.Samples.Mapping.NotificationManager.Instance.GenerateError("Network Error");
                Debug.Log(string.Format("Failed to save alignment for map id {0}\n{1}", mapId, e));
            };

            await j.RunJobAsync();
        }
        virtual public async void Capture()
        {
            await Task.Delay(250);

            m_bCaptureRunning = true;
            float captureStartTime = Time.realtimeSinceStartup;
            float uploadStartTime  = Time.realtimeSinceStartup;

            XRCpuImage      image;
            ARCameraManager cameraManager   = m_Sdk.cameraManager;
            var             cameraSubsystem = cameraManager.subsystem;

            if (cameraSubsystem != null && cameraSubsystem.TryAcquireLatestCpuImage(out image))
            {
                JobCaptureAsync j = new JobCaptureAsync();
                j.run    = (int)(m_ImageRun & 0xEFFFFFFF);
                j.index  = m_ImageIndex++;
                j.anchor = false;

                if (AutomaticCaptureLocationProvider.Instance.gpsOn)
                {
                    j.latitude  = AutomaticCaptureLocationProvider.Instance.latitude;
                    j.longitude = AutomaticCaptureLocationProvider.Instance.longitude;
                    j.altitude  = AutomaticCaptureLocationProvider.Instance.altitude;
                }
                else
                {
                    j.latitude = j.longitude = j.altitude = 0.0;
                }

                ARHelper.GetIntrinsics(out j.intrinsics);
                Quaternion rot = m_MainCamera.transform.rotation;
                Vector3    pos = m_MainCamera.transform.position;
                ARHelper.GetRotation(ref rot);
                j.rotation = ARHelper.SwitchHandedness(Matrix4x4.Rotate(rot));
                j.position = ARHelper.SwitchHandedness(pos);

                int width  = image.width;
                int height = image.height;

                byte[] pixels;
                int    channels = 1;

                if (m_RgbCapture)
                {
                    ARHelper.GetPlaneDataRGB(out pixels, image);
                    channels = 3;
                }
                else
                {
                    ARHelper.GetPlaneData(out pixels, image);
                }

                byte[] capture = new byte[channels * width * height + 1024];

                Task <icvCaptureInfo> captureTask = Task.Run(() =>
                {
                    return(Core.CaptureImage(capture, capture.Length, pixels, width, height, channels));
                });

                await captureTask;

                string path = string.Format("{0}/{1}", tempImagePath, System.Guid.NewGuid());
                using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(path)))
                {
                    writer.Write(capture, 0, captureTask.Result.captureSize);
                }

                j.imagePath    = path;
                j.encodedImage = "";

                j.OnStart += () =>
                {
                    uploadStartTime = Time.realtimeSinceStartup;
                };
                j.OnResult += (SDKImageResult result) =>
                {
                    float et = Time.realtimeSinceStartup - uploadStartTime;
                    Debug.Log(string.Format("Image uploaded successfully in {0} seconds", et));
                    OnImageUploaded?.Invoke();
                };
                j.Progress.ProgressChanged += (s, progress) =>
                {
                    int value = (int)(100f * progress);
                    Debug.Log(string.Format("Upload progress: {0}%", value));
                };
                j.OnError += (e) =>
                {
                    Debug.Log(string.Format("Capture error: " + e));
                };

                m_Jobs.Add(j);
                image.Dispose();

                float elapsedTime = Time.realtimeSinceStartup - captureStartTime;
                Debug.Log(string.Format("Capture in {0} seconds", elapsedTime));
            }

            m_bCaptureRunning = false;
        }
예제 #3
0
        public async void SubmitAlignment()
        {
            if (mapperSettings == null)
            {
                Debug.Log("ActiveMapListControl: MapperSettings not found");
                return;
            }

            bool transformRootToOrigin = mapperSettings.transformRootToOrigin;

            // Debug.Log(string.Format("clicked, root id: {0}, map count {1}", rootMapId, m_ActiveMaps.Count));
            if (rootMapId > 0 && m_ActiveMaps.Count > 1)
            {
                Transform root           = ARSpace.mapIdToMap[rootMapId].transform;
                Matrix4x4 worldSpaceRoot = root.localToWorldMatrix;

                foreach (KeyValuePair <int, ARMap> entry in ARSpace.mapIdToMap)
                {
                    if (entry.Value.mapId != rootMapId)
                    {
                        // Debug.Log(string.Format("looping... {0}", entry.Value.mapId));
                        Transform xf = entry.Value.transform;
                        Matrix4x4 worldSpaceTransform = xf.localToWorldMatrix;

                        if (transformRootToOrigin)
                        {
                            Matrix4x4 offset = worldSpaceRoot.inverse * worldSpaceTransform;
                            await MapAlignmentSave(entry.Value.mapId, offset);
                        }
                        else
                        {
                            // TODO: implement ECEF/double support
                            Vector3    rootPosMetadata = new Vector3((float)ARSpace.mapIdToMap[rootMapId].mapAlignment.tx, (float)ARSpace.mapIdToMap[rootMapId].mapAlignment.ty, (float)ARSpace.mapIdToMap[rootMapId].mapAlignment.tz);
                            Quaternion rootRotMetadata = new Quaternion((float)ARSpace.mapIdToMap[rootMapId].mapAlignment.qx, (float)ARSpace.mapIdToMap[rootMapId].mapAlignment.qy, (float)ARSpace.mapIdToMap[rootMapId].mapAlignment.qz, (float)ARSpace.mapIdToMap[rootMapId].mapAlignment.qw);

                            // IMPORTANT
                            // Switch coordinate system handedness back from Immersal Cloud Service's default right-handed system to Unity's left-handed system
                            Matrix4x4 a;
                            Matrix4x4 b = Matrix4x4.TRS(rootPosMetadata, rootRotMetadata, Vector3.one);
                            ARHelper.SwitchHandedness(out a, b);

                            Matrix4x4 offset = a * worldSpaceRoot.inverse * worldSpaceTransform;
                            await MapAlignmentSave(entry.Value.mapId, offset);
                        }
                    }
                    else
                    {
                        if (transformRootToOrigin)
                        {
                            // set root to origin
                            Matrix4x4 identity = Matrix4x4.identity;
                            await MapAlignmentSave(entry.Value.mapId, identity);
                        }
                        else
                        {
                            // or keep the root transform
                            // await MapAlignmentSave(entry.Value.mapId, worldSpaceRoot);
                        }
                    }
                }

                m_VisualizeManager?.DefaultView();
                Immersal.Samples.Mapping.NotificationManager.Instance.GenerateSuccess("Map Alignments Saved");
            }
        }
예제 #4
0
        protected override async void Capture(bool anchor)
        {
            await Task.Delay(250);

            if (this.stats.imageCount + this.stats.queueLen >= this.stats.imageMax)
            {
                ImageLimitExceeded();
            }

            m_bCaptureRunning = true;
            float captureStartTime = Time.realtimeSinceStartup;
            float uploadStartTime  = Time.realtimeSinceStartup;

#if PLATFORM_LUMIN && UNITY_2020_1
            XRCameraImage image;
#else
            XRCpuImage image;
#endif
            ARCameraManager cameraManager   = m_Sdk.cameraManager;
            var             cameraSubsystem = cameraManager.subsystem;

#if PLATFORM_LUMIN && UNITY_2020_1
            if (cameraSubsystem != null && cameraSubsystem.TryGetLatestImage(out image))
#else
            if (cameraSubsystem != null && cameraSubsystem.TryAcquireLatestCpuImage(out image))
#endif
            {
                JobCaptureAsync j = new JobCaptureAsync();
                j.run    = (int)(m_ImageRun & 0x7FFFFFFF);
                j.index  = m_ImageIndex++;
                j.anchor = anchor;

                if (mapperSettings.useGps)
                {
                    j.latitude  = m_Latitude;
                    j.longitude = m_Longitude;
                    j.altitude  = m_Altitude;
                }
                else
                {
                    j.latitude = j.longitude = j.altitude = 0.0;
                }

                Camera cam = this.mainCamera;
                ARHelper.GetIntrinsics(out j.intrinsics);
                Quaternion rot = cam.transform.rotation;
                Vector3    pos = cam.transform.position;
                ARHelper.GetRotation(ref rot);
                j.rotation = ARHelper.SwitchHandedness(Matrix4x4.Rotate(rot));
                j.position = ARHelper.SwitchHandedness(pos);

                int width  = image.width;
                int height = image.height;

                byte[] pixels;
                int    channels = 1;

                if (mapperSettings.captureRgb)
                {
                    ARHelper.GetPlaneDataRGB(out pixels, image);
                    channels = 3;
                }
                else
                {
                    ARHelper.GetPlaneData(out pixels, image);
                }

                byte[] capture     = new byte[channels * width * height + 8192];
                int    useMatching = mapperSettings.checkConnectivity ? 1 : 0;

                Task <icvCaptureInfo> captureTask = Task.Run(() =>
                {
                    return(Core.CaptureImage(capture, capture.Length, pixels, width, height, channels, useMatching));
                });

                await captureTask;

                string path = string.Format("{0}/{1}", this.tempImagePath, System.Guid.NewGuid());
                using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(path)))
                {
                    writer.Write(capture, 0, captureTask.Result.captureSize);
                }

                j.imagePath    = path;
                j.encodedImage = "";

                if (mapperSettings.checkConnectivity)
                {
                    NotifyIfConnected(captureTask.Result);
                }

                if (m_SessionFirstImage)
                {
                    m_SessionFirstImage = false;
                }

                j.OnStart += () =>
                {
                    uploadStartTime = Time.realtimeSinceStartup;
                    mappingUIManager.SetProgress(0);
                    mappingUIManager.ShowProgressBar();
                };
                j.OnResult += (SDKImageResult result) =>
                {
                    float et = Time.realtimeSinceStartup - uploadStartTime;
                    Debug.Log(string.Format("Image uploaded successfully in {0} seconds", et));

                    mappingUIManager.HideProgressBar();
                };
                j.Progress.ProgressChanged += (s, progress) =>
                {
                    int value = (int)(100f * progress);
                    //Debug.Log(string.Format("Upload progress: {0}%", value));
                    mappingUIManager.SetProgress(value);
                };
                j.OnError += (e) =>
                {
                    mappingUIManager.HideProgressBar();
                };

                m_Jobs.Add(j);
                image.Dispose();

                float elapsedTime = Time.realtimeSinceStartup - captureStartTime;
                Debug.Log(string.Format("Capture in {0} seconds", elapsedTime));
            }

            m_bCaptureRunning = false;
            var captureButton = workspaceManager.captureButton.GetComponent <Button>();
            captureButton.interactable = true;
        }