コード例 #1
0
    /// <summary>
    /// Delete a TrackedObjectProject from the table.
    /// </summary>
    /// <param name="instance">Object to delete.</param>
    /// <returns>Success result of deletion.</returns>
    public async Task <bool> DeleteSpatialAnchor(SpatialAnchor instance)
    {
        var deleteOperation = TableOperation.Delete(instance);
        var result          = await spatialAnchorTable.ExecuteAsync(deleteOperation);

        return(result.HttpStatusCode == (int)HttpStatusCode.OK);
    }
コード例 #2
0
    public string CreateAnchor(Vec3 at, string id = null)
    {
        string anchorID = id == null
                        ? Guid.NewGuid().ToString()
                        : id;

        SpatialLocator locator = SpatialLocator.GetDefault();
        SpatialStationaryFrameOfReference stationary = locator.CreateStationaryFrameOfReferenceAtCurrentLocation();
        SpatialAnchor anchor = SpatialAnchor.TryCreateRelativeTo(stationary.CoordinateSystem);
        Pose          pose   = World.FromPerceptionAnchor(anchor);

        Pose newAnchor = pose.ToMatrix().Inverse.Transform(new Pose(at, Quat.Identity));

        anchor = SpatialAnchor.TryCreateRelativeTo(stationary.CoordinateSystem, newAnchor.position, newAnchor.orientation);
        pose   = World.FromPerceptionAnchor(anchor);

        if (anchor != null)
        {
            anchorPoses.Add(anchorID, pose);
        }

        return(anchorStore.TrySave(anchorID, anchor)
                        ? anchorID
                        : null);
    }
コード例 #3
0
 public void Init(SpatialAnchor source)
 {
     toolTipPanel.SetActive(true);
     spatialAnchorObject = source;
     //Workaround because TextMeshPro label is not ready until next frame
     StartCoroutine(DelayedInitCoroutine());
 }
コード例 #4
0
    public AnchorPosition UpdateNewAnchorPositionInformation()
    {
        // get the information from the createAnchorPanel
        // update information of the currentSpatialAnchor
        var newSpatialAnchor = new SpatialAnchor(anchorNameInputField.text);

        newSpatialAnchor.Type               = anchorTypeRadialSet.ToggleList[anchorTypeRadialSet.CurrentIndex].name;
        newSpatialAnchor.AnchorPosition     = currentAnchorPosition.transform.position.ToString();
        newSpatialAnchor.WorldToLocalMatrix = currentAnchorPosition.transform.worldToLocalMatrix.ToString();

        // if there is previousSpatial anchor
        if (previousAnchorPosition != null)
        {
            // update information of the edge
            currentEdge.ConnectedName = anchorNameInputField.text;
            currentEdge.Distance      = Vector3.Distance(currentAnchorPosition.transform.position, previousAnchorPosition.transform.position);
        }

        // initialize anchorPosition
        currentAnchorPosition.Init(newSpatialAnchor);

        // disable tap to place of the currentAnchorPosition
        currentAnchorPosition.GetComponent <TapToPlace>().enabled = false;

        // reset anchorNameInputFile TEXT
        anchorNameInputField.text = "";

        return(currentAnchorPosition);
    }
コード例 #5
0
    /// <summary>
    /// Generates and creates an anchor and its GameObjects
    /// </summary>
    /// <param name="relativePose"></param>
    /// <param name="parentAnchor"></param>
    /// <returns></returns>
    public SpatialAnchorController CreateAnchor(RobotUtilities.Pose relativePose, SpatialAnchor parentAnchor)
    {
        SpatialAnchor newAnchor = new WaypointControl.Anchor.SpatialAnchor(null, relativePose, parentAnchor != null ? parentAnchor.Id : "root");

        mission.AddAnchor(newAnchor);
        var controller = CreateAnchorGameObject(newAnchor, parentAnchor);

        return(controller);
    }
コード例 #6
0
 private void OnLocated(SpatialLocator loc, object args)
 {
     if (frame != null || loc.Locatability != SpatialLocatability.PositionalTrackingActive)
     {
         return;
     }
     frame  = loc.CreateStationaryFrameOfReferenceAtCurrentLocation();
     anchor = SpatialAnchor.TryCreateRelativeTo(frame.CoordinateSystem);
     root   = World.FromPerceptionAnchor(anchor).ToMatrix();
     UpdateBounds(center, radius);
 }
コード例 #7
0
ファイル: Operators.cs プロジェクト: sandrist/psi
        /// <summary>
        /// Converts a <see cref="CoordinateSystem"/> in \psi basis to a <see cref="SpatialCoordinateSystem"/> in HoloLens basis.
        /// </summary>
        /// <param name="coordinateSystem">The <see cref="CoordinateSystem"/> in \psi basis.</param>
        /// <returns>The <see cref="SpatialCoordinateSystem"/>.</returns>
        public static SpatialCoordinateSystem TryConvertPsiCoordinateSystemToSpatialCoordinateSystem(this CoordinateSystem coordinateSystem)
        {
            var holoLensMatrix = coordinateSystem.RebaseToHoloLensSystemMatrix();
            var translation    = holoLensMatrix.Translation;

            holoLensMatrix.Translation = Vector3.Zero;
            var rotation      = Quaternion.CreateFromRotationMatrix(holoLensMatrix);
            var spatialAnchor = SpatialAnchor.TryCreateRelativeTo(MixedReality.WorldSpatialCoordinateSystem, translation, rotation);

            return(spatialAnchor?.CoordinateSystem);
        }
コード例 #8
0
 public void AddSpatialAnchor(SpatialAnchor anchor)
 {
     if (CreatedSpatialAnchors == null)
     {
         CreatedSpatialAnchors = new Dictionary <string, SpatialAnchor>();
     }
     if (!CreatedSpatialAnchors.ContainsKey(anchor.Name))
     {
         CreatedSpatialAnchors.Add(anchor.Name, anchor);
     }
 }
コード例 #9
0
    /// <summary>
    /// Insert a new or update an TrackedObjectProject instance on the table storage.
    /// </summary>
    /// <param name="spatialAnchor">Instance to write or update.</param>
    /// <returns>Success result.</returns>
    public async Task <bool> UploadOrUpdate(SpatialAnchor spatialAnchor)
    {
        if (string.IsNullOrWhiteSpace(spatialAnchor.PartitionKey))
        {
            spatialAnchor.PartitionKey = partitionKey;
        }

        var insertOrMergeOperation = TableOperation.InsertOrMerge(spatialAnchor);
        var result = await spatialAnchorTable.ExecuteAsync(insertOrMergeOperation);

        return(result.Result != null);
    }
コード例 #10
0
    public void InitAsync(SpatialAnchor anchor)
    {
        Anchor = anchor;

        if (anchor.Id == null)
        {
            //create anchor and set id
            startAnchorCreationOnNextUpdate = true;
        }
        else
        {
            //find anchor from id
            shouldStartLookingForAnchor = true;
        }
    }
コード例 #11
0
        /// <summary>
        /// Initializes static members of the <see cref="MixedReality"/> class.
        /// Attempts to initialize the world coordinate system from a given spatial anchor.
        /// If no spatial anchor is given, it attempts to load a default spatial anchor.
        /// If the default spatial anchor is not found (e.g., if the app is being run for the first time),
        /// a stationary frame of reference for the world is created at the current location.
        /// </summary>
        /// <param name="worldSpatialAnchor">A spatial anchor to use for the world (optional).</param>
        /// <param name="regenerateDefaultWorldSpatialAnchorIfNeeded">Optional flag indicating whether to regenerate and persist default world spatial anchor if currently persisted anchor fails to localize in the current environment (default: false).</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        /// <remarks>
        /// This method should be called after SK.Initialize.
        /// </remarks>
        public static async Task InitializeAsync(SpatialAnchor worldSpatialAnchor = null, bool regenerateDefaultWorldSpatialAnchorIfNeeded = false)
        {
            if (!SK.IsInitialized)
            {
                throw new InvalidOperationException("StereoKit is not initialized. Call SK.Initialize before calling MixedReality.InitializeAsync.");
            }

            // Create the spatial anchor helper
            SpatialAnchorHelper = new SpatialAnchorHelper(await SpatialAnchorManager.RequestStoreAsync());

            InitializeWorldCoordinateSystem(worldSpatialAnchor, regenerateDefaultWorldSpatialAnchorIfNeeded);

            // By default, don't render the hands or register with StereoKit physics system.
            Input.HandVisible(Handed.Max, false);
            Input.HandSolid(Handed.Max, false);
        }
        Node AddNode(SpatialAnchor anchor, PerceptionTimestamp perceptionTimestamp)
        {
            var position = Vector3.Zero;
            var forward  = Vector3.Zero;

            var anchorPose = SpatialPointerPose.TryGetAtTimestamp(anchor.CoordinateSystem, perceptionTimestamp);

            if (anchorPose != null)
            {
                position = anchorPose.Head.Position;
                forward  = anchorPose.Head.ForwardDirection;
            }

            var node = new Node(anchor, position, forward);

            nodes.Add(node);

            return(node);
        }
コード例 #13
0
    public void CreateEdge(SpatialAnchor anchor1, SpatialAnchor anchor2, double distance)
    {
        if (CreatedEdges == null)
        {
            CreatedEdges = new Dictionary <string, Edge>();
        }
        if ((!CreatedEdges.ContainsKey(anchor1.SpatialAnchorId + ',' + anchor2.SpatialAnchorId)) && (!CreatedEdges.ContainsKey(anchor2.SpatialAnchorId + ',' + anchor1.SpatialAnchorId)))
        {
            Edge edge = new Edge();
            edge.Name                     = anchor1.Name;
            edge.SpatialAnchorId          = anchor1.SpatialAnchorId;
            edge.ConnectedName            = anchor2.Name;
            edge.ConnectedSpatialAnchorId = anchor2.SpatialAnchorId;
            edge.Id       = anchor1.Name + ',' + anchor2.Name;
            edge.RowKey   = edge.Id;
            edge.Distance = distance;

            CreatedEdges.Add(edge.Id, edge);
        }
    }
コード例 #14
0
    /// <summary>
    /// Initializes the mission with an EntryElement. If none exists already, it creates one
    /// </summary>
    private void InitMission()
    {
        //Entry Element Configuration
        var EntryElement = this.GetComponentInChildren <WaypointController>();

        if (EntryElement == null)
        {
            //Create and add the root anchor
            mission.SpatialAnchors.Clear();

            SpatialAnchor RootAnchor = CreateAnchor(new RobotUtilities.Pose(), null).GetAnchor();

            EntryElement = CreateWpController(new RobotUtilities.Pose(), RootAnchor);
        }

        mission.SetEntryPoint(EntryElement.waypoint);

        //Add some debugging stuff
        var newWp1 = AddChild(EntryElement);
        var newWp2 = AddChild(newWp1);
    }
コード例 #15
0
    public AnchorPosition UpdateNewAnchorPositionInformation()
    {
        // get the information from the createAnchorPanel
        // update information of the currentSpatialAnchor
        var newSpatialAnchor = new SpatialAnchor(anchorNameInputField.text);

        newSpatialAnchor.Type               = anchorTypeRadialSet.ToggleList[anchorTypeRadialSet.CurrentIndex].name;
        newSpatialAnchor.AnchorPosition     = currentAnchorPosition.transform.position.ToString();
        newSpatialAnchor.WorldToLocalMatrix = currentAnchorPosition.transform.worldToLocalMatrix.ToString();

        string connectAnchorName = connectAnchorDropdown.options[connectAnchorDropdown.value].text;

        if (connectAnchorName != null)
        {
            var connectAnchor = GetAnchorPosition(connectAnchorName);
            Debug.Log($"Connect to {connectAnchor.SpatialAnchorObject.Name}");
            currentEdge.Name            = connectAnchorName;
            currentEdge.SpatialAnchorId = connectAnchor.SpatialAnchorObject.SpatialAnchorId;
            previousAnchorPosition      = connectAnchor;
        }

        if (previousAnchorPosition != null)
        {
            // update information of the edge
            currentEdge.ConnectedName = anchorNameInputField.text;
            currentEdge.Distance      = Vector3.Distance(currentAnchorPosition.transform.position, previousAnchorPosition.transform.position);
        }

        // initialize anchorPosition
        currentAnchorPosition.Init(newSpatialAnchor);

        // disable tap to place of the currentAnchorPosition
        currentAnchorPosition.GetComponent <TapToPlace>().enabled = false;

        // reset anchorNameInputFile TEXT
        anchorNameInputField.text = "";

        return(currentAnchorPosition);
    }
コード例 #16
0
    /// <summary>
    /// Create an Anchors GameObjects
    /// </summary>
    /// <param name="newAnchor"></param>
    /// <param name="parentAnchor"></param>
    /// <returns></returns>
    private SpatialAnchorController CreateAnchorGameObject(SpatialAnchor newAnchor, SpatialAnchor parentAnchor = null)
    {
        GameObject anchorObject            = Instantiate(SpatialAnchorPrefab, SpatialAnchorsContainer.transform);
        SpatialAnchorController controller = anchorObject.GetComponent <SpatialAnchorController>();

        mission.AddAnchor(newAnchor);
        controller.InitAsync(newAnchor);

        SpatialAnchorToControllerMap[newAnchor] = controller;

        if (parentAnchor == null)
        {
            parentAnchor = mission.SpatialAnchors.FirstOrDefault(x => x.Id == newAnchor.ParentAnchorId);
        }

        if (parentAnchor != null)
        {
            controller.SetPose(SpatialAnchorToControllerMap[parentAnchor]);
        }

        return(controller);
    }
コード例 #17
0
        /// <summary>
        /// Initializes the world coordinate system for the application using a pre-defined spatial anchor,
        /// or creates it at a stationary frame of reference if it does not exist. Once initialized, the
        /// world coordinate system will be consistent across application sessions, unless the associated
        /// spatial anchor is modified or deleted.
        /// <param name="worldSpatialAnchor">A spatial anchor to use for the world (may be null).</param>
        /// <param name="regenerateDefaultWorldSpatialAnchorIfNeeded">Flag indicating whether to regenerate and persist default world spatial anchor if currently persisted anchor fails to localize in the current environment (default: false).</param>
        /// </summary>
        private static void InitializeWorldCoordinateSystem(SpatialAnchor worldSpatialAnchor, bool regenerateDefaultWorldSpatialAnchorIfNeeded)
        {
            SpatialAnchor TryCreateDefaultWorldSpatialAnchor(SpatialStationaryFrameOfReference world)
            {
                // Save the world spatial coordinate system
                WorldSpatialCoordinateSystem = world.CoordinateSystem;

                // Create a spatial anchor to represent the world origin and persist it to the spatial
                // anchor store to ensure that the origin remains coherent between sessions.
                return(SpatialAnchorHelper.TryCreateSpatialAnchor(DefaultWorldSpatialAnchorId, WorldSpatialCoordinateSystem));
            }

            // If no world anchor was given, try to load the default world spatial anchor if it was previously persisted
            worldSpatialAnchor ??= SpatialAnchorHelper.TryGetSpatialAnchor(DefaultWorldSpatialAnchorId);

            if (worldSpatialAnchor != null)
            {
                // Set the world spatial coordinate system using the spatial anchor
                WorldSpatialCoordinateSystem = worldSpatialAnchor.CoordinateSystem;
                if (regenerateDefaultWorldSpatialAnchorIfNeeded)
                {
                    var locator = SpatialLocator.GetDefault();
                    if (locator == null)
                    {
                        throw new Exception($"Could not get spatial locator.");
                    }

                    // determine whether we can localize in the current environment
                    var world   = locator.CreateStationaryFrameOfReferenceAtCurrentLocation();
                    var success = world.CoordinateSystem.TryGetTransformTo(WorldSpatialCoordinateSystem) != null;
                    if (!success)
                    {
                        SpatialAnchorHelper.RemoveSpatialAnchor(DefaultWorldSpatialAnchorId);
                        worldSpatialAnchor = TryCreateDefaultWorldSpatialAnchor(world);
                        if (worldSpatialAnchor == null)
                        {
                            throw new Exception("Could not create the persistent world spatial anchor.");
                        }
                    }
                }
            }
            else
            {
                // Generate and persist the default world spatial anchor
                var locator = SpatialLocator.GetDefault();

                if (locator != null)
                {
                    // This creates a stationary frame of reference which we will use as our world origin
                    var world = locator.CreateStationaryFrameOfReferenceAtCurrentLocation();
                    worldSpatialAnchor = TryCreateDefaultWorldSpatialAnchor(world);

                    if (worldSpatialAnchor == null)
                    {
                        System.Diagnostics.Trace.WriteLine($"WARNING: Could not create the persistent world spatial anchor.");
                    }
                }
                else
                {
                    System.Diagnostics.Trace.WriteLine($"WARNING: Could not get spatial locator (expected in StereoKit on desktop).");
                }
            }

            if (worldSpatialAnchor != null)
            {
                // At startup, we need to capture the pose of StereoKit with respect to the world anchor, and vice versa.
                // These transforms will allow us to convert world coordinates to/from StereoKit coordinates where needed:
                // on input from StereoKit -> \psi, and on output (rendering) \psi -> StereoKit

                // Query the pose of the world anchor. We use this pose for rendering correctly in the world,
                // and for transforming from world coordinates to StereoKit coordinates.
                StereoKitTransforms.WorldHierarchy   = World.FromPerceptionAnchor(worldSpatialAnchor).ToMatrix();
                StereoKitTransforms.WorldToStereoKit = StereoKitTransforms.WorldHierarchy.ToCoordinateSystem();

                // Inverting gives us a coordinate system that can be used for transforming from StereoKit to world coordinates.
                StereoKitTransforms.StereoKitToWorld = StereoKitTransforms.WorldToStereoKit.Invert();

                System.Diagnostics.Trace.WriteLine($"StereoKit origin: {StereoKitTransforms.StereoKitToWorld.Origin.X},{StereoKitTransforms.StereoKitToWorld.Origin.Y},{StereoKitTransforms.StereoKitToWorld.Origin.Z}");

                // TODO: It would be nice if we could actually just shift the origin coordinate system in StereoKit
                // to the pose currently defined in StereoKitTransforms.WorldPose.
                // There's currently an open issue for this: https://github.com/maluoi/StereoKit/issues/189

                // Simply setting the renderer camera root does not work, as its transform appears to be applied in the wrong order.
                // E.g., if the starting StereoKit pose is at a yaw rotation of 180 degrees, we would want to apply that transform
                // first, then apply the transform of the headset pose (perhaps pitching up). Instead, it appears that the headset
                // pose is applied first (e.g., pitching up), and *then* the Renderer.CameraRoot transform is applied (yaw of 180 degrees)
                // which in this example manifests as the pitch going down, opposite of what we desired.
                ////Renderer.CameraRoot = stereoKitTransform.Inverse;
            }
        }
コード例 #18
0
 private void OnCoordinateSystemAdjusted(SpatialAnchor sender, SpatialAnchorRawCoordinateSystemAdjustedEventArgs args)
 {
 }