コード例 #1
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();
            }
        }
コード例 #2
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;
        }
コード例 #3
0
        public void GetMeasurements()
        {
            measurementsRequested = true;
            //next image ready will trigger the GetMeasurements

            requestTime = Time.time;
            ScapeLogging.LogDebug("ScapeSessionNative::GetMeasurements() requested " + Time.time);
        }
コード例 #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));
        }
コード例 #5
0
ファイル: GeoAnchor.cs プロジェクト: nickblock/UnityGeoTest
        void Update()
        {
            if (needsUpdate)
            {
                this.gameObject.transform.position = new Vector3(ScenePos.x, 0.0f, ScenePos.y);

                ScapeLogging.Log(message: "OriginEvent() set position = " + this.gameObject.transform.localPosition);

                needsUpdate = false;
            }
        }
コード例 #6
0
ファイル: GeoAnchor.cs プロジェクト: nickblock/UnityGeoTest
        void Awake()
        {
            ScapeLogging.Log(message: "OGeoAnchor::Awake " + this.gameObject.name);

            // this.gameObject.SetActive(false);

            GeoWorldRoot.GetInstance().RegisterGeoEvent(this.OriginEvent);

            WorldCoordinates = new Coordinates {
                longitude = Longitude, latitude = Latitude
            };
            WorldPos = GeoConversions.VectorFromCoordinates(WorldCoordinates);
        }
コード例 #7
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;
            }
        }
コード例 #8
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);
            }
        }
コード例 #9
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;
        }
コード例 #10
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();
            }
        }
コード例 #11
0
        static void onAquireLocationMeasurements(ref ScapeNative.location_measurements lm)
        {
            if (haveLocation)
            {
                lm.longitude = lastInfo.longitude;
                lm.latitude  = lastInfo.latitude;
            }
            else
            {
                ScapeLogging.LogError("ScapeClientNative::onAquireLocationMeasurements called but Unity has not retrieved location measurements from device yet. Have Location Permissions been allowed?");

                lm.longitude = 0.0;
                lm.latitude  = 0.0;
            }
        }
コード例 #12
0
        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);
        }
コード例 #13
0
        /// <summary>
        /// The public function to request a ScapeMeasurement.
        /// </summary>
        public void GetMeasurements()
        {
            if (this.scapeMeasurementInProgress)
            {
                ScapeLogging.LogError("GetMeasuremnts ignored, scapeMeasurements already in progress");
                return;
            }

            if (this.scapeSessionNative != null)
            {
                this.scapeMeasurementInProgress = true;
                this.scapeSessionNative.GetMeasurements();
            }
            else
            {
                ScapeLogging.LogError("GetMeasurements called before scapeSessionNative initialized");
            }
        }
コード例 #14
0
        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;
            }
        }
コード例 #15
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()");
        }
コード例 #16
0
        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));
        }
コード例 #17
0
        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;
            }
        }
コード例 #18
0
        void SynchronizeARCamera(ScapeMeasurements scapeMeasurements)
        {
            Coordinates LocalCoordinates  = GeoConversions.CoordinatesFromVector(new Vector2(PositionAtScapeMeasurements.x, PositionAtScapeMeasurements.z));
            Coordinates OriginCoordinates = new Coordinates()
            {
                longitude = scapeMeasurements.coordinates.longitude - LocalCoordinates.longitude,
                latitude  = scapeMeasurements.coordinates.latitude - LocalCoordinates.latitude
            };

            ScapeLogging.Log(message: "SynchronizeARCamera() scapecoords = " + GeoConversions.CoordinatesToString(scapeMeasurements.coordinates));
            ScapeLogging.Log(message: "SynchronizeARCamera() localcoords = " + GeoConversions.CoordinatesToString(LocalCoordinates));
            ScapeLogging.Log(message: "SynchronizeARCamera() origincoords = " + GeoConversions.CoordinatesToString(OriginCoordinates));

            GeoWorldRoot.GetInstance().SetWorldOrigin(OriginCoordinates);

            Quaternion worldEulerRotation = new Quaternion((float)scapeMeasurements.orientation.x,
                                                           (float)scapeMeasurements.orientation.y,
                                                           (float)scapeMeasurements.orientation.z,
                                                           (float)scapeMeasurements.orientation.w);

            ScapeDirectionFix = worldEulerRotation * Quaternion.Inverse(RotationAtScapeMeasurements);
            ScapeLogging.Log(message: "SynchronizeARCamera() ScapeDirectionFix = " + ScapeDirectionFix);
        }
コード例 #19
0
        /// <summary>
        /// used at runtime to retrieve the api key for the ScapeClient
        /// </summary>
        /// <returns>
        /// returns the apikey if found
        /// </returns>
        public static string RetrieveKeyFromResources()
        {
            try
            {
            #if UNITY_EDITOR
                using (StreamReader streamReader = new StreamReader(resPath + apikeyFileName + ".txt"))
                {
                    string apiKey = streamReader.ReadLine();

                    return(apiKey);
                }
            #else
                string apiKey = Resources.Load <TextAsset>(apikeyFileName).ToString();

                return(apiKey);
            #endif
            }
            catch (Exception ex)
            {
                ScapeLogging.LogError("Exception retrieving apikey: " + ex.ToString());
                return(string.Empty);
            }
        }
コード例 #20
0
ファイル: GeoAnchor.cs プロジェクト: nickblock/UnityGeoTest
        void OriginEvent(Coordinates SceneOriginCoordinates)
        {
            Vector2 SceneOrigin = GeoConversions.VectorFromCoordinates(SceneOriginCoordinates);

            ScenePos = WorldPos - SceneOrigin;

            string name = this.gameObject.name;

            ScapeLogging.Log(message: "OriginEvent() " + name + " ScenePos = " + ScenePos.ToString());
            ScapeLogging.Log(message: "OriginEvent() " + name + " WorldCoords = " + GeoConversions.CoordinatesToString(WorldCoordinates));

            if (ScenePos.magnitude < MaxDistance)
            {
                needsUpdate = true;

                this.gameObject.SetActive(true);
            }
            else
            {
                ScapeLogging.Log(message: "OriginEvent() " + name + " beyond max distance (" + ScenePos.magnitude + ")");

                this.gameObject.SetActive(false);
            }
        }
コード例 #21
0
        /// <summary>
        /// save the api key to the specific file in resources folder
        /// </summary>
        /// <param name="apiKey">
        /// the apikey as string
        /// </param>
        public static void SaveApiKeyToResource(string apiKey)
        {
            try
            {
                if (apiKey.Length == 0)
                {
                    return;
                }

                if (!Directory.Exists(resPath))
                {
                    Directory.CreateDirectory(resPath);
                }

                using (StreamWriter writer = new StreamWriter(resPath + apikeyFileName + ".txt", false))
                {
                    writer.WriteLine(apiKey.Trim());
                }
            }
            catch (Exception e)
            {
                ScapeLogging.LogError(message: "Failed to save apikey to '" + resPath + "'");
            }
        }
コード例 #22
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());
 }