예제 #1
0
        /// <summary>
        /// Cleans the path. Removes all not needed entries from the Path.
        /// The returned path is a copy of the orignal nodes!
        /// </summary>
        /// <returns>The path.</returns>
        /// <param name="Path">Path.</param>
        public static RRTPath CleanPath(RRTPath Path)
        {
            List <RRTNode> nodes = Path.ToList();
            //Clone all nodes
            List <RRTNode> clonedNodes = new List <RRTNode>();

            foreach (var item in nodes)
            {
                clonedNodes.Add(item.Clone());
            }
            //Reconnect the nodes
            //First item is end
            //Last item is start
            RRTNode start = clonedNodes[0];
            RRTNode end   = clonedNodes[clonedNodes.Count - 1];

            for (int i = 0; i < clonedNodes.Count - 1; i++)
            {
                clonedNodes [i].Predecessor = clonedNodes [i + 1];
                clonedNodes[i + 1].AddSucessor(clonedNodes[i]);
            }
            RRTPath cleanedPath = new RRTPath(start, end);

            cleanedPath.Color                = Path.Color;
            cleanedPath.DistanceToEnd        = Path.DistanceToEnd;
            cleanedPath.OrientationDeviation = Path.OrientationDeviation;
            return(cleanedPath);
        }
예제 #2
0
        /// <summary>
        /// Draws the given Node + its orientation.
        /// </summary>
        /// <param name="Base">Base.</param>
        /// <param name="_Map">Map.</param>
        /// <param name="additional">Additional.</param>
        /// <param name="col">Col.</param>
        public static void DrawImportantNode(RRTNode Base, Map _Map, int additional, Color col)
        {
            Point position = _Map.ToMapCoordinates(Base.Position);

            for (int x = position.X - additional; x < position.X + additional; x++)
            {
                for (int y = position.Y - additional; y < position.Y + additional; y++)
                {
                    _Map.DrawPixelOnBitmap(new Point(x, y), col);
                }
            }
            for (int i = 0; i < 15; i++)
            {
                if (!Base.Inverted)
                {
                    int x = Base.Position.X + (int)(i * Math.Cos(Base.Orientation * ToRadians));
                    int y = Base.Position.Y + (int)(i * Math.Sin(Base.Orientation * ToRadians));
                    _Map.DrawPixelOnBitmap(_Map.ToMapCoordinates(new Point(x, y)), Color.DarkRed);
                }
                else
                {
                    int x = Base.Position.X + (int)(i * Math.Cos(Base.Orientation * ToRadians));
                    int y = Base.Position.Y + (int)(i * Math.Sin(Base.Orientation * ToRadians));
                    _Map.DrawPixelOnBitmap(_Map.ToMapCoordinates(new Point(x, y)), Color.DarkOliveGreen);
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Gets a RandomNode starting from a BaseNode in a random distance and random drift angle
        /// </summary>
        /// <returns>The random straight point.</returns>
        /// <param name="BaseNode">Base node.</param>
        /// <param name="MaximumDrift">Maximum drift.</param>
        public static RRTNode GetRandomStraightPoint(RRTNode BaseNode, double MaximumDrift, int InvertProbability, int MaximumDistance = 400)
        {
            double Distance = Randomizer.NextDouble() * MaximumDistance;
            double Angle    = (Randomizer.NextDouble() - 0.5) * 2 * MaximumDrift;
            double NewAngle;
            double Orientation = BaseNode.Orientation;

            bool Inverted = BooleanRandom(InvertProbability);

            if (Inverted)
            {
                NewAngle = InvertOrientation(BaseNode.Orientation) + Angle;
            }
            else
            {
                NewAngle = BaseNode.Orientation + Angle;
            }

            int NewX = (int)(BaseNode.Position.X + (Distance * Math.Cos(NewAngle * ToRadians)));
            int NewY = (int)(BaseNode.Position.Y + (Distance * Math.Sin(NewAngle * ToRadians)));

            Point   NewPos  = new Point(NewX, NewY);
            RRTNode NewNode = new RRTNode(NewPos, Orientation, null);

            NewNode.Inverted = Inverted;

            return(NewNode);
        }
예제 #4
0
        /// <summary>
        /// Clone this instance without copying predecessors and sucessors.
        /// </summary>
        public RRTNode Clone()
        {
            RRTNode temp = new RRTNode(this.Position, this.Orientation, null);

            temp.Inverted = this.Inverted;
            return(temp);
        }
예제 #5
0
 public RRTNode(Point _Position, double _Orientation, RRTNode _Predecessor)
 {
     this.Position    = _Position;
     this.Orientation = _Orientation;
     this.Predecessor = _Predecessor;
     this.Successors  = new List <RRTNode> ();
 }
예제 #6
0
        public RRTPath(RRTNode _Start, RRTNode _End)
        {
            this.Start = _Start;
            this.End   = _End;

            //Calculate length and amount of nodes
            CalculateLength();
        }
예제 #7
0
 /// <summary>
 /// Helper method for iterating through the tree.
 /// </summary>
 /// <param name="Base">Base.</param>
 /// <param name="_Action">Action.</param>
 private static void StepThroughTree(RRTNode Base, Action <RRTNode> _Action)
 {
     foreach (var item in Base.Successors)
     {
         StepThroughTree(item, _Action);
         _Action(item);
     }
 }
예제 #8
0
        private void SelectPoints(Random random, int distance, out RRTNode node1, out RRTNode node2)
        {
            //Select two random points
            int indexNode1 = random.Next(distance + 1, Path.CountNodes - 1);

            node1 = Path.SelectNode(indexNode1);

            node2 = Path.SelectNode(random.Next(1, indexNode1 - distance));
        }
예제 #9
0
        /// <summary>
        /// Take the nodes in this path and put them into a list. Used for easier iteration.
        /// </summary>
        /// <returns>The list.</returns>
        public List <RRTNode> ToList()
        {
            List <RRTNode> nodes = new List <RRTNode> ();

            RRTNode node = Start;

            while (node != null)
            {
                nodes.Add(node);
                node = node.Predecessor;
            }
            return(nodes);
        }
예제 #10
0
파일: RRT.cs 프로젝트: michaelchi08/BRRT
        /// <summary>
        /// Steps to node.
        /// Takes a start and an end node and the argument wether to go straight or in a circle.
        /// Steps into this direction
        /// </summary>
        /// <param name="Start">Start.</param>
        /// <param name="End">End.</param>
        private void StepToNodeStraight(RRTNode Start, RRTNode End)
        {
            double  distance      = RRTHelpers.CalculateDistance(Start, End);
            double  angle         = RRTHelpers.CalculateAngle(Start, End);
            double  cosArgument   = Math.Cos(angle);
            double  sinArgument   = Math.Sin(angle);
            RRTNode lastFoundNode = null;

            //Lambda function that calculates a new point from a given x value
            //Checks if the node is valid
            //Adds it into the list of nodes.
            //Returns false if point not valid
            Func <double, bool> CalculateNewPoint = (double x) =>
            {
                int NewX = Start.Position.X + (int)((double)x * cosArgument);
                int NewY = Start.Position.Y + (int)((double)x * sinArgument);
                if (!PointValid(new Point(NewX, NewY)))
                {
                    if (lastFoundNode == null)
                    {
                        RRTNode BetweenNode = new RRTNode(new Point(NewX, NewY), Start.Orientation, Start);
                        Start.AddSucessor(BetweenNode);
                        lastFoundNode        = BetweenNode;
                        BetweenNode.Inverted = End.Inverted;
                        this.AllNodes.Add(BetweenNode);
                    }
                    else
                    {
                        RRTNode BetweenNode = new RRTNode(new Point(NewX, NewY), lastFoundNode.Orientation, lastFoundNode);
                        lastFoundNode.AddSucessor(BetweenNode);
                        lastFoundNode        = BetweenNode;
                        BetweenNode.Inverted = End.Inverted;
                        this.AllNodes.Add(BetweenNode);
                    }
                    return(true);
                }
                else
                {
                    return(false);
                }
            };

            for (double x = 0; x < distance; x += StepWidth)
            {
                if (!CalculateNewPoint(x))
                {
                    break;
                }
            }
        }
예제 #11
0
        /// <summary>
        /// Initializes a new instance of the <see cref="BRRT.PathOptimizer"/> class.
        /// </summary>
        /// <param name="_Path">Path.</param>
        /// <param name="_Map">Map.</param>
        /// <param name="_EndPoint">End point.</param>
        public PathOptimizer(RRTPath _Path, Map _Map, RRTNode _EndPoint)
        {
            this.InternalMap                 = _Map;
            this.Path                        = _Path;
            this.Iterations                  = 30000;
            this.MaximumDriftAngle           = 10;
            this.MinimumRadius               = 20;
            this.AllowedOrientationDeviation = 1;

            this.StepWidthStraight = 15;
            this.EndPoint          = _EndPoint;
            this.StepWidthEnd      = 4;
            this.StepWidthCurve    = 10;
        }
예제 #12
0
        /// <summary>
        /// Draws the given RRTPath.
        /// </summary>
        /// <param name="Path">Path.</param>
        /// <param name="_Map">Map.</param>
        /// <param name="PathPen">Path pen.</param>
        public static void DrawPath(RRTPath Path, Map _Map, Pen PathPen)
        {
            RRTNode  previous = Path.Start;
            Graphics g        = Graphics.FromImage(_Map.ImageMap);

            while (previous != null)
            {
                RRTHelpers.DrawImportantNode(previous, _Map, 2, Path.Color);
                if (previous.Predecessor != null)
                {
                    g.DrawLine(PathPen, _Map.ToMapCoordinates(previous.Position), _Map.ToMapCoordinates(previous.Predecessor.Position));
                }
                previous = previous.Predecessor;
            }
        }
예제 #13
0
        /// <summary>
        /// Draws the tree from the startpoint.
        /// </summary>
        /// <param name="Base">Base.</param>
        /// <param name="_Map">Map.</param>
        public static void DrawTree(RRTNode Base, Map _Map)
        {
            DrawImportantNode(Base, _Map, 5, Color.Red);
            Action <RRTNode> DrawAction = null;

            DrawAction = (RRTNode node) => {
                DrawImportantNode(node, _Map, 2, Color.Blue);
                foreach (var item in node.Successors)
                {
                    Point    position    = _Map.ToMapCoordinates(node.Position);
                    Point    sucPosition = _Map.ToMapCoordinates(item.Position);
                    Graphics g           = Graphics.FromImage(_Map.ImageMap);
                    g.DrawLine(Pens.Black, position, sucPosition);
                }
            };
            StepThroughTree(Base, DrawAction);
        }
예제 #14
0
파일: RRT.cs 프로젝트: michaelchi08/BRRT
        /// <summary>
        /// Do a step into the right direction
        /// </summary>
        private void DoStep()
        {
            bool Curve = RRTHelpers.BooleanRandom(this.PreferStraight);
            //Select a random base node from the list of all nodes
            RRTNode RandomNode = RRTHelpers.SelectRandomNode(AllNodes);

            //large value -> don' take nearest so often
            bool SelectNearest = RRTHelpers.BooleanRandom(130);

            if (SelectNearest)
            {
                //Take from 10 nodes the node that is the nearest to the endpoint
                double bestDistance = RRTHelpers.CalculateDistance(RandomNode, EndRRTNode);
                for (int i = 0; i < 10; i++)
                {
                    RRTNode NewNode  = RRTHelpers.SelectRandomNode(AllNodes);
                    double  distance = RRTHelpers.CalculateDistance(NewNode, EndRRTNode);
                    if (distance < bestDistance)
                    {
                        bestDistance = distance;
                        RandomNode   = NewNode;
                    }
                }
            }
            if (!Curve)
            {
                //First go straight
                //Get a new straight or drift random node
                RRTNode NewStraightNode = RRTHelpers.GetRandomStraightPoint(RandomNode, this.MaximumDrift, this.StraightInvertProbability);
                //Now step to the new node
                StepToNodeStraight(RandomNode, NewStraightNode);
            }
            else
            {
                //Second go curve
                double  Distance     = 0;
                double  Angle        = 0;
                double  BaseAngle    = 0;
                bool    Left         = false;
                Point   Middle       = new Point();
                RRTNode NewCurveNode = RRTHelpers.GetRandomCurvePoint(RandomNode, this.MinumumRadius, ref Distance, ref Angle, ref BaseAngle, ref Middle, ref Left);
                //RRTHelpers.DrawImportantNode(NewCurveNode, InternalMap, 4, Color.CornflowerBlue);
                StepToNodeCurve(RandomNode, NewCurveNode, Distance, Angle, BaseAngle, Middle, Left);
            }
        }
예제 #15
0
        /// <summary>
        /// Calculates the length and the amount of nodes in the path.
        /// </summary>
        public void CalculateLength()
        {
            Length     = 0;
            CountNodes = 0;
            RRTNode previous = Start;

            while (previous != null)
            {
                if (previous.Predecessor != null)
                {
                    Length += RRTHelpers.CalculateDistance(previous, previous.Predecessor);
                }
                previous = previous.Predecessor;
                CountNodes++;
            }
            //Put them into the list.
            NodesList = ToList();
        }
예제 #16
0
        /// <summary>
        /// Gets the random curve point.
        /// </summary>
        /// <returns>The random curve point.</returns>
        /// <param name="BaseNode">Base node.</param>
        /// <param name="MinimumRadius">Minimum radius.</param>
        /// <param name="_Distance">Distance.</param>
        /// <param name="_Angle">Angle.</param>
        public static RRTNode GetRandomCurvePoint(RRTNode BaseNode, double MinimumRadius, ref double _Distance, ref double _Angle, ref double _BaseAngle, ref Point _Middle, ref bool Left, int MaximumCurveDistance = 300)
        {
            //Decide whether we want to have right or left turn
            //True = left , Right = false
            bool LeftOrRight = BooleanRandom(256 / 2);

            Left = LeftOrRight;

            //Get Random value for the distance between or choosen point and the middle of the circle.
            double Distance = Randomizer.NextDouble() * MaximumCurveDistance + MinimumRadius;

            // Angle between 0 and 360.
            double Angle = (Randomizer.NextDouble()) * 360;

            //Angle to our middle point (orthogonal to orientation)
            double AngleToMiddle = BaseNode.Orientation;

            if (Left)
            {
                AngleToMiddle += 90;
            }
            else
            {
                AngleToMiddle -= 90;
            }
            AngleToMiddle = SanatizeAngle(AngleToMiddle);

            //Calculate center point
            double MiddleX = BaseNode.Position.X + Math.Cos(AngleToMiddle * ToRadians) * Distance;
            double MiddleY = BaseNode.Position.Y + Math.Sin(AngleToMiddle * ToRadians) * Distance;


            Point Middle = new Point((int)MiddleX, (int)MiddleY);

            double BaseAngle = 0;

            BaseAngle = Math.Atan2(BaseNode.Position.Y - Middle.Y, BaseNode.Position.X - Middle.X) * ToDegree;
            BaseAngle = SanatizeAngle(BaseAngle);

            //Calculate new point
            int NewX = 0;
            int NewY = 0;

            NewX   = Middle.X + (int)((double)Distance * Math.Cos((Angle) * ToRadians));
            NewY   = Middle.Y + (int)((double)Distance * Math.Sin((Angle) * ToRadians));
            _Angle = Angle;

            //We drive backwarts if Angle > Baseangle
            bool Inverted = (InvertOrientation(BaseAngle) > Angle) && (Angle > BaseAngle);              //^ BaseNode.Inverted;


            double NewOrientation = 0;

            NewOrientation = BaseNode.Orientation - (BaseAngle - Angle);

            NewOrientation = SanatizeAngle(NewOrientation);
            //Console.WriteLine("Orientation: " + NewOrientation);
            _Distance = Distance;

            _Middle    = Middle;
            _BaseAngle = BaseAngle;

            RRTNode Node = new RRTNode(new Point(NewX, NewY), NewOrientation, null);

            Node.Inverted = Inverted;
            //Console.WriteLine(Node);
            //Console.WriteLine();
            return(Node);
        }
예제 #17
0
파일: RRT.cs 프로젝트: michaelchi08/BRRT
        private void GenerateStartLine()
        {
            //TODO calculate distance
            double Distance = 1000;


            for (int offset = (int)-MaximumDrift; offset < (int)MaximumDrift; offset++)
            {
                RRTNode lastFound = null;
                for (int i = 0; i < Distance; i = i + StepWidth)
                {
                    int NewX = StartRRTNode.Position.X + (int)((double)i * Math.Cos((StartRRTNode.Orientation + offset) * RRTHelpers.ToRadians));
                    int NewY = StartRRTNode.Position.Y + (int)((double)i * Math.Sin((StartRRTNode.Orientation + offset) * RRTHelpers.ToRadians));
                    if (!PointValid(new Point((int)NewX, (int)NewY)))
                    {
                        if (lastFound == null)
                        {
                            RRTNode NewNode = new RRTNode(new Point(NewX, NewY), StartRRTNode.Orientation + offset, StartRRTNode);
                            StartRRTNode.AddSucessor(NewNode);
                            this.AllNodes.Add(NewNode);
                            lastFound = NewNode;
                        }
                        else
                        {
                            RRTNode NewNode = new RRTNode(new Point(NewX, NewY), StartRRTNode.Orientation + offset, lastFound);
                            lastFound.AddSucessor(NewNode);
                            this.AllNodes.Add(NewNode);
                            lastFound = NewNode;
                        }
                    }
                    else
                    {
                        break;
                    }
                }
                lastFound = null;
                for (int i = 0; i < Distance; i = i + StepWidth)
                {
                    int NewX = StartRRTNode.Position.X + (int)((double)i * Math.Cos(RRTHelpers.InvertOrientation(StartRRTNode.Orientation + offset) * RRTHelpers.ToRadians));
                    int NewY = StartRRTNode.Position.Y + (int)((double)i * Math.Sin(RRTHelpers.InvertOrientation(StartRRTNode.Orientation + offset) * RRTHelpers.ToRadians));
                    if (!PointValid(new Point((int)NewX, (int)NewY)))
                    {
                        if (lastFound == null)
                        {
                            RRTNode NewNode = new RRTNode(new Point(NewX, NewY), StartRRTNode.Orientation + offset, StartRRTNode);
                            NewNode.Inverted = true;
                            StartRRTNode.AddSucessor(NewNode);
                            this.AllNodes.Add(NewNode);
                            lastFound = NewNode;
                        }
                        else
                        {
                            RRTNode NewNode = new RRTNode(new Point(NewX, NewY), StartRRTNode.Orientation + offset, lastFound);
                            lastFound.AddSucessor(NewNode);
                            this.AllNodes.Add(NewNode);
                            lastFound        = NewNode;
                            NewNode.Inverted = true;
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
예제 #18
0
 /// <summary>
 /// Calculates the angle from a to b. (a center of coordinate system)
 /// </summary>
 /// <returns>The angle.</returns>
 /// <param name="a">The alpha component.</param>
 /// <param name="b">The blue component.</param>
 public static double CalculateAngle(RRTNode a, RRTNode b)
 {
     return(Math.Atan2(b.Position.Y - a.Position.Y, b.Position.X - a.Position.X));
 }
예제 #19
0
 /// <summary>
 /// Calculates the distance between the two nodes.
 /// </summary>
 /// <returns>The distance.</returns>
 /// <param name="a">The alpha component.</param>
 /// <param name="b">The blue component.</param>
 public static double CalculateDistance(RRTNode a, RRTNode b)
 {
     return(Math.Sqrt(Math.Pow(a.Position.X - b.Position.X, 2) + Math.Pow(a.Position.Y - b.Position.Y, 2)));
 }
예제 #20
0
파일: RRT.cs 프로젝트: michaelchi08/BRRT
        /// <summary>
        /// Steps to random node in a curve.
        /// </summary>
        /// <param name="Start">Start.</param>
        /// <param name="End">End.</param>
        /// <param name="Distance">Distance.</param>
        /// <param name="Angle">Angle.</param>
        /// <param name="BaseAngle">Base angle.</param>
        /// <param name="Middle">Middle.</param>
        /// <param name="Left">If set to <c>true</c> left.</param>
        private void StepToNodeCurve(RRTNode Start, RRTNode End, double Distance, double Angle, double BaseAngle, Point Middle, bool Left)
        {
            RRTNode lastFoundNode = null;
            //RRTHelpers.DrawImportantNode(new RRTNode(Middle, BaseAngle,null), InternalMap, 5, Color.Coral);

            Func <double, bool> CalculateNewPoint = (double x) =>
            {
                //We interpret the random angle as the angle in a polar coordinate system

                int NewX = Middle.X + (int)((double)Distance * Math.Cos((x) * RRTHelpers.ToRadians));
                int NewY = Middle.Y + (int)((double)Distance * Math.Sin((x) * RRTHelpers.ToRadians));


                double Orientation = Start.Orientation - (BaseAngle - x);

                Orientation = RRTHelpers.SanatizeAngle(Orientation);
                if (!PointValid(new Point((int)NewX, (int)NewY)))
                {
                    if (lastFoundNode == null)
                    {
                        RRTNode BetweenNode = new RRTNode(new Point((int)NewX, (int)NewY), Orientation, Start);
                        Start.AddSucessor(BetweenNode);
                        lastFoundNode        = BetweenNode;
                        BetweenNode.Inverted = End.Inverted;
                        this.AllNodes.Add(BetweenNode);
                    }
                    else
                    {
                        RRTNode BetweenNode = new RRTNode(new Point((int)NewX, (int)NewY), Orientation, lastFoundNode);
                        lastFoundNode.AddSucessor(BetweenNode);
                        lastFoundNode        = BetweenNode;
                        BetweenNode.Inverted = End.Inverted;
                        this.AllNodes.Add(BetweenNode);
                    }
                    return(true);
                }
                else
                {
                    return(false);
                }
            };

            double AdaptedStepWidth = (CircleStepWidth * 360.0) / (2 * Math.PI * Distance);

            if (Left)
            {
                for (double x = (BaseAngle) + AdaptedStepWidth; x < Angle; x += AdaptedStepWidth)
                {
                    if (!CalculateNewPoint(x))                     //Break if a not valid point was stepped into
                    {
                        break;
                    }
                }
            }
            else
            {
                for (double x = (BaseAngle) - AdaptedStepWidth; x > Angle; x -= AdaptedStepWidth)
                {
                    if (!CalculateNewPoint(x))                     //Break if a not valid point was stepped into
                    {
                        break;
                    }
                }
            }
        }
예제 #21
0
파일: RRT.cs 프로젝트: michaelchi08/BRRT
        /// <summary>
        /// Find a path from the endpoint to the startpoint.
        /// This is done by looking at all points and selecting the points that are in the given target area.
        /// Their orientation may only vary by the given AcceptableOrientationDeviation.
        /// </summary>
        /// <returns>The path to target.</returns>
        public List <RRTPath> FindPathToTarget()
        {
            //Move area around the endpoint
            Rectangle TranslatedTargetArea = new Rectangle(EndPoint.X - TargetArea.Width / 2, EndPoint.Y + TargetArea.Height / 2, TargetArea.Width, TargetArea.Height);
            Graphics  g = Graphics.FromImage(InternalMap.ImageMap);

            g.DrawRectangle(Pens.Fuchsia, new Rectangle(InternalMap.ToMapCoordinates(TranslatedTargetArea.Location), TranslatedTargetArea.Size));

            List <RRTNode> NodesInTargetArea = new List <RRTNode>();
            List <RRTPath> Paths             = new List <RRTPath>();

            //Step through all nodes
            foreach (var item in AllNodes)
            {
                //Check if the rectangle contains the point and check the orientation
                if (Math.Abs(item.Orientation - EndRRTNode.Orientation) < AcceptableOrientationDeviation)
                {
                    if ((Math.Abs(EndPoint.X - item.Position.X) < TargetArea.Width / 2) && (Math.Abs(EndPoint.Y - item.Position.Y) < TargetArea.Height / 2))
                    {
                        //Add to the list of found nodes.
                        NodesInTargetArea.Add(item);
                        Console.WriteLine("Found node in target area: " + item);
                    }
                }
            }
            //In case no point was found return
            if (NodesInTargetArea.Count == 0)
            {
                return(Paths);
            }

            //Some helpers for creating a nice color for the paths ;)
            int B    = 0;
            int R    = 255;
            int Step = 255 / NodesInTargetArea.Count;

            //Step through all found nodes
            foreach (var item in NodesInTargetArea)
            {
                //Calculate length
                double length = 0;

                //Follow the Predecessor until their is none (this is the startpoint then)
                RRTNode previous = item.Predecessor;
                RRTNode end      = null;

                while (previous != null)
                {
                    if (previous.Predecessor != null)
                    {
                        //TODO replace with RRTHelpers.CalculateDistance
                        length += RRTHelpers.CalculateDistance(previous, previous.Predecessor);
                        //length += Math.Sqrt (Math.Pow (previous.Position.X - previous.Predecessor.Position.X, 2) + Math.Pow (previous.Position.Y - previous.Predecessor.Position.Y, 2));
                    }
                    else
                    {
                        end = previous;
                    }
                    previous = previous.Predecessor;
                }
                //Create new path from start and end item
                RRTPath path = new RRTPath(item, end);
                Paths.Add(path);
                path.Color = Color.FromArgb(R, 50, B);

                path.DistanceToEnd        = RRTHelpers.CalculateDistance(path.Start, EndRRTNode);
                path.OrientationDeviation = path.Start.Orientation - EndRRTNode.Orientation;
                B += Step;
                R -= Step;
            }

            //Sort the list by the cost function of the given paths
            Paths.Sort((RRTPath x, RRTPath y) => {
                if (x.Cost() > y.Cost())
                {
                    return(1);
                }
                else
                {
                    return(-1);
                }
            });
            //List<RRTPath> SortedList = Paths.AsParallel().OrderBy(o => o.Cost()).ToList();
            foreach (var item in Paths)
            {
                Console.WriteLine("Length for path " + item.Color.ToString() + " : " + item.Length + " Distance to End: " + item.DistanceToEnd + " OrientationDif: " + item.OrientationDeviation);
            }


            return(Paths);
        }
예제 #22
0
        /// <summary>
        /// Optimize our path so we hit the endpoint
        /// </summary>
        public void OptimizeForEndPoint()
        {
            //Go along from then nearest point to the endpoint
            RRTNode previous = Path.Start;

            Console.WriteLine("Path length before optimization for endpoint: " + Path.Length + " Count: " + Path.CountNodes + " Cost: " + Path.Cost());
            Console.WriteLine();

            while (previous != null)
            {
                if (previous == null)
                {
                    break;
                }
                //Calculate angle delta (angle between orientations) (in degrees)
                double delta = previous.Orientation - EndPoint.Orientation;
                double angle = RRTHelpers.CalculateAngle(previous, EndPoint);
                //Check if the orientation of the selected point is nearly the same as the orientation of the endpoint
                //if (Math.Abs(previous.Orientation - EndPoint.Orientation) < AllowedOrientationDeviation * 5 || 180 -Math.Abs(previous.Orientation - EndPoint.Orientation) < AllowedOrientationDeviation * 5 )
                if (AnglesAreClose(delta, 0, AllowedOrientationDeviation) && (AnglesAreClose(EndPoint.Orientation, angle * RRTHelpers.ToDegree, MaximumDriftAngle)))
                {
                    //Okey connect them
                    RRTNode selectedNode = previous;
                    RRTNode lastNode     = null;
                    //Create a clone we can work on
                    RRTNode start    = selectedNode.Clone();
                    double  Distance = RRTHelpers.CalculateDistance(selectedNode, EndPoint);

                    if (Math.Abs(RRTHelpers.SanatizeAngle(angle * RRTHelpers.ToDegree)) > this.MaximumDriftAngle)
                    {
                        previous = previous.Predecessor;
                        continue;
                    }
                    bool success = true;

                    //Connect them
                    for (double i = 0; i <= Distance; i += StepWidthEnd)
                    {
                        //Create new point
                        int NewX = (int)(selectedNode.Position.X + i * Math.Cos(angle));
                        int NewY = (int)(selectedNode.Position.Y + i * Math.Sin(angle));

                        //Check if this point is occupied
                        if (InternalMap.IsOccupied(NewX, NewY))
                        {
                            success = false;
                            break;
                        }


                        RRTNode newNode = null;
                        if (lastNode == null)
                        {
                            newNode = new RRTNode(new System.Drawing.Point(NewX, NewY), start.Orientation, start);
                            start.Successors.Add(newNode);
                        }
                        else
                        {
                            newNode = new RRTNode(new System.Drawing.Point(NewX, NewY), start.Orientation, lastNode);
                            lastNode.Successors.Add(newNode);
                        }
                        lastNode = newNode;
                    }
                    if (lastNode == null)
                    {
                        success = false;
                    }
                    if (success)
                    {
                        Path.Start = lastNode;
                        //Replace the selectNode with our start node.
                        start.Predecessor = selectedNode.Predecessor;
                        selectedNode.Predecessor.Successors.Clear();
                        selectedNode.Predecessor.AddSucessor(start);
                        selectedNode.Predecessor = null;
                        selectedNode.Successors.Clear();
                        previous = start;
                    }
                }
                previous = previous.Predecessor;
            }
            Path.CalculateLength();
            Console.WriteLine("Path length after optimization for endpoint: " + Path.Length + " Count: " + Path.CountNodes + " Cost: " + Path.Cost());
        }
예제 #23
0
        /// <summary>
        /// Optimize two points taken from the path by trying to connect them via a curve.
        /// </summary>
        public bool OptimizeCurves(RRTNode start, RRTNode end)
        {
            //Calculate distance
            double distance = RRTHelpers.CalculateDistance(start, end);

            //Distance is too small that it makes sense to optimize it
            if (distance < 10)
            {
                return(false);
            }
            //Calculate angle delta (angle between orientations) (in degrees)
            double delta = end.Orientation - start.Orientation;
            //Calculate angle between points (in radians)
            double angle = RRTHelpers.CalculateAngle(start, end);

            //We can't go from inverted to not inverted (not from forward to backwards or the other way round)
            //NOTE Mit Kurvenfahrt ist das kein Problem, kann aber vermehrt zu Wendeschleifen führen
            if (start.Inverted != end.Inverted)
            {
                return(false);
            }

            //Now decide if going straight is way to go
            //NOTE delta ist entweder sehr klein oder sehr groß (fast 360°, siehe Hilfsfunktion "anglesAreClose" in pseudocode)
            //NOTE Im zweiten Check prüfe, ob Orientierung und Fahrtwinkel näher zusammenliegen als MaximumDriftAngle
            if (AnglesAreClose(delta, 0, AllowedOrientationDeviation) && (AnglesAreClose(start.Orientation, angle * RRTHelpers.ToDegree, MaximumDriftAngle)))
            //if (Math.Abs (delta) < AllowedOrientationDeviation*5 && Math.Abs(angle*RRTHelpers.ToDegree) < MaximumDriftAngle)
            {
                //The deviation in the orientation is small enough we can accept going straight (or drift)
                //And the angle between the points is smaller than the maximum drift we can do


                //Step straight or in a drift. This function may manipulate the path
                bool ret = StepStraight(start, end, distance, angle);
                return(ret);
            }
            else
            {
                //We try a curve


                double theta  = RRTHelpers.SanatizeAngle(angle * RRTHelpers.ToDegree + Math.Sign(delta) * (180 - Math.Abs(delta)) / 2) * RRTHelpers.ToRadians;
                double radius = Math.Abs(distance / (2 * Math.Sin(delta * RRTHelpers.ToRadians / 2)));
                //Check if the radius is > minimum radius
                if (radius < MinimumRadius)
                {
                    return(false);
                }

                //Calculate middle point (theta is in radians)
                double midX = start.Position.X + Math.Cos(theta) * radius;
                double midY = start.Position.Y + Math.Sin(theta) * radius;

                //RRTHelpers.DrawImportantNode (new RRTNode (new System.Drawing.Point ((int)midX, (int)midY), theta, null), InternalMap, 5, System.Drawing.Color.DarkMagenta);
                //Theta in radians, delta in degrees -> gamma in degrees
                double gamma = start.Orientation - RRTHelpers.SanatizeAngle(theta * RRTHelpers.ToDegree - Math.Sign(delta) * 90);

                double driftAngle = gamma;                 //In degree


                if (Math.Abs(driftAngle) / MaximumDriftAngle + MinimumRadius / radius >= 1)
                {
                    return(false);
                }



                bool ret = StepCurve(start, end, delta, new System.Drawing.Point((int)midX, (int)midY), radius, angle, theta);
                return(ret);
            }
        }
예제 #24
0
 /// <summary>
 /// Adds a sucessor to the list of successors
 /// </summary>
 /// <param name="Node">Node.</param>
 public void AddSucessor(RRTNode Node)
 {
     Successors.Add(Node);
 }
예제 #25
0
        private bool StepCurve(RRTNode node1, RRTNode node2, double delta, System.Drawing.Point middle, double radius, double angle, double theta)
        {
            double outerlength = Math.Abs(delta * RRTHelpers.ToRadians * radius);
            double steps       = outerlength / StepWidthCurve;
            double angleStep   = delta / steps;

            RRTNode start = node1.Clone();
            RRTNode end   = node2.Clone();

            double  beforeLength = 0;
            RRTNode temp         = node1;

            while (temp.Position != end.Position)
            {
                if (temp == null || temp.Predecessor == null)
                {
                    break;
                }
                beforeLength += RRTHelpers.CalculateDistance(temp, temp.Predecessor);
                temp          = temp.Predecessor;
            }

            RRTNode lastNode = null;
            bool    success  = true;

            for (int i = 0; i < (int)steps; i++)
            {
                int    NewX           = (int)(middle.X - Math.Cos(RRTHelpers.SanatizeAngle(theta * RRTHelpers.ToDegree + i * angleStep) * RRTHelpers.ToRadians) * radius);
                int    NewY           = (int)(middle.Y - Math.Sin(RRTHelpers.SanatizeAngle(theta * RRTHelpers.ToDegree + i * angleStep) * RRTHelpers.ToRadians) * radius);
                double NewOrientation = RRTHelpers.SanatizeAngle(node1.Orientation + i * angleStep);
                if (InternalMap.IsOccupied(NewX, NewY))
                {
                    success = false;
                    break;
                }

                RRTNode newNode = null;
                if (lastNode == null)
                {
                    newNode          = new RRTNode(new System.Drawing.Point(NewX, NewY), NewOrientation, start);
                    newNode.Inverted = start.Inverted;
                    start.Successors.Add(newNode);
                }
                else
                {
                    newNode = new RRTNode(new System.Drawing.Point(NewX, NewY), NewOrientation, lastNode);
                    lastNode.Successors.Add(newNode);
                    newNode.Inverted = lastNode.Inverted;
                    //RRTHelpers.DrawImportantNode (newNode, InternalMap, 5, Color.DarkOrange);
                }
                lastNode = newNode;
            }

            if (lastNode == null)
            {
                success = false;
            }

            //We successfully connected them
            if (success)
            {
                double afterLength = 0;
                temp = lastNode;
                while (temp.Position != end.Position)
                {
                    if (temp == null || temp.Predecessor == null)
                    {
                        break;
                    }
                    afterLength += RRTHelpers.CalculateDistance(temp, temp.Predecessor);
                    temp         = temp.Predecessor;
                }

                if (afterLength > beforeLength)
                {
                    return(false);
                }
                end.Predecessor = lastNode;
                lastNode.AddSucessor(end);
                if (node1.Predecessor != null)
                {
                    node1.Predecessor.Successors.Clear();
                    node1.Predecessor.AddSucessor(start);

                    start.Predecessor = node1.Predecessor;
                }
                else
                {
                    Console.WriteLine("Node1.Predecessor was null");
                }

                if (node2.Successors.Count > 0)
                {
                    end.AddSucessor(node2.Successors[0]);
                    node2.Successors[0].Predecessor = end;
                    node2.Predecessor = null;
                    node2.Successors.Clear();
                }
                else
                {
                    Console.WriteLine("Node2.Successor[0] was null");
                }
                node1.Successors.Clear();
                node2.Successors.Clear();
                node2.Predecessor = null;
                node1.Predecessor = null;
                Path.CalculateLength();
                return(true);
            }
            return(false);
        }
예제 #26
0
        private bool StepStraight(RRTNode node1, RRTNode node2, double Distance, double Angle)
        {
            RRTNode start = node1.Clone();
            RRTNode end   = node2.Clone();

            RRTNode lastNode = null;
            bool    success  = true;

            //Connect them
            for (double i = 0; i <= Distance; i += StepWidthStraight)
            {
                int NewX = (int)(start.Position.X + i * Math.Cos(Angle));
                int NewY = (int)(start.Position.Y + i * Math.Sin(Angle));

                if (InternalMap.IsOccupied(NewX, NewY))
                {
                    success = false;
                    break;
                }

                RRTNode newNode = null;
                if (lastNode == null)
                {
                    newNode          = new RRTNode(new System.Drawing.Point(NewX, NewY), node1.Orientation, start);
                    newNode.Inverted = start.Inverted;
                    start.Successors.Add(newNode);
                }
                else
                {
                    newNode = new RRTNode(new System.Drawing.Point(NewX, NewY), node1.Orientation, lastNode);
                    lastNode.Successors.Add(newNode);
                    newNode.Inverted = lastNode.Inverted;
                }
                lastNode = newNode;
            }
            if (lastNode == null)
            {
                success = false;
            }

            //We successfully connected them
            if (success)
            {
                end.Predecessor = lastNode;
                lastNode.AddSucessor(end);
                if (node1.Predecessor != null)
                {
                    node1.Predecessor.Successors.Clear();
                    node1.Predecessor.AddSucessor(start);

                    start.Predecessor = node1.Predecessor;
                }
                else
                {
                    Console.WriteLine("Node1.Predecessor was null");
                }

                if (node2.Successors.Count > 0)
                {
                    end.AddSucessor(node2.Successors[0]);
                    node2.Successors[0].Predecessor = end;
                    node2.Predecessor = null;
                    node2.Successors.Clear();
                }
                else
                {
                    Console.WriteLine("Node2.Successor[0] was null");
                }
                node1.Successors.Clear();
                node2.Successors.Clear();
                node2.Predecessor = null;
                node1.Predecessor = null;
                Path.CalculateLength();
                return(true);
            }
            return(false);
        }