/// <summary>
        /// Recursive function that traverses through nodes in order to check for a ray intersection.
        /// </summary>
        /// <param name="ray">The ray that will be used in the intersection query.</param>
        /// <param name="currentNodeSize">The node size the current recursive traversal is on.</param>
        /// <param name="currentNodeCentre">The node centre the current recursive traversal is on.</param>
        /// <param name="currentNodeId">The node ID the current recursive traversal is on.</param>
        /// <returns></returns>
        private Vector3?GetRayIntersectionRecursive(ref Ray ray, float currentNodeSize, Vector3 currentNodeCentre,
                                                    uint currentNodeId)
        {
            // Check if the ray intersects the current nodes bounds
            Bounds bounds = new Bounds(currentNodeCentre,
                                       new Vector3(currentNodeSize, currentNodeSize, currentNodeSize));

            if (!bounds.IntersectRay(ray))
            {
                return(null);
            }

            // If the ray intersects the current node, check if the current node is occupied
            OctoMapNode currentNode = _nodes[currentNodeId];

            if (CheckNodeOccupied(currentNode))
            {
                return(currentNodeCentre);
            }

            // If the ray intersects the current node but the node is not occupied, check its children if it has any
            if (currentNode.ChildArrayId != null)
            {
                for (int i = 0; i < 8; i++)
                {
                    uint    childId       = _nodeChildren[currentNode.ChildArrayId.Value][i];
                    float   newNodeSize   = currentNodeSize / 2;
                    Vector3 newNodeCentre = GetBestFitChildNodeCentre(i, newNodeSize, currentNodeCentre);

                    Vector3?intersectedNodeCentre =
                        GetRayIntersectionRecursive(ref ray, newNodeSize, newNodeCentre, childId);
                    if (intersectedNodeCentre != null)
                    {
                        return(intersectedNodeCentre);
                    }
                }
            }

            return(null);
        }
Exemple #2
0
        /// <summary>
        /// Recursive function that traverses through node children and writes the relationships to a compact bit stream.
        /// </summary>
        /// <param name="bitStream">The bitstream to write to.</param>
        /// <param name="currentNodeId">The node ID the current recursive traversal is on.</param>
        private void ConvertToBitStreamRecursive(BitStream bitStream, uint currentNodeId)
        {
            OctoMapNode currentNode = _nodes[currentNodeId];

            if (currentNode.ChildArrayId != null)
            {
                // Build up the current nodes bit stream based on status of its children
                for (int i = 0; i < 8; i++)
                {
                    OctoMapNode childNode = _nodes[_nodeChildren[currentNode.ChildArrayId.Value][i]];
                    if (childNode.ChildArrayId != null) // INNER NODE
                    {
                        bitStream.WriteBit(1);
                        bitStream.WriteBit(1);
                    }
                    else if (CheckNodeFree(childNode)) // FREE
                    {
                        bitStream.WriteBit(1);
                        bitStream.WriteBit(0);
                    }
                    else if (CheckNodeOccupied(childNode)) // OCCUPIED
                    {
                        bitStream.WriteBit(0);
                        bitStream.WriteBit(1);
                    }
                    else // UNKNOWN
                    {
                        bitStream.WriteBit(0);
                        bitStream.WriteBit(0);
                    }
                }

                for (int i = 0; i < 8; i++)
                {
                    uint childId = _nodeChildren[currentNode.ChildArrayId.Value][i];
                    ConvertToBitStreamRecursive(bitStream, childId);
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Recursively traverses though the octomap in order to find leaf nodes and then adds them to a list
        /// </summary>
        /// <param name="positions">The list of node of node centre positions</param>
        /// <param name="sizes">The list of node sizes</param>
        /// <param name="currentNodeSize">The node size the current recursive traversal is on.</param>
        /// <param name="currentNodeCentre">The node centre the current recursive traversal is on.</param>
        /// <param name="currentNodeId">The node ID the current recursive traversal is on.</param>
        private void GatherOctoMapNodes(List <Vector3> positions, List <float> sizes, float currentNodeSize,
                                        Vector3 currentNodeCentre,
                                        uint currentNodeId)
        {
            OctoMapNode currentNode = _nodes[currentNodeId];

            if (CheckNodeOccupied(currentNode))
            {
                positions.Add(currentNodeCentre);
                sizes.Add(currentNodeSize);
            }

            if (currentNode.ChildArrayId != null)
            {
                for (int i = 0; i < 8; i++)
                {
                    uint    childId       = _nodeChildren[currentNode.ChildArrayId.Value][i];
                    float   newNodeSize   = currentNodeSize / 2;
                    Vector3 newNodeCentre = GetBestFitChildNodeCentre(i, newNodeSize, currentNodeCentre);
                    GatherOctoMapNodes(positions, sizes, newNodeSize, newNodeCentre, childId);
                }
            }
        }
Exemple #4
0
 /// <summary>
 /// Returns true or false depending on whether a specific node is not occupied. Can be extended further.
 /// </summary>
 /// <param name="octoMapNode">The node that will be checked</param>
 /// <returns>True or false depending on whether a specific node is not occupied.</returns>
 private static bool CheckNodeFree(OctoMapNode octoMapNode)
 {
     return(octoMapNode.Occupied <= -1);
 }
Exemple #5
0
 /// <summary>
 /// Returns true or false depending on whether a specific node is occupied. Can be extended further.
 /// </summary>
 /// <param name="octoMapNode">The node that will be checked</param>
 /// <returns>True or false depending on whether a specific node is occupied.</returns>
 private static bool CheckNodeOccupied(OctoMapNode octoMapNode)
 {
     return(octoMapNode.Occupied >= 1);
 }
Exemple #6
0
 /// <summary>
 /// Sets the occupied state of a node to -1. Can be extended further.
 /// </summary>
 /// <param name="octoMapNode">The node to set the occupied state on</param>
 /// <returns>The same node but with the occupied state changed</returns>
 private static OctoMapNode DecreaseNodeOccupation(OctoMapNode octoMapNode)
 {
     octoMapNode.Occupied = -1;
     return(octoMapNode);
 }
Exemple #7
0
        /// <summary>
        /// The recursive function that adds a new point to the OctoMap.
        /// </summary>
        /// <param name="point">The point to add to the OctoMap.</param>
        /// <param name="currentNodeSize">The node size the current recursive traversal is on.</param>
        /// <param name="currentNodeCentre">The node centre the current recursive traversal is on.</param>
        /// <param name="currentNodeId">The node ID the current recursive traversal is on.</param>
        private void AddPointRecursive(ref Vector3 point, float currentNodeSize, Vector3 currentNodeCentre,
                                       uint currentNodeId)
        {
            OctoMapNode node = _nodes[currentNodeId];

            // If we're at the deepest level possible, this current node becomes a leaf node.
            if (currentNodeSize < _minimumNodeSize)
            {
                _nodes[currentNodeId] = IncreaseNodeOccupation(node);
                return;
            }

            // If the node doesn't encompass this point, return out early
            Bounds bounds = new Bounds(currentNodeCentre,
                                       new Vector3(currentNodeSize, currentNodeSize, currentNodeSize));

            if (!bounds.Contains(point))
            {
                return;
            }

            // If this node doesn't have any children, new children need to be generated
            if (node.ChildArrayId == null)
            {
                node.ChildArrayId     = GenerateChildren();
                _nodes[currentNodeId] = node;
            }

            Debug.Assert(_nodes[currentNodeId].ChildArrayId != null);

            // Now handle the new object we're adding now
            int  bestFitChild = BestFitChildIndex(point, currentNodeCentre);
            uint childNodeId  = _nodeChildren[node.ChildArrayId.Value][bestFitChild];

            float   newNodeSize   = currentNodeSize / 2;
            Vector3 newNodeCentre = GetBestFitChildNodeCentre(bestFitChild, newNodeSize, currentNodeCentre);

            AddPointRecursive(ref point, newNodeSize, newNodeCentre, childNodeId);

            // Loop through all children and check if they all share the same occupied state
            bool childrenOccupancy = false;

            for (int i = 0; i < 8; i++)
            {
                OctoMapNode child = _nodes[_nodeChildren[node.ChildArrayId.Value][i]];
                if (child.ChildArrayId != null)
                {
                    return;
                }

                bool occupancy = CheckNodeOccupied(child);

                if (i == 0)
                {
                    childrenOccupancy = occupancy;
                }
                else
                {
                    if (occupancy != childrenOccupancy)
                    {
                        return;
                    }
                }
            }

            // If the code reaches here that means all the children share the same state
            // Remove all the child nodes
            for (int i = 0; i < 8; i++)
            {
                var childArrayId = _nodes[currentNodeId].ChildArrayId;
                if (childArrayId != null)
                {
                    uint childId = _nodeChildren[childArrayId.Value][i];
                    _nodes.Remove(childId);
                }
                else
                {
                    Debug.Log("Failed to remove node from node dictionary");
                }
            }

            var arrayId = _nodes[currentNodeId].ChildArrayId;

            if (arrayId != null)
            {
                // Remove the node children array
                _nodeChildren.Remove(arrayId.Value);
            }
            else
            {
                Debug.Log("Failed to remove child array from child dictionary.");
            }

            // Set the current nodes occupancy state to that of its children
            OctoMapNode currentNode = _nodes[currentNodeId];

            currentNode.ChildArrayId = null;
            currentNode = childrenOccupancy ? IncreaseNodeOccupation(currentNode) : DecreaseNodeOccupation(currentNode);

            _nodes[currentNodeId] = currentNode;
        }