Esempio n. 1
0
    ObstacleGrid CreateProperObstaclePattern(ObstacleGrid obstacle)
    {
        var obs = obstacle;

        if (RoadWidth > obs.Grid.Count)
        {
            var emptyColumn      = new Column(obs.Grid[0].column.Count);
            var emptyColumnCount = RoadWidth - obs.Grid.Count;
            for (int i = 0; i < emptyColumnCount * .5f; i++)
            {
                obs.Grid.Insert(0, emptyColumn);
            }

            while (RoadWidth > obs.Grid.Count)
            {
                obs.Grid.Insert(obs.Grid.Count, emptyColumn);
            }
        }

        else if (RoadWidth < obs.Grid.Count)
        {
            for (int i = 0; i < (obs.Grid.Count - RoadWidth) * .5f; i++)
            {
                obstacle.Grid.RemoveAt(0);
            }

            while (RoadWidth < obs.Grid.Count)
            {
                obs.Grid.RemoveAt(obs.Grid.Count - 1);
            }
        }
        return(obs);
    }
Esempio n. 2
0
        public GVDKarla(ObstacleGrid grid)
        {
            this.grid = grid;

            open = new IntervalHeap<GridCellValue>();
            ties = new LinkedList<GridCell>();
            dist = new float[grid.NumColumns, grid.NumRows];
            distNew = new float[grid.NumColumns, grid.NumRows];
            parent = new GridCell[grid.NumColumns, grid.NumRows];
            tie = new GridCell[grid.NumColumns, grid.NumRows];
            obst = new int[grid.NumColumns, grid.NumRows];
            valid = new HashSet<int>();
            voro = new bool[grid.NumColumns, grid.NumRows];

            for (int c = grid.NumColumns - 1; c >= 0; c--)
                for (int r = grid.NumRows - 1; r >= 0; r--)
                {
                    dist[c, r] = float.PositiveInfinity;
                    distNew[c, r] = float.PositiveInfinity;
                    parent[c, r] = GridCell.Unknown;
                    tie[c, r] = GridCell.Unknown;
                    obst[c, r] = -1;
                    voro[c, r] = false;
                }
        }
Esempio n. 3
0
    ObstacleGrid MapAllRoad(int difficulty)
    {
        var Map      = new ObstacleGrid(RoadWidth, FirstObstacleStartPosition);
        var obstacle = GetRandomObstacle();

        Map.AddSameSizeRowGrid(CreateProperObstaclePattern(obstacle).Grid);
        var currentColumn = FirstObstacleStartPosition + obstacle.Grid[0].column.Count + 1;

        while (currentColumn < RoadLength - 5)
        {
            var ObstacleChance = difficulty * ObstacleChanceConstant;
            var putObstacle    = Random.Range(0, 1f) < ObstacleChance;
            if (putObstacle)
            {
                obstacle = GetRandomObstacle();
                Map.AddSameSizeRowGrid(CreateProperObstaclePattern(obstacle).Grid);
                currentColumn += obstacle.Grid[0].column.Count;
            }
            Map.AddEmptyRow();
            currentColumn++;
        }

        while (Map.Grid[0].column.Count < RoadLength)
        {
            Map.AddEmptyRow();
        }

        return(Map);
    }
Esempio n. 4
0
 public ObstacleRelaxed(ObstacleGrid grid)
 {
     this.grid = grid;
 }
Esempio n. 5
0
 public CombinedHeuristic(ObstacleGrid grid)
 {
     one = new NonholonomicRelaxed(grid);
     two = new ObstacleRelaxed(grid);
 }
Esempio n. 6
0
 public NonholonomicRelaxed(ObstacleGrid grid)
 {
     this.grid = grid;
     heuristic = new float[grid.NumColumns, grid.NumRows];
     unit      = grid.Resolution * discount; // factor to discount the suboptimality of 8-neighbor paths
 }
Esempio n. 7
0
        public void InitSim(bool autoStart, bool smoothingOn, Mission mission)
        {
            gridDone          = false;
            pathDone          = false;
            pathSmoothDone    = false;
            pathSearching     = false;
            pathSearchingDone = false;
            autoDrive         = true;
            run             = false;
            isCollided      = false;
            currentControls = new CarControls(0f, 0f, 0f);

            if (camera == null)
            {
                camera          = new Camera(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 0.1f, 1000f);
                camera.Position = new Vector3(75f, 75f, 180f);
            }

            startPose                  = mission.Start;
            goalPose                   = mission.Goal;
            HybridAStar.Epsilon        = mission.AStarEpsilon;
            HybridAStar.GridResolution = mission.AStarGridResolution;
            HybridAStar.SafetyFactor   = 1.5f;
            HybridAStar.Reset();

            car  = new Car(world, startPose);
            grid = new ObstacleGrid(world, mission.Environment);

            car.Body.OnCollision += new OnCollisionEventHandler(OnCollision);

            gridDone          = false;
            pathDone          = false;
            pathSearchingDone = false;
            bg = new Thread(() =>
            {
                DateTime now = DateTime.Now;
                grid.BuildGVD();
                console.WriteLine("GVD Generation Time: " + Math.Round((DateTime.Now - now).TotalMilliseconds) + " ms");
                gridDone = true;

                now                = DateTime.Now;
                pathSearching      = true;
                astar              = HybridAStar.FindPath(grid, startPose, goalPose);
                TimeSpan astarTime = DateTime.Now - now;
                poses              = astar.Path;

                pathSearching     = false;
                pathSearchingDone = true;

                if (astar.Path.Count > 0)
                {
                    pathDone = true;
                }

                now = DateTime.Now;
                if (smoothingOn)
                {
                    smoothedPath = Smoother.Smooth(astar.Path, grid);
                }
                else
                {
                    smoothedPath = astar.Path;
                }
                TimeSpan smoothingTime = DateTime.Now - now;

                int numUnsafe = Smoother.UnsafeIndices != null ? Smoother.UnsafeIndices.Count : 0;

                console.WriteLine("A*: Total Planning Time: " + Math.Round((astarTime + smoothingTime).TotalMilliseconds) + " ms");
                console.WriteLine("         Heuristic Time: " + Math.Round(astar.HeuristicInitTime.TotalMilliseconds) + " ms");
                console.WriteLine("         Searching Time: " + Math.Round((astarTime - astar.HeuristicInitTime).TotalMilliseconds) + " ms");
                console.WriteLine("         Smoothing Time: " + Math.Round(smoothingTime.TotalMilliseconds) + " ms (" + Smoother.NumIterations + " iterations, " + Smoother.Change + "m, " + numUnsafe + " unsafe points)");
                console.WriteLine("    " + astar.Discovered.Count + " nodes discovered");
                console.WriteLine("    " + astar.Expanded.Count + " nodes expanded");

                controller = new StanleyFSMController(smoothedPath, goalPose);

                pathSmoothDone = true;
                if (autoStart)
                {
                    run = true;
                }
            });
            bg.IsBackground = true;
            bg.Priority     = ThreadPriority.Lowest;
            bg.Start();
        }
Esempio n. 8
0
        public static HybridAStarResults FindPath(ObstacleGrid aGrid, Pose start, Pose aGoal)
        {
            grid             = aGrid;
            goal             = aGoal;
            heuristicUpdated = false;
            heuristicBitmap  = null;
            IntervalHeap <Node> open = new IntervalHeap <Node>();

            //heuristic = new EuclideanHeuristic();
            //heuristic = new ObstacleRelaxed(grid);
            heuristic = new NonholonomicRelaxed(grid);
            //heuristic = new CombinedHeuristic(grid);

            DateTime now = DateTime.Now;

            heuristic.Update(goal);
            heuristicUpdated = true;
            TimeSpan heuristicInitTime = DateTime.Now - now;

            Expanded = new LinkedList <Node>();
            LinkedList <Node> discovered = new LinkedList <Node>();

            int numCols = (int)Math.Ceiling(grid.NumColumns * grid.Resolution / GridResolution);
            int numRows = (int)Math.Ceiling(grid.NumRows * grid.Resolution / GridResolution);

            CellState?[, , ,] cells = new CellState?[numCols, numRows, numOrientations, 2];

            Cell startCell = poseToCell(start, 0);
            IPriorityQueueHandle <Node> startHandle = null;
            float heuristicValue = heuristic.GetHeuristicValue(start, goal);
            Node  startNode      = new Node(startCell, new ReedsSheppAction(Steer.Straight, Gear.Forward, 0f), start, 0, Epsilon * heuristicValue, null);

            open.Add(ref startHandle, startNode);
            discovered.Add(startNode);
            cells[startCell.c, startCell.r, startCell.o, startCell.rev] = new CellState(start, Epsilon * heuristicValue, startHandle);

            while (!open.IsEmpty)
            {
                Node n = open.DeleteMin();

                lock (Expanded)
                {
                    Expanded.Add(n);
                }
                CellState?c = cells[n.cell.c, n.cell.r, n.cell.o, n.cell.rev];

                if (c.Value.continuousPose == goal)
                {
                    return(new HybridAStarResults(reconstructPath(n), Expanded, discovered, heuristicInitTime));
                }

                float dt = GridResolution / VehicleModel.SlowVelocity;
                //GridCell nodeCell = grid.PointToCellPosition(c.Value.continuousPose.Position);
                //float dt = MathHelper.Max(GridResolution, 0.5f * (grid.GVD.GetObstacleDistance(nodeCell) + grid.GVD.GetVoronoiDistance(nodeCell)));
                //dt /= VehicleModel.SlowVelocity;

                for (int g = 0; g < VehicleModel.NumGears; g++)
                {
                    Gear gear = (Gear)g;

                    foreach (Node child in getChildren(c.Value.continuousPose, gear, dt, goal))
                    {
                        int   rev = gear == Gear.Forward ? 0 : 1;
                        float tentativeg;

                        if (child.actionSet == null)
                        {
                            tentativeg = n.g + pathCost(n.pose, n.cell.rev, child.pose, rev, dt);
                        }
                        else
                        {
                            tentativeg = n.g + child.actionSet.CalculateCost(VehicleModel.TurnRadius, reverseFactor, switchPenalty);
                        }

                        float tentativef = tentativeg + Epsilon * heuristic.GetHeuristicValue(child.pose, goal);

                        child.cell = poseToCell(child.pose, rev);
                        CellState?currentCell = cells[child.cell.c, child.cell.r, child.cell.o, child.cell.rev];

                        if (!currentCell.HasValue)
                        {
                            IPriorityQueueHandle <Node> childHandle = null;
                            child.g    = tentativeg;
                            child.f    = tentativef;
                            child.from = n;

                            open.Add(ref childHandle, child);
                            discovered.Add(child);
                            cells[child.cell.c, child.cell.r, child.cell.o, child.cell.rev] = new CellState(child.pose, tentativef, childHandle);
                        }
                        else if (tentativef < currentCell.Value.f)
                        {
                            IPriorityQueueHandle <Node> currentHandle = currentCell.Value.handle;
                            child.g    = tentativeg;
                            child.f    = tentativef;
                            child.from = n;

                            Node temp;
                            if (open.Find(currentHandle, out temp))
                            {
                                open[currentHandle] = child;
                            }
                            else
                            {
                                open.Add(ref currentHandle, child);
                            }

                            discovered.Add(child);
                            cells[child.cell.c, child.cell.r, child.cell.o, child.cell.rev] = new CellState(child.pose, tentativef, currentHandle);
                        }
                    }
                }

                if (Delay > 0)
                {
                    Thread.Sleep(Delay);
                }
            }

            return(new HybridAStarResults(new ArrayList <Pose>(), Expanded, discovered, heuristicInitTime));
        }
Esempio n. 9
0
 public static ArrayList<Pose> Smooth(ArrayList<Pose> path, ObstacleGrid grid)
 {
     return Smooth(path, grid, null);
 }
Esempio n. 10
0
        public void InitSim(bool autoStart, bool smoothingOn, Mission mission)
        {
            gridDone = false;
            pathDone = false;
            pathSmoothDone = false;
            pathSearching = false;
            pathSearchingDone = false;
            autoDrive = true;
            run = false;
            isCollided = false;
            currentControls = new CarControls(0f, 0f, 0f);

            if (camera == null)
            {
                camera = new Camera(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 0.1f, 1000f);
                camera.Position = new Vector3(75f, 75f, 180f);
            }

            startPose = mission.Start;
            goalPose = mission.Goal;
            HybridAStar.Epsilon = mission.AStarEpsilon;
            HybridAStar.GridResolution = mission.AStarGridResolution;
            HybridAStar.SafetyFactor = 1.5f;
            HybridAStar.Reset();

            car = new Car(world, startPose);
            grid = new ObstacleGrid(world, mission.Environment);

            car.Body.OnCollision += new OnCollisionEventHandler(OnCollision);

            gridDone = false;
            pathDone = false;
            pathSearchingDone = false;
            bg = new Thread(() =>
            {
                DateTime now = DateTime.Now;
                grid.BuildGVD();
                console.WriteLine("GVD Generation Time: " + Math.Round((DateTime.Now - now).TotalMilliseconds) + " ms");
                gridDone = true;

                now = DateTime.Now;
                pathSearching = true;
                astar = HybridAStar.FindPath(grid, startPose, goalPose);
                TimeSpan astarTime = DateTime.Now - now;
                poses = astar.Path;

                pathSearching = false;
                pathSearchingDone = true;

                if (astar.Path.Count > 0)
                    pathDone = true;

                now = DateTime.Now;
                if (smoothingOn)
                    smoothedPath = Smoother.Smooth(astar.Path, grid);
                else
                    smoothedPath = astar.Path;
                TimeSpan smoothingTime = DateTime.Now - now;

                int numUnsafe = Smoother.UnsafeIndices != null ? Smoother.UnsafeIndices.Count : 0;

                console.WriteLine("A*: Total Planning Time: " + Math.Round((astarTime + smoothingTime).TotalMilliseconds) + " ms");
                console.WriteLine("         Heuristic Time: " + Math.Round(astar.HeuristicInitTime.TotalMilliseconds) + " ms");
                console.WriteLine("         Searching Time: " + Math.Round((astarTime - astar.HeuristicInitTime).TotalMilliseconds) + " ms");
                console.WriteLine("         Smoothing Time: " + Math.Round(smoothingTime.TotalMilliseconds) + " ms (" + Smoother.NumIterations + " iterations, " + Smoother.Change + "m, " + numUnsafe + " unsafe points)");
                console.WriteLine("    " + astar.Discovered.Count + " nodes discovered");
                console.WriteLine("    " + astar.Expanded.Count + " nodes expanded");

                controller = new StanleyFSMController(smoothedPath, goalPose);

                pathSmoothDone = true;
                if (autoStart)
                    run = true;
            });
            bg.IsBackground = true;
            bg.Priority = ThreadPriority.Lowest;
            bg.Start();
        }
Esempio n. 11
0
        private static HashSet<int> checkPath(ArrayList<Pose> path, ObstacleGrid grid)
        {
            HashSet<int> unsafeIndices = new HashSet<int>();

            int count = path.Count;

            for (int i = 2; i < count - 2; i++)
            {
                if (path[i - 2].Gear != path[i - 1].Gear) continue;
                if (path[i - 1].Gear != path[i].Gear) continue;
                if (path[i].Gear != path[i + 1].Gear) continue;
                if (path[i + 1].Gear != path[i + 2].Gear) continue;

                Vector2 currPos = path[i].Position;
                Vector2 prevPos = path[i - 1].Position;
                Vector2 displacement = 0.25f * (currPos - prevPos) + 0.75f * (currPos - currPos);
                float pathOrientation = (float)Math.Atan2(displacement.Y, displacement.X);

                if (!grid.IsSafe(new Pose(currPos, pathOrientation), 1.1f))
                {
                    unsafeIndices.Add(i);
                    unsafeIndices.Add(i - 1);
                }
            }

            return unsafeIndices;
        }
Esempio n. 12
0
        public static ArrayList<Pose> Smooth(ArrayList<Pose> path, ObstacleGrid grid, HashSet<int> unsafeIndices)
        {
            UnsafeIndices = Anchoring ? unsafeIndices : null;

            if (path.Count < 5)
            {
                ArrayList<Pose> thepath = new ArrayList<Pose>();
                thepath.AddAll(path);
                return thepath;
            }

            int num = currentCount = path.Count;

            currentPath = new Pose[num];
            for (int i = 0; i < num; i++)
                currentPath[i] = path[i];

            int count = 0;
            float change = Tolerance;
            while (/*change >= Tolerance && */count < MaxIterations)
            {
                float cdmax2 = CollisionDmax * CollisionDmax;
                change = 0f;
                for (int i = 2; i < num - 2; i++)
                {
                    // Keep this point fixed if it is or is adjacent to a cusp point
                    if (currentPath[i - 2].Gear != currentPath[i - 1].Gear) continue;
                    if (currentPath[i - 1].Gear != currentPath[i].Gear) continue;
                    if (currentPath[i].Gear != currentPath[i + 1].Gear) continue;
                    if (currentPath[i + 1].Gear != currentPath[i + 2].Gear) continue;

                    // Keep this point fixed if it is unsafe
                    if (Anchoring && unsafeIndices != null && unsafeIndices.Contains(i))
                        continue;

                    Vector2 curr = currentPath[i].Position;
                    Vector2 correction = Vector2.Zero;

                    // Original path term
                    correction += PathWeight * (path[i].Position - curr);
                    if (float.IsNaN(correction.X) || float.IsNaN(correction.Y))
                    {
                        float noop;
                    }

                    if (grid.IsPointInGrid(curr))
                    {
                        // Collision term
                        Vector2 closestObstacleVec = curr - grid.CellPositionToPoint(grid.GVD.GetNearestObstacle(grid.PointToCellPosition(curr)));
                        float obstDist = closestObstacleVec.Length();
                        if (obstDist < CollisionDmax)
                            correction -= CollisionWeight * (obstDist - CollisionDmax) * closestObstacleVec / obstDist;

                        if (float.IsNaN(correction.X) || float.IsNaN(correction.Y))
                        {
                            float noop;
                        }

                        // Voronoi term
                        if (obstDist < VoronoiDmax && VoronoiWeight > 0f)
                        {
                            Vector2 closestVoronoiVec = curr - grid.CellPositionToPoint(grid.GVD.GetNearestVoronoiEdge(grid.PointToCellPosition(curr)));
                            float voroDist = closestVoronoiVec.Length();

                            if (voroDist > 0f)
                            {
                                float alphaplusdo = grid.GVD.AlphaActual + obstDist;
                                float dominusdmax = obstDist - VoronoiDmax;
                                float doplusdv = obstDist + voroDist;
                                float dmaxsquared = VoronoiDmax * VoronoiDmax;
                                float pvdv = (grid.GVD.AlphaActual / alphaplusdo) * (dominusdmax * dominusdmax / dmaxsquared) * (obstDist / (doplusdv * doplusdv));
                                float pvdo = (grid.GVD.AlphaActual / alphaplusdo) * (voroDist / doplusdv) * (dominusdmax / dmaxsquared) * (-dominusdmax / alphaplusdo - dominusdmax / doplusdv + 2);

                                correction -= VoronoiWeight * (pvdo * closestObstacleVec / obstDist + pvdv * closestVoronoiVec / voroDist);

                                if (float.IsNaN(correction.X) || float.IsNaN(correction.Y))
                                {
                                    float noop;
                                }
                            }
                        }
                    }

                    // Smoothing term
                    correction -= SmoothWeight * (currentPath[i - 2].Position - 4 * currentPath[i - 1].Position + 6 * curr - 4 * currentPath[i + 1].Position + currentPath[i + 2].Position);

                    if (float.IsNaN(correction.X) || float.IsNaN(correction.Y))
                    {
                        float noop;
                    }

                    // Curvature term
                    correction -= CurvatureWeight * calcCurvatureTerm(currentPath[i - 1].Position, currentPath[i].Position, currentPath[i + 1].Position);
                    if (float.IsNaN(correction.X) || float.IsNaN(correction.Y))
                    {
                        calcCurvatureTerm(currentPath[i - 1].Position, currentPath[i].Position, currentPath[i + 1].Position);
                    }

                    correction /= CollisionWeight + SmoothWeight + VoronoiWeight + PathWeight + CurvatureWeight;

                    currentPath[i].Position = curr + Alpha * correction;
                    change += correction.Length();
                }

                count++;
                if (Delay > 0)
                    Thread.Sleep(Delay);
            }

            NumIterations = count;
            Change = change;

            ArrayList<Pose> thenewpath = new ArrayList<Pose>();
            thenewpath.AddAll(currentPath);

            if (Anchoring && unsafeIndices == null)
            {
                HashSet<int> newUnsafes = checkPath(thenewpath, grid);
                if (newUnsafes.Count > 0)
                    thenewpath = Smooth(path, grid, newUnsafes);
            }

            foreach (Pose p in thenewpath)
            {
                if (float.IsNaN(p.Position.X) || float.IsNaN(p.Position.Y))
                {
                    float noop;
                }
            }

            return thenewpath;
        }
Esempio n. 13
0
 public CombinedHeuristic(ObstacleGrid grid)
 {
     one = new NonholonomicRelaxed(grid);
     two = new ObstacleRelaxed(grid);
 }
Esempio n. 14
0
 public ObstacleRelaxed(ObstacleGrid grid)
 {
     this.grid = grid;
 }
Esempio n. 15
0
 public NonholonomicRelaxed(ObstacleGrid grid)
 {
     this.grid = grid;
     heuristic = new float[grid.NumColumns, grid.NumRows];
     unit = grid.Resolution * discount; // factor to discount the suboptimality of 8-neighbor paths
 }