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; }
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"); } }
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; }