/// <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(); } }
/// <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; }
public void GetMeasurements() { measurementsRequested = true; //next image ready will trigger the GetMeasurements requestTime = Time.time; ScapeLogging.LogDebug("ScapeSessionNative::GetMeasurements() requested " + Time.time); }
/// <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)); }
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; } }
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); }
/// <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; } }
/// <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); } }
/// <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; }
/// <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(); } }
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; } }
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); }
/// <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"); } }
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; } }
/// <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; } }
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); }
/// <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); } }
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); } }
/// <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 + "'"); } }
/// <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()); }