Exemplo n.º 1
0
        /// <summary>
        /// called by ScapeSessionComponent.
        /// Here the scape measurement is used to update the world transform object
        /// in order to position and orient the camera with respect to the scene's origin.
        /// </summary>
        /// <param name="coordinates">
        /// GPS Coordinates given by scape measurements
        /// </param>
        /// <param name="heading">
        /// The compass heading given by scape measurements
        /// </param>
        /// <param name="altitude">
        /// The the altitude from the ground the camera is at. This is currently supplied by
        /// ARKit/Core using the GroundTracker
        /// </param>
        public void SynchronizeARCamera(LatLng coordinates, float heading, float altitude)
        {
            if (groundTracker)
            {
                bool  success = false;
                float height  = groundTracker.GetGroundHeight(out success);
                if (success)
                {
                    altitude = -height;
                }
                else
                {
                    ScapeLogging.LogError(message: "groundTracker.getHeight not found before ScapeMeasurement, falling back to Scape's RawMeasurementEstimate");
                }
            }

            ScapeLogging.LogDebug(message: "SynchronizeARCamera() LatLngCoordinates = " + ScapeUtils.CoordinatesToString(coordinates));

            ScapeLogging.LogDebug(message: "SynchronizeARCamera() ARHeading = " + rotationAtScapeMeasurements.y);
            ScapeLogging.LogDebug(message: "SynchronizeARCamera() ARPosition = " + positionAtScapeMeasurements.ToString());

            if (s2CellId == 0)
            {
                FindS2CellId(coordinates);
            }

            // the Unity position the camera should be in, that is it's position relative to the S2 cell based on it's
            // gps coordinates
            cameraS2Position = ScapeUtils.WgsToLocal(
                coordinates.Latitude,
                coordinates.Longitude,
                altitude,
                s2CellId);

            // the world transform direction corrects the camera's Heading to be relative to North.
            worldTransformDirection = heading - rotationAtScapeMeasurements.y;

            if (worldTransformDirection < 0.0)
            {
                worldTransformDirection += 360.0f;
            }

            ScapeLogging.LogDebug(message: "SynchronizeARCamera() worldTransformDirectionYAngle = " + worldTransformDirection);

            Vector3 positionAtScapeMeasurementsRotated = Quaternion.AngleAxis(worldTransformDirection, Vector3.up) * positionAtScapeMeasurements;

            // the world transform position corrects the camera's final position after applying the direction correction
            worldTransformPosition = cameraS2Position - positionAtScapeMeasurementsRotated;
            ScapeLogging.LogDebug(message: "SynchronizeARCamera() worldTransformPosition = " + worldTransformPosition.ToString());

            if (updateWorldTransform)
            {
                previousYDirection = lerpDirection;
                previousPosition   = lerpPosition;
            }

            updateWorldTransform = true;

            updateStartTime = Time.time;
        }
Exemplo n.º 2
0
        /// <summary>
        /// update the world transform object having been given new scape measurements
        /// </summary>
        private void UpdateWorldTransform()
        {
            if (updateWorldTransform)
            {
                ScapeLogging.LogDebug(message: "GeoCameraComponent::UpdateWorldTransform()");

                float elapsed = Time.time - updateStartTime;

                float   lerpDirection = worldTransformDirection;
                Vector3 lerpPosition  = worldTransformPosition;
                if (elapsed >= updateTransformTime || previousYDirection == 0.0f)
                {
                    previousYDirection   = worldTransformDirection;
                    previousPosition     = worldTransformPosition;
                    updateWorldTransform = false;
                }
                else
                {
                    float lerp = elapsed / updateTransformTime;
                    lerpDirection = Mathf.Lerp(previousYDirection, worldTransformDirection, lerp);
                    lerpPosition  = Vector3.Lerp(previousPosition, worldTransformPosition, lerp);
                }

                worldTransformObject.transform.rotation = Quaternion.AngleAxis(lerpDirection, Vector3.up);
                worldTransformObject.transform.position = lerpPosition;

                PrintError();
            }
        }
        public void GetMeasurements()
        {
            measurementsRequested = true;
            //next image ready will trigger the GetMeasurements

            requestTime = Time.time;
            ScapeLogging.LogDebug("ScapeSessionNative::GetMeasurements() requested " + Time.time);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Identify which S2Cell will be used for the root.
        /// Find the S2Cell's GPS Coordinates.
        /// </summary>
        /// <param name="latLng">
        /// the LatLng coordinates from the first scape measurement
        /// </param>
        private void FindS2CellCoordinates(LatLng latLng)
        {
            S2CellId = ScapeUtils.CellIdForWgs(latLng.Latitude, latLng.Longitude, ScapeUtils.S2CellLevel);

            S2CellCoordinates = ScapeUtils.LocalToWgs(new Vector3(0, 0, 0), S2CellId);

            ScapeLogging.LogDebug(message: "GeoAnchorManager::S2CellId = " + S2CellId.ToString("X"));
            ScapeLogging.LogDebug(message: "GeoAnchorManager::S2CellCoordinates = " + ScapeUtils.CoordinatesToString(S2CellCoordinates));
        }
Exemplo n.º 5
0
        /// <summary>
        /// Initializes the GeoAnchorManager, should only happen once
        /// Sets the S2Cell if the user has given GPS coordinates, other wise that is done later
        /// when the ScapeMeasurement comes in.
        /// </summary>
        private void StaticInit()
        {
            ScapeLogging.LogDebug(message: "GeoAnchorManager::StaticInit()");

            if (geoAnchorManager != null)
            {
                ScapeLogging.LogError(message: "Error: more than one GeoAnchorManager detected in scene!");
            }
            else
            {
                geoAnchorManager = this;
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// The OriginEvent function is connected to the GeoAnchorManager's GeoOriginEvent action
        /// which is triggered when the ScapeSessionObject receives a successful scape measurement.
        /// At this point the object calculates it's position in the Unity scene and is set to active.
        /// Due to the update to the GameObject's transform, it must be ensured that this function is
        /// only called on the main thread.
        /// </summary>
        public void OriginEvent()
        {
            ScapeLogging.LogDebug(message: "GeoAnchor::OriginEvent() " + gameObjectName);

            isInstantiated = true;

            CalculateLocalCoordinates();

            if (WithinMaxDistance())
            {
                this.gameObject.SetActive(true);
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// InstantiateOrigin is called by the main camera when a successful scape meaasurements event happens.
        /// The Coordinates passed in are the Geo Location of Unity's origin.
        /// </summary>
        /// <param name="rootSessionCoords">
        /// The GPS coordinates for the origin of the Unity scene,
        /// </param>
        public void InstantiateOrigin(LatLng rootSessionCoords)
        {
            ScapeLogging.LogDebug(message: "GeoAnchorManager::InstantiateOrigin()");
            if (isInstantiated == false)
            {
                FindS2CellCoordinates(rootSessionCoords);

                isInstantiated = true;
            }

            if (geoOriginEvent != null)
            {
                geoOriginEvent.Invoke();
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// The game object calculates it's position in the Unity scene by comparing its World coordinate to the center
        /// of the unique S2 cell defined in the scene's GeoAnchorManager object.
        /// </summary>
        private void CalculateLocalCoordinates()
        {
            if (!isInstantiated)
            {
                return;
            }

            ScapeLogging.LogDebug(message: "GeoAnchor::GetWorldCoordinates() WorldCoords = " + latLng.Latitude + ", " + latLng.Longitude);

            Vector3 scenePos = ScapeUtils.WgsToLocal(latLng.Latitude, latLng.Longitude, altitude, GeoAnchorManager.Instance.S2CellId);

            ScapeLogging.LogDebug(message: "GeoAnchor::GetWorldCoordinates() ScenePos = " + scenePos.ToString());

            this.gameObject.transform.localPosition = scenePos;
        }
        private void CopyImageBuffer(NativeArray <byte> imageBuffer)
        {
            if (imageBufferCopy == null || imageBufferCopy.Length != imageBuffer.Length)
            {
                FreeHandle();

                imageBufferCopy = new byte[imageBuffer.Length];
                handle          = GCHandle.Alloc(imageBufferCopy, GCHandleType.Pinned);
                imagePtr        = handle.AddrOfPinnedObject();

                ScapeLogging.LogDebug("CopyImageBuffer() " + (Time.time - requestTime));
            }

            imageBuffer.CopyTo(imageBufferCopy);
        }
        private void GetImageAsync()
        {
            currentXRImage = new XRCameraImage();

            if (cameraManager.TryGetLatestImage(out currentXRImage))
            {
                currentXRImage.ConvertAsync(new XRCameraImageConversionParams
                {
                    inputRect        = new RectInt(0, 0, currentXRImage.width, currentXRImage.height),
                    outputDimensions = new Vector2Int(ScapeImgWidth, ScapeImgHeight),
                    outputFormat     = TextureFormat.R8
                }, ProcessImage);

                currentXRImage.Dispose();

                ScapeLogging.LogDebug("GetImageAsync() " + (Time.time - requestTime));
                measurementsRequested = false;
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// on scape measurements result, print the result to the Text box.
        /// </summary>
        /// <param name="scapeMeasurements">
        /// scapeMeasurements from scape system
        /// </param>
        private void OnScapeMeasurementsEvent(ScapeMeasurements scapeMeasurements)
        {
            if (scapeMeasurements.MeasurementsStatus == ScapeMeasurementStatus.ResultsFound)
            {
                // Use the scape scape position
                newText = "OnScapeMeasurementsEvent:\n" +
                          "timestamp: " + scapeMeasurements.Timestamp + "\n" +
                          "coordinates: " + scapeMeasurements.LatLng.Longitude + " " + scapeMeasurements.LatLng.Latitude + "\n" +
                          "heading: " + scapeMeasurements.Heading + "\n" +
                          "rawHeightEstimate: " + scapeMeasurements.RawHeightEstimate + "\n" +
                          "confidenceScore: " + scapeMeasurements.ConfidenceScore + "\n" +
                          "measurementsStatus: " + scapeMeasurements.MeasurementsStatus + "\n\n";

                updateText        = true;
                setButtonEnabled  = true;
                showLoadingCicles = false;
            }

            ScapeLogging.LogDebug("ScapeSimpleUI::OnScapeMeasurementsEvent()");
        }
        private void ProcessImage(AsyncCameraImageConversionStatus status,
                                  XRCameraImageConversionParams conversionParams,
                                  NativeArray <byte> imageBuffer)
        {
            if (status != AsyncCameraImageConversionStatus.Ready)
            {
                // attempt to call getMeasurements with empty image will compel SDK core to report error
                // triggering session to request another
                ScapeNative.citf_setYChannelPtr(this.scapeClient, IntPtr.Zero, 0, 0);
                ScapeNative.citf_getMeasurements(this.scapeClient);
                return;
            }

            CopyImageBuffer(imageBuffer);

            ScapeNative.citf_setYChannelPtr(this.scapeClient, imagePtr, ScapeImgWidth, ScapeImgHeight);
            ScapeNative.citf_getMeasurements(this.scapeClient);

            ScapeLogging.LogDebug("citf_getMeasurements() " + (Time.time - requestTime));
        }
        private void TryGetIntrinsics(float scaleX, float scaleY)
        {
            XRCameraIntrinsics intrinsics = new XRCameraIntrinsics();

            if (cameraManager.TryGetIntrinsics(out intrinsics))
            {
                ScapeNative.citf_setCameraIntrinsics(this.scapeClient,
                                                     intrinsics.focalLength.x * scaleX,
                                                     intrinsics.focalLength.y * scaleY,
                                                     intrinsics.principalPoint.x * scaleX,
                                                     intrinsics.principalPoint.y * scaleY);

                ScapeLogging.LogDebug("setCameraIntrinsics " + "\n" +
                                      "focalLength.x = " + (intrinsics.focalLength.x * scaleX) + "\n" +
                                      "focalLength.y = " + (intrinsics.focalLength.y * scaleY) + "\n" +
                                      "principalPoint.x = " + (intrinsics.principalPoint.x * scaleX) + "\n" +
                                      "principalPoint.y = " + (intrinsics.principalPoint.y * scaleY) + "\n");

                gotIntrinsics = true;
            }
        }
Exemplo n.º 14
0
 /// <summary>
 /// print some debug output for logging purposes
 /// </summary>
 private void PrintError()
 {
     ScapeLogging.LogDebug(message: "CameraS2Position = " + cameraS2Position.ToString());
     ScapeLogging.LogDebug(message: "CameraCWPosition = " + transform.position.ToString());
 }